Overview
Thanks to AWS Site-to-Site VPN you can establish a secure connection over insecure infrastructure (e.g. the public internet) between a VPC and your on-premises data center. With such a connection in place, you can communicate with your EC2 instances as if they were within your existing corporate network. It is much cheaper and quicker to establish this option rather than AWS Direct Connect, although it is less reliable in terms of performance and has a lower cap for bandwidth. It’s not uncommon to have both in place, with AWS Site-to-Site VPN being the backup option. Furthermore, if you have multiple data centers, each with an AWS Site-to-Site VPN connection to a central Virtual Private Gateway (that’s the logical construct on which the VPN connection is terminated), you can provide secure communications between those in a hub-and-spoke model using something that AWS advertises as VPN CloudHub. As far as billing is concerned, you pay for each hour during which the VPN connection is in the ‘available’ state (thus, to avoid unnecessary costs you should terminate it whenever it’s not in use), plus the usual fee for the data out transfer.
Implementation and validation
As mentioned in the overview section, in most cases you’d use AWS Site-to-Site VPN to connect your on-premises data center to AWS. However, for the sake of simplicity, we’re going to connect two VPCs together using the Software VPN-to-AWS Managed VPN approach. Since we’ll reuse the VpcStack
and InstanceStack
classes that we’ve created in part 1, the only class we’re missing is the one for the Customer Gateway Device (CGD):
➜ ping-me-cdk-example$ touch lib/cgd.ts
ping-me-cdk-example/lib/instance.ts
import * as cdk from '@aws-cdk/core'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; // <--- this module is not available from the start; remember to import it: `npm install @aws-cdk/aws-iam` interface CustomerGatewayDeviceProps extends cdk.StackProps { vpc: ec2.Vpc; // <--- the VPC in which the Customer Gateway Device will be created } export class CustomerGatewayDeviceStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props: CustomerGatewayDeviceProps) { super(scope, id, props); // Prepare the user data to be applied to the Windows EC2 instance on its initial boot-up const userData = ec2.UserData.forWindows(); userData.addCommands( // The below PowerShell commands were taken from here: https://github.com/ACloudGuru-Resources/course-aws-certified-advanced-networking-specialty/blob/3a687ba5c70d507a53743037b8f1c5a52d05d357/SteveResources/OnPremNet.yaml#L126 '<powershell>', '# Disable Internet Explorer Enhanced Security Configuration for Administrators', 'Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}" -Name "IsInstalled" -Value 0 -Force', 'Stop-Process -Name iexplore -ErrorAction SilentlyContinue', '# Begin configuration for VPN services', 'Set-NetAdapterAdvancedProperty -DisplayName "IPv4 Checksum Offload" -DisplayValue "Disabled"', 'Set-NetAdapterAdvancedProperty -DisplayName "TCP Checksum Offload (IPv4)" -DisplayValue "Disabled"', 'Set-NetAdapterAdvancedProperty -DisplayName "UDP Checksum Offload (IPv4)" -DisplayValue "Disabled"', 'Invoke-WebRequest https://steveatacg.s3-us-west-1.amazonaws.com/advnetspec/Win2019VPNServerConfig.xml -OutFile c:\config.xml', 'Install-WindowsFeature -ConfigurationFilePath c:\config.xml -computername $env:COMPUTERNAME -Restart', 'Install-RemoteAccess -VpnType VpnS2S', '</powershell>', ) // Create an IAM role allowing the instance to be managed by SSM const ssmRoleForEc2 = new iam.Role(this, 'SsmRoleForEc2', { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore')], }); // Create an EC2 instance to serve as the software VPN const cgd = new ec2.Instance(this, 'CGW', { vpc: props.vpc, instanceType: new ec2.InstanceType('t2.micro'), machineImage: ec2.MachineImage.fromSSMParameter('/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-Base', ec2.OperatingSystemType.WINDOWS, userData), // <--- use the latest Amazon Machine Image for Windows Server 2019 vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC, // <--- place the instance in a public subnet }, role: ssmRoleForEc2, // <--- use the created earlier IAM role as the instance profile sourceDestCheck: false, // <--- make sure the source/destination check is turned off }); // Output the instance's public IP new cdk.CfnOutput(this, 'CustomerGatewayDevicePublicIp', { value: cgd.instancePublicIp, }); } }
➜ ping-me-cdk-example$ npm install @aws-cdk/[email protected] npm WARN [email protected] No repository field. npm WARN [email protected] No license field. + @aws-cdk/[email protected] updated 1 package and audited 847 packages in 5.085s 27 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
1.73.0
version (the exact same one as for our @aws-cdk/core
and @aws-cdk/aws-ec2
modules) to avoid the possibility of seeing the Argument of type ‘this’ is not assignable to parameter of type ‘Construct’ error. Since we got all the pieces of the puzzle, let’s start putting them together. First, we’ll initialize the VPN source VPC (that’s the one that mocks an on-prem network) and place a Customer Gateway Device (a software VPN in our case) in it: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'; // <--- added in part 2 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)" WAS REMOVED FOR VISIBILITY */ // Create a VPN source VPC const vpcVpnSource = new VpcStack(app, 'VpcVpnSourceStack', { vpcSetup: { cidrs: ['10.0.2.0/24'], 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 a Customer Gateway Device in the VPN source VPC new CustomerGatewayDeviceStack(app, 'CustomerGatewayDeviceStack', { vpc: vpcVpnSource.createdVpcs[0], });
VpcVpnSourceStack
is a dependency of CustomerGatewayDeviceStack
we can just call the latter in our command and still both are going to be built out:➜ ping-me-cdk-example$ cdk deploy CustomerGatewayDeviceStack --require-approval never Including dependency stacks: VpcVpnSourceStack VpcVpnSourceStack VpcVpnSourceStack: deploying... VpcVpnSourceStack: creating CloudFormation changeset... [██████████████████████████████████████████████████████████] (16/16) ✅ VpcVpnSourceStack Outputs: VpcVpnSourceStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.2.0/24 VpcVpnSourceStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-0d8d8118923b40b85 VpcVpnSourceStack.ExportsOutputRefVpc0publicSubnet1SubnetB977A71E8C9155C7 = subnet-037467ea871b103c1 Stack ARN: arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcVpnSourceStack/f9d46c70-3005-11eb-8c3a-06fab0925578 CustomerGatewayDeviceStack CustomerGatewayDeviceStack: deploying... CustomerGatewayDeviceStack: creating CloudFormation changeset... [██████████████████████████████████████████████████████████] (6/6) ✅ CustomerGatewayDeviceStack Outputs: CustomerGatewayDeviceStack.CustomerGatewayDevicePublicIp = 52.51.199.29 # <--- COPY THE PUBLIC IP OF THE CUSTOMER GATEWAY DEVICE (CGD) Stack ARN: arn:aws:cloudformation:eu-west-1:REDACTED:stack/CustomerGatewayDeviceStack/665a19d0-3006-11eb-9492-0a91d0eaa80f
aws cloudformation describe-stacks --stack-name CustomerGatewayDeviceStack --query "Stacks[].Outputs[].OutputValue"
) and move on to creating a VPN destination VPC, with a Site-to-Site VPN connection to the VPN source VPC already in place, and an EC2 instance that’ll serve as our ping destination.ping-me-cdk-example/bin/ping-me-cdk-example.ts
/** * ALL PRECEDING CODE WAS REMOVED FOR VISIBILITY */ const vpcVpnDestination = new VpcStack(app, 'VpcVpnDestinationStack', { vpcSetup: { cidrs: ['10.0.3.0/24'], 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) vpnConnections: { toOnPrem: { ip: '52.51.199.29', // <--- grab this from the outputs of CustomerGatewayDeviceStack, e.g.: aws cloudformation describe-stacks --stack-name CustomerGatewayDeviceStack --query "Stacks[].Outputs[].OutputValue" staticRoutes: [ vpcVpnSource.createdVpcs[0].vpcCidrBlock, ] } } }, }); new InstanceStack(app, 'InstanceVpnDestinationStack', { vpcs: vpcVpnDestination.createdVpcs, });
➜ ping-me-cdk-example$ cdk deploy InstanceVpnDestinationStack --require-approval never Including dependency stacks: VpcVpnDestinationStack, VpcVpnSourceStack VpcVpnSourceStack VpcVpnSourceStack: deploying... ✅ VpcVpnSourceStack (no changes) Outputs: VpcVpnSourceStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.2.0/24 VpcVpnSourceStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-0d8d8118923b40b85 VpcVpnSourceStack.ExportsOutputRefVpc0publicSubnet1SubnetB977A71E8C9155C7 = subnet-037467ea871b103c1 Stack ARN: arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcVpnSourceStack/f9d46c70-3005-11eb-8c3a-06fab0925578 VpcVpnDestinationStack VpcVpnDestinationStack: deploying... VpcVpnDestinationStack: creating CloudFormation changeset... [██████████████████████████████████████████████████████████] (22/22) ✅ VpcVpnDestinationStack Outputs: VpcVpnDestinationStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0e750a0ff54ed08aa VpcVpnDestinationStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-0149bc2a09ea2bc34 Stack ARN: arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcVpnDestinationStack/af2f9e90-3007-11eb-93e5-0a4cff3749d5 InstanceVpnDestinationStack InstanceVpnDestinationStack: deploying... InstanceVpnDestinationStack: creating CloudFormation changeset... [██████████████████████████████████████████████████████████] (6/6) ✅ InstanceVpnDestinationStack Outputs: InstanceVpnDestinationStack.Instance0BastionHostId1959CA92 = i-02e376354bcb4b094 InstanceVpnDestinationStack.Instance0PrivateIp = 10.0.3.49 Stack ARN: arn:aws:cloudformation:eu-west-1:REDACTED:stack/InstanceVpnDestinationStack/c2a92a30-3008-11eb-a26f-0639b3b50e04
- AWS Console -> VPC -> Site-to-Site VPN Connections -> select our new connection -> click on Download Configuration


! Script for Tunnel 1: netsh advfirewall consec add rule Name="vgw-0e89a3295d6b100c2 Tunnel 1" ^ Enable=Yes Profile=any Type=Static Mode=Tunnel ^ LocalTunnelEndpoint=[Windows_Server_Private_IP_address] ^ RemoteTunnelEndpoint=34.253.60.42 Endpoint1=[Your_Static_Route_IP_Prefix] ^ Endpoint2=[Your_VPC_CIDR_Block] Protocol=Any Action=RequireInClearOut ^ Auth1=ComputerPSK Auth1PSK=iKV4pvEVAxVk6wKeVma38F8ZDxVfPhNA ^ QMSecMethods=ESP:SHA1-AES128+60min+100000kb ^ ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2 ! Script for Tunnel 2: netsh advfirewall consec add rule Name="vgw-0e89a3295d6b100c2 Tunnel 2" ^ Enable=Yes Profile=any Type=Static Mode=Tunnel ^ LocalTunnelEndpoint=[Windows_Server_Private_IP_address] ^ RemoteTunnelEndpoint=52.50.166.48 Endpoint1=[Your_Static_Route_IP_Prefix] ^ Endpoint2=[Your_VPC_CIDR_Block] Protocol=Any Action=RequireInClearOut ^ Auth1=ComputerPSK Auth1PSK=PAoYUDzM_V93hRcJxvVkMCV6VjpWFtKt ^ QMSecMethods=ESP:SHA1-AES128+60min+100000kb ^ ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2
[Windows_Server_Private_IP_address]
for the private IP address of your CGD (you can get it using the AWS CLI: aws ec2 describe-instances --filters "Name=tag:Name,Values=CustomerGatewayDeviceStack/CGW" --query "Reservations[].Instances[].PrivateIpAddress"
), [Your_Static_Route_IP_Prefix]
for the VPN source VPC’s CIDR (10.0.2.0/24
), [Your_VPC_CIDR_Block]
for the VPN destination VPC’s CIDR (10.0.3.0/24
), escape the quotation marks ("
) by preceding them with backslashes (\
) and remove all the carets (^
) and following new lines to make both scripts into one-liners, e.g.:netsh advfirewall consec add rule Name=\"vgw-06fab417114297dd1 Tunnel 1\" Enable=Yes Profile=any Type=Static Mode=Tunnel LocalTunnelEndpoint=10.0.2.18 RemoteTunnelEndpoint=34.249.222.228 Endpoint1=10.0.2.0/24 Endpoint2=10.0.3.0/24 Protocol=Any Action=RequireInClearOut Auth1=ComputerPSK Auth1PSK=F_BjSjPg8ctE6XeX183INrtAPxkaktXm QMSecMethods=ESP:SHA1-AES128+60min+100000kb ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2
i-03dd90e66a0e6a145
) for the appropriate value before running the below:➜ ping-me-cdk-example$ aws ssm send-command --document-name "AWS-RunPowerShellScript" \ --document-version "1" \ --targets '[{"Key":"InstanceIds","Values":["i-03dd90e66a0e6a145"]}]' \ --parameters '{"workingDirectory":[""],"executionTimeout":["3600"],"commands":["netsh advfirewall consec add rule Name=\"vgw-06fab417114297dd1 Tunnel 1\" Enable=Yes Profile=any Type=Static Mode=Tunnel LocalTunnelEndpoint=10.0.2.18 RemoteTunnelEndpoint=34.249.222.228 Endpoint1=10.0.2.0/24 Endpoint2=10.0.3.0/24 Protocol=Any Action=RequireInClearOut Auth1=ComputerPSK Auth1PSK=F_BjSjPg8ctE6XeX183INrtAPxkaktXm QMSecMethods=ESP:SHA1-AES128+60min+100000kb ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2"]}' \ --timeout-seconds 600 \ --max-concurrency "50" \ --max-errors "0" { "Command": { "CommandId": "ab32f5e8-78c9-4e5b-95d4-944e02814682", "DocumentName": "AWS-RunPowerShellScript", "DocumentVersion": "1", "Comment": "", "ExpiresAfter": "2020-11-26T19:27:48.114000+01:00", "Parameters": { "commands": [ "netsh advfirewall consec add rule Name=\"vgw-06fab417114297dd1 Tunnel 1\" Enable=Yes Profile=any Type=Static Mode=Tunnel LocalTunnelEndpoint=10.0.2.18 RemoteTunnelEndpoint=34.249.222.228 Endpoint1=10.0.2.0/24 Endpoint2=10.0.3.0/24 Protocol=Any Action=RequireInClearOut Auth1=ComputerPSK Auth1PSK=F_BjSjPg8ctE6XeX183INrtAPxkaktXm QMSecMethods=ESP:SHA1-AES128+60min+100000kb ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2" ], "executionTimeout": [ "3600" ], "workingDirectory": [ "" ] }, "InstanceIds": [], "Targets": [ { "Key": "InstanceIds", "Values": [ "i-03dd90e66a0e6a145" ] } ], "RequestedDateTime": "2020-11-26T18:17:48.114000+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 } }
ab32f5e8-78c9-4e5b-95d4-944e02814682
) and the ID of the Windows instance (i-03dd90e66a0e6a145
) for appropriate values before running the below:➜ ping-me-cdk-example$ aws ssm get-command-invocation --command-id ab32f5e8-78c9-4e5b-95d4-944e02814682 --instance-id i-03dd90e66a0e6a145 { "CommandId": "ab32f5e8-78c9-4e5b-95d4-944e02814682", "InstanceId": "i-03dd90e66a0e6a145", "Comment": "", "DocumentName": "AWS-RunPowerShellScript", "DocumentVersion": "1", "PluginName": "aws:runPowerShellScript", "ResponseCode": 0, "ExecutionStartDateTime": "2020-11-26T17:17:49.795Z", "ExecutionElapsedTime": "PT1.96S", "ExecutionEndDateTime": "2020-11-26T17:17:50.795Z", "Status": "Success", "StatusDetails": "Success", "StandardOutputContent": "Ok.\r\n\r\n", "StandardOutputUrl": "", "StandardErrorContent": "", "StandardErrorUrl": "", "CloudWatchOutputConfig": { "CloudWatchLogGroupName": "", "CloudWatchOutputEnabled": false } }
➜ ping-me-cdk-example$ aws ssm send-command --document-name "AWS-RunPowerShellScript" \ --document-version "1" \ --targets '[{"Key":"InstanceIds","Values":["i-03dd90e66a0e6a145"]}]' \ --parameters '{"workingDirectory":[""],"executionTimeout":["3600"],"commands":["netsh advfirewall consec add rule Name=\"vgw-06fab417114297dd1 Tunnel 2\" Enable=Yes Profile=any Type=Static Mode=Tunnel LocalTunnelEndpoint=10.0.2.18 RemoteTunnelEndpoint=54.77.85.166 Endpoint1=10.0.2.0/24 Endpoint2=10.0.3.0/24 Protocol=Any Action=RequireInClearOut Auth1=ComputerPSK Auth1PSK=sPGbITqCkW.PSrwuhlycnn6CgFFbjS0w QMSecMethods=ESP:SHA1-AES128+60min+100000kb ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2"]}' \ --timeout-seconds 600 \ --max-concurrency "50" \ --max-errors "0" { "Command": { "CommandId": "dd7bb695-51e2-41eb-a898-eec8fc4562f4", "DocumentName": "AWS-RunPowerShellScript", "DocumentVersion": "1", "Comment": "", "ExpiresAfter": "2020-11-26T19:30:10.955000+01:00", "Parameters": { "commands": [ "netsh advfirewall consec add rule Name=\"vgw-06fab417114297dd1 Tunnel 2\" Enable=Yes Profile=any Type=Static Mode=Tunnel LocalTunnelEndpoint=10.0.2.18 RemoteTunnelEndpoint=54.77.85.166 Endpoint1=10.0.2.0/24 Endpoint2=10.0.3.0/24 Protocol=Any Action=RequireInClearOut Auth1=ComputerPSK Auth1PSK=sPGbITqCkW.PSrwuhlycnn6CgFFbjS0w QMSecMethods=ESP:SHA1-AES128+60min+100000kb ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2" ], "executionTimeout": [ "3600" ], "workingDirectory": [ "" ] }, "InstanceIds": [], "Targets": [ { "Key": "InstanceIds", "Values": [ "i-03dd90e66a0e6a145" ] } ], "RequestedDateTime": "2020-11-26T18:20:10.955000+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 } }
➜ ping-me-cdk-example$ aws ssm get-command-invocation --command-id dd7bb695-51e2-41eb-a898-eec8fc4562f4 --instance-id i-03dd90e66a0e6a145 { "CommandId": "dd7bb695-51e2-41eb-a898-eec8fc4562f4", "InstanceId": "i-03dd90e66a0e6a145", "Comment": "", "DocumentName": "AWS-RunPowerShellScript", "DocumentVersion": "1", "PluginName": "aws:runPowerShellScript", "ResponseCode": 0, "ExecutionStartDateTime": "2020-11-26T17:20:11.557Z", "ExecutionElapsedTime": "PT0.647S", "ExecutionEndDateTime": "2020-11-26T17:20:11.557Z", "Status": "Success", "StatusDetails": "Success", "StandardOutputContent": "Ok.\r\n\r\n", "StandardOutputUrl": "", "StandardErrorContent": "", "StandardErrorUrl": "", "CloudWatchOutputConfig": { "CloudWatchLogGroupName": "", "CloudWatchOutputEnabled": false } }
i-03dd90e66a0e6a145
) and the private IP of the Linux instance for appropriate values before running the below:aws ssm send-command --document-name "AWS-RunPowerShellScript" --document-version "1" --targets '[{"Key":"InstanceIds","Values":["i-03dd90e66a0e6a145"]}]' --parameters '{"workingDirectory":[""],"executionTimeout":["3600"],"commands":["ping 10.0.3.49"]}' --timeout-seconds 600 --max-concurrency "50" --max-errors "0" { "Command": { "CommandId": "09785d32-8b7e-4f24-9581-90aed774aa7d", "DocumentName": "AWS-RunPowerShellScript", "DocumentVersion": "1", "Comment": "", "ExpiresAfter": "2020-11-26T20:16:40.640000+01:00", "Parameters": { "commands": [ "ping 10.0.3.49" ], "executionTimeout": [ "3600" ], "workingDirectory": [ "" ] }, "InstanceIds": [], "Targets": [ { "Key": "InstanceIds", "Values": [ "i-03dd90e66a0e6a145" ] } ], "RequestedDateTime": "2020-11-26T19:06:40.640000+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 } }
➜ ping-me-cdk-example$ aws ssm get-command-invocation --command-id 09785d32-8b7e-4f24-9581-90aed774aa7d --instance-id i-03dd90e66a0e6a145 { "CommandId": "09785d32-8b7e-4f24-9581-90aed774aa7d", "InstanceId": "i-03dd90e66a0e6a145", "Comment": "", "DocumentName": "AWS-RunPowerShellScript", "DocumentVersion": "1", "PluginName": "aws:runPowerShellScript", "ResponseCode": 0, "ExecutionStartDateTime": "2020-11-26T18:06:41.265Z", "ExecutionElapsedTime": "PT7.529S", "ExecutionEndDateTime": "2020-11-26T18:06:48.265Z", "Status": "Success", "StatusDetails": "Success", "StandardOutputContent": "\r\nPinging 10.0.3.49 with 32 bytes of data:\r\nRequest timed out.\r\nReply from 10.0.3.49: bytes=32 time=1ms TTL=254\r\nReply from 10.0.3.49: bytes=32 time<1ms TTL=254\r\nReply from 10.0.3.49: bytes=32 time<1ms TTL=254\r\n\r\nPing statistics for 10.0.3.49:\r\n Packets: Sent = 4, Received = 3, Lost = 1 (25% loss),\r\nApproximate round trip times in milli-seconds:\r\n Minimum = 0ms, Maximum = 1ms, Average = 0ms\r\n", "StandardOutputUrl": "", "StandardErrorContent": "", "StandardErrorUrl": "", "CloudWatchOutputConfig": { "CloudWatchLogGroupName": "", "CloudWatchOutputEnabled": false } }
- before the ping

- after the ping
Cleanup
For the sake of our wallets, let’s promptly destroy the current infrastructure before moving on. When prompted, type y
for yes:
➜ ping-me-cdk-example$ cdk destroy --all Are you sure you want to delete: InstanceVpnDestinationStack, VpcVpnDestinationStack, PeeringStack, InstancePeersStack, CustomerGatewayDeviceStack, VpcVpnSourceStack, VpcPeersStack (y/n)? y InstanceVpnDestinationStack: destroying... 19:15:58 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | InstanceVpnDestinationStack ✅ InstanceVpnDestinationStack: destroyed VpcVpnDestinationStack: destroying... 19:16:55 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | VpcVpnDestinationStack 19:18:39 | DELETE_IN_PROGRESS | AWS::EC2::InternetGateway | Vpc0/IGW 19:18:39 | DELETE_IN_PROGRESS | AWS::EC2::VPC | Vpc0 ✅ VpcVpnDestinationStack: destroyed PeeringStack: destroying... ✅ PeeringStack: destroyed InstancePeersStack: destroying... ✅ InstancePeersStack: destroyed CustomerGatewayDeviceStack: destroying... 19:19:00 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | CustomerGatewayDeviceStack 19:19:52 | DELETE_IN_PROGRESS | AWS::IAM::Role | SsmRoleForEc2 ✅ CustomerGatewayDeviceStack: destroyed VpcVpnSourceStack: destroying... 19:19:58 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | VpcVpnSourceStack ✅ VpcVpnSourceStack: destroyed VpcPeersStack: destroying... ✅ VpcPeersStack: destroyed