Amazon web services 跨不同AWS帐户在CloudFormation中添加VPC对等路由
使用此功能,我可以成功地在不同aws帐户之间添加vpc对等连接 连接被自动接受,因为在请求连接时,接受者帐户中的IAM角色设置被授予该权限并在请求者帐户中被引用 这一切都很好,但是如果两个VPC中都没有路由表条目,那么这个连接就没有意义了 查看示例中的第二个模板;创建Amazon web services 跨不同AWS帐户在CloudFormation中添加VPC对等路由,amazon-web-services,amazon-cloudformation,amazon-vpc,Amazon Web Services,Amazon Cloudformation,Amazon Vpc,使用此功能,我可以成功地在不同aws帐户之间添加vpc对等连接 连接被自动接受,因为在请求连接时,接受者帐户中的IAM角色设置被授予该权限并在请求者帐户中被引用 这一切都很好,但是如果两个VPC中都没有路由表条目,那么这个连接就没有意义了 查看示例中的第二个模板;创建AWS::EC2::VPCPeeringConnection的那个,有没有办法在第一个模板中创建的VPC的路由表条目中添加路由 我当然可以将路由表id传递给第二个模板,但我认为这还不够。我认为,账户之间必须有一种额外的信任关系,这样
AWS::EC2::VPCPeeringConnection
的那个,有没有办法在第一个模板中创建的VPC的路由表条目中添加路由
我当然可以将路由表id传递给第二个模板,但我认为这还不够。我认为,账户之间必须有一种额外的信任关系,这样才能做到这一点
你知道怎么做吗?我可以通过以下方法来完成这项工作:
1) In the accepter account
-- added an SNS topic
-- added a lambda function that uses boto3 to create the route entry. It receives the peering connection id and CIDR and adds it to the route table of the accepter VPC
-- added a permission to tirgger the lambda from the SNS topic
-- updated the PeerRole to allow cross account access to sns:Publish on Arn of the topic
-- added a topic policy to allow cross account publish on sns topic
2) On the requester account
-- added a lambda that sends a message to the SNS topic with the VPC Peer Id, and the CIDR
这有点冗长,但这里是接受程序模板的json的一部分
"AcceptVPCPeerLambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"Path": "/",
"Policies": [
{
"PolicyName": "CrossAccountVPCPeering",
"PolicyDocument": {
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:GetLogEvents",
"logs:PutLogEvents",
],
"Resource": [ "arn:aws:logs:*:*:*" ],
"Effect": "Allow"
},
{
"Effect":"Allow",
"Action":["ec2:*Route*"],
"Resource":"*"
}
]
}
}
],
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": [ "sts:AssumeRole" ],
"Effect": "Allow",
"Principal": {
"Service": [ "lambda.amazonaws.com" ]
}
}]
}
}
},
"AcceptVPCPeerLambdaFunction": {
"DependsOn": ["AcceptVPCPeerLambdaExecutionRole"],
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile" : { "Fn::Join" : ["\n", [
"import json",
"import boto3",
"import logging",
"logger = logging.getLogger()",
"logger.setLevel(logging.INFO)",
"def handler(event, context):",
" message = json.loads(event['Records'][0]['Sns']['Message'])",
" #logger.info('got event {}'.format(event))",
" logger.info('message {}'.format(message))",
" client = boto3.client('ec2')",
" response = client.create_route(",
" DestinationCidrBlock=message.get('destCidrBlock'),",
" VpcPeeringConnectionId=message.get('ReqVpcPeeringId'),",
{"Fn::Sub" : [" RouteTableId='${RouteTableId}'", {"RouteTableId" : {"Ref" : "PrivateRouteTable"}}]},
" )",
" logger.info('response code is {} '.format(",
" response['Return']",
" ))",
]]
}
},
"Description": "Accept A VPC Peering Connection From Requested By Another Account",
"MemorySize": 128,
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [ "AcceptVPCPeerLambdaExecutionRole", "Arn" ]
},
"Timeout": 300,
"Runtime": "python2.7"
}
},
"AcceptVPCPeerSNSTopic": {
"DependsOn": [ "AcceptVPCPeerLambdaFunction" ],
"Type": "AWS::SNS::Topic",
"Properties": {
"Subscription": [{
"Endpoint": {"Fn::GetAtt": [ "AcceptVPCPeerLambdaFunction", "Arn" ]},
"Protocol": "lambda"
}]
}
},
"SNSTopicPolicy" : {
"Type" : "AWS::SNS::TopicPolicy",
"Properties" :{
"PolicyDocument" : {
"Version":"2012-10-17",
"Id":"AWSAccountTopicAccess",
"Statement" :[
{
"Sid":"allow-publish-vpc-peering",
"Effect":"Allow",
"Principal" :{
"AWS": {"Ref": "PeerRequesterAccounts"}
},
"Action":["sns:Publish"],
"Resource" : "*"
}
]
},
"Topics" : [ {"Ref" : "AcceptVPCPeerSNSTopic"}]
}
}
请求者模板的Lambda是
"VpcPeeringConnection": {
"Type": "AWS::EC2::VPCPeeringConnection",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"PeerVpcId": {
"Ref": "PeerVPCId"
},
"PeerOwnerId": {
"Ref": "PeerVPCAccountId"
},
"PeerRoleArn": {
"Ref": "PeerRoleArn"
},
"Tags" : [
{"Key" : "Name", "Value" : "DevOps Account To VPN Account"}
]
}
},
"RequesterVPCPeerLambdaFunction": {
"DependsOn": ["RequesterVPCPeerLambdaExecutionRole", "VPC", "VpcPeeringConnection"],
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile" : { "Fn::Join" : ["\n", [
"import json",
"import boto3",
"import cfnresponse",
"def handler(event, context):",
" message = {",
{ "Fn::Sub": [ " 'ReqVpcPeeringId' : '${VpcPeeringId}',", { "VpcPeeringId": {"Ref" : "VpcPeeringConnection" }} ]},
{ "Fn::Sub": [ " 'destCidrBlock' : '${destCidrBlock}'", { "destCidrBlock": {"Ref" : "TestPrivateSubnet1Cidr" }} ]},
" }",
" client = boto3.client('sns')",
" response = client.publish(",
{ "Fn::Sub": [ " TargetArn='${TargetArn}',", { "TargetArn": {"Ref" : "AcceptVPCPeerSNSTopicArn" }} ]},
" Message=json.dumps({'default': json.dumps(message)}),",
" MessageStructure='json'",
" )"
]]
}
},
"Description": "Lambda Function To Publish the VPC Peering Connection Id to The VPN Accepter SNS Topic",
"MemorySize": 128,
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [ "RequesterVPCPeerLambdaExecutionRole", "Arn" ]
},
"Timeout": 300,
"Runtime": "python2.7"
}
}
可以从第二个模板中创建第一个VPC中的路由表条目。第二个模板中可能包含的相关云信息资源示例:
Resources:
IsolationVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: "10.1.0.0/16"
PrimaryPrivateSubnet:
DependsOn:
- IsolationVPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: IsolationVPC
AvailabilityZone: ${self:provider.region}a
CidrBlock: 10.1.1.0/24
PrimaryPrivateSubnetRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: IsolationVPC
DependsOn:
- IsolationVPC
PrimaryPublicSubnet:
DependsOn:
- IsolationVPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: IsolationVPC
AvailabilityZone: ${self:provider.region}a
CidrBlock: 10.1.2.0/24
PrimaryPublicSubnetRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: IsolationVPC
DependsOn:
- IsolationVPC
PeeringConnection:
Type: AWS::EC2::VPCPeeringConnection
DependsOn:
- IsolationVPC
Properties:
PeerVpcId: <first VPC ID goes here>
VpcId:
Ref: IsolationVPC
PublicRoutingTableEntry:
Type: AWS::EC2::Route
DependsOn:
- PrimaryPublicSubnetRouteTable
- PeeringConnection
Properties:
RouteTableId:
Ref: PrimaryPublicSubnetRouteTable
DestinationCidrBlock: <first VPC CIDR block goes here>
VpcPeeringConnectionId:
Ref: PeeringConnection
PrivateRoutingTableEntry:
Type: AWS::EC2::Route
DependsOn:
- PrimaryPrivateSubnetRouteTable
- PeeringConnection
Properties:
RouteTableId:
Ref: PrimaryPrivateSubnetRouteTable
DestinationCidrBlock: <first VPC CIDR block goes here>
VpcPeeringConnectionId:
Ref: PeeringConnection
ReversePublicRoutingTableEntry:
Type: AWS::EC2::Route
DependsOn:
- PeeringConnection
Properties:
RouteTableId: <first VPC public route table ID goes here>
DestinationCidrBlock: 10.1.0.0/16
VpcPeeringConnectionId:
Ref: PeeringConnection
ReversePrivateRoutingTableEntry:
Type: AWS::EC2::Route
DependsOn:
- PeeringConnection
Properties:
RouteTableId: <first VPC private route table ID goes here>
DestinationCidrBlock: 10.1.0.0/16
VpcPeeringConnectionId:
Ref: PeeringConnection
资源:
隔离VPC:
类型:AWS::EC2::VPC
特性:
CidrBlock:“10.1.0.0/16”
PrimaryPrivateSubnet:
德彭森:
-隔离VPC
类型:AWS::EC2::子网
特性:
VpcId:
参考:隔离VPC
AvailabilityZone:${self:provider.region}a
CidrBlock:10.1.1.0/24
Primary Private SubnetrouteTable:
类型:AWS::EC2::RouteTable
特性:
VpcId:
参考:隔离VPC
德彭森:
-隔离VPC
PrimaryPublicSubnet:
德彭森:
-隔离VPC
类型:AWS::EC2::子网
特性:
VpcId:
参考:隔离VPC
AvailabilityZone:${self:provider.region}a
CidrBlock:10.1.2.0/24
PrimaryPublicSubnetuteTable:
类型:AWS::EC2::RouteTable
特性:
VpcId:
参考:隔离VPC
德彭森:
-隔离VPC
对等连接:
类型:AWS::EC2::VPCPeeringConnection
德彭森:
-隔离VPC
特性:
PeerVpcId:
VpcId:
参考:隔离VPC
PublicRoutingTableEntry:
类型:AWS::EC2::路由
德彭森:
-主公共子目录
-对等连接
特性:
RouteTableId:
参考:PrimaryPublicSubnetuteTable
目标IDRBLOCK:
VpcPeeringConnectionId:
参考:对等连接
PrivateRoutingTableEntry:
类型:AWS::EC2::路由
德彭森:
-一级私有子网
-对等连接
特性:
RouteTableId:
参考:Primary Private SubnetrouteTable
目标IDRBLOCK:
VpcPeeringConnectionId:
参考:对等连接
ReversePublicationTableEntry:
类型:AWS::EC2::路由
德彭森:
-对等连接
特性:
RouteTableId:
目标IDRBLOCK:10.1.0.0/16
VpcPeeringConnectionId:
参考:对等连接
ReversePrivateRoutingTableEntry:
类型:AWS::EC2::路由
德彭森:
-对等连接
特性:
RouteTableId:
目标IDRBLOCK:10.1.0.0/16
VpcPeeringConnectionId:
参考:对等连接
直到阅读了这里提供的示例,我才意识到这一点:但后来我成功地对其进行了测试。对于后代,我们一直在使用它来创建VPC之间的对等 它使用我们的自定义资源提供程序创建远程对等路由和标记,并可选择授权进入远程安全组(例如):
可以独立存在,也可以嵌套在另一个堆栈中。我将探索SNS/Lambda实现这一点的方法。我对“请求者帐户中引用的”感到好奇。我正试图通过请求者的web界面,将作为接受者启动的对等连接自动化。它们还公开了用于启动请求的api和api,但我不清楚您上面的陈述,以及我必须如何通知请求者。我希望这有意义?
RemotePeeringRoute:
Type: 'Custom::CreatePeeringRoute'
Version: 1.0
DependsOn: PeeringConnection
Properties:
ServiceToken: !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:generic-custom-resource-provider'
RoleArn: !Sub 'arn:${AWS::Partition}:iam::${TargetAccountId}:role/VPCPeeringRole'
AgentService: ec2
AgentType: client
AgentRegion: !Sub '${TargetRegion}'
AgentCreateMethod: create_route
AgentDeleteMethod: delete_route
AgentCreateArgs:
DestinationCidrBlock: !Sub '${RequesterCidrBlock.CidrBlock}'
RouteTableId: !Select [ 0, !Split [ ',', !Ref 'TargetRouteTableIds' ]]
VpcPeeringConnectionId: !Sub '${PeeringConnection}'
AgentDeleteArgs:
DestinationCidrBlock: !Sub '${RequesterCidrBlock.CidrBlock}'
RouteTableId: !Select [ 0, !Split [ ',', !Ref 'TargetRouteTableIds' ]]