diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/aws-cdk-vpc-nat-instances-v2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/aws-cdk-vpc-nat-instances-v2.assets.json new file mode 100644 index 0000000000000..8f3b0364817c7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/aws-cdk-vpc-nat-instances-v2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "48ef9ffa2dccd900a9cc067bf63064119b67fe363f5ad1257d4261278bcba220": { + "source": { + "path": "aws-cdk-vpc-nat-instances-v2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "48ef9ffa2dccd900a9cc067bf63064119b67fe363f5ad1257d4261278bcba220.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/aws-cdk-vpc-nat-instances-v2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/aws-cdk-vpc-nat-instances-v2.template.json new file mode 100644 index 0000000000000..1e751a92cac60 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/aws-cdk-vpc-nat-instances-v2.template.json @@ -0,0 +1,544 @@ +{ + "Resources": { + "MyVpcF9F0CA6F": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc" + } + ] + } + }, + "MyVpcPublicSubnet1SubnetF6608456": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet1RouteTableC46AB2F4": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet1RouteTableAssociation2ECEE1CB": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + }, + "SubnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + } + } + }, + "MyVpcPublicSubnet1DefaultRoute95FDF9EB": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "RouteTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + }, + "DependsOn": [ + "MyVpcVPCGW488ACE0D" + ] + }, + "MyVpcPublicSubnet1NatInstanceInstanceRole394B648D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance" + } + ] + } + }, + "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "MyVpcPublicSubnet1NatInstanceInstanceRole394B648D" + } + ] + } + }, + "MyVpcPublicSubnet1NatInstance8E94E5F7": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "IamInstanceProfile": { + "Ref": "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.small", + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcNatSecurityGroupAA76397E", + "GroupId" + ] + } + ], + "SourceDestCheck": false, + "SubnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash\nyum install iptables-services -y\nsystemctl enable iptables\nsystemctl start iptables\necho \"net.ipv4.ip_forward=1\" > /etc/sysctl.d/custom-ip-forwarding.conf\nsudo sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf\nsudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nsudo /sbin/iptables -F FORWARD\nsudo service iptables save" + } + }, + "DependsOn": [ + "MyVpcPublicSubnet1NatInstanceInstanceRole394B648D" + ] + }, + "MyVpcPublicSubnet2Subnet492B6BFB": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet2RouteTable1DF17386": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet2RouteTableAssociation227DE78D": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + }, + "SubnetId": { + "Ref": "MyVpcPublicSubnet2Subnet492B6BFB" + } + } + }, + "MyVpcPublicSubnet2DefaultRoute052936F6": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "RouteTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + } + }, + "DependsOn": [ + "MyVpcVPCGW488ACE0D" + ] + }, + "MyVpcPublicSubnet2NatInstanceInstanceRoleFD8EE84D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance" + } + ] + } + }, + "MyVpcPublicSubnet2NatInstanceInstanceProfile5AB09EF6": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "MyVpcPublicSubnet2NatInstanceInstanceRoleFD8EE84D" + } + ] + } + }, + "MyVpcPublicSubnet2NatInstance04BCE4E3": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "IamInstanceProfile": { + "Ref": "MyVpcPublicSubnet2NatInstanceInstanceProfile5AB09EF6" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.small", + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcNatSecurityGroupAA76397E", + "GroupId" + ] + } + ], + "SourceDestCheck": false, + "SubnetId": { + "Ref": "MyVpcPublicSubnet2Subnet492B6BFB" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash\nyum install iptables-services -y\nsystemctl enable iptables\nsystemctl start iptables\necho \"net.ipv4.ip_forward=1\" > /etc/sysctl.d/custom-ip-forwarding.conf\nsudo sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf\nsudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nsudo /sbin/iptables -F FORWARD\nsudo service iptables save" + } + }, + "DependsOn": [ + "MyVpcPublicSubnet2NatInstanceInstanceRoleFD8EE84D" + ] + }, + "MyVpcPrivateSubnet1Subnet5057CF7E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet1RouteTable8819E6E2": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet1RouteTableAssociation56D38C7E": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + }, + "SubnetId": { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + } + }, + "MyVpcPrivateSubnet1DefaultRouteA8CDE2FA": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "InstanceId": { + "Ref": "MyVpcPublicSubnet1NatInstance8E94E5F7" + }, + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + } + }, + "MyVpcPrivateSubnet2Subnet0040C983": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet2RouteTableCEDCEECE": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet2RouteTableAssociation86A610DA": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + }, + "SubnetId": { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + } + }, + "MyVpcPrivateSubnet2DefaultRoute9CE96294": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "InstanceId": { + "Ref": "MyVpcPublicSubnet2NatInstance04BCE4E3" + }, + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + } + }, + "MyVpcIGW5C4A4F63": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc" + } + ] + } + }, + "MyVpcVPCGW488ACE0D": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcNatSecurityGroupAA76397E": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security Group for NAT instances", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "from 0.0.0.0/0:ALL TRAFFIC", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-vpc-nat-instances-v2/MyVpc" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + } + }, + "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/integ.json new file mode 100644 index 0000000000000..b042e68b55a72 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "nat-instance-v2-integ-test/DefaultTest": { + "stacks": [ + "aws-cdk-vpc-nat-instances-v2" + ], + "assertionStack": "nat-instance-v2-integ-test/DefaultTest/DeployAssert", + "assertionStackName": "natinstancev2integtestDefaultTestDeployAssertD7458A47" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/manifest.json new file mode 100644 index 0000000000000..d297b349779d2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/manifest.json @@ -0,0 +1,275 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-vpc-nat-instances-v2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-vpc-nat-instances-v2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-vpc-nat-instances-v2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-vpc-nat-instances-v2.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/48ef9ffa2dccd900a9cc067bf63064119b67fe363f5ad1257d4261278bcba220.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-vpc-nat-instances-v2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-vpc-nat-instances-v2.assets" + ], + "metadata": { + "/aws-cdk-vpc-nat-instances-v2/MyVpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcF9F0CA6F" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1SubnetF6608456" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1RouteTableAssociation2ECEE1CB" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1DefaultRoute95FDF9EB" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1NatInstanceInstanceRole394B648D" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1NatInstance8E94E5F7", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2Subnet492B6BFB" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2RouteTable1DF17386" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2RouteTableAssociation227DE78D" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2DefaultRoute052936F6" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2NatInstanceInstanceRoleFD8EE84D" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2NatInstanceInstanceProfile5AB09EF6" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2NatInstance04BCE4E3", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1RouteTableAssociation56D38C7E" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1DefaultRouteA8CDE2FA" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2Subnet0040C983" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2RouteTableAssociation86A610DA" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2DefaultRoute9CE96294" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcIGW5C4A4F63" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcVPCGW488ACE0D" + } + ], + "/aws-cdk-vpc-nat-instances-v2/MyVpc/NatSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcNatSecurityGroupAA76397E" + } + ], + "/aws-cdk-vpc-nat-instances-v2/SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/aws-cdk-vpc-nat-instances-v2/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-vpc-nat-instances-v2/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-vpc-nat-instances-v2" + }, + "natinstancev2integtestDefaultTestDeployAssertD7458A47.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "natinstancev2integtestDefaultTestDeployAssertD7458A47.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "natinstancev2integtestDefaultTestDeployAssertD7458A47": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "natinstancev2integtestDefaultTestDeployAssertD7458A47.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "natinstancev2integtestDefaultTestDeployAssertD7458A47.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "natinstancev2integtestDefaultTestDeployAssertD7458A47.assets" + ], + "metadata": { + "/nat-instance-v2-integ-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/nat-instance-v2-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "nat-instance-v2-integ-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/natinstancev2integtestDefaultTestDeployAssertD7458A47.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/natinstancev2integtestDefaultTestDeployAssertD7458A47.assets.json new file mode 100644 index 0000000000000..7be1e1506e14a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/natinstancev2integtestDefaultTestDeployAssertD7458A47.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "natinstancev2integtestDefaultTestDeployAssertD7458A47.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/natinstancev2integtestDefaultTestDeployAssertD7458A47.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/natinstancev2integtestDefaultTestDeployAssertD7458A47.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/natinstancev2integtestDefaultTestDeployAssertD7458A47.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/tree.json new file mode 100644 index 0000000000000..784f2d49842f1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.js.snapshot/tree.json @@ -0,0 +1,963 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-vpc-nat-instances-v2": { + "id": "aws-cdk-vpc-nat-instances-v2", + "path": "aws-cdk-vpc-nat-instances-v2", + "children": { + "MyVpc": { + "id": "MyVpc", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + }, + "subnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "routeTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "NatInstance": { + "id": "NatInstance", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance", + "children": { + "InstanceRole": { + "id": "InstanceRole", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "MyVpcPublicSubnet1NatInstanceInstanceRole394B648D" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "iamInstanceProfile": { + "Ref": "MyVpcPublicSubnet1NatInstanceInstanceProfile2FD934CB" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.small", + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcNatSecurityGroupAA76397E", + "GroupId" + ] + } + ], + "sourceDestCheck": false, + "subnetId": { + "Ref": "MyVpcPublicSubnet1SubnetF6608456" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet1/NatInstance" + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash\nyum install iptables-services -y\nsystemctl enable iptables\nsystemctl start iptables\necho \"net.ipv4.ip_forward=1\" > /etc/sysctl.d/custom-ip-forwarding.conf\nsudo sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf\nsudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nsudo /sbin/iptables -F FORWARD\nsudo service iptables save" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Instance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + }, + "subnetId": { + "Ref": "MyVpcPublicSubnet2Subnet492B6BFB" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "routeTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "NatInstance": { + "id": "NatInstance", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance", + "children": { + "InstanceRole": { + "id": "InstanceRole", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "MyVpcPublicSubnet2NatInstanceInstanceRoleFD8EE84D" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "iamInstanceProfile": { + "Ref": "MyVpcPublicSubnet2NatInstanceInstanceProfile5AB09EF6" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.small", + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcNatSecurityGroupAA76397E", + "GroupId" + ] + } + ], + "sourceDestCheck": false, + "subnetId": { + "Ref": "MyVpcPublicSubnet2Subnet492B6BFB" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PublicSubnet2/NatInstance" + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash\nyum install iptables-services -y\nsystemctl enable iptables\nsystemctl start iptables\necho \"net.ipv4.ip_forward=1\" > /etc/sysctl.d/custom-ip-forwarding.conf\nsudo sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf\nsudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nsudo /sbin/iptables -F FORWARD\nsudo service iptables save" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Instance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + }, + "subnetId": { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "instanceId": { + "Ref": "MyVpcPublicSubnet1NatInstance8E94E5F7" + }, + "routeTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + }, + "subnetId": { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "instanceId": { + "Ref": "MyVpcPublicSubnet2NatInstance04BCE4E3" + }, + "routeTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + }, + "NatSecurityGroup": { + "id": "NatSecurityGroup", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/NatSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-vpc-nat-instances-v2/MyVpc/NatSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "Security Group for NAT instances", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "-1", + "description": "from 0.0.0.0/0:ALL TRAFFIC" + } + ], + "tags": [ + { + "key": "Name", + "value": "aws-cdk-vpc-nat-instances-v2/MyVpc" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "aws-cdk-vpc-nat-instances-v2/SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "aws-cdk-vpc-nat-instances-v2/SsmParameterValue:--aws--service--ami-amazon-linux-latest--al2023-ami-kernel-6.1-x86_64:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-vpc-nat-instances-v2/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-vpc-nat-instances-v2/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "nat-instance-v2-integ-test": { + "id": "nat-instance-v2-integ-test", + "path": "nat-instance-v2-integ-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "nat-instance-v2-integ-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "nat-instance-v2-integ-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "nat-instance-v2-integ-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "nat-instance-v2-integ-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "nat-instance-v2-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.ts new file mode 100644 index 0000000000000..50e7bcdfb28d5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.nat-instances-v2.ts @@ -0,0 +1,33 @@ +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { EC2_RESTRICT_DEFAULT_SECURITY_GROUP } from 'aws-cdk-lib/cx-api'; + +class NatInstanceStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + this.node.setContext(EC2_RESTRICT_DEFAULT_SECURITY_GROUP, false); + + // Configure the `natGatewayProvider` when defining a Vpc + const natGatewayProvider = ec2.NatProvider.instanceV2({ + instanceType: new ec2.InstanceType('t3.small'), + }); + + const vpc = new ec2.Vpc(this, 'MyVpc', { + natGatewayProvider, + + // The 'natGateways' parameter now controls the number of NAT instances + natGateways: 2, + }); + + Array.isArray(vpc); + Array.isArray(natGatewayProvider.configuredGateways); + } +} + +const app = new cdk.App(); +const stack = new NatInstanceStack(app, 'aws-cdk-vpc-nat-instances-v2'); + +new IntegTest(app, 'nat-instance-v2-integ-test', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-ec2/README.md b/packages/aws-cdk-lib/aws-ec2/README.md index fef870d937a84..50b7bf8d2c72b 100644 --- a/packages/aws-cdk-lib/aws-ec2/README.md +++ b/packages/aws-cdk-lib/aws-ec2/README.md @@ -189,9 +189,7 @@ are managed by AWS. If you would prefer to use your own managed NAT *instances* instead, specify a different value for the `natGatewayProvider` property, as follows: -[using NAT instances](test/integ.nat-instances.lit.ts) - -The construct will automatically search for the most recent NAT gateway AMI. +The construct will automatically selects the latest version of Amazon Linux 2023. If you prefer to use a custom AMI, use `machineImage: MachineImage.genericLinux({ ... })` and configure the right AMI ID for the regions you want to deploy to. @@ -204,6 +202,25 @@ the VPC: ```ts declare const instanceType: ec2.InstanceType; +const provider = ec2.NatProvider.instanceV2({ + instanceType, + defaultAllowedTraffic: ec2.NatTrafficDirection.OUTBOUND_ONLY, +}); +new ec2.Vpc(this, 'TheVPC', { + natGatewayProvider: provider, +}); +provider.connections.allowFrom(ec2.Peer.ipv4('1.2.3.4/8'), ec2.Port.tcp(80)); +``` + +[using NAT instances](test/integ.nat-instances.lit.ts) [Deprecated] + +The construct will use the AWS official NAT instance AMI, which has already +reached EOL on Dec 31, 2023. For more information, see the following blog post: +[Amazon Linux AMI end of life](https://aws.amazon.com/blogs/aws/update-on-amazon-linux-ami-end-of-life/). + +```ts +declare const instanceType: ec2.InstanceType; + const provider = ec2.NatProvider.instance({ instanceType, defaultAllowedTraffic: ec2.NatTrafficDirection.OUTBOUND_ONLY, diff --git a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts index 48c2ac0de94f2..d8463c742b9fd 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/nat.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/nat.ts @@ -3,9 +3,10 @@ import { Instance } from './instance'; import { InstanceType } from './instance-types'; import { IKeyPair } from './key-pair'; import { CpuCredits } from './launch-template'; -import { IMachineImage, LookupMachineImage } from './machine-image'; +import { AmazonLinuxGeneration, AmazonLinuxImage, IMachineImage, LookupMachineImage } from './machine-image'; import { Port } from './port'; import { ISecurityGroup, SecurityGroup } from './security-group'; +import { UserData } from './user-data'; import { PrivateSubnet, PublicSubnet, RouterType, Vpc } from './vpc'; import * as iam from '../../aws-iam'; import { Fn, Token } from '../../core'; @@ -76,11 +77,29 @@ export abstract class NatProvider { * your own NatProvider based on AutoScaling groups if you need that. * * @see https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html + * + * @deprecated use instanceV2. 'instance' is deprecated since NatInstanceProvider + * uses a instance image that has reached EOL on Dec 31 2023 */ public static instance(props: NatInstanceProps): NatInstanceProvider { return new NatInstanceProvider(props); } + /** + * Use NAT instances to provide NAT services for your VPC + * + * NAT instances are managed by you, but in return allow more configuration. + * + * Be aware that instances created using this provider will not be + * automatically replaced if they are stopped for any reason. You should implement + * your own NatProvider based on AutoScaling groups if you need that. + * + * @see https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html + */ + public static instanceV2(props: NatInstanceProps): NatInstanceProviderV2 { + return new NatInstanceProviderV2(props); + } + /** * Return list of gateways spawned by the provider */ @@ -280,6 +299,9 @@ class NatGatewayProvider extends NatProvider { /** * NAT provider which uses NAT Instances + * + * @deprecated use NatInstanceProviderV2. NatInstanceProvider is deprecated since + * the instance image used has reached EOL on Dec 31 2023 */ export class NatInstanceProvider extends NatProvider implements IConnectable { private gateways: PrefSet = new PrefSet(); @@ -303,7 +325,7 @@ export class NatInstanceProvider extends NatProvider implements IConnectable { (this.props.allowAllTraffic ?? true ? NatTrafficDirection.INBOUND_AND_OUTBOUND : NatTrafficDirection.OUTBOUND_ONLY); // Create the NAT instances. They can share a security group and a Role. - const machineImage = this.props.machineImage || new NatInstanceImage(); + const machineImage = this.props.machineImage ?? new NatInstanceImage(); this._securityGroup = this.props.securityGroup ?? new SecurityGroup(options.vpc, 'NatSecurityGroup', { vpc: options.vpc, description: 'Security Group for NAT instances', @@ -409,6 +431,117 @@ class PrefSet { } } +/** + * Modern NAT provider which uses NAT Instances. + * The instance uses Amazon Linux 2023 as the operating system. + */ +export class NatInstanceProviderV2 extends NatProvider implements IConnectable { + private gateways: PrefSet = new PrefSet(); + private _securityGroup?: ISecurityGroup; + private _connections?: Connections; + + constructor(private readonly props: NatInstanceProps) { + super(); + + if (props.defaultAllowedTraffic !== undefined && props.allowAllTraffic !== undefined) { + throw new Error('Can not specify both of \'defaultAllowedTraffic\' and \'defaultAllowedTraffic\'; prefer \'defaultAllowedTraffic\''); + } + + if (props.keyName && props.keyPair) { + throw new Error('Cannot specify both of \'keyName\' and \'keyPair\'; prefer \'keyPair\''); + } + } + + public configureNat(options: ConfigureNatOptions) { + const defaultDirection = this.props.defaultAllowedTraffic ?? + (this.props.allowAllTraffic ?? true ? NatTrafficDirection.INBOUND_AND_OUTBOUND : NatTrafficDirection.OUTBOUND_ONLY); + + // Create the NAT instances. They can share a security group and a Role. The new NAT instance created uses latest + // Amazon Linux 2023 image. This is important since the original NatInstanceProvider uses an instance image that has + // reached EOL on Dec 31 2023 + const machineImage = this.props.machineImage || new AmazonLinuxImage({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2023 }); + this._securityGroup = this.props.securityGroup ?? new SecurityGroup(options.vpc, 'NatSecurityGroup', { + vpc: options.vpc, + description: 'Security Group for NAT instances', + allowAllOutbound: isOutboundAllowed(defaultDirection), + }); + this._connections = new Connections({ securityGroups: [this._securityGroup] }); + + if (isInboundAllowed(defaultDirection)) { + this.connections.allowFromAnyIpv4(Port.allTraffic()); + } + + // Enable iptables on the instance, enable persistent IP forwarding, configure NAT on instance + // https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html#create-nat-ami + const userData = UserData.forLinux(); + userData.addCommands( + 'yum install iptables-services -y', + 'systemctl enable iptables', + 'systemctl start iptables', + 'echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/custom-ip-forwarding.conf', + 'sudo sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf', + 'sudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE', + 'sudo /sbin/iptables -F FORWARD', + 'sudo service iptables save', + ); + + for (const sub of options.natSubnets) { + const natInstance = new Instance(sub, 'NatInstance', { + instanceType: this.props.instanceType, + machineImage, + sourceDestCheck: false, // Required for NAT + vpc: options.vpc, + vpcSubnets: { subnets: [sub] }, + securityGroup: this._securityGroup, + keyPair: this.props.keyPair, + keyName: this.props.keyName, + userData, + }); + // NAT instance routes all traffic, both ways + this.gateways.add(sub.availabilityZone, natInstance); + } + + // Add routes to them in the private subnets + for (const sub of options.privateSubnets) { + this.configureSubnet(sub); + } + } + + /** + * The Security Group associated with the NAT instances + */ + public get securityGroup(): ISecurityGroup { + if (!this._securityGroup) { + throw new Error('Pass the NatInstanceProvider to a Vpc before accessing \'securityGroup\''); + } + return this._securityGroup; + } + + /** + * Manage the Security Groups associated with the NAT instances + */ + public get connections(): Connections { + if (!this._connections) { + throw new Error('Pass the NatInstanceProvider to a Vpc before accessing \'connections\''); + } + return this._connections; + } + + public get configuredGateways(): GatewayConfig[] { + return this.gateways.values().map(x => ({ az: x[0], gatewayId: x[1].instanceId })); + } + + public configureSubnet(subnet: PrivateSubnet) { + const az = subnet.availabilityZone; + const gatewayId = this.gateways.pick(az).instanceId; + subnet.addRoute('DefaultRoute', { + routerType: RouterType.INSTANCE, + routerId: gatewayId, + enablesInternetConnectivity: true, + }); + } +} + /** * Machine image representing the latest NAT instance image * diff --git a/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts b/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts index 52bad89bb72dc..0fcd7e08734f9 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts @@ -1578,6 +1578,50 @@ describe('vpc', () => { }); + test('Can configure NAT instances V2 instead of NAT gateways', () => { + // GIVEN + const stack = getTestStack(); + + // WHEN + const natGatewayProvider = NatProvider.instanceV2({ + instanceType: new InstanceType('q86.mega'), + machineImage: new GenericLinuxImage({ + 'us-east-1': 'ami-1', + }), + }); + new Vpc(stack, 'TheVPC', { natGatewayProvider }); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::EC2::Instance', 3); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + ImageId: 'ami-1', + InstanceType: 'q86.mega', + SourceDestCheck: false, + }); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Route', { + RouteTableId: { Ref: 'TheVPCPrivateSubnet1RouteTableF6513BC2' }, + DestinationCidrBlock: '0.0.0.0/0', + InstanceId: { Ref: 'TheVPCPublicSubnet1NatInstanceCC514192' }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { + SecurityGroupEgress: [ + { + CidrIp: '0.0.0.0/0', + Description: 'Allow all outbound traffic by default', + IpProtocol: '-1', + }, + ], + SecurityGroupIngress: [ + { + CidrIp: '0.0.0.0/0', + Description: 'from 0.0.0.0/0:ALL TRAFFIC', + IpProtocol: '-1', + }, + ], + }); + + }); + test('natGateways controls amount of NAT instances', () => { // GIVEN const stack = getTestStack(); @@ -1597,6 +1641,25 @@ describe('vpc', () => { Template.fromStack(stack).resourceCountIs('AWS::EC2::Instance', 1); }); + test('natGateways controls amount of NAT instances V2', () => { + // GIVEN + const stack = getTestStack(); + + // WHEN + new Vpc(stack, 'TheVPC', { + natGatewayProvider: NatProvider.instanceV2({ + instanceType: new InstanceType('q86.mega'), + machineImage: new GenericLinuxImage({ + 'us-east-1': 'ami-1', + }), + }), + natGateways: 1, + }); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::EC2::Instance', 1); + }); + testDeprecated('can configure Security Groups of NAT instances with allowAllTraffic false', () => { // GIVEN const stack = getTestStack();