I'm trying to set up a multi-account environment with VPC peering using AWS CDK (type script), but I'm facing some issues when trying to set up related routing tables.
I'm working on Account A which is the ops environment, that is trusted by target-environment Account B (trusted for both - deployment and lookup), as stated in CDK Bootstrap.
I've tried two approaches:
I) First Approach
1) stack executed on ops-env (Account A):
- Create VPC A
- Create peer role containing inter alia the following permissions:
ec2:AcceptVpcPeeringConnection
,ec2:ModifyVpcPeeringConnectionOptions
,ec2:CreateRoute
. The role can be assumed by target env Account B Principal.
2) stack executed on target-env (Account B):
- Create VPC B
- Create VPC Peering with peer role created in stack 1) so that it can be accepted
- Create Route Table (using CfnRoute) on all subnets of VPC B with VPC A CIDR
3) stack executed on ops-env (Account A) again:
- Create Route Table (using CfnRoute) on all subnets of VPC A with VPC B CIDR
This however won't even synth because of stack 3) - I have to pass resources created in stack 2) (mainly target-env VPC CIDR), which cannot be done because of:
Cross stack references are only supported for stacks deployed to the same account or between nested stacks and their parent stack
II) Second Approach
The main difference is that there's no stack 3, rather I use lambda functions in stack 2 (executed on Account B) to create route tables on Account A (cross-account lambda call):
1) stack executed on ops-env (Account A):
- Create VPC A
- Create peer role containing inter alia the following permissions:
ec2:AcceptVpcPeeringConnection
,ec2:ModifyVpcPeeringConnectionOptions
,ec2:CreateRoute
. The role can be assumed by target env Account B Principal.
2) stack executed on target-env (Account B):
- Create VPC B
- Create VPC Peering with peer role created in stack 1) so that it can be accepted
- Create Route Table (using CfnRoute) on all subnets of VPC B with VPC A CIDR
- Create CustomResource AwsSdkCall that executes EC2:createRoute with assumed peer role (the exact CDK construct below).
However, I get the following error from the Custom Resource:
Received response status [FAILED] from custom resource. Message returned: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
If I do it without assuming the peer role, I get (which makes sense):
Received response status [FAILED] from custom resource. Message returned: User [ACCOUNT_B_ID] does not have permission to modify the accepter side peering options
What's the right approach here ?
CDK cross-account ec2.createRoute construct:
const onCreate: custom_resources.AwsSdkCall = {
service: "EC2",
action: "createRoute",
assumedRoleArn: props.role?.roleArn,
parameters: {
RouteTableId: props.routeTableId,
DestinationCidrBlock: props.destinationCidrBlock,
VpcPeeringConnectionId: props.vpcPeeringConnectionId
},
physicalResourceId: custom_resources.PhysicalResourceId.of(`createRoute:${props.vpcPeeringConnectionId}`),
};
const onUpdate = onCreate;
const onDelete: custom_resources.AwsSdkCall = {
service: "EC2",
action: "deleteRoute",
assumedRoleArn: props.role?.roleArn,
parameters: {
RouteTableId: props.routeTableId,
DestinationCidrBlock: props.destinationCidrBlock,
},
};
const customResource = new custom_resources.AwsCustomResource(this, "create", {
policy: custom_resources.AwsCustomResourcePolicy.fromStatements([
new PolicyStatement({
effect: Effect.ALLOW,
resources: ["*"],
actions: [
"ec2:CreateRoute",
"ec2:DeleteRoute"
]
}),
]),
logRetention: RetentionDays.ONE_DAY,
onCreate,
onUpdate,
onDelete,
installLatestAwsSdk: false
});