Skip to content

Commit b01d66b

Browse files
committed
feat(ec2): add support for IPAM CIDR allocation in Subnet configuration
1 parent aae5274 commit b01d66b

File tree

3 files changed

+456
-4
lines changed

3 files changed

+456
-4
lines changed

packages/aws-cdk-lib/aws-ec2/README.md

+63
Original file line numberDiff line numberDiff line change
@@ -2603,3 +2603,66 @@ new ec2.Instance(this, 'Instance', {
26032603
instanceProfile,
26042604
});
26052605
```
2606+
2607+
### Using IPAM for Subnet CIDR Allocation
2608+
2609+
Instead of specifying a CIDR block directly, you can allocate a CIDR from an [IPAM pool](https://docs.aws.amazon.com/vpc/latest/ipam/what-it-is-ipam.html) for your subnet. This allows for more flexible and managed IP address allocation.
2610+
2611+
For IPv4, use the `ipv4IpamAllocation` property:
2612+
2613+
```ts
2614+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
2615+
2616+
const vpc = new ec2.Vpc(this, 'Vpc');
2617+
2618+
// Create a subnet with IPv4 CIDR allocated from an IPAM pool
2619+
new ec2.Subnet(this, 'Subnet', {
2620+
vpcId: vpc.vpcId,
2621+
availabilityZone: 'us-east-1a',
2622+
ipv4IpamAllocation: {
2623+
ipamPoolId: 'ipam-pool-12345',
2624+
netmaskLength: 24, // Optional: if not specified, uses the default netmask length from the IPAM pool
2625+
},
2626+
});
2627+
```
2628+
2629+
For IPv6, use the `ipv6IpamAllocation` property:
2630+
2631+
```ts
2632+
// Create a subnet with IPv6 CIDR allocated from an IPAM pool
2633+
new ec2.Subnet(this, 'Subnet', {
2634+
vpcId: vpc.vpcId,
2635+
availabilityZone: 'us-east-1a',
2636+
cidrBlock: '10.0.0.0/24', // IPv4 CIDR is required
2637+
ipv6IpamAllocation: {
2638+
ipamPoolId: 'ipam-pool-67890',
2639+
netmaskLength: 64, // Optional: if not specified, uses the default netmask length from the IPAM pool
2640+
},
2641+
assignIpv6AddressOnCreation: true,
2642+
});
2643+
```
2644+
2645+
You can also use both IPv4 and IPv6 IPAM allocations together:
2646+
2647+
```ts
2648+
// Create a subnet with both IPv4 and IPv6 CIDR allocated from IPAM pools
2649+
new ec2.Subnet(this, 'Subnet', {
2650+
vpcId: vpc.vpcId,
2651+
availabilityZone: 'us-east-1a',
2652+
ipv4IpamAllocation: {
2653+
ipamPoolId: 'ipam-pool-12345',
2654+
// netmaskLength is optional and will use the IPAM pool's default if not specified
2655+
},
2656+
ipv6IpamAllocation: {
2657+
ipamPoolId: 'ipam-pool-67890',
2658+
// netmaskLength is optional and will use the IPAM pool's default if not specified
2659+
},
2660+
assignIpv6AddressOnCreation: true,
2661+
});
2662+
```
2663+
2664+
Note that:
2665+
- You cannot specify both `cidrBlock` and `ipv4IpamAllocation` at the same time
2666+
- You cannot specify both `ipv6CidrBlock` and `ipv6IpamAllocation` at the same time
2667+
- If you specify `assignIpv6AddressOnCreation: true`, you must also specify either `ipv6CidrBlock` or `ipv6IpamAllocation`
2668+
- The `netmaskLength` property in both `ipv4IpamAllocation` and `ipv6IpamAllocation` is optional. If not specified, the default netmask length configured in the IPAM pool will be used.

packages/aws-cdk-lib/aws-ec2/lib/vpc.ts

+90-4
Original file line numberDiff line numberDiff line change
@@ -1962,7 +1962,45 @@ function subnetTypeTagValue(type: SubnetType) {
19621962
}
19631963

19641964
/**
1965-
* Specify configuration parameters for a VPC subnet
1965+
* IPv4 IPAM pool allocation configuration.
1966+
*/
1967+
export interface Ipv4IpamAllocation {
1968+
/**
1969+
* The ID of the IPv4 IPAM pool from which to allocate the CIDR.
1970+
*/
1971+
readonly ipamPoolId: string;
1972+
1973+
/**
1974+
* The netmask length of the IPv4 CIDR to allocate to the subnet.
1975+
*
1976+
* If not specified, the default netmask length configured for the IPAM pool will be used.
1977+
*
1978+
* @default - The default netmask length configured in the IPAM pool
1979+
*/
1980+
readonly netmaskLength?: number;
1981+
}
1982+
1983+
/**
1984+
* IPv6 IPAM pool allocation configuration.
1985+
*/
1986+
export interface Ipv6IpamAllocation {
1987+
/**
1988+
* The ID of the IPv6 IPAM pool from which to allocate the CIDR.
1989+
*/
1990+
readonly ipamPoolId: string;
1991+
1992+
/**
1993+
* The netmask length of the IPv6 CIDR to allocate to the subnet.
1994+
*
1995+
* If not specified, the default netmask length configured for the IPAM pool will be used.
1996+
*
1997+
* @default - The default netmask length configured in the IPAM pool
1998+
*/
1999+
readonly netmaskLength?: number;
2000+
}
2001+
2002+
/**
2003+
* Properties for defining a Subnet.
19662004
*/
19672005
export interface SubnetProps {
19682006

@@ -1978,8 +2016,11 @@ export interface SubnetProps {
19782016

19792017
/**
19802018
* The CIDR notation for this subnet
2019+
*
2020+
* Either `cidrBlock` or `ipv4IpamAllocation` must be specified, but not both.
2021+
* @default - No CIDR block is specified. Use ipv4IpamAllocation to specify IPv4 allocation.
19812022
*/
1982-
readonly cidrBlock: string;
2023+
readonly cidrBlock?: string;
19832024

19842025
/**
19852026
* Controls if a public IP is associated to an instance at launch
@@ -1993,18 +2034,42 @@ export interface SubnetProps {
19932034
*
19942035
* If you specify AssignIpv6AddressOnCreation, you must also specify Ipv6CidrBlock.
19952036
*
2037+
* Either `ipv6CidrBlock` or `ipv6IpamAllocation` must be specified, but not both.
2038+
*
19962039
* @default - no IPv6 CIDR block.
19972040
*/
19982041
readonly ipv6CidrBlock?: string;
19992042

20002043
/**
20012044
* Indicates whether a network interface created in this subnet receives an IPv6 address.
20022045
*
2003-
* If you specify AssignIpv6AddressOnCreation, you must also specify Ipv6CidrBlock.
2046+
* If you specify AssignIpv6AddressOnCreation, you must also specify Ipv6CidrBlock or ipv6IpamAllocation.
20042047
*
20052048
* @default false
20062049
*/
20072050
readonly assignIpv6AddressOnCreation?: boolean;
2051+
2052+
/**
2053+
* IPv4 IPAM pool allocation configuration.
2054+
*
2055+
* Use this property to allocate a CIDR from an IPv4 IPAM pool to this subnet.
2056+
*
2057+
* Either `cidrBlock` or `ipv4IpamAllocation` must be specified, but not both.
2058+
*
2059+
* @default - IPAM is not used for IPv4 address allocation
2060+
*/
2061+
readonly ipv4IpamAllocation?: Ipv4IpamAllocation;
2062+
2063+
/**
2064+
* IPv6 IPAM pool allocation configuration.
2065+
*
2066+
* Use this property to allocate a CIDR from an IPv6 IPAM pool to this subnet.
2067+
*
2068+
* Either `ipv6CidrBlock` or `ipv6IpamAllocation` must be specified, but not both.
2069+
*
2070+
* @default - IPAM is not used for IPv6 address allocation
2071+
*/
2072+
readonly ipv6IpamAllocation?: Ipv6IpamAllocation;
20082073
}
20092074

20102075
/**
@@ -2091,19 +2156,40 @@ export class Subnet extends Resource implements ISubnet {
20912156
// Enhanced CDK Analytics Telemetry
20922157
addConstructMetadata(this, props);
20932158

2159+
// Validate the properties
2160+
if (props.cidrBlock === undefined && props.ipv4IpamAllocation === undefined) {
2161+
throw new ValidationError('Either cidrBlock or ipv4IpamAllocation must be specified', this);
2162+
}
2163+
if (props.cidrBlock !== undefined && props.ipv4IpamAllocation !== undefined) {
2164+
throw new ValidationError('Cannot specify both cidrBlock and ipv4IpamAllocation', this);
2165+
}
2166+
if (props.ipv6CidrBlock !== undefined && props.ipv6IpamAllocation !== undefined) {
2167+
throw new ValidationError('Cannot specify both ipv6CidrBlock and ipv6IpamAllocation', this);
2168+
}
2169+
if (props.assignIpv6AddressOnCreation && props.ipv6CidrBlock === undefined && props.ipv6IpamAllocation === undefined) {
2170+
throw new ValidationError('If you specify assignIpv6AddressOnCreation, you must also specify ipv6CidrBlock or ipv6IpamAllocation', this);
2171+
}
2172+
20942173
Object.defineProperty(this, VPC_SUBNET_SYMBOL, { value: true });
20952174

20962175
Tags.of(this).add(NAME_TAG, this.node.path);
20972176

20982177
this.availabilityZone = props.availabilityZone;
2099-
this.ipv4CidrBlock = props.cidrBlock;
2178+
// If ipv4IpamAllocation is used, ipv4CidrBlock will be determined by CloudFormation at runtime
2179+
this.ipv4CidrBlock = props.cidrBlock ?? '';
21002180
const subnet = new CfnSubnet(this, 'Subnet', {
21012181
vpcId: props.vpcId,
21022182
cidrBlock: props.cidrBlock,
21032183
availabilityZone: props.availabilityZone,
21042184
mapPublicIpOnLaunch: props.mapPublicIpOnLaunch,
21052185
ipv6CidrBlock: props.ipv6CidrBlock,
21062186
assignIpv6AddressOnCreation: props.assignIpv6AddressOnCreation,
2187+
// Add IPv4 IPAM properties if provided
2188+
ipv4IpamPoolId: props.ipv4IpamAllocation?.ipamPoolId,
2189+
ipv4NetmaskLength: props.ipv4IpamAllocation?.netmaskLength,
2190+
// Add IPv6 IPAM properties if provided
2191+
ipv6IpamPoolId: props.ipv6IpamAllocation?.ipamPoolId,
2192+
ipv6NetmaskLength: props.ipv6IpamAllocation?.netmaskLength,
21072193
});
21082194
this.subnetId = subnet.ref;
21092195
this.subnetVpcId = subnet.attrVpcId;

0 commit comments

Comments
 (0)