From df48fd781a476ada79b6b49f006a60f33f73d409 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Sat, 30 Mar 2024 11:41:37 +0100 Subject: [PATCH] fix(ec2): global vpc endpoint support (#29563) ### Issue # (if applicable) Closes #29560. ### Reason for this change The service name generated by the CDK for global VPC endpoints was incorrect, as it contained the stack's region: ```sh $ aws ec2 describe-vpc-endpoint-services --region=us-east-1 --service-names=com.amazonaws.s3-global.accesspoint | jq '.ServiceDetails[] | .ServiceName' "com.amazonaws.s3-global.accesspoint" ``` ```ts new CfnOutput(this, "endpoint", { value: ec2.InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS.name, }); // TestDeployStack.endpoint = com.amazonaws.eu-west-1.s3-global.accesspoint ``` In addition, another global endpoint was missing from `InterfaceVpcEndpointAwsService`. ### Description of changes * The `InterfaceVpcEndpointAwsService` constructor was modified to * I would have preferred to switch to a single object for the optional constructor properties (`prefix`, `port`, and now `global`), but couldn't make a breaking change to a publicly accessible constructor * `InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS` was changed to be a global VPC endpoint * `InterfaceVpcEndpointAwsService.CODECATALYST` was added ### Description of how you validated changes I've added a unit test to check that the global endpoints' name were set correctly. I also added an integration test for `InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS`. To test it, I created a publicly accessible EC2 instance on the VPC, connected to it and ran `nslookup accesspoint.s3-global.amazonaws.com` to make sure it was resolvable (see [Configuring a Multi-Region Access Point for use with AWS PrivateLink](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiRegionAccessPointsPrivateLink.html)): Without the `InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS` interface endpoint: ```sh $ nslookup accesspoint.s3-global.amazonaws.com Server: 10.0.0.2 Address: 10.0.0.2#53 Non-authoritative answer: *** Can't find accesspoint.s3-global.amazonaws.com: No answer ``` With the `InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS` interface endpoint: ```sh $ nslookup accesspoint.s3-global.amazonaws.com Server: 10.0.0.2 Address: 10.0.0.2#53 Non-authoritative answer: Name: accesspoint.s3-global.amazonaws.com Address: 10.0.156.75 Name: accesspoint.s3-global.amazonaws.com Address: 10.0.246.83 ``` ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../cdk.out | 1 + ...efaultTestDeployAssertE52DED6D.assets.json | 19 + ...aultTestDeployAssertE52DED6D.template.json | 36 + .../integ.json | 12 + .../manifest.json | 221 ++++++ .../test-globalvpcendpoint.assets.json | 19 + .../test-globalvpcendpoint.template.json | 410 ++++++++++ .../tree.json | 721 ++++++++++++++++++ .../aws-ec2/test/integ.vpc-global-endpoint.ts | 63 ++ .../aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts | 29 +- .../aws-ec2/test/vpc-endpoint.test.ts | 22 + 11 files changed, 1548 insertions(+), 5 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.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.vpc-global-endpoint.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.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.assets.json new file mode 100644 index 0000000000000..245c7a9220969 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "globalvpcendpointDefaultTestDeployAssertE52DED6D.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.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/globalvpcendpointDefaultTestDeployAssertE52DED6D.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.vpc-global-endpoint.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/integ.json new file mode 100644 index 0000000000000..6261adc7adb91 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "globalvpcendpoint/DefaultTest": { + "stacks": [ + "test-globalvpcendpoint" + ], + "assertionStack": "globalvpcendpoint/DefaultTest/DeployAssert", + "assertionStackName": "globalvpcendpointDefaultTestDeployAssertE52DED6D" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/manifest.json new file mode 100644 index 0000000000000..83683aaddaff0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/manifest.json @@ -0,0 +1,221 @@ +{ + "version": "36.0.0", + "artifacts": { + "test-globalvpcendpoint.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "test-globalvpcendpoint.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "test-globalvpcendpoint": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "test-globalvpcendpoint.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}/5322eda79d17c722a06e07a2eebb395a34cb4d6962eb17e264c11ec8bcaa0922.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "test-globalvpcendpoint.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": [ + "test-globalvpcendpoint.assets" + ], + "metadata": { + "/test-globalvpcendpoint/MyVpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcF9F0CA6F" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1SubnetF6608456" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1RouteTableC46AB2F4" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1RouteTableAssociation2ECEE1CB" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet1DefaultRoute95FDF9EB" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2Subnet492B6BFB" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2RouteTable1DF17386" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2RouteTableAssociation227DE78D" + } + ], + "/test-globalvpcendpoint/MyVpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPublicSubnet2DefaultRoute052936F6" + } + ], + "/test-globalvpcendpoint/MyVpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + ], + "/test-globalvpcendpoint/MyVpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1RouteTable8819E6E2" + } + ], + "/test-globalvpcendpoint/MyVpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet1RouteTableAssociation56D38C7E" + } + ], + "/test-globalvpcendpoint/MyVpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2Subnet0040C983" + } + ], + "/test-globalvpcendpoint/MyVpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + } + ], + "/test-globalvpcendpoint/MyVpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcPrivateSubnet2RouteTableAssociation86A610DA" + } + ], + "/test-globalvpcendpoint/MyVpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcIGW5C4A4F63" + } + ], + "/test-globalvpcendpoint/MyVpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcVPCGW488ACE0D" + } + ], + "/test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcS3MultiRegionAccessEndpointSecurityGroup0B79B22B" + } + ], + "/test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyVpcS3MultiRegionAccessEndpointBBDE5F84" + } + ], + "/test-globalvpcendpoint/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/test-globalvpcendpoint/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "test-globalvpcendpoint" + }, + "globalvpcendpointDefaultTestDeployAssertE52DED6D.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "globalvpcendpointDefaultTestDeployAssertE52DED6D.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "globalvpcendpointDefaultTestDeployAssertE52DED6D": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "globalvpcendpointDefaultTestDeployAssertE52DED6D.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": [ + "globalvpcendpointDefaultTestDeployAssertE52DED6D.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": [ + "globalvpcendpointDefaultTestDeployAssertE52DED6D.assets" + ], + "metadata": { + "/globalvpcendpoint/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/globalvpcendpoint/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "globalvpcendpoint/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.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.assets.json new file mode 100644 index 0000000000000..f1fa5b4b5ea05 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "5322eda79d17c722a06e07a2eebb395a34cb4d6962eb17e264c11ec8bcaa0922": { + "source": { + "path": "test-globalvpcendpoint.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "5322eda79d17c722a06e07a2eebb395a34cb4d6962eb17e264c11ec8bcaa0922.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.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.template.json new file mode 100644 index 0000000000000..4108bb1189d52 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/test-globalvpcendpoint.template.json @@ -0,0 +1,410 @@ +{ + "Resources": { + "MyVpcF9F0CA6F": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/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": "test-globalvpcendpoint/MyVpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet1RouteTableC46AB2F4": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/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" + ] + }, + "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": "test-globalvpcendpoint/MyVpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPublicSubnet2RouteTable1DF17386": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/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" + ] + }, + "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": "Isolated" + }, + { + "Key": "Name", + "Value": "test-globalvpcendpoint/MyVpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet1RouteTable8819E6E2": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/MyVpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet1RouteTableAssociation56D38C7E": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet1RouteTable8819E6E2" + }, + "SubnetId": { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + } + } + }, + "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": "Isolated" + }, + { + "Key": "Name", + "Value": "test-globalvpcendpoint/MyVpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet2RouteTableCEDCEECE": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/MyVpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcPrivateSubnet2RouteTableAssociation86A610DA": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPrivateSubnet2RouteTableCEDCEECE" + }, + "SubnetId": { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + } + }, + "MyVpcIGW5C4A4F63": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/MyVpc" + } + ] + } + }, + "MyVpcVPCGW488ACE0D": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + }, + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcS3MultiRegionAccessEndpointSecurityGroup0B79B22B": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "CidrBlock" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "CidrBlock" + ] + }, + ":443" + ] + ] + }, + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "test-globalvpcendpoint/MyVpc" + } + ], + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "MyVpcS3MultiRegionAccessEndpointBBDE5F84": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcS3MultiRegionAccessEndpointSecurityGroup0B79B22B", + "GroupId" + ] + } + ], + "ServiceName": "com.amazonaws.s3-global.accesspoint", + "SubnetIds": [ + { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + }, + { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + ], + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + } + }, + "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.vpc-global-endpoint.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/tree.json new file mode 100644 index 0000000000000..6d3f43832ff75 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.js.snapshot/tree.json @@ -0,0 +1,721 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "test-globalvpcendpoint": { + "id": "test-globalvpcendpoint", + "path": "test-globalvpcendpoint", + "children": { + "MyVpc": { + "id": "MyVpc", + "path": "test-globalvpcendpoint/MyVpc", + "children": { + "Resource": { + "id": "Resource", + "path": "test-globalvpcendpoint/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": "test-globalvpcendpoint/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "test-globalvpcendpoint/MyVpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "test-globalvpcendpoint/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": "test-globalvpcendpoint/MyVpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "test-globalvpcendpoint/MyVpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "test-globalvpcendpoint/MyVpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "test-globalvpcendpoint/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": "test-globalvpcendpoint/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" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "test-globalvpcendpoint/MyVpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "test-globalvpcendpoint/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": "test-globalvpcendpoint/MyVpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "test-globalvpcendpoint/MyVpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "test-globalvpcendpoint/MyVpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "test-globalvpcendpoint/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": "test-globalvpcendpoint/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" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "test-globalvpcendpoint/MyVpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "test-globalvpcendpoint/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": "Isolated" + }, + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "test-globalvpcendpoint/MyVpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "test-globalvpcendpoint/MyVpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "test-globalvpcendpoint/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" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "test-globalvpcendpoint/MyVpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "test-globalvpcendpoint/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": "Isolated" + }, + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "test-globalvpcendpoint/MyVpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "test-globalvpcendpoint/MyVpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "test-globalvpcendpoint/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" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "test-globalvpcendpoint/MyVpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "test-globalvpcendpoint/MyVpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "test-globalvpcendpoint/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" + } + }, + "S3MultiRegionAccessEndpoint": { + "id": "S3MultiRegionAccessEndpoint", + "path": "test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint", + "children": { + "SecurityGroup": { + "id": "SecurityGroup", + "path": "test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/SecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "securityGroupIngress": [ + { + "cidrIp": { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "CidrBlock" + ] + }, + "ipProtocol": "tcp", + "fromPort": 443, + "toPort": 443, + "description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "MyVpcF9F0CA6F", + "CidrBlock" + ] + }, + ":443" + ] + ] + } + } + ], + "tags": [ + { + "key": "Name", + "value": "test-globalvpcendpoint/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" + } + }, + "Resource": { + "id": "Resource", + "path": "test-globalvpcendpoint/MyVpc/S3MultiRegionAccessEndpoint/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCEndpoint", + "aws:cdk:cloudformation:props": { + "privateDnsEnabled": true, + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "MyVpcS3MultiRegionAccessEndpointSecurityGroup0B79B22B", + "GroupId" + ] + } + ], + "serviceName": "com.amazonaws.s3-global.accesspoint", + "subnetIds": [ + { + "Ref": "MyVpcPrivateSubnet1Subnet5057CF7E" + }, + { + "Ref": "MyVpcPrivateSubnet2Subnet0040C983" + } + ], + "vpcEndpointType": "Interface", + "vpcId": { + "Ref": "MyVpcF9F0CA6F" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCEndpoint", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.InterfaceVpcEndpoint", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "test-globalvpcendpoint/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "test-globalvpcendpoint/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "globalvpcendpoint": { + "id": "globalvpcendpoint", + "path": "globalvpcendpoint", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "globalvpcendpoint/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "globalvpcendpoint/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "globalvpcendpoint/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "globalvpcendpoint/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "globalvpcendpoint/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.vpc-global-endpoint.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.ts new file mode 100644 index 0000000000000..d47c81343ecd9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.vpc-global-endpoint.ts @@ -0,0 +1,63 @@ +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { EC2_RESTRICT_DEFAULT_SECURITY_GROUP } from 'aws-cdk-lib/cx-api'; + +/* + * Stack verification steps: + * * Create an instance in the VPC + * * Connect to that instance (via SSH using `keyPair` should be easiest) + * * Run the following command: `nslookup accesspoint.s3-global.amazonaws.com` + * + * You should see a response with the IP address of the global S3 endpoint. +*/ +class Test extends cdk.Stack { + constructor(scope: cdk.App, id: string) { + super(scope, id); + this.node.setContext(EC2_RESTRICT_DEFAULT_SECURITY_GROUP, false); + + const vpc = new ec2.Vpc(this, 'MyVpc', { + enableDnsSupport: true, + subnetConfiguration: [ + { + name: 'Public', + subnetType: ec2.SubnetType.PUBLIC, + mapPublicIpOnLaunch: true, + }, + { + name: 'Private', + subnetType: ec2.SubnetType.PRIVATE_ISOLATED, + }, + ], + }); + + vpc.addInterfaceEndpoint('S3MultiRegionAccessEndpoint', { + service: ec2.InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS, + }); + + // Create an instance to test the endpoint + /* const securityGroup = new ec2.SecurityGroup(this, 'MySecurityGroup', { + vpc, + allowAllOutbound: true, + }); + securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'Allow SSH access'); + + new ec2.Instance(this, 'MyInstance', { + vpc, + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + securityGroup, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO), + machineImage: ec2.MachineImage.latestAmazonLinux2023(), + keyPair: ec2.KeyPair.fromKeyPairName(this, 'KeyPair', 'my-key-pair-name'), + }); */ + } +} + +const app = new cdk.App(); + +const testCase = new Test(app, 'test-globalvpcendpoint'); +new IntegTest(app, 'globalvpcendpoint', { + testCases: [testCase], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts index 7a9322fc522a6..8cd8424219d2b 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts @@ -255,6 +255,19 @@ export class InterfaceVpcEndpointService implements IInterfaceVpcEndpointService } } +/** + * Optional properties for the InterfaceVpcEndpointAwsService class + */ +export interface InterfaceVpcEndpointAwsServiceProps { + /** + * If true, the service is a global endpoint and + * its name will not be prefixed with the stack's region. + * + * @default false + */ + readonly global?: boolean; +} + /** * An AWS service for an interface VPC endpoint. */ @@ -320,6 +333,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ public static readonly CODEARTIFACT_REPOSITORIES = new InterfaceVpcEndpointAwsService('codeartifact.repositories'); public static readonly CODEBUILD = new InterfaceVpcEndpointAwsService('codebuild'); public static readonly CODEBUILD_FIPS = new InterfaceVpcEndpointAwsService('codebuild-fips'); + public static readonly CODECATALYST = new InterfaceVpcEndpointAwsService('codecatalyst', 'aws.api.global', undefined, { global: true }); public static readonly CODECATALYST_GIT = new InterfaceVpcEndpointAwsService('codecatalyst.git'); public static readonly CODECATALYST_PACKAGES = new InterfaceVpcEndpointAwsService('codecatalyst.packages'); public static readonly CODECOMMIT = new InterfaceVpcEndpointAwsService('codecommit'); @@ -484,7 +498,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ public static readonly ROBOMAKER = new InterfaceVpcEndpointAwsService('robomaker'); public static readonly S3 = new InterfaceVpcEndpointAwsService('s3'); public static readonly S3_OUTPOSTS = new InterfaceVpcEndpointAwsService('s3-outposts'); - public static readonly S3_MULTI_REGION_ACCESS_POINTS = new InterfaceVpcEndpointAwsService('s3-global.accesspoint', 'com.amazonaws'); + public static readonly S3_MULTI_REGION_ACCESS_POINTS = new InterfaceVpcEndpointAwsService('s3-global.accesspoint', 'com.amazonaws', undefined, { global: true }); public static readonly SAGEMAKER_API = new InterfaceVpcEndpointAwsService('sagemaker.api'); public static readonly SAGEMAKER_FEATURESTORE_RUNTIME = new InterfaceVpcEndpointAwsService('sagemaker.featurestore-runtime'); public static readonly SAGEMAKER_GEOSPATIAL = new InterfaceVpcEndpointAwsService('sagemaker-geospatial'); @@ -553,10 +567,15 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ */ public readonly privateDnsDefault?: boolean = true; - constructor(name: string, prefix?: string, port?: number) { - const region = Lazy.uncachedString({ + constructor( + name: string, + prefix?: string, + port?: number, + props?: InterfaceVpcEndpointAwsServiceProps, + ) { + const regionPrefix = props?.global ? '' : (Lazy.uncachedString({ produce: (context) => Stack.of(context.scope).region, - }); + }) + '.'); const defaultEndpointPrefix = Lazy.uncachedString({ produce: (context) => { const regionName = Stack.of(context.scope).region; @@ -570,7 +589,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ }, }); - this.name = `${prefix || defaultEndpointPrefix}.${region}.${name}${defaultEndpointSuffix}`; + this.name = `${prefix || defaultEndpointPrefix}.${regionPrefix}${name}${defaultEndpointSuffix}`; this.shortName = name; this.port = port || 443; } diff --git a/packages/aws-cdk-lib/aws-ec2/test/vpc-endpoint.test.ts b/packages/aws-cdk-lib/aws-ec2/test/vpc-endpoint.test.ts index dc7265357dc9c..3c1c05ba8dfa8 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/vpc-endpoint.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/vpc-endpoint.test.ts @@ -912,5 +912,27 @@ describe('vpc endpoint', () => { ServiceName: 'com.amazonaws.us-west-2.application-autoscaling', }); }); + + test('global vpc interface endpoints', () => { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-west-2' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('Global S3 API Endpoint', { + service: InterfaceVpcEndpointAwsService.S3_MULTI_REGION_ACCESS_POINTS, + }); + vpc.addInterfaceEndpoint('Global CodeCatalyst API Endpoint', { + service: InterfaceVpcEndpointAwsService.CODECATALYST, + }); + + //THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', { + ServiceName: 'com.amazonaws.s3-global.accesspoint', + }); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', { + ServiceName: 'aws.api.global.codecatalyst', + }); + }); }); });