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 d186d00987317..7e3cedf219e09 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts @@ -9,6 +9,7 @@ import { ISubnet, IVpc, SubnetSelection } from './vpc'; import * as iam from '../../aws-iam'; import * as cxschema from '../../cloud-assembly-schema'; import { Aws, ContextProvider, IResource, Lazy, Resource, Stack, Token } from '../../core'; +import { PARTITION_MAP } from '../../region-info/build-tools/fact-tables'; /** * A VPC endpoint. @@ -666,8 +667,21 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ 'redshift', 'redshift-data', 's3', 'sagemaker.api', 'sagemaker.featurestore-runtime', 'sagemaker.runtime', 'securityhub', 'servicecatalog', 'sms', 'sqs', 'states', 'sts', 'sync-states', 'synthetics', 'transcribe', 'transcribestreaming', 'transfer', 'workspaces', 'xray'], + 'us-isof-': ['ecr.api', 'ecr.dkr'], + 'eu-isoe-': ['ecr.api', 'ecr.dkr'], }; - if (VPC_ENDPOINT_SERVICE_EXCEPTIONS[region]?.includes(name)) { + + const regionPartition = region.split('-').slice(0, 2).join('-'); + const partitionDetails = PARTITION_MAP[`${regionPartition}-`]; + + // Check for specific service name under isolated region prefix + const serviceInExceptions = VPC_ENDPOINT_SERVICE_EXCEPTIONS[`${regionPartition}-`]?.includes(name); + + if (serviceInExceptions) { + // Endpoints generated in reverse of domain suffix for the services mentioned in map + const reverseString = partitionDetails.domainSuffix.split('.').reverse().join('.'); + return reverseString; + } else if (VPC_ENDPOINT_SERVICE_EXCEPTIONS[region]?.includes(name)) { return 'cn.com.amazonaws'; } else { return 'com.amazonaws'; 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 3c1c05ba8dfa8..2e9ae880d7147 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 @@ -694,6 +694,37 @@ describe('vpc endpoint', () => { }); }); + + test.each([ + ['us-isof-test-1', 'gov.ic.hci.csp'], + ['eu-isoe-test-1', 'uk.adc-e.cloud'], + ['us-east-1', 'com.amazonaws'], + ['us-gov-west-1', 'com.amazonaws'], + ['cn-northwest-1', 'cn.com.amazonaws'], + ['cn-north-1', 'cn.com.amazonaws'], + ])('test vpc interface endpoint for ECR can be created correctly in all regions', (region : string, domain: string) => { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: region } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('ECR Endpoint', { + service: InterfaceVpcEndpointAwsService.ECR, + }); + + vpc.addInterfaceEndpoint('ECR Docker Endpoint', { + service: InterfaceVpcEndpointAwsService.ECR_DOCKER, + }); + + //THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', { + ServiceName: `${domain}.${region}.ecr.api`, + }); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', { + ServiceName: `${domain}.${region}.ecr.dkr`, + }); + }); + test.each([ ['transcribe', InterfaceVpcEndpointAwsService.TRANSCRIBE], ])('test vpc interface endpoint with .cn suffix for %s can be created correctly in China regions', (name: string, given: InterfaceVpcEndpointAwsService) => {