51
loading...
This website collects cookies to deliver better user experience
VpcStack
and InstanceStack
classes that we created in part 1. Additionally, we'll create two classes, both will live in one file, one for a TGW and the other for routes leading to it:➜ ping-me-cdk-example$ touch lib/tgw.ts
ping-me-cdk-example/lib/tgw.ts
import * as ec2 from '@aws-cdk/aws-ec2';
import * as cdk from '@aws-cdk/core';
interface TransitGatewayProps extends cdk.StackProps {
vpcs: [ec2.Vpc, ec2.Vpc, ...ec2.Vpc[]]; // <--- a list of VPC objects (at least two are required) to be attached to the Transit Gateway; NB only routes between the first two VPCs will be created
}
export class TransitGatewayStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: TransitGatewayProps) {
super(scope, id, props);
// create a Transit Gateway
const tgw = new ec2.CfnTransitGateway(this, 'Tgw');
// For each supplied VPC, create a Transit Gateway attachment
props.vpcs.forEach((vpc, index) => {
new ec2.CfnTransitGatewayAttachment(this, `TgwVpcAttachment${index}`, {
subnetIds: vpc.privateSubnets.map(privateSubnet => privateSubnet.subnetId),
transitGatewayId: tgw.ref,
vpcId: vpc.vpcId,
});
});
// Output the Transit Gateway's ID
new cdk.CfnOutput(this, 'TransitGatewayId', {
value: tgw.ref,
exportName: 'TransitGatewayId',
});
}
}
export class RoutesToTransitGatewayStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: TransitGatewayProps) {
super(scope, id, props);
// Add route from the private subnet of the first VPC to the second VPC over the Transit Gateway
// NB the below was taken from: https://stackoverflow.com/questions/62525195/adding-entry-to-route-table-with-cdk-typescript-when-its-private-subnet-alread
props.vpcs[0].privateSubnets.forEach(({ routeTable: { routeTableId } }, index) => {
new ec2.CfnRoute(this, 'RouteFromPrivateSubnetOfVpc1ToVpc2' + index, {
destinationCidrBlock: props.vpcs[1].vpcCidrBlock,
routeTableId,
transitGatewayId: cdk.Fn.importValue('TransitGatewayId'), // Transit Gateway must already exist
});
});
// Add route from the private subnet of the second VPC to the first VPC over the Transit Gateway
props.vpcs[1].privateSubnets.forEach(({ routeTable: { routeTableId } }, index) => {
new ec2.CfnRoute(this, 'RouteFromPrivateSubnetOfVpc2ToVpc1' + index, {
destinationCidrBlock: props.vpcs[0].vpcCidrBlock,
routeTableId,
transitGatewayId: cdk.Fn.importValue('TransitGatewayId'), // Transit Gateway must already exist
});
});
}
}
ping-me-cdk-example/bin/ping-me-cdk-example.ts
import * as cdk from '@aws-cdk/core';
import { VpcStack } from '../lib/vpc';
import { InstanceStack } from '../lib/instance';
import { PeeringStack } from '../lib/peering';
import { CustomerGatewayDeviceStack } from '../lib/cgd';
import { TransitGatewayStack, RoutesToTransitGatewayStack } from '../lib/tgw';
const app = new cdk.App(); // <--- you can read more about the App construct here: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.App.html
/**
* CODE FROM "Ping Me! (Part 1: VPC Peering Using CDK)" AND "Ping Me! (Part 2: Site-to-Site VPN Using CDK)" WAS REMOVED FOR VISIBILITY
*/
// Create two VPCs
const vpcsMetInTransit = new VpcStack(app, 'VpcsMetInTransitStack', {
vpcSetup: {
cidrs: ['10.0.4.0/24', '10.0.5.0/24'], // <--- two non-overlapping CIDR ranges for our two VPCs
maxAzs: 1, // <--- to keep the costs down, we'll stick to 1 availability zone per VPC (obviously, not something you'd want to do in production)
},
});
// Create two EC2 instances, one in each VPC
new InstanceStack(app, 'InstanceTransitStack', {
vpcs: vpcsMetInTransit.createdVpcs,
});
// Create a Transit Gateway and attach both VPCs to it
new TransitGatewayStack(app, 'TransitGatewayStack', {
vpcs: [vpcsMetInTransit.createdVpcs[0], vpcsMetInTransit.createdVpcs[1]],
});
// Create routes between both VPCs over the Transit Gateway
new RoutesToTransitGatewayStack(app, 'RoutesToTransitGatewayStack', {
vpcs: [vpcsMetInTransit.createdVpcs[0], vpcsMetInTransit.createdVpcs[1]],
});
InstanceTransitStack
(implicitly with VpcsMetInTransitStack
).➜ ping-me-cdk-example$ cdk deploy InstanceTransitStack --require-approval never
Including dependency stacks: VpcsMetInTransitStack
VpcsMetInTransitStack
VpcsMetInTransitStack: deploying...
VpcsMetInTransitStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (30/30)
✅ VpcsMetInTransitStack
Outputs:
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.4.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0b97deeeacfd5627d
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BCidrBlock933A5AA8 = 10.0.5.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BDefaultSecurityGroup87C47BC2 = sg-0dfe3c25a0cd42e84
VpcsMetInTransitStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-063e0aaa8aaf32b32
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1RouteTableB5C6777D52F53FE8 = rtb-053b342d2f9950c58
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-002286581738a15da
VpcsMetInTransitStack.ExportsOutputRefVpc1C211860B64169B74 = vpc-0020c0197873df61c
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1RouteTable339A93B3DFC75FCA = rtb-0b3cac3abd02c16d6
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1Subnet41967AFDFF883DAB = subnet-0c10da57ee874b680
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcsMetInTransitStack/a54b7350-3560-11eb-ae91-0643678755c5
InstanceTransitStack
InstanceTransitStack: deploying...
InstanceTransitStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (10/10)
✅ InstanceTransitStack
Outputs:
InstanceTransitStack.Instance0BastionHostId1959CA92 = i-03d7c391c35302d4a # <--- COPY THE ID OF YOUR SOURCE EC2 INSTANCE!
InstanceTransitStack.Instance0PrivateIp = 10.0.4.58
InstanceTransitStack.Instance1BastionHostIdEF2AA144 = i-0d315dbb89ed80f82
InstanceTransitStack.Instance1PrivateIp = 10.0.5.54 # <--- COPY THE PRIVATE IP OF YOUR DESTINATION EC2 INSTANCE!
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/InstanceTransitStack/11f0b6a0-3561-11eb-842c-0aa13688a741
TransitGatewayStack
➜ ping-me-cdk-example$ cdk deploy TransitGatewayStack --require-approval never
Including dependency stacks: VpcsMetInTransitStack
VpcsMetInTransitStack
VpcsMetInTransitStack: deploying...
✅ VpcsMetInTransitStack (no changes)
Outputs:
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.4.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0b97deeeacfd5627d
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BCidrBlock933A5AA8 = 10.0.5.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BDefaultSecurityGroup87C47BC2 = sg-0dfe3c25a0cd42e84
VpcsMetInTransitStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-063e0aaa8aaf32b32
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1RouteTableB5C6777D52F53FE8 = rtb-053b342d2f9950c58
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-002286581738a15da
VpcsMetInTransitStack.ExportsOutputRefVpc1C211860B64169B74 = vpc-0020c0197873df61c
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1RouteTable339A93B3DFC75FCA = rtb-0b3cac3abd02c16d6
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1Subnet41967AFDFF883DAB = subnet-0c10da57ee874b680
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcsMetInTransitStack/a54b7350-3560-11eb-ae91-0643678755c5
TransitGatewayStack
TransitGatewayStack: deploying...
TransitGatewayStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (5/5)
✅ TransitGatewayStack
Outputs:
TransitGatewayStack.TransitGatewayId = tgw-057de86d7c789626e
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/TransitGatewayStack/e86b7b70-3561-11eb-b82a-0ad12ebbcfd9
RoutesToTransitGatewayStack
➜ ping-me-cdk-example$ cdk deploy RoutesToTransitGatewayStack --require-approval never
Including dependency stacks: VpcsMetInTransitStack
VpcsMetInTransitStack
VpcsMetInTransitStack: deploying...
✅ VpcsMetInTransitStack (no changes)
Outputs:
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.4.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0b97deeeacfd5627d
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BCidrBlock933A5AA8 = 10.0.5.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BDefaultSecurityGroup87C47BC2 = sg-0dfe3c25a0cd42e84
VpcsMetInTransitStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-063e0aaa8aaf32b32
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1RouteTableB5C6777D52F53FE8 = rtb-053b342d2f9950c58
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-002286581738a15da
VpcsMetInTransitStack.ExportsOutputRefVpc1C211860B64169B74 = vpc-0020c0197873df61c
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1RouteTable339A93B3DFC75FCA = rtb-0b3cac3abd02c16d6
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1Subnet41967AFDFF883DAB = subnet-0c10da57ee874b680
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcsMetInTransitStack/a54b7350-3560-11eb-ae91-0643678755c5
RoutesToTransitGatewayStack
RoutesToTransitGatewayStack: deploying...
RoutesToTransitGatewayStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (4/4)
✅ RoutesToTransitGatewayStack
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/RoutesToTransitGatewayStack/d803d8d0-3562-11eb-aaeb-02e586bc56f0
i-03d7c391c35302d4a
) and the private IP of the destination EC2 instance (10.0.5.54
) for appropriate values before running the below:aws ssm send-command \
--document-name "AWS-RunShellScript" \
--document-version "1" \
--targets '[{"Key":"InstanceIds","Values":["i-03d7c391c35302d4a"]}]' \
--parameters '{"workingDirectory":[""],"executionTimeout":["3600"],"commands":["ping 10.0.5.54 -c 3"]}' \
--timeout-seconds 600 \
--max-concurrency "50" \
--max-errors "0"
{
"Command": {
"CommandId": "f7ed8e0e-a313-405a-a811-7885b4d532e7",
"DocumentName": "AWS-RunShellScript",
"DocumentVersion": "1",
"Comment": "",
"ExpiresAfter": "2020-12-03T15:06:43.691000+01:00",
"Parameters": {
"commands": [
"ping 10.0.5.54 -c 3"
],
"executionTimeout": [
"3600"
],
"workingDirectory": [
""
]
},
"InstanceIds": [],
"Targets": [
{
"Key": "InstanceIds",
"Values": [
"i-03d7c391c35302d4a"
]
}
],
"RequestedDateTime": "2020-12-03T13:56:43.691000+01:00",
"Status": "Pending",
"StatusDetails": "Pending",
"OutputS3BucketName": "",
"OutputS3KeyPrefix": "",
"MaxConcurrency": "50",
"MaxErrors": "0",
"TargetCount": 0,
"CompletedCount": 0,
"ErrorCount": 0,
"DeliveryTimedOutCount": 0,
"ServiceRole": "",
"NotificationConfig": {
"NotificationArn": "",
"NotificationEvents": [],
"NotificationType": ""
},
"CloudWatchOutputConfig": {
"CloudWatchLogGroupName": "",
"CloudWatchOutputEnabled": false
},
"TimeoutSeconds": 600
}
}
aws ssm get-command-invocation
command.f7ed8e0e-a313-405a-a811-7885b4d532e7
) and the ID of the source EC2 instance (i-03d7c391c35302d4a
) for appropriate values before running the below:➜ ping-me-cdk-example$ aws ssm get-command-invocation --command-id f7ed8e0e-a313-405a-a811-7885b4d532e7 --instance-id i-03d7c391c35302d4a
{
"CommandId": "f7ed8e0e-a313-405a-a811-7885b4d532e7",
"InstanceId": "i-03d7c391c35302d4a",
"Comment": "",
"DocumentName": "AWS-RunShellScript",
"DocumentVersion": "1",
"PluginName": "aws:runShellScript",
"ResponseCode": 0,
"ExecutionStartDateTime": "2020-12-03T12:56:44.343Z",
"ExecutionElapsedTime": "PT2.044S",
"ExecutionEndDateTime": "2020-12-03T12:56:46.343Z",
"Status": "Success",
"StatusDetails": "Success",
"StandardOutputContent": "PING 10.0.5.54 (10.0.5.54) 56(84) bytes of data.\n64 bytes from 10.0.5.54: icmp_seq=1 ttl=254 time=0.489 ms\n64 bytes from 10.0.5.54: icmp_seq=2 ttl=254 time=0.311 ms\n64 bytes from 10.0.5.54: icmp_seq=3 ttl=254 time=0.306 ms\n\n--- 10.0.5.54 ping statistics ---\n3 packets transmitted, 3 received, 0% packet loss, time 2027ms\nrtt min/avg/max/mdev = 0.306/0.368/0.489/0.087 ms\n",
"StandardOutputUrl": "",
"StandardErrorContent": "",
"StandardErrorUrl": "",
"CloudWatchOutputConfig": {
"CloudWatchLogGroupName": "",
"CloudWatchOutputEnabled": false
}
}
3 packets transmitted, 3 received, 0% packet loss
. That's an astounding success!y
for yes:
➜ ping-me-cdk-example$ cdk destroy RoutesToTransitGatewayStack
Are you sure you want to delete: RoutesToTransitGatewayStack (y/n)? y
RoutesToTransitGatewayStack: destroying...
14:08:49 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | RoutesToTransitGatewayStack
14:08:51 | DELETE_IN_PROGRESS | AWS::EC2::Route | RouteFromPrivateSubnetOfVpc2ToVpc10
✅ RoutesToTransitGatewayStack: destroyed
y
for yes:
➜ ping-me-cdk-example$ cdk destroy --all
Are you sure you want to delete: InstanceVpnDestinationStack, VpcVpnDestinationStack, TransitGatewayStack, RoutesToTransitGatewayStack, PeeringStack, InstanceTransitStack, InstancePeersStack, CustomerGatewayDeviceStack, VpcsMetInTransitStack, VpcVpnSourceStack, VpcPeersStack (y/n)? y
InstanceVpnDestinationStack: destroying...
✅ InstanceVpnDestinationStack: destroyed
VpcVpnDestinationStack: destroying...
✅ VpcVpnDestinationStack: destroyed
TransitGatewayStack: destroying...
14:12:23 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | TransitGatewayStack
✅ TransitGatewayStack: destroyed
RoutesToTransitGatewayStack: destroying...
✅ RoutesToTransitGatewayStack: destroyed
PeeringStack: destroying...
✅ PeeringStack: destroyed
InstanceTransitStack: destroying...
14:15:30 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | InstanceTransitStack
✅ InstanceTransitStack: destroyed
InstancePeersStack: destroying...
✅ InstancePeersStack: destroyed
CustomerGatewayDeviceStack: destroying...
✅ CustomerGatewayDeviceStack: destroyed
VpcsMetInTransitStack: destroying...
14:16:49 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | VpcsMetInTransitStack
14:18:56 | DELETE_IN_PROGRESS | AWS::EC2::InternetGateway | Vpc0/IGW
14:18:56 | DELETE_IN_PROGRESS | AWS::EC2::VPC | Vpc0
✅ VpcsMetInTransitStack: destroyed
VpcVpnSourceStack: destroying...
✅ VpcVpnSourceStack: destroyed
VpcPeersStack: destroying...
✅ VpcPeersStack: destroyed