From 610875b9de22c141e0b2b18ce2030fb5b3b07559 Mon Sep 17 00:00:00 2001 From: shikha372 Date: Tue, 14 Jan 2025 14:22:44 -0800 Subject: [PATCH] feat(VpcV2): add BYOIP IPv6 to VPCv2 --- packages/@aws-cdk/aws-ec2-alpha/README.md | 32 ++ .../@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts | 2 +- packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 75 +++- .../@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts | 2 +- packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts | 98 ++++- .../test/integ.byoip-ipv6.js.snapshot/cdk.out | 1 + .../integ.byoip-ipv6.js.snapshot/integ.json | 12 + ...efaultTestDeployAssertCF40BD53.assets.json | 19 + ...aultTestDeployAssertCF40BD53.template.json | 36 ++ .../manifest.json | 155 ++++++++ .../integ.byoip-ipv6.js.snapshot/tree.json | 361 ++++++++++++++++++ .../vpc-byoip-ipv6.assets.json | 19 + .../vpc-byoip-ipv6.template.json | 176 +++++++++ .../aws-ec2-alpha/test/integ.byoip-ipv6.ts | 55 +++ .../aws-ec2-alpha/test/subnet-v2.test.ts | 21 + .../@aws-cdk/aws-ec2-alpha/test/util.test.ts | 12 +- .../aws-ec2-alpha/test/vpc-v2.test.ts | 50 ++- 17 files changed, 1100 insertions(+), 26 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index a01295ac1da67..8544358635719 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -105,6 +105,38 @@ new VpcV2(this, 'Vpc', { Since `VpcV2` does not create subnets automatically, users have full control over IP addresses allocation across subnets. +### Bring your own IPv6 addresses (BYOIP) + +If you have your own IP address that you would like to use with EC2, you can set up an IPv6 pool via the AWS CLI, and use that pool ID in your application. + +Once you have certified your IP address block with an ROA and have an X-509 certificate, you can run the following command to provision your CIDR block in AWS account: + +```shell +aws ec2 provision-byoip-cidr --region --cidr --cidr-authorization-context Message="1|aws||||SHA256".Signature="" +``` + +When your BYOIP CIDR is provisioned, you can run the following command to retrieve your IPv6 pool ID, which will be used in your VPC declaration: + +```shell +aws ec2 describe-byoip-cidr --region +``` + +For more help on setting up your IPv6 address, please review the [EC2 Documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-byoip.html). + +Once you have provisioned your address block, you can use the IPv6 in your VPC as follows: + +```ts +const myVpc = new VpcV2(this, 'Vpc', { + primaryAddressBlock: IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [IpAddresses.ipv6ByoipPool({ + cidrBlockName: 'MyByoipCidrBlock', + ipv6PoolId: 'ipv6pool-ec2-someHashValue', + ipv6CidrBlock: '2001:db8::/32' + })], + enableDnsHostnames: true, + enableDnsSupport: true, +}); +``` ## Routing diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts index ad144439ce2c3..434c1de066273 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/subnet-v2.ts @@ -455,7 +455,7 @@ function storeSubnetToVpcByType(vpc: IVpcV2, subnet: SubnetV2, type: SubnetType) function validateSupportIpv6(vpc: IVpcV2) { if (vpc.secondaryCidrBlock) { if (vpc.secondaryCidrBlock.some((secondaryAddress) => secondaryAddress.amazonProvidedIpv6CidrBlock === true || - secondaryAddress.ipv6IpamPoolId != undefined)) { + secondaryAddress.ipv6IpamPoolId !== undefined || secondaryAddress.ipv6Pool !== undefined)) { return true; } else { throw new Error('To use IPv6, the VPC must enable IPv6 support.'); diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts index 7566ce711e0c4..bb9377b6dc86f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -323,13 +323,54 @@ export class CidrBlockIpv6 { } /** - * @returns Maximum IPv6 address for a provided CIDR + * Calculates the maximum IPv6 address in the CIDR block + * @returns The maximum IPv6 address as a string */ public maxIp(): string { + /** + * Calculate how many 16-bit blocks are needed for the network portion + * e.g. for /56, networkPartLength = ceil(56/16) = 4 blocks + */ + const networkPartLength = Math.ceil(this.cidrPrefix / 16); + /** + * Calculate remaining bits in last network block + * e.g. for /56, remainingBits = 56 % 16 = 8 bits + */ + const remainingBits = this.cidrPrefix % 16; + /** + * Create copy of network portion of address + * e.g. [2001, db8, 0, 0] for 2001:db8::/56 + */ const endIP = [...this.networkPart]; - const hostPart = Array(8 - this.networkPart.length).fill(BigInt(0xffff)); - endIP.push(...hostPart); + /** + * If there are remaining bits in last network block, + * create appropriate bitmask and apply to last network block + * e.g. for /56: mask = (1 << (16-8)) - 1 = 0x00FF + */ + if (remainingBits > 0) { + const lastNetworkIndex = networkPartLength - 1; + const mask = (BigInt(1) << BigInt(16 - remainingBits)) - BigInt(1); + /** + * Apply bitmask to last network block using bitwise OR + * e.g. if lastNetworkIndex=3 and mask=0x00FF: + * networkPart[3]=0x0000 | 0x00FF = 0x00FF + */ + endIP[lastNetworkIndex] = this.networkPart[lastNetworkIndex] | mask; + } + + /** + * Fill remaining blocks with maximum value 0xFFFF + * e.g. [2001, db8, 0, ff, ffff, ffff, ffff, ffff] + */ + for (let i = networkPartLength; i < 8; i++) { + endIP.push(BigInt('0xffff')); + } + + /** + * Convert blocks to hex strings and join with colons + * e.g. 2001:db8:0:ff:ffff:ffff:ffff:ffff + */ return endIP.map(this.formatIPv6Part).join(':'); } @@ -342,26 +383,18 @@ export class CidrBlockIpv6 { * @returns true if two ranges overlap, false otherwise */ public rangesOverlap(range1: string, range2: string): boolean { - const [start1, end1] = this.getIPv6Range(range1); - const [start2, end2] = this.getIPv6Range(range2); + // Create new CidrBlockIpv6 instances for both ranges + const cidr1 = new CidrBlockIpv6(range1); + const cidr2 = new CidrBlockIpv6(range2); - return (start1 <= end2) && (start2 <= end1); - } + // Convert min and max IPs to numeric values for comparison + const start1 = this.ipv6ToNumber(cidr1.minIp()); + const end1 = this.ipv6ToNumber(cidr1.maxIp()); + const start2 = this.ipv6ToNumber(cidr2.minIp()); + const end2 = this.ipv6ToNumber(cidr2.maxIp()); - /** - * - * @param cidr - * @returns Range in the from of big int number [start, end] - */ - private getIPv6Range(cidr: string): [bigint, bigint] { - const [ipv6Address, prefixLength] = cidr.split('/'); - const ipv6Number = this.ipv6ToNumber(ipv6Address); - const mask = (BigInt(1) << BigInt(128 - Number(prefixLength))) - BigInt(1); - const networkPrefix = ipv6Number & ~mask; - const start = networkPrefix; - const end = networkPrefix | mask; - - return [start, end]; + // Check for overlap + return (start1 <= end2) && (start2 <= end1); } /** diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts index 32b2bceec2720..3fc1daa26d115 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2-base.ts @@ -430,7 +430,7 @@ export abstract class VpcV2Base extends Resource implements IVpcV2 { let useIpv6; if (this.secondaryCidrBlock) { useIpv6 = (this.secondaryCidrBlock.some((secondaryAddress) => secondaryAddress.amazonProvidedIpv6CidrBlock === true || - secondaryAddress.ipv6IpamPoolId != undefined)); + secondaryAddress.ipv6IpamPoolId !== undefined || secondaryAddress.ipv6CidrBlock !== undefined)); } if (!useIpv6) { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts index ea493343f8802..381eb190b9e8f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/vpc-v2.ts @@ -17,6 +17,27 @@ export interface SecondaryAddressProps { readonly cidrBlockName: string; } +/** + * Additional props needed for BYOIP IPv6 address props + */ +export interface Ipv6PoolSecondaryAddressProps extends SecondaryAddressProps { + /** + * ID of the IPv6 address pool from which to allocate the IPv6 CIDR block + * Note: BYOIP Pool ID is different than the pool ID of IPAM. + * To onboard your IPv6 address range to AWS account please refer to below documentation + * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/byoip-onboard.html + */ + readonly ipv6PoolId: string; + + /** + * An valid IPv6 CIDR block from the IPv6 address pool onboarded to AWS using BYOIP. + * The most specific IPv6 address range that you can bring is /48 for CIDRs that are publicly advertisable + * and /56 for CIDRs that are not publicly advertisable. + * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-byoip.html#byoip-definitions + */ + readonly ipv6CidrBlock: string; +} + /** * IpAddress options to define VPC V2 */ @@ -49,6 +70,13 @@ export class IpAddresses { public static amazonProvidedIpv6(props: SecondaryAddressProps) : IIpAddresses { return new AmazonProvided(props); } + + /** + * A BYOIP IPv6 address pool + */ + public static ipv6ByoipPool(props: Ipv6PoolSecondaryAddressProps): IIpAddresses { + return new Ipv6Pool(props); + } } /** @@ -121,6 +149,20 @@ export interface VpcCidrOptions { * @default - no IPAM IPv4 CIDR range is provisioned using IPAM */ readonly ipv4IpamProvisionedCidrs?: string[]; + + /** + * IPv6 CIDR block from the BOYIP IPv6 address pool. + * + * @default - None + */ + readonly ipv6CidrBlock?: string; + + /** + * ID of the BYOIP IPv6 address pool from which to allocate the IPv6 CIDR block + * + * @default - None + */ + readonly ipv6PoolId?: string; } /** @@ -499,7 +541,7 @@ export class VpcV2 extends VpcV2Base { throw new Error('Cidr Block Name is required to create secondary IP address'); } - if (secondaryVpcOptions.amazonProvided || secondaryVpcOptions.ipv6IpamPool) { + if (secondaryVpcOptions.amazonProvided || secondaryVpcOptions.ipv6IpamPool || secondaryVpcOptions.ipv6PoolId) { this.useIpv6 = true; } //validate CIDR ranges per RFC 1918 @@ -520,6 +562,10 @@ export class VpcV2 extends VpcV2Base { ipv6NetmaskLength: secondaryVpcOptions.ipv6NetmaskLength, ipv6IpamPoolId: secondaryVpcOptions.ipv6IpamPool?.ipamPoolId, amazonProvidedIpv6CidrBlock: secondaryVpcOptions.amazonProvided, + //BYOIP IPv6 Address + ipv6CidrBlock: secondaryVpcOptions?.ipv6CidrBlock, + //BYOIP Pool for IPv6 address + ipv6Pool: secondaryVpcOptions?.ipv6PoolId, }); if (secondaryVpcOptions.dependencies) { for (const dep of secondaryVpcOptions.dependencies) { @@ -633,6 +679,22 @@ class IpamIpv4 implements IIpAddresses { } } +/** + * Supports assigning IPv6 address to VPC in an address pool + */ +class Ipv6Pool implements IIpAddresses { + + constructor(private readonly props: Ipv6PoolSecondaryAddressProps) { + } + allocateVpcCidr(): VpcCidrOptions { + return { + ipv6CidrBlock: this.props.ipv6CidrBlock, + ipv6PoolId: this.props.ipv6PoolId, + cidrBlockName: this.props?.cidrBlockName, + }; + } +} + /** * Interface to create L2 for VPC Cidr Block */ @@ -658,6 +720,16 @@ export interface IVPCCidrBlock { * IPAM pool for IPv4 address type */ readonly ipv4IpamPoolId ?: string; + + /** + * The IPv6 CIDR block from the specified IPv6 address pool. + */ + readonly ipv6CidrBlock?: string; + + /** + * The ID of the IPv6 address pool from which to allocate the IPv6 CIDR block. + */ + readonly ipv6Pool?: string; } /** @@ -721,6 +793,20 @@ export interface VPCCidrBlockattributes { * @default - no IPAM IPv4 CIDR range is provisioned using IPAM */ readonly ipv4IpamProvisionedCidrs?: string[]; + + /** + * The IPv6 CIDR block from the specified IPv6 address pool. + * + * @default - No IPv6 CIDR block associated with VPC. + */ + readonly ipv6CidrBlock?: string; + + /** + * The ID of the IPv6 address pool from which to allocate the IPv6 CIDR block. + * Note: BYOIP Pool ID is different than IPAM Pool ID. + * @default - No BYOIP pool associated with VPC. + */ + readonly ipv6Pool?: string; } /** @@ -748,6 +834,9 @@ class VPCCidrBlock extends Resource implements IVPCCidrBlock { public readonly amazonProvidedIpv6CidrBlock ?: boolean = props.amazonProvidedIpv6CidrBlock; public readonly ipv6IpamPoolId ?: string = props.ipv6IpamPoolId; public readonly ipv4IpamPoolId ?: string = props.ipv4IpamPoolId; + //BYOIP Pool Attributes + public readonly ipv6Pool?: string = props.ipv6Pool; + public readonly ipv6CidrBlock?: string = props.ipv6CidrBlock; } return new Import(scope, id); } @@ -762,6 +851,10 @@ class VPCCidrBlock extends Resource implements IVPCCidrBlock { public readonly ipv4IpamPoolId?: string; + public readonly ipv6CidrBlock?: string; + + public readonly ipv6Pool?: string; + constructor(scope: Construct, id: string, props: VPCCidrBlockProps) { super(scope, id); this.resource = new CfnVPCCidrBlock(this, id, props); @@ -770,6 +863,9 @@ class VPCCidrBlock extends Resource implements IVPCCidrBlock { this.ipv6IpamPoolId = props.ipv6IpamPoolId; this.ipv4IpamPoolId = props.ipv4IpamPoolId; this.amazonProvidedIpv6CidrBlock = props.amazonProvidedIpv6CidrBlock; + //BYOIP Pool and CIDR Block + this.ipv6CidrBlock = props.ipv6CidrBlock; + this.ipv6Pool = props.ipv6Pool; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/cdk.out new file mode 100644 index 0000000000000..91e1a8b9901d5 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"39.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integ.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integ.json new file mode 100644 index 0000000000000..1953228ca8e7a --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "39.0.0", + "testCases": { + "integtest-model/DefaultTest": { + "stacks": [ + "vpc-byoip-ipv6" + ], + "assertionStack": "integtest-model/DefaultTest/DeployAssert", + "assertionStackName": "integtestmodelDefaultTestDeployAssertCF40BD53" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json new file mode 100644 index 0000000000000..928ed61bb88d0 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json @@ -0,0 +1,19 @@ +{ + "version": "39.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodelDefaultTestDeployAssertCF40BD53.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/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.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/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/manifest.json new file mode 100644 index 0000000000000..cbc7813bcae89 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/manifest.json @@ -0,0 +1,155 @@ +{ + "version": "39.0.0", + "artifacts": { + "vpc-byoip-ipv6.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "vpc-byoip-ipv6.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "vpc-byoip-ipv6": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "vpc-byoip-ipv6.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}/2ac973cd3fa2ed1a3934fbe78ee77203b26df0366d34997e96d1570af96f2614.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "vpc-byoip-ipv6.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": [ + "vpc-byoip-ipv6.assets" + ], + "metadata": { + "/vpc-byoip-ipv6/VPC-integ-test-1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1EBA1CB75" + } + ], + "/vpc-byoip-ipv6/VPC-integ-test-1/MyByoipIpv6Block/MyByoipIpv6Block": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCintegtest1MyByoipIpv6BlockC474849A" + } + ], + "/vpc-byoip-ipv6/Subnet-integ-test-1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "Subnetintegtest1Subnet33DEE36B" + } + ], + "/vpc-byoip-ipv6/Subnet-integ-test-1/RouteTable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "Subnetintegtest1RouteTableD7246BB7" + } + ], + "/vpc-byoip-ipv6/Subnet-integ-test-1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "Subnetintegtest1RouteTableAssociation25E3C72D" + } + ], + "/vpc-byoip-ipv6/Subnet-integ-test-2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "Subnetintegtest2Subnet5A56D422" + } + ], + "/vpc-byoip-ipv6/Subnet-integ-test-2/RouteTable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "Subnetintegtest2RouteTable2528D856" + } + ], + "/vpc-byoip-ipv6/Subnet-integ-test-2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "Subnetintegtest2RouteTableAssociation9569A2C6" + } + ], + "/vpc-byoip-ipv6/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/vpc-byoip-ipv6/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "vpc-byoip-ipv6" + }, + "integtestmodelDefaultTestDeployAssertCF40BD53.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodelDefaultTestDeployAssertCF40BD53.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodelDefaultTestDeployAssertCF40BD53": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodelDefaultTestDeployAssertCF40BD53.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": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.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": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.assets" + ], + "metadata": { + "/integtest-model/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/tree.json new file mode 100644 index 0000000000000..47b5abdeda2b3 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/tree.json @@ -0,0 +1,361 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "vpc-byoip-ipv6": { + "id": "vpc-byoip-ipv6", + "path": "vpc-byoip-ipv6", + "children": { + "VPC-integ-test-1": { + "id": "VPC-integ-test-1", + "path": "vpc-byoip-ipv6/VPC-integ-test-1", + "children": { + "Resource": { + "id": "Resource", + "path": "vpc-byoip-ipv6/VPC-integ-test-1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.1.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "vpc-byoip-ipv6/VPC-integ-test-1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "MyByoipIpv6Block": { + "id": "MyByoipIpv6Block", + "path": "vpc-byoip-ipv6/VPC-integ-test-1/MyByoipIpv6Block", + "children": { + "MyByoipIpv6Block": { + "id": "MyByoipIpv6Block", + "path": "vpc-byoip-ipv6/VPC-integ-test-1/MyByoipIpv6Block/MyByoipIpv6Block", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "ipv6CidrBlock": "2600:f0f0:8::/56", + "ipv6Pool": "ipv6pool-ec2-0a95217e154b65493", + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "Subnet-integ-test-1": { + "id": "Subnet-integ-test-1", + "path": "vpc-byoip-ipv6/Subnet-integ-test-1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "vpc-byoip-ipv6/Subnet-integ-test-1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-2a", + "cidrBlock": "10.1.1.0/24", + "ipv6CidrBlock": "2600:f0f0:8:1::/64", + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "vpc-byoip-ipv6/Subnet-integ-test-1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "vpc-byoip-ipv6/Subnet-integ-test-1/RouteTable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "vpc-byoip-ipv6/Subnet-integ-test-1/RouteTable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "DefaultCDKRouteTable" + } + ], + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "vpc-byoip-ipv6/Subnet-integ-test-1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "Subnetintegtest1RouteTableD7246BB7", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "Subnetintegtest1Subnet33DEE36B" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "Subnet-integ-test-2": { + "id": "Subnet-integ-test-2", + "path": "vpc-byoip-ipv6/Subnet-integ-test-2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "vpc-byoip-ipv6/Subnet-integ-test-2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-west-2a", + "cidrBlock": "10.1.0.0/24", + "ipv6CidrBlock": "2600:f0f0:8:0::/64", + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "vpc-byoip-ipv6/Subnet-integ-test-2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "vpc-byoip-ipv6/Subnet-integ-test-2/RouteTable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "vpc-byoip-ipv6/Subnet-integ-test-2/RouteTable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "DefaultCDKRouteTable" + } + ], + "vpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "vpc-byoip-ipv6/Subnet-integ-test-2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "Subnetintegtest2RouteTable2528D856", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "Subnetintegtest2Subnet5A56D422" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "vpc-byoip-ipv6/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "vpc-byoip-ipv6/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integtest-model": { + "id": "integtest-model", + "path": "integtest-model", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model/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/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.assets.json new file mode 100644 index 0000000000000..b1aceb6a1dfef --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.assets.json @@ -0,0 +1,19 @@ +{ + "version": "39.0.0", + "files": { + "2ac973cd3fa2ed1a3934fbe78ee77203b26df0366d34997e96d1570af96f2614": { + "source": { + "path": "vpc-byoip-ipv6.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "2ac973cd3fa2ed1a3934fbe78ee77203b26df0366d34997e96d1570af96f2614.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/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.template.json new file mode 100644 index 0000000000000..83856929ba1d8 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.js.snapshot/vpc-byoip-ipv6.template.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "VPCintegtest1EBA1CB75": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.1.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "vpc-byoip-ipv6/VPC-integ-test-1" + } + ] + } + }, + "VPCintegtest1MyByoipIpv6BlockC474849A": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "Ipv6CidrBlock": "2600:f0f0:8::/56", + "Ipv6Pool": "ipv6pool-ec2-0a95217e154b65493", + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + } + }, + "Subnetintegtest1Subnet33DEE36B": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-2a", + "CidrBlock": "10.1.1.0/24", + "Ipv6CidrBlock": "2600:f0f0:8:1::/64", + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + }, + "DependsOn": [ + "VPCintegtest1MyByoipIpv6BlockC474849A" + ] + }, + "Subnetintegtest1RouteTableD7246BB7": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "DefaultCDKRouteTable" + } + ], + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + }, + "DependsOn": [ + "VPCintegtest1MyByoipIpv6BlockC474849A" + ] + }, + "Subnetintegtest1RouteTableAssociation25E3C72D": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "Subnetintegtest1RouteTableD7246BB7", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "Subnetintegtest1Subnet33DEE36B" + } + }, + "DependsOn": [ + "VPCintegtest1MyByoipIpv6BlockC474849A" + ] + }, + "Subnetintegtest2Subnet5A56D422": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-2a", + "CidrBlock": "10.1.0.0/24", + "Ipv6CidrBlock": "2600:f0f0:8:0::/64", + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + }, + "DependsOn": [ + "VPCintegtest1MyByoipIpv6BlockC474849A" + ] + }, + "Subnetintegtest2RouteTable2528D856": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "DefaultCDKRouteTable" + } + ], + "VpcId": { + "Fn::GetAtt": [ + "VPCintegtest1EBA1CB75", + "VpcId" + ] + } + }, + "DependsOn": [ + "VPCintegtest1MyByoipIpv6BlockC474849A" + ] + }, + "Subnetintegtest2RouteTableAssociation9569A2C6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "Subnetintegtest2RouteTable2528D856", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "Subnetintegtest2Subnet5A56D422" + } + }, + "DependsOn": [ + "VPCintegtest1MyByoipIpv6BlockC474849A" + ] + } + }, + "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/aws-ec2-alpha/test/integ.byoip-ipv6.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.ts new file mode 100644 index 0000000000000..03338ef5ee674 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.byoip-ipv6.ts @@ -0,0 +1,55 @@ +/* + * This integration test deploys a VPC that contains a BYOIP IPv6 address. + * The address is owned by the CDK maintainers, who are able to run and + * update the test if need be for future changes. + * + * Notes on how to run this integ test + * Replace the ipv6PoolId and ipv6CidrBlock for VPC with the one that is owned by your account. + */ + +import * as vpc_v2 from '../lib/vpc-v2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { IpCidr, SubnetV2 } from '../lib'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'vpc-byoip-ipv6'); + +const myVpc = new vpc_v2.VpcV2(stack, 'VPC-integ-test-1', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [ + vpc_v2.IpAddresses.ipv6ByoipPool({ + ipv6PoolId: 'ipv6pool-ec2-0a95217e154b65493', //To Be Replaced + cidrBlockName: 'MyByoipIpv6Block', + ipv6CidrBlock: '2600:f0f0:8::/56', //To Be Replaced + }), + ], + enableDnsHostnames: true, + enableDnsSupport: true, +}); + +new SubnetV2(stack, 'Subnet-integ-test-1', { + vpc: myVpc, + ipv4CidrBlock: new IpCidr('10.1.1.0/24'), + ipv6CidrBlock: new IpCidr('2600:f0f0:8:1::/64'), //To Be Replaced + availabilityZone: 'us-west-2a', + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +/** + * Check for non-ovelapping subnet range + */ +new SubnetV2(stack, 'Subnet-integ-test-2', { + vpc: myVpc, + ipv4CidrBlock: new IpCidr('10.1.0.0/24'), + ipv6CidrBlock: new IpCidr('2600:f0f0:8:0::/64'), //To Be Replaced + availabilityZone: 'us-west-2a', + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +new IntegTest(app, 'integtest-model', { + testCases: [stack], +}); + diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts index b43f9be207f74..a78c1c3806a1a 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/subnet-v2.test.ts @@ -221,6 +221,27 @@ describe('Subnet V2 with custom IP and routing', () => { }); }); + test('Create Subnet with IPv6 if VPC has IPv6 CIDR block enabled', () => { + const TestVPC = new vpc.VpcV2(stack, 'TestVPC', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv6ByoipPool( + { + ipv6PoolId: 'test-byoip-pool', + ipv6CidrBlock: '2001:db8:1::/56', + cidrBlockName: 'secondaryIpv6Pool', + }, + )], + }); + + new subnet.SubnetV2(stack, 'IpamSubnet', { + vpc: TestVPC, + ipv4CidrBlock: new subnet.IpCidr('10.1.0.0/24'), + ipv6CidrBlock: new subnet.IpCidr('2001:db8:1::/64'), + availabilityZone: 'us-east-1a', + subnetType: SubnetType.PUBLIC, + }); + }); + test('Should throw error if overlapping CIDR block(IPv6) for the subnet', () => { const ipam = new Ipam(stack, 'TestIpam', { operatingRegion: ['us-west-1'], diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/util.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/util.test.ts index 2d5f1890674f4..56764458f3044 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/util.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/util.test.ts @@ -1,4 +1,4 @@ -import { CidrBlock } from '../lib/util'; +import { CidrBlock, CidrBlockIpv6 } from '../lib/util'; describe('Tests for the CidrBlock.rangesOverlap method to check if IPv4 ranges overlap', () =>{ test('Should return false for non-overlapping IP ranges', () => { @@ -35,4 +35,14 @@ describe('Tests for the CidrBlock.rangesOverlap method to check if IPv4 ranges o const range2 = ['10.0.16.0', '10.0.19.255'] as [string, string]; expect(testCidr.rangesOverlap(range1, range2)).toBe(false); }); + + test('Should return false for non-overlapping IPv6 ranges with prefix', () => { + const testCidr = new CidrBlockIpv6('2001:db8::/32'); + expect(testCidr.rangesOverlap('2001:db8:8::/56', '2001:db8:9::/56')).toBe(false); + }); + + test('Should return true for overlapping IPv6 ranges with prefix', () => { + const testCidr = new CidrBlockIpv6('2001:db8::/32'); + expect(testCidr.rangesOverlap('2001:db8::1/64', '2001:db8::1/60')).toBe(true); + }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts index 6c3087ce42a77..beb8fcda41c79 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/vpc-v2.test.ts @@ -256,5 +256,53 @@ describe('Vpc V2 with full control', () => { }, }); }); -}); + test('VPC with secondary IPv6 Pool address', () => { + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv6ByoipPool({ + cidrBlockName: 'SecondaryIPv6', + ipv6PoolId: 'SecondaryIPv6Pool', + ipv6CidrBlock: '2001:db8::/32', + })], + enableDnsHostnames: true, + enableDnsSupport: true, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCCidrBlock', { + VpcId: { + 'Fn::GetAtt': [ + 'TestVpcE77CE678', + 'VpcId', + ], + }, + Ipv6CidrBlock: '2001:db8::/32', + Ipv6Pool: 'SecondaryIPv6Pool', + }); + }); + + test('VPC with multiple IPv6 Pool addresses', () => { + // WHEN + new vpc.VpcV2(stack, 'TestVpc', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [ + vpc.IpAddresses.ipv6ByoipPool({ + cidrBlockName: 'SecondaryIPv6One', + ipv6PoolId: 'Pool1', + ipv6CidrBlock: '2001:db8:1::/48', + }), + vpc.IpAddresses.ipv6ByoipPool({ + cidrBlockName: 'SecondaryIPv6Two', + ipv6PoolId: 'Pool2', + ipv6CidrBlock: '2001:db8:2::/48', + }), + ], + enableDnsHostnames: true, + enableDnsSupport: true, + }); + + // THEN + const template = Template.fromStack(stack); + template.resourceCountIs('AWS::EC2::VPCCidrBlock', 2); + }); +});