Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ec2): support ipAddressType property for interface VPC endpoints #32634

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { App, Stack } from 'aws-cdk-lib/core';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { IntegTest } from '@aws-cdk/integ-tests-alpha';

const app = new App();
const stack = new Stack(app, 'VpcEndpointIpAddressTypeStack');

const vpc = new ec2.Vpc(stack, 'DualStackVpc', {
ipProtocol: ec2.IpProtocol.DUAL_STACK,
});

vpc.addInterfaceEndpoint('IPv4', {
privateDnsEnabled: false,
service: ec2.InterfaceVpcEndpointAwsService.BEDROCK,
subnets: { subnetType: ec2.SubnetType.PUBLIC },
ipAddressType: ec2.IpAddressType.IPV4,
});

vpc.addInterfaceEndpoint('IPv6', {
privateDnsEnabled: false,
service: ec2.InterfaceVpcEndpointAwsService.S3_TABLES,
subnets: { subnetType: ec2.SubnetType.PUBLIC },
ipAddressType: ec2.IpAddressType.IPV6,
});

new IntegTest(app, 'VpcEndpointIpAddressTypeTest', {
testCases: [stack],
});
12 changes: 12 additions & 0 deletions packages/aws-cdk-lib/aws-ec2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,18 @@ new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', {
});
```

You can choose ip address type by setting `ipAddressType` property:

```ts
declare const vpc: ec2.Vpc;

new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', {
vpc,
service: ec2.InterfaceVpcEndpointAwsService.EC2,
ipAddressType: ec2.IpAddressType.IPV6, // ip address type
});
```

#### Security groups for interface VPC endpoints

By default, interface VPC endpoints create a new security group and all traffic to the endpoint from within the VPC will be automatically allowed.
Expand Down
44 changes: 42 additions & 2 deletions packages/aws-cdk-lib/aws-ec2/lib/vpc-endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ export interface InterfaceVpcEndpointOptions {
readonly securityGroups?: ISecurityGroup[];

/**
* Whether to automatically allow VPC traffic to the endpoint
* Whether to automatically allow VPC traffic to the endpoint when ipAddressType is IPv4 or Dual-stack.
*
* If enabled, all traffic to the endpoint from within the VPC will be
* automatically allowed. This is done based on the VPC's CIDR range.
Expand All @@ -774,6 +774,43 @@ export interface InterfaceVpcEndpointOptions {
* @default false
*/
readonly lookupSupportedAzs?: boolean;

/**
* The supported IP address types.
*
* @default IpAddressType.IPV4
*/
readonly ipAddressType?: IpAddressType;
}

/**
* The supported IP address types.
*
* @see https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#create-interface-endpoint-aws
*/
export enum IpAddressType {
/**
* Assign IPv4 addresses to the endpoint network interfaces.
* This option is supported only if all selected subnets have IPv4 address ranges and the service accepts IPv4 requests.
*/
IPV4 = 'ipv4',

/**
* Assign IPv6 addresses to the endpoint network interfaces.
* This option is supported only if all selected subnets are IPv6 only subnets and the service accepts IPv6 requests.
*/
IPV6 = 'ipv6',

/**
* Assign both IPv4 and IPv6 addresses to the endpoint network interfaces.
* This option is supported only if all selected subnets have both IPv4 and IPv6 address ranges and the service accepts both IPv4 and IPv6 requests.
*/
DUAL_STACK = 'dualstack',

/**
* not specified
*/
NOT_SPECIFIED = 'not-specified',
}

/**
Expand Down Expand Up @@ -878,7 +915,9 @@ export class InterfaceVpcEndpoint extends VpcEndpoint implements IInterfaceVpcEn
});

if (props.open !== false) {
this.connections.allowDefaultPortFrom(Peer.ipv4(props.vpc.vpcCidrBlock));
if (props.ipAddressType === undefined || [IpAddressType.IPV4, IpAddressType.DUAL_STACK].includes(props.ipAddressType)) {
this.connections.allowDefaultPortFrom(Peer.ipv4(props.vpc.vpcCidrBlock));
}
}

// Determine which subnets to place the endpoint in
Expand All @@ -892,6 +931,7 @@ export class InterfaceVpcEndpoint extends VpcEndpoint implements IInterfaceVpcEn
vpcEndpointType: VpcEndpointType.INTERFACE,
subnetIds,
vpcId: props.vpc.vpcId,
ipAddressType: props.ipAddressType,
});

this.vpcEndpointId = endpoint.ref;
Expand Down
57 changes: 57 additions & 0 deletions packages/aws-cdk-lib/aws-ec2/test/vpc-endpoint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as cxschema from '../../cloud-assembly-schema';
import { ContextProvider, Fn, Stack } from '../../core';
// eslint-disable-next-line max-len
import { GatewayVpcEndpoint, GatewayVpcEndpointAwsService, InterfaceVpcEndpoint, InterfaceVpcEndpointAwsService, InterfaceVpcEndpointService, SecurityGroup, SubnetFilter, SubnetType, Vpc } from '../lib';
import { IpAddressType } from '../lib/vpc-endpoint';

describe('vpc endpoint', () => {
describe('gateway endpoint', () => {
Expand Down Expand Up @@ -954,5 +955,61 @@ describe('vpc endpoint', () => {
VpcEndpointType: 'Interface',
});
});

test.each([
IpAddressType.IPV4,
IpAddressType.IPV6,
IpAddressType.DUAL_STACK,
IpAddressType.NOT_SPECIFIED,
])('test vpc interface endpoint when ip address type is %s.', (ipAddressType) => {
//GIVEN
const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-west-2' } });
const vpc = new Vpc(stack, 'VPC');

//WHEN
vpc.addInterfaceEndpoint('EC2 Endpoint', {
service: InterfaceVpcEndpointAwsService.EC2,
privateDnsEnabled: false,
ipAddressType,
});

//THEN
Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', {
ServiceName: 'com.amazonaws.us-west-2.ec2',
VpcId: stack.resolve(vpc.vpcId),
PrivateDnsEnabled: false,
VpcEndpointType: 'Interface',
IpAddressType: ipAddressType,
});
});

test.each([
IpAddressType.IPV4,
IpAddressType.DUAL_STACK,
])('test security group with vpc interface endpoint when ip address type is %s.', (ipAddressType) => {
//GIVEN
const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-west-2' } });
const vpc = new Vpc(stack, 'VPC');

//WHEN
vpc.addInterfaceEndpoint('EC2 Endpoint', {
service: InterfaceVpcEndpointAwsService.EC2,
privateDnsEnabled: false,
ipAddressType,
open: true,
});

//THEN
Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', {
SecurityGroupIngress: [
{
CidrIp: stack.resolve(vpc.vpcCidrBlock),
FromPort: 443,
IpProtocol: 'tcp',
ToPort: 443,
},
],
});
});
});
});
Loading