From 76418b85f2a2b6c39710f1c73b60db0752c3c061 Mon Sep 17 00:00:00 2001 From: watany <76135106+watany-dev@users.noreply.github.com> Date: Tue, 18 Mar 2025 07:47:02 +0000 Subject: [PATCH] feat(ec2): Connectable Prefixlist --- .../__entrypoint__.js | 155 ++++++ .../index.js | 1 + .../integ.prefix-list.js.snapshot/cdk.out | 2 +- .../integ-ec2-prefix-list-test.assets.json | 19 +- .../integ-ec2-prefix-list-test.template.json | 469 +++++++++++++++++- .../integ.prefix-list.js.snapshot/integ.json | 2 +- ...efaultTestDeployAssert24D5C536.assets.json | 2 +- .../manifest.json | 204 +++++++- .../integ.prefix-list.js.snapshot/tree.json | 137 +---- .../test/aws-ec2/test/integ.prefix-list.ts | 8 +- packages/aws-cdk-lib/aws-ec2/README.md | 7 +- .../aws-cdk-lib/aws-ec2/lib/prefix-list.ts | 44 +- .../aws-ec2/test/prefix-list.test.ts | 22 + 13 files changed, 921 insertions(+), 151 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/__entrypoint__.js create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/index.js diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/__entrypoint__.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/__entrypoint__.js new file mode 100644 index 0000000000000..ff3a517fba12d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/__entrypoint__.js @@ -0,0 +1,155 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.external = void 0; +exports.handler = handler; +exports.withRetries = withRetries; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + const parsedUrl = url.parse(event.ResponseURL); + const loggingSafeUrl = `${parsedUrl.protocol}//${parsedUrl.hostname}/${parsedUrl.pathname}?***`; + exports.external.log('submit response to cloudformation', loggingSafeUrl, json); + const responseBody = JSON.stringify(json); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { + 'content-type': '', + 'content-length': Buffer.byteLength(responseBody, 'utf8'), + }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, requestBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, (response) => { + response.resume(); // Consume the response but don't care about it + if (!response.statusCode || response.statusCode >= 400) { + reject(new Error(`Unsuccessful HTTP response: ${response.statusCode}`)); + } + else { + resolve(); + } + }); + request.on('error', reject); + request.write(requestBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/index.js b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/index.js new file mode 100644 index 0000000000000..013bcaffd8fe5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c/index.js @@ -0,0 +1 @@ +"use strict";var I=Object.create;var t=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty;var G=(r,e)=>{for(var o in e)t(r,o,{get:e[o],enumerable:!0})},n=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of P(e))!l.call(r,s)&&s!==o&&t(r,s,{get:()=>e[s],enumerable:!(i=y(e,s))||i.enumerable});return r};var R=(r,e,o)=>(o=r!=null?I(g(r)):{},n(e||!r||!r.__esModule?t(o,"default",{value:r,enumerable:!0}):o,r)),S=r=>n(t({},"__esModule",{value:!0}),r);var k={};G(k,{handler:()=>f});module.exports=S(k);var a=R(require("@aws-sdk/client-ec2")),u=new a.EC2({});function c(r,e){return{GroupId:r,IpPermissions:[{UserIdGroupPairs:[{GroupId:r,UserId:e}],IpProtocol:"-1"}]}}function d(r){return{GroupId:r,IpPermissions:[{IpRanges:[{CidrIp:"0.0.0.0/0"}],IpProtocol:"-1"}]}}async function f(r){let e=r.ResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.Account;switch(r.RequestType){case"Create":return p(e,o);case"Update":return h(r);case"Delete":return m(e,o)}}async function h(r){let e=r.OldResourceProperties.DefaultSecurityGroupId,o=r.ResourceProperties.DefaultSecurityGroupId;e!==o&&(await m(e,r.ResourceProperties.Account),await p(o,r.ResourceProperties.Account))}async function p(r,e){try{await u.revokeSecurityGroupEgress(d(r))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}try{await u.revokeSecurityGroupIngress(c(r,e))}catch(o){if(o.name!=="InvalidPermission.NotFound")throw o}}async function m(r,e){await u.authorizeSecurityGroupIngress(c(r,e)),await u.authorizeSecurityGroupEgress(d(r))}0&&(module.exports={handler}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/cdk.out index 7925065efbcc4..1e02a2deb191b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"31.0.0"} \ No newline at end of file +{"version":"40.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.assets.json index 16839acb7274c..1d825a3d5d8b3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.assets.json @@ -1,7 +1,20 @@ { - "version": "31.0.0", + "version": "40.0.0", "files": { - "2cb0a44838e31f68717daa5de0b7b2149c2fedb3892bff48470b979550060afa": { + "a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c": { + "source": { + "path": "asset.a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "27d9fada3b961311f705f13e5835b80945a377474bf00d59cb5351c8a03af95b": { "source": { "path": "integ-ec2-prefix-list-test.template.json", "packaging": "file" @@ -9,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2cb0a44838e31f68717daa5de0b7b2149c2fedb3892bff48470b979550060afa.json", + "objectKey": "27d9fada3b961311f705f13e5835b80945a377474bf00d59cb5351c8a03af95b.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.template.json index 19a92b33dc58d..88d191fa5aaa6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ-ec2-prefix-list-test.template.json @@ -4,8 +4,6 @@ "Type": "AWS::EC2::PrefixList", "Properties": { "AddressFamily": "IPv4", - "MaxEntries": 2, - "PrefixListName": "integec2prefixlisttestPrefixList498BBB96", "Entries": [ { "Cidr": "10.0.0.1/32" @@ -14,8 +12,475 @@ "Cidr": "10.0.0.2/32", "Description": "sample1" } + ], + "MaxEntries": 2, + "PrefixListName": "integec2prefixlisttestPrefixList498BBB96" + } + }, + "vpcA2121C38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-prefix-list-test/vpc" + } + ] + } + }, + "vpcPublicSubnet1Subnet2E65531E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/17", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ec2-prefix-list-test/vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "vpcPublicSubnet1RouteTable48A2DF9B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-prefix-list-test/vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "vpcPublicSubnet1RouteTableAssociation5D3F4579": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "vpcPublicSubnet1RouteTable48A2DF9B" + }, + "SubnetId": { + "Ref": "vpcPublicSubnet1Subnet2E65531E" + } + } + }, + "vpcPublicSubnet1DefaultRoute10708846": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "vpcIGWE57CBDCA" + }, + "RouteTableId": { + "Ref": "vpcPublicSubnet1RouteTable48A2DF9B" + } + }, + "DependsOn": [ + "vpcVPCGW7984C166" + ] + }, + "vpcIsolatedSubnet1Subnet8B28CEB3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/17", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Isolated" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Isolated" + }, + { + "Key": "Name", + "Value": "integ-ec2-prefix-list-test/vpc/IsolatedSubnet1" + } + ], + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "vpcIsolatedSubnet1RouteTable0D6B2D3D": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-prefix-list-test/vpc/IsolatedSubnet1" + } + ], + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "vpcIsolatedSubnet1RouteTableAssociation172210D4": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "vpcIsolatedSubnet1RouteTable0D6B2D3D" + }, + "SubnetId": { + "Ref": "vpcIsolatedSubnet1Subnet8B28CEB3" + } + } + }, + "vpcIGWE57CBDCA": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ec2-prefix-list-test/vpc" + } ] } + }, + "vpcVPCGW7984C166": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "vpcIGWE57CBDCA" + }, + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "vpcRestrictDefaultSecurityGroupCustomResourceA6EBC6D0": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "vpcA2121C38", + "DefaultSecurityGroup" + ] + }, + "Account": { + "Ref": "AWS::AccountId" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ec2:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":security-group/", + { + "Fn::GetAtt": [ + "vpcA2121C38", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "a1acfc2b5f4f6b183fd2bb9863f486bc5edef6a357b355a070d9a0e502df418c.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0", + "Arn" + ] + }, + "Runtime": { + "Fn::FindInMap": [ + "LatestNodeRuntimeMap", + { + "Ref": "AWS::Region" + }, + "value" + ] + }, + "Description": "Lambda function for removing all inbound/outbound rules from the VPC default security group" + }, + "DependsOn": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + ] + }, + "sg29196201": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "integ-ec2-prefix-list-test/sg", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "sgfromIndirectPeerUDP80D51D8E2F": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "Description": { + "Fn::Join": [ + "", + [ + "from ", + { + "Fn::GetAtt": [ + "PrefixList469FCC0B", + "PrefixListId" + ] + }, + ":UDP 80" + ] + ] + }, + "FromPort": 80, + "GroupId": { + "Fn::GetAtt": [ + "sg29196201", + "GroupId" + ] + }, + "IpProtocol": "udp", + "SourcePrefixListId": { + "Fn::GetAtt": [ + "PrefixList469FCC0B", + "PrefixListId" + ] + }, + "ToPort": 80 + } + } + }, + "Mappings": { + "LatestNodeRuntimeMap": { + "af-south-1": { + "value": "nodejs20.x" + }, + "ap-east-1": { + "value": "nodejs20.x" + }, + "ap-northeast-1": { + "value": "nodejs20.x" + }, + "ap-northeast-2": { + "value": "nodejs20.x" + }, + "ap-northeast-3": { + "value": "nodejs20.x" + }, + "ap-south-1": { + "value": "nodejs20.x" + }, + "ap-south-2": { + "value": "nodejs20.x" + }, + "ap-southeast-1": { + "value": "nodejs20.x" + }, + "ap-southeast-2": { + "value": "nodejs20.x" + }, + "ap-southeast-3": { + "value": "nodejs20.x" + }, + "ap-southeast-4": { + "value": "nodejs20.x" + }, + "ap-southeast-5": { + "value": "nodejs20.x" + }, + "ap-southeast-7": { + "value": "nodejs20.x" + }, + "ca-central-1": { + "value": "nodejs20.x" + }, + "ca-west-1": { + "value": "nodejs20.x" + }, + "cn-north-1": { + "value": "nodejs20.x" + }, + "cn-northwest-1": { + "value": "nodejs20.x" + }, + "eu-central-1": { + "value": "nodejs20.x" + }, + "eu-central-2": { + "value": "nodejs20.x" + }, + "eu-isoe-west-1": { + "value": "nodejs18.x" + }, + "eu-north-1": { + "value": "nodejs20.x" + }, + "eu-south-1": { + "value": "nodejs20.x" + }, + "eu-south-2": { + "value": "nodejs20.x" + }, + "eu-west-1": { + "value": "nodejs20.x" + }, + "eu-west-2": { + "value": "nodejs20.x" + }, + "eu-west-3": { + "value": "nodejs20.x" + }, + "il-central-1": { + "value": "nodejs20.x" + }, + "me-central-1": { + "value": "nodejs20.x" + }, + "me-south-1": { + "value": "nodejs20.x" + }, + "mx-central-1": { + "value": "nodejs20.x" + }, + "sa-east-1": { + "value": "nodejs20.x" + }, + "us-east-1": { + "value": "nodejs20.x" + }, + "us-east-2": { + "value": "nodejs20.x" + }, + "us-gov-east-1": { + "value": "nodejs20.x" + }, + "us-gov-west-1": { + "value": "nodejs20.x" + }, + "us-iso-east-1": { + "value": "nodejs18.x" + }, + "us-iso-west-1": { + "value": "nodejs18.x" + }, + "us-isob-east-1": { + "value": "nodejs18.x" + }, + "us-west-1": { + "value": "nodejs20.x" + }, + "us-west-2": { + "value": "nodejs20.x" + } } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ.json index d40abfebc1d07..e8809a618ad82 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "31.0.0", + "version": "40.0.0", "testCases": { "integ-test/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json index ecd9f6bd2a455..abf03ee6018d7 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/integtestDefaultTestDeployAssert24D5C536.assets.json @@ -1,5 +1,5 @@ { - "version": "31.0.0", + "version": "40.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/manifest.json index 71062d7cae93d..4926f81f8417b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "31.0.0", + "version": "40.0.0", "artifacts": { "integ-ec2-prefix-list-test.assets": { "type": "cdk:asset-manifest", @@ -14,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "integ-ec2-prefix-list-test.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}/2cb0a44838e31f68717daa5de0b7b2149c2fedb3892bff48470b979550060afa.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/27d9fada3b961311f705f13e5835b80945a377474bf00d59cb5351c8a03af95b.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -33,12 +34,210 @@ "integ-ec2-prefix-list-test.assets" ], "metadata": { + "/integ-ec2-prefix-list-test/PrefixList": [ + { + "type": "aws:cdk:analytics:construct", + "data": {} + } + ], "/integ-ec2-prefix-list-test/PrefixList/Resource": [ { "type": "aws:cdk:logicalId", "data": "PrefixList469FCC0B" } ], + "/integ-ec2-prefix-list-test/vpc": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "natGateways": "*", + "maxAzs": "*" + } + } + ], + "/integ-ec2-prefix-list-test/vpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcA2121C38" + } + ], + "/integ-ec2-prefix-list-test/vpc/PublicSubnet1": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "availabilityZone": "*", + "vpcId": "*", + "cidrBlock": "*", + "mapPublicIpOnLaunch": true, + "ipv6CidrBlock": "*", + "assignIpv6AddressOnCreation": "*" + } + }, + { + "type": "aws:cdk:analytics:construct", + "data": { + "availabilityZone": "*", + "vpcId": "*", + "cidrBlock": "*", + "mapPublicIpOnLaunch": true, + "ipv6CidrBlock": "*", + "assignIpv6AddressOnCreation": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": {} + } + ], + "/integ-ec2-prefix-list-test/vpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcPublicSubnet1Subnet2E65531E" + } + ], + "/integ-ec2-prefix-list-test/vpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcPublicSubnet1RouteTable48A2DF9B" + } + ], + "/integ-ec2-prefix-list-test/vpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcPublicSubnet1RouteTableAssociation5D3F4579" + } + ], + "/integ-ec2-prefix-list-test/vpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcPublicSubnet1DefaultRoute10708846" + } + ], + "/integ-ec2-prefix-list-test/vpc/IsolatedSubnet1": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "availabilityZone": "*", + "vpcId": "*", + "cidrBlock": "*", + "mapPublicIpOnLaunch": false, + "ipv6CidrBlock": "*", + "assignIpv6AddressOnCreation": "*" + } + }, + { + "type": "aws:cdk:analytics:construct", + "data": { + "availabilityZone": "*", + "vpcId": "*", + "cidrBlock": "*", + "mapPublicIpOnLaunch": false, + "ipv6CidrBlock": "*", + "assignIpv6AddressOnCreation": "*" + } + } + ], + "/integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcIsolatedSubnet1Subnet8B28CEB3" + } + ], + "/integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcIsolatedSubnet1RouteTable0D6B2D3D" + } + ], + "/integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcIsolatedSubnet1RouteTableAssociation172210D4" + } + ], + "/integ-ec2-prefix-list-test/vpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcIGWE57CBDCA" + } + ], + "/integ-ec2-prefix-list-test/vpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcVPCGW7984C166" + } + ], + "/integ-ec2-prefix-list-test/vpc/RestrictDefaultSecurityGroupCustomResource": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/integ-ec2-prefix-list-test/vpc/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "vpcRestrictDefaultSecurityGroupCustomResourceA6EBC6D0" + } + ], + "/integ-ec2-prefix-list-test/LatestNodeRuntimeMap": [ + { + "type": "aws:cdk:logicalId", + "data": "LatestNodeRuntimeMap" + } + ], + "/integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider": [ + { + "type": "aws:cdk:is-custom-resource-handler-customResourceProvider", + "data": true + } + ], + "/integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/integ-ec2-prefix-list-test/sg": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "vpc": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addIngressRule": [ + { + "canInlineRule": false, + "uniqueId": "*", + "connections": "*" + }, + {}, + "*", + false + ] + } + } + ], + "/integ-ec2-prefix-list-test/sg/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "sg29196201" + } + ], + "/integ-ec2-prefix-list-test/sg/from {IndirectPeer}:UDP 80": [ + { + "type": "aws:cdk:logicalId", + "data": "sgfromIndirectPeerUDP80D51D8E2F" + } + ], "/integ-ec2-prefix-list-test/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -67,6 +266,7 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "integtestDefaultTestDeployAssert24D5C536.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}", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/tree.json index ca1b5265d7056..814fe84883363 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.js.snapshot/tree.json @@ -1,136 +1 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "integ-ec2-prefix-list-test": { - "id": "integ-ec2-prefix-list-test", - "path": "integ-ec2-prefix-list-test", - "children": { - "PrefixList": { - "id": "PrefixList", - "path": "integ-ec2-prefix-list-test/PrefixList", - "children": { - "Resource": { - "id": "Resource", - "path": "integ-ec2-prefix-list-test/PrefixList/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::PrefixList", - "aws:cdk:cloudformation:props": { - "addressFamily": "IPv4", - "maxEntries": 2, - "prefixListName": "integec2prefixlisttestPrefixList498BBB96", - "entries": [ - { - "cidr": "10.0.0.1/32" - }, - { - "cidr": "10.0.0.2/32", - "description": "sample1" - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnPrefixList", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.PrefixList", - "version": "0.0.0" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "integ-ec2-prefix-list-test/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "integ-ec2-prefix-list-test/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - }, - "integ-test": { - "id": "integ-test", - "path": "integ-test", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "integ-test/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "integ-test/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.270" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "integ-test/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "integ-test/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "aws-cdk-lib.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", - "version": "0.0.0" - } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.270" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.App", - "version": "0.0.0" - } - } -} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","children":{"integ-ec2-prefix-list-test":{"id":"integ-ec2-prefix-list-test","path":"integ-ec2-prefix-list-test","children":{"PrefixList":{"id":"PrefixList","path":"integ-ec2-prefix-list-test/PrefixList","children":{"Resource":{"id":"Resource","path":"integ-ec2-prefix-list-test/PrefixList/Resource","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::PrefixList","aws:cdk:cloudformation:props":{"addressFamily":"IPv4","entries":[{"cidr":"10.0.0.1/32"},{"cidr":"10.0.0.2/32","description":"sample1"}],"maxEntries":2,"prefixListName":"integec2prefixlisttestPrefixList498BBB96"}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnPrefixList","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PrefixList","version":"0.0.0","metadata":[{}]}},"vpc":{"id":"vpc","path":"integ-ec2-prefix-list-test/vpc","children":{"Resource":{"id":"Resource","path":"integ-ec2-prefix-list-test/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-prefix-list-test/vpc"}]}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnVPC","version":"0.0.0"}},"PublicSubnet1":{"id":"PublicSubnet1","path":"integ-ec2-prefix-list-test/vpc/PublicSubnet1","children":{"Subnet":{"id":"Subnet","path":"integ-ec2-prefix-list-test/vpc/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/17","mapPublicIpOnLaunch":true,"tags":[{"key":"aws-cdk:subnet-name","value":"Public"},{"key":"aws-cdk:subnet-type","value":"Public"},{"key":"Name","value":"integ-ec2-prefix-list-test/vpc/PublicSubnet1"}],"vpcId":{"Ref":"vpcA2121C38"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"}},"Acl":{"id":"Acl","path":"integ-ec2-prefix-list-test/vpc/PublicSubnet1/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"integ-ec2-prefix-list-test/vpc/PublicSubnet1/RouteTable","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"integ-ec2-prefix-list-test/vpc/PublicSubnet1"}],"vpcId":{"Ref":"vpcA2121C38"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"integ-ec2-prefix-list-test/vpc/PublicSubnet1/RouteTableAssociation","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"vpcPublicSubnet1RouteTable48A2DF9B"},"subnetId":{"Ref":"vpcPublicSubnet1Subnet2E65531E"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"}},"DefaultRoute":{"id":"DefaultRoute","path":"integ-ec2-prefix-list-test/vpc/PublicSubnet1/DefaultRoute","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Route","aws:cdk:cloudformation:props":{"destinationCidrBlock":"0.0.0.0/0","gatewayId":{"Ref":"vpcIGWE57CBDCA"},"routeTableId":{"Ref":"vpcPublicSubnet1RouteTable48A2DF9B"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRoute","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PublicSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":true,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{}]}},"IsolatedSubnet1":{"id":"IsolatedSubnet1","path":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1","children":{"Subnet":{"id":"Subnet","path":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/Subnet","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::Subnet","aws:cdk:cloudformation:props":{"availabilityZone":{"Fn::Select":[0,{"Fn::GetAZs":""}]},"cidrBlock":"10.0.128.0/17","mapPublicIpOnLaunch":false,"tags":[{"key":"aws-cdk:subnet-name","value":"Isolated"},{"key":"aws-cdk:subnet-type","value":"Isolated"},{"key":"Name","value":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1"}],"vpcId":{"Ref":"vpcA2121C38"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnet","version":"0.0.0"}},"Acl":{"id":"Acl","path":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/Acl","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"RouteTable":{"id":"RouteTable","path":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/RouteTable","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::RouteTable","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1"}],"vpcId":{"Ref":"vpcA2121C38"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnRouteTable","version":"0.0.0"}},"RouteTableAssociation":{"id":"RouteTableAssociation","path":"integ-ec2-prefix-list-test/vpc/IsolatedSubnet1/RouteTableAssociation","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SubnetRouteTableAssociation","aws:cdk:cloudformation:props":{"routeTableId":{"Ref":"vpcIsolatedSubnet1RouteTable0D6B2D3D"},"subnetId":{"Ref":"vpcIsolatedSubnet1Subnet8B28CEB3"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.PrivateSubnet","version":"0.0.0","metadata":[{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"},{"availabilityZone":"*","vpcId":"*","cidrBlock":"*","mapPublicIpOnLaunch":false,"ipv6CidrBlock":"*","assignIpv6AddressOnCreation":"*"}]}},"IGW":{"id":"IGW","path":"integ-ec2-prefix-list-test/vpc/IGW","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::InternetGateway","aws:cdk:cloudformation:props":{"tags":[{"key":"Name","value":"integ-ec2-prefix-list-test/vpc"}]}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnInternetGateway","version":"0.0.0"}},"VPCGW":{"id":"VPCGW","path":"integ-ec2-prefix-list-test/vpc/VPCGW","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::VPCGatewayAttachment","aws:cdk:cloudformation:props":{"internetGatewayId":{"Ref":"vpcIGWE57CBDCA"},"vpcId":{"Ref":"vpcA2121C38"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment","version":"0.0.0"}},"RestrictDefaultSecurityGroupCustomResource":{"id":"RestrictDefaultSecurityGroupCustomResource","path":"integ-ec2-prefix-list-test/vpc/RestrictDefaultSecurityGroupCustomResource","children":{"Default":{"id":"Default","path":"integ-ec2-prefix-list-test/vpc/RestrictDefaultSecurityGroupCustomResource/Default","constructInfo":{"fqn":"aws-cdk-lib.CfnResource","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.CustomResource","version":"0.0.0","metadata":["*"]}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.Vpc","version":"0.0.0","metadata":[{"natGateways":"*","maxAzs":"*"}]}},"LatestNodeRuntimeMap":{"id":"LatestNodeRuntimeMap","path":"integ-ec2-prefix-list-test/LatestNodeRuntimeMap","constructInfo":{"fqn":"aws-cdk-lib.CfnMapping","version":"0.0.0"}},"Custom::VpcRestrictDefaultSGCustomResourceProvider":{"id":"Custom::VpcRestrictDefaultSGCustomResourceProvider","path":"integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider","children":{"Staging":{"id":"Staging","path":"integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"Role":{"id":"Role","path":"integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role","constructInfo":{"fqn":"aws-cdk-lib.CfnResource","version":"0.0.0"}},"Handler":{"id":"Handler","path":"integ-ec2-prefix-list-test/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler","constructInfo":{"fqn":"aws-cdk-lib.CfnResource","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.CustomResourceProviderBase","version":"0.0.0"}},"sg":{"id":"sg","path":"integ-ec2-prefix-list-test/sg","children":{"Resource":{"id":"Resource","path":"integ-ec2-prefix-list-test/sg/Resource","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SecurityGroup","aws:cdk:cloudformation:props":{"groupDescription":"integ-ec2-prefix-list-test/sg","securityGroupEgress":[{"cidrIp":"0.0.0.0/0","description":"Allow all outbound traffic by default","ipProtocol":"-1"}],"vpcId":{"Ref":"vpcA2121C38"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSecurityGroup","version":"0.0.0"}},"from {IndirectPeer}:UDP 80":{"id":"from {IndirectPeer}:UDP 80","path":"integ-ec2-prefix-list-test/sg/from {IndirectPeer}:UDP 80","attributes":{"aws:cdk:cloudformation:type":"AWS::EC2::SecurityGroupIngress","aws:cdk:cloudformation:props":{"description":{"Fn::Join":["",["from ",{"Fn::GetAtt":["PrefixList469FCC0B","PrefixListId"]},":UDP 80"]]},"fromPort":80,"groupId":{"Fn::GetAtt":["sg29196201","GroupId"]},"ipProtocol":"udp","sourcePrefixListId":{"Fn::GetAtt":["PrefixList469FCC0B","PrefixListId"]},"toPort":80}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.CfnSecurityGroupIngress","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.aws_ec2.SecurityGroup","version":"0.0.0","metadata":[{"vpc":"*"},{"addIngressRule":[{"canInlineRule":false,"uniqueId":"*","connections":"*"},{},"*",false]}]}},"BootstrapVersion":{"id":"BootstrapVersion","path":"integ-ec2-prefix-list-test/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"integ-ec2-prefix-list-test/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"}},"integ-test":{"id":"integ-test","path":"integ-test","children":{"DefaultTest":{"id":"DefaultTest","path":"integ-test/DefaultTest","children":{"Default":{"id":"Default","path":"integ-test/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"integ-test/DefaultTest/DeployAssert","children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"integ-test/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}},"constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"}}},"constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"}}},"constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}},"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.prefix-list.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.ts index a4b24d571241f..29eb82af729e9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.prefix-list.ts @@ -10,12 +10,18 @@ import { Construct } from 'constructs'; export class TestCase extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); - new ec2.PrefixList(this, 'PrefixList', { + const prefixList = new ec2.PrefixList(this, 'PrefixList', { entries: [ { cidr: '10.0.0.1/32' }, { cidr: '10.0.0.2/32', description: 'sample1' }, ], }); + const vpc = new ec2.Vpc(this, 'vpc', { + natGateways: 0, + maxAzs: 1, + }); + const sg = new ec2.SecurityGroup(this, 'sg', { vpc }); + sg.connections.allowFrom(prefixList, ec2.Port.udp(80)); } } diff --git a/packages/aws-cdk-lib/aws-ec2/README.md b/packages/aws-cdk-lib/aws-ec2/README.md index 923024a630393..e290e5430f842 100644 --- a/packages/aws-cdk-lib/aws-ec2/README.md +++ b/packages/aws-cdk-lib/aws-ec2/README.md @@ -2485,9 +2485,14 @@ Create and manage customer-managed prefix lists. If you don't specify anything i You can also create an empty Prefix List with only the maximum number of entries specified, as shown in the following code. If nothing is specified, maxEntries=1. ```ts -new ec2.PrefixList(this, 'EmptyPrefixList', { +declare const sg: ec2.SecurityGroup; + +const prefixList = new ec2.PrefixList(this, 'EmptyPrefixList', { maxEntries: 100, }); + +// Attach to Security Group +sg.connections.allowFrom(prefixList, Port.tcp(443)); ``` `maxEntries` can also be omitted as follows. In this case `maxEntries: 2`, will be set. diff --git a/packages/aws-cdk-lib/aws-ec2/lib/prefix-list.ts b/packages/aws-cdk-lib/aws-ec2/lib/prefix-list.ts index 6e7628493d349..081df525aa584 100644 --- a/packages/aws-cdk-lib/aws-ec2/lib/prefix-list.ts +++ b/packages/aws-cdk-lib/aws-ec2/lib/prefix-list.ts @@ -1,12 +1,14 @@ import { Construct } from 'constructs'; +import { IConnectable, Connections } from './connections'; import { CfnPrefixList } from './ec2.generated'; -import { IResource, Lazy, Resource, Names } from '../../core'; +import { IPeer } from './peer'; +import { IResource, Lazy, Resource, Names, Token } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; /** * A prefix list */ -export interface IPrefixList extends IResource { +export interface IPrefixList extends IResource, IConnectable { /** * The ID of the prefix list * @@ -64,6 +66,28 @@ export interface PrefixListProps extends PrefixListOptions { readonly entries?: CfnPrefixList.EntryProperty[]; } +/** + * A prefix list peer for security group rules + */ +class PrefixListPeer implements IPeer { + public readonly canInlineRule = false; + public readonly uniqueId: string; + public readonly connections: Connections; + + constructor(private readonly prefixListId: string) { + this.uniqueId = Token.isUnresolved(prefixListId) ? prefixListId : `pl-${prefixListId}`; + this.connections = new Connections({ peer: this }); + } + + public toIngressRuleConfig(): any { + return { sourcePrefixListId: this.prefixListId }; + } + + public toEgressRuleConfig(): any { + return { destinationPrefixListId: this.prefixListId }; + } +} + /** * The base class for a prefix list */ @@ -74,6 +98,20 @@ abstract class PrefixListBase extends Resource implements IPrefixList { * @attribute */ public abstract readonly prefixListId: string; + + /** + * The network connections associated with this prefix list. + */ + public readonly connections: Connections; + + constructor(scope: Construct, id: string, props: { physicalName?: string } = {}) { + super(scope, id, props); + + // Create connections using a lazy peer that will be created once the prefix list ID is available + this.connections = new Connections({ + peer: new PrefixListPeer(Lazy.string({ produce: () => this.prefixListId })), + }); + } } /** @@ -86,7 +124,7 @@ export class PrefixList extends PrefixListBase { * */ public static fromPrefixListId(scope: Construct, id: string, prefixListId: string): IPrefixList { - class Import extends Resource implements IPrefixList { + class Import extends PrefixListBase { public readonly prefixListId = prefixListId; } return new Import(scope, id); diff --git a/packages/aws-cdk-lib/aws-ec2/test/prefix-list.test.ts b/packages/aws-cdk-lib/aws-ec2/test/prefix-list.test.ts index 209f6cb665e02..012a07da008a0 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/prefix-list.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/prefix-list.test.ts @@ -1,6 +1,9 @@ import { Template } from '../../assertions'; import { Stack } from '../../core'; +import { Port } from '../lib/port'; import { AddressFamily, PrefixList } from '../lib/prefix-list'; +import { SecurityGroup } from '../lib/security-group'; +import { Vpc } from '../lib/vpc'; describe('prefix list', () => { test('default empty prefixlist', () => { @@ -53,6 +56,25 @@ describe('prefix list', () => { }); }); + test('security group with prefix list', () => { + const stack = new Stack(); + + const prefixList = new PrefixList(stack, 'prefix-list', { + maxEntries: 100, + entries: [ + { cidr: '10.0.0.1/32' }, + ], + }); + + const vpc = new Vpc(stack, 'vpc', {}); + const sg = new SecurityGroup(stack, 'SecurityGroup', { vpc }); + + sg.connections.allowFrom(prefixList, Port.tcp(443)); + sg.connections.allowTo(prefixList, Port.tcp(443)); + + // THEN -- no crash + }); + test('invalid prefixlist name startwith amazon', () => { // GIVEN const stack = new Stack();