diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/cdk.out new file mode 100644 index 0000000000000..7925065efbcc4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"31.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json new file mode 100644 index 0000000000000..92c11858a9333 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.assets.json @@ -0,0 +1,19 @@ +{ + "version": "31.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "instancetestDefaultTestDeployAssert5516EAF1.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.instance-public.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/instancetestDefaultTestDeployAssert5516EAF1.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.instance-public.js.snapshot/integ-ec2-instance.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/integ-ec2-instance.assets.json new file mode 100644 index 0000000000000..24fa7fa28b059 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/integ-ec2-instance.assets.json @@ -0,0 +1,19 @@ +{ + "version": "31.0.0", + "files": { + "488d9cf540c6790fc09af871e06438e043f47d03101ef192131f1dafbbb434cb": { + "source": { + "path": "integ-ec2-instance.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "488d9cf540c6790fc09af871e06438e043f47d03101ef192131f1dafbbb434cb.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.instance-public.js.snapshot/integ-ec2-instance.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/integ-ec2-instance.template.json new file mode 100644 index 0000000000000..4026ad159f736 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/integ-ec2-instance.template.json @@ -0,0 +1,362 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance/VPC" + } + ] + } + }, + "VPCpublicsubnet1Subnet1Subnet39B927A0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/24", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "public-subnet-1" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-instance/VPC/public-subnet-1Subnet1" + } + ] + } + }, + "VPCpublicsubnet1Subnet1RouteTable1127E157": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance/VPC/public-subnet-1Subnet1" + } + ] + } + }, + "VPCpublicsubnet1Subnet1RouteTableAssociation99DE76A6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCpublicsubnet1Subnet1RouteTable1127E157" + }, + "SubnetId": { + "Ref": "VPCpublicsubnet1Subnet1Subnet39B927A0" + } + } + }, + "VPCpublicsubnet1Subnet1DefaultRouteEFD0DA69": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCpublicsubnet1Subnet1RouteTable1127E157" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCpublicsubnet1Subnet2Subnet1B74FFEC": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.1.0/24", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "public-subnet-1" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-instance/VPC/public-subnet-1Subnet2" + } + ] + } + }, + "VPCpublicsubnet1Subnet2RouteTable6613D6DE": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance/VPC/public-subnet-1Subnet2" + } + ] + } + }, + "VPCpublicsubnet1Subnet2RouteTableAssociation4859253B": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCpublicsubnet1Subnet2RouteTable6613D6DE" + }, + "SubnetId": { + "Ref": "VPCpublicsubnet1Subnet2Subnet1B74FFEC" + } + } + }, + "VPCpublicsubnet1Subnet2DefaultRoute3D53F956": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCpublicsubnet1Subnet2RouteTable6613D6DE" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "IntegSg68DC2C7E": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "integ-ec2-instance/IntegSg", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + }, + { + "CidrIpv6": "::/0", + "Description": "Allow all outbound ipv6 traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "from 0.0.0.0/0:ICMP Type 8", + "FromPort": 8, + "IpProtocol": "icmp", + "ToPort": -1 + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "InstanceInstanceRoleE9785DE5": { + "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": "integ-ec2-instance/Instance" + } + ] + } + }, + "InstanceInstanceRoleDefaultPolicy4ACE9290": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "ssm:*", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "InstanceInstanceRoleDefaultPolicy4ACE9290", + "Roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "InstanceInstanceProfileAB5AEF02": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "InstanceC1063A87": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "IamInstanceProfile": { + "Ref": "InstanceInstanceProfileAB5AEF02" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t3.nano", + "Monitoring": true, + "NetworkInterfaces": [ + { + "AssociatePublicIpAddress": true, + "DeviceIndex": "0", + "GroupSet": [ + { + "Fn::GetAtt": [ + "IntegSg68DC2C7E", + "GroupId" + ] + } + ], + "SubnetId": { + "Ref": "VPCpublicsubnet1Subnet1Subnet39B927A0" + } + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-instance/Instance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash\nyum install -y" + } + }, + "DependsOn": [ + "InstanceInstanceRoleDefaultPolicy4ACE9290", + "InstanceInstanceRoleE9785DE5", + "VPCpublicsubnet1Subnet1DefaultRouteEFD0DA69", + "VPCpublicsubnet1Subnet1RouteTableAssociation99DE76A6", + "VPCpublicsubnet1Subnet2DefaultRoute3D53F956", + "VPCpublicsubnet1Subnet2RouteTableAssociation4859253B" + ] + } + }, + "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" + }, + "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.instance-public.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/integ.json new file mode 100644 index 0000000000000..f7b474f3d5a35 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "31.0.0", + "testCases": { + "instance-test/DefaultTest": { + "stacks": [ + "integ-ec2-instance" + ], + "assertionStack": "instance-test/DefaultTest/DeployAssert", + "assertionStackName": "instancetestDefaultTestDeployAssert5516EAF1" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/manifest.json new file mode 100644 index 0000000000000..aa23896e254e6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/manifest.json @@ -0,0 +1,207 @@ +{ + "version": "31.0.0", + "artifacts": { + "integ-ec2-instance.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-ec2-instance.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-ec2-instance": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-ec2-instance.template.json", + "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}/488d9cf540c6790fc09af871e06438e043f47d03101ef192131f1dafbbb434cb.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-ec2-instance.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": [ + "integ-ec2-instance.assets" + ], + "metadata": { + "/integ-ec2-instance/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet1Subnet39B927A0" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet1RouteTable1127E157" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet1RouteTableAssociation99DE76A6" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet1DefaultRouteEFD0DA69" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet2Subnet1B74FFEC" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet2RouteTable6613D6DE" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet2RouteTableAssociation4859253B" + } + ], + "/integ-ec2-instance/VPC/public-subnet-1Subnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCpublicsubnet1Subnet2DefaultRoute3D53F956" + } + ], + "/integ-ec2-instance/VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIGWB7E252D3" + } + ], + "/integ-ec2-instance/VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCVPCGW99B986DC" + } + ], + "/integ-ec2-instance/IntegSg/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "IntegSg68DC2C7E" + } + ], + "/integ-ec2-instance/Instance/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceRoleE9785DE5" + } + ], + "/integ-ec2-instance/Instance/InstanceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceRoleDefaultPolicy4ACE9290" + } + ], + "/integ-ec2-instance/Instance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceInstanceProfileAB5AEF02" + } + ], + "/integ-ec2-instance/Instance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceC1063A87" + } + ], + "/integ-ec2-instance/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/integ-ec2-instance/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-ec2-instance/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-ec2-instance" + }, + "instancetestDefaultTestDeployAssert5516EAF1.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "instancetestDefaultTestDeployAssert5516EAF1.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "instancetestDefaultTestDeployAssert5516EAF1": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "instancetestDefaultTestDeployAssert5516EAF1.template.json", + "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": [ + "instancetestDefaultTestDeployAssert5516EAF1.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": [ + "instancetestDefaultTestDeployAssert5516EAF1.assets" + ], + "metadata": { + "/instance-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/instance-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "instance-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.instance-public.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/tree.json new file mode 100644 index 0000000000000..87142e2d428c9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.js.snapshot/tree.json @@ -0,0 +1,645 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-ec2-instance": { + "id": "integ-ec2-instance", + "path": "integ-ec2-instance", + "children": { + "VPC": { + "id": "VPC", + "path": "integ-ec2-instance/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance/VPC/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": "integ-ec2-instance/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "public-subnet-1Subnet1": { + "id": "public-subnet-1Subnet1", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/24", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "public-subnet-1" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ec2-instance/VPC/public-subnet-1Subnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance/VPC/public-subnet-1Subnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCpublicsubnet1Subnet1RouteTable1127E157" + }, + "subnetId": { + "Ref": "VPCpublicsubnet1Subnet1Subnet39B927A0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCpublicsubnet1Subnet1RouteTable1127E157" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "public-subnet-1Subnet2": { + "id": "public-subnet-1Subnet2", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.1.0/24", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "public-subnet-1" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ec2-instance/VPC/public-subnet-1Subnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance/VPC/public-subnet-1Subnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCpublicsubnet1Subnet2RouteTable6613D6DE" + }, + "subnetId": { + "Ref": "VPCpublicsubnet1Subnet2Subnet1B74FFEC" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ec2-instance/VPC/public-subnet-1Subnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCpublicsubnet1Subnet2RouteTable6613D6DE" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "integ-ec2-instance/VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "integ-ec2-instance/VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "internetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "IntegSg": { + "id": "IntegSg", + "path": "integ-ec2-instance/IntegSg", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance/IntegSg/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "integ-ec2-instance/IntegSg", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + }, + { + "ipProtocol": "-1", + "cidrIpv6": "::/0", + "description": "Allow all outbound ipv6 traffic by default" + } + ], + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "icmp", + "fromPort": 8, + "toPort": -1, + "description": "from 0.0.0.0/0:ICMP Type 8" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "Instance": { + "id": "Instance", + "path": "integ-ec2-instance/Instance", + "children": { + "InstanceRole": { + "id": "InstanceRole", + "path": "integ-ec2-instance/Instance/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "integ-ec2-instance/Instance/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance/Instance/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": "integ-ec2-instance/Instance" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ec2-instance/Instance/InstanceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance/Instance/InstanceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "ssm:*", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "InstanceInstanceRoleDefaultPolicy4ACE9290", + "roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "integ-ec2-instance/Instance/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "InstanceInstanceRoleE9785DE5" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ec2-instance/Instance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "iamInstanceProfile": { + "Ref": "InstanceInstanceProfileAB5AEF02" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t3.nano", + "monitoring": true, + "networkInterfaces": [ + { + "deviceIndex": "0", + "associatePublicIpAddress": true, + "subnetId": { + "Ref": "VPCpublicsubnet1Subnet1Subnet39B927A0" + }, + "groupSet": [ + { + "Fn::GetAtt": [ + "IntegSg68DC2C7E", + "GroupId" + ] + } + ] + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ec2-instance/Instance" + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash\nyum install -y" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Instance", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "integ-ec2-instance/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "integ-ec2-instance/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-ec2-instance/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-ec2-instance/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "instance-test": { + "id": "instance-test", + "path": "instance-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "instance-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "instance-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.9" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "instance-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "instance-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "instance-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.2.9" + } + } + }, + "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.instance-public.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.ts new file mode 100644 index 0000000000000..63b910e6e4fbd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.instance-public.ts @@ -0,0 +1,57 @@ +import { PolicyStatement } from 'aws-cdk-lib/aws-iam'; +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { EC2_RESTRICT_DEFAULT_SECURITY_GROUP } from 'aws-cdk-lib/cx-api'; + +const app = new cdk.App(); + +class TestStack 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); + + const vpc = new ec2.Vpc(this, 'VPC', { + cidr: '10.0.0.0/16', + natGateways: 0, + maxAzs: 3, + subnetConfiguration: [ + { + name: 'public-subnet-1', + subnetType: ec2.SubnetType.PUBLIC, + cidrMask: 24, + }, + ], + }); + + const securityGroup = new ec2.SecurityGroup(this, 'IntegSg', { + vpc, + allowAllIpv6Outbound: true, + }); + + const instance = new ec2.Instance(this, 'Instance', { + vpc, + vpcSubnets: { subnetGroupName: 'public-subnet-1' }, + securityGroup, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), + machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), + detailedMonitoring: true, + associatePublicIpAddress: true, + }); + + instance.addToRolePolicy(new PolicyStatement({ + actions: ['ssm:*'], + resources: ['*'], + })); + + instance.connections.allowFromAnyIpv4(ec2.Port.icmpPing()); + + instance.addUserData('yum install -y'); + } +} + +const testCase = new TestStack(app, 'integ-ec2-instance'); + +new IntegTest(app, 'instance-test', { + testCases: [testCase], +}); diff --git a/packages/aws-cdk-lib/aws-ec2/README.md b/packages/aws-cdk-lib/aws-ec2/README.md index 84a4b63436246..4dde61bfa3fa8 100644 --- a/packages/aws-cdk-lib/aws-ec2/README.md +++ b/packages/aws-cdk-lib/aws-ec2/README.md @@ -1553,6 +1553,34 @@ const aspect = new ec2.InstanceRequireImdsv2Aspect(); Aspects.of(this).add(aspect); ``` +### Associating a Public IP Address with an Instance + +All subnets have an attribute that determines whether instances launched into that subnet are assigned a public IPv4 address. This attribute is set to true by default for default public subnets. Thus, an EC2 instance launched into a default public subnet will be assigned a public IPv4 address. Nondefault public subnets have this attribute set to false by default and any EC2 instance launched into a nondefault public subnet will not be assigned a public IPv4 address automatically. To automatically assign a public IPv4 address to an instance launched into a nondefault public subnet, you can set the `associatePublicIpAddress` property on the `Instance` construct to true. Alternatively, to not automatically assign a public IPv4 address to an instance launched into a default public subnet, you can set `associatePublicIpAddress` to false. Including this property, removing this property, or updating the value of this property on an existing instance will result in replacement of the instance. + +```ts +const vpc = new ec2.Vpc(this, 'VPC', { + cidr: '10.0.0.0/16', + natGateways: 0, + maxAzs: 3, + subnetConfiguration: [ + { + name: 'public-subnet-1', + subnetType: ec2.SubnetType.PUBLIC, + cidrMask: 24, + }, + ], +}); + +const instance = new ec2.Instance(this, 'Instance', { + vpc, + vpcSubnets: { subnetGroupName: 'public-subnet-1' }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), + machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }), + detailedMonitoring: true, + associatePublicIpAddress: true, +}); +``` + ## VPC Flow Logs VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs and Amazon S3. After you've created a flow log, you can retrieve and view its data in the chosen destination. (). diff --git a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts index e9f877cff1558..b18911161a0ee 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/instance.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/instance.ts @@ -271,6 +271,13 @@ export interface InstanceProps { * @default false */ readonly ssmSessionPermissions?: boolean; + + /** + * Whether to associate a public IP address to the primary network interface attached to this instance. + * + * @default - public IP address is automatically assigned based on default behavior + */ + readonly associatePublicIpAddress?: boolean; } /** @@ -373,7 +380,7 @@ export class Instance extends Resource implements IInstance { const userDataToken = Lazy.string({ produce: () => Fn.base64(this.userData.render()) }); const securityGroupsToken = Lazy.list({ produce: () => this.securityGroups.map(sg => sg.securityGroupId) }); - const { subnets } = props.vpc.selectSubnets(props.vpcSubnets); + const { subnets, hasPublic } = props.vpc.selectSubnets(props.vpcSubnets); let subnet; if (props.availabilityZone) { const selected = subnets.filter(sn => sn.availabilityZone === props.availabilityZone); @@ -398,14 +405,22 @@ export class Instance extends Resource implements IInstance { }); } + // network interfaces array is set to configure the primary network interface if associatePublicIpAddress is true or false + const networkInterfaces = props.associatePublicIpAddress !== undefined + ? [{ deviceIndex: '0', associatePublicIpAddress: props.associatePublicIpAddress, subnetId: subnet.subnetId, groupSet: securityGroupsToken }] + : undefined; + + // if network interfaces array is configured then subnetId and securityGroupIds are configured on the network interface + // level and there is no need to configure them on the instance level this.instance = new CfnInstance(this, 'Resource', { imageId: imageConfig.imageId, keyName: props.keyName, instanceType: props.instanceType.toString(), - securityGroupIds: securityGroupsToken, + subnetId: networkInterfaces ? undefined : subnet.subnetId, + securityGroupIds: networkInterfaces ? undefined : securityGroupsToken, + networkInterfaces, iamInstanceProfile: iamProfile.ref, userData: userDataToken, - subnetId: subnet.subnetId, availabilityZone: subnet.availabilityZone, sourceDestCheck: props.sourceDestCheck, blockDeviceMappings: props.blockDevices !== undefined ? instanceBlockDeviceMappings(this, props.blockDevices) : undefined, @@ -415,6 +430,16 @@ export class Instance extends Resource implements IInstance { }); this.instance.node.addDependency(this.role); + // if associatePublicIpAddress is true, then there must be a dependency on internet connectivity + if (props.associatePublicIpAddress !== undefined && props.associatePublicIpAddress) { + const internetConnected = props.vpc.selectSubnets(props.vpcSubnets).internetConnectivityEstablished; + this.instance.node.addDependency(internetConnected); + } + + if (!hasPublic && props.associatePublicIpAddress) { + throw new Error("To set 'associatePublicIpAddress: true' you must select Public subnets (vpcSubnets: { subnetType: SubnetType.PUBLIC })"); + } + this.osType = imageConfig.osType; this.node.defaultChild = this.instance; diff --git a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts index 16ccd3bd75f21..42de157891c8c 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/instance.test.ts @@ -19,6 +19,8 @@ import { LaunchTemplate, UserData, Vpc, + SubnetType, + SecurityGroup, } from '../lib'; let stack: Stack; @@ -644,3 +646,94 @@ test('sameInstanceClassAs compares different InstanceTypes correctly', () => { expect(instanceType.sameInstanceClassAs(comparitor)).toBeFalsy(); }); +test('associate public IP address with instance', () => { + // GIVEN + const securityGroup = new SecurityGroup(stack, 'SecurityGroup', { vpc }); + + // WHEN + new Instance(stack, 'Instance', { + vpc, + vpcSubnets: { subnetType: SubnetType.PUBLIC }, + securityGroup, + machineImage: new AmazonLinuxImage(), + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), + sourceDestCheck: false, + associatePublicIpAddress: true, + }); + + // THEN + Template.fromStack(stack).hasResource('AWS::EC2::Instance', { + Properties: { + NetworkInterfaces: [{ + AssociatePublicIpAddress: true, + DeviceIndex: '0', + GroupSet: [ + { + 'Fn::GetAtt': [ + 'SecurityGroupDD263621', + 'GroupId', + ], + }, + ], + SubnetId: { + Ref: 'VPCPublicSubnet1SubnetB4246D30', + }, + }], + }, + DependsOn: [ + 'InstanceInstanceRoleE9785DE5', + 'VPCPublicSubnet1DefaultRoute91CEF279', + 'VPCPublicSubnet1RouteTableAssociation0B0896DC', + 'VPCPublicSubnet2DefaultRouteB7481BBA', + 'VPCPublicSubnet2RouteTableAssociation5A808732', + ], + }); +}); + +test('do not associate public IP address with instance', () => { + // GIVEN + const securityGroup = new SecurityGroup(stack, 'SecurityGroup', { vpc }); + + // WHEN + new Instance(stack, 'Instance', { + vpc, + vpcSubnets: { subnetType: SubnetType.PUBLIC }, + securityGroup, + machineImage: new AmazonLinuxImage(), + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), + sourceDestCheck: false, + associatePublicIpAddress: false, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', { + NetworkInterfaces: [{ + AssociatePublicIpAddress: false, + DeviceIndex: '0', + GroupSet: [ + { + 'Fn::GetAtt': [ + 'SecurityGroupDD263621', + 'GroupId', + ], + }, + ], + SubnetId: { + Ref: 'VPCPublicSubnet1SubnetB4246D30', + }, + }], + }); +}); + +test('associate public IP address with instance and no public subnet', () => { + // WHEN/THEN + expect(() => { + new Instance(stack, 'Instance', { + vpc, + machineImage: new AmazonLinuxImage(), + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), + sourceDestCheck: false, + associatePublicIpAddress: true, + }); + }).toThrow("To set 'associatePublicIpAddress: true' you must select Public subnets (vpcSubnets: { subnetType: SubnetType.PUBLIC })"); +});