ec2: vpc interface endpoint not attaching to selected subnets
#37144 opened on Mar 3, 2026
Description
Describe the bug
When I run cdk synth the generated yaml template does not use the subnets that I specified for the VPC interface endpoint.
Regression Issue
- Select this option if this issue appears to be a regression.
Last Known Working CDK Library Version
No response
Expected Behavior
The generated yaml template will use the subnets that I specify, e.g. the subnet I have provided to the ec2.SubnetSelection object, when creating the VPC interface endpoint.
Current Behavior
Running cdk synth generates a yaml template like the following where there are no subnets selected in the SubnetIds property. This results in a VPC endpoint that does not work because it is not attached to subnets and there is therefore no route to it.
ExampleVpcSSMEndpointB39410AA:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- Fn::GetAtt:
- ExampleVpcSSMEndpointSecurityGroup8A8CCA72
- GroupId
ServiceName:
Fn::Join:
- ""
- - com.amazonaws.
- Ref: AWS::Region
- .ssm
SubnetIds: []
Tags:
- Key: Name
Value: ExampleAppStack/ExampleVpc
VpcEndpointType: Interface
VpcId:
Ref: ExampleVpc7799291B
Metadata:
aws:cdk:path: ExampleAppStack/ExampleVpc/SSMEndpoint/Resource
I have other stacks that use the exact same code for subnet selection and they synth correctly, the only difference being is that those stacks only have a single private subnet. My understanding is that it's fine to have more than one private subnet in a VPC, but you can only associate a single subnet per AZ with the VPC interface, so it feels like this should work since I am only selecting a single subnet.
Reproduction Steps
Example reproduction stack (created from cdk init app --language python with the following code pasted into example_app_stack.py)
from aws_cdk import (
Stack,
aws_ec2 as ec2
)
from constructs import Construct
class ExampleAppStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
self.vpc = ec2.Vpc(
self,
"ExampleVpc",
ip_addresses=ec2.IpAddresses.cidr("10.0.0.0/16"),
max_azs=3, # Use up to 3 AZs for high availability
nat_gateways=0,
subnet_configuration=[],
create_internet_gateway=False,
enable_dns_support=True,
enable_dns_hostnames=True,
)
self.default_network_acl = ec2.CfnNetworkAcl(
self,
"DefaultNetworkAcl",
vpc_id=self.vpc.vpc_id,
)
self.igw = ec2.CfnInternetGateway(self, "InternetGateway")
# Attach Internet Gateway to VPC
self.igw_attachment = ec2.CfnVPCGatewayAttachment(
self,
"IGWAttachment",
vpc_id=self.vpc.vpc_id,
internet_gateway_id=self.igw.ref,
)
# Ensure IGW is created before attachment
self.igw_attachment.add_dependency(self.igw)
# Create public subnet
self.public_subnet = ec2.CfnSubnet(
self,
"PublicSubnet",
vpc_id=self.vpc.vpc_id,
cidr_block="10.0.1.0/24",
availability_zone="ap-southeast-2a",
map_public_ip_on_launch=False,
)
self.eip = ec2.CfnEIP(self, "NATGatewayEIP", domain="vpc")
self.nat_gateway = ec2.CfnNatGateway(
self,
"NATGateway",
subnet_id=self.public_subnet.ref,
allocation_id=self.eip.attr_allocation_id,
)
self.public_route_table = ec2.CfnRouteTable(
self,
"PublicRouteTable",
vpc_id=self.vpc.vpc_id,
)
self.public_route = ec2.CfnRoute(
self,
"PublicRoute",
route_table_id=self.public_route_table.ref,
destination_cidr_block="0.0.0.0/0",
gateway_id=self.igw.ref,
)
self.public_route.add_dependency(self.igw_attachment)
ec2.CfnSubnetRouteTableAssociation(
self,
"PublicSubnetRouteTableAssociation",
subnet_id=self.public_subnet.ref,
route_table_id=self.public_route_table.ref,
)
# Create private subnets
self.private_subnet_a = ec2.CfnSubnet(
self,
id="PrivateSubnetA",
vpc_id=self.vpc.vpc_id,
cidr_block="10.0.2.0/24",
availability_zone="ap-southeast-2a",
map_public_ip_on_launch=False,
)
self.private_subnet_b = ec2.CfnSubnet(
self,
id="PrivateSubnetB",
vpc_id=self.vpc.vpc_id,
cidr_block="10.0.3.0/24",
availability_zone="ap-southeast-2a",
map_public_ip_on_launch=False,
)
self.private_route_table = ec2.CfnRouteTable(
self,
"PrivateRouteTable",
vpc_id=self.vpc.vpc_id,
)
self.private_route = ec2.CfnRoute(
self,
"PrivateRoute",
route_table_id=self.private_route_table.ref,
destination_cidr_block="0.0.0.0/0",
nat_gateway_id=self.nat_gateway.ref,
)
# Ensure the NAT Gateway is created before creating the route
self.private_route.add_dependency(self.nat_gateway)
# Associate private route table with private subnets
ec2.CfnSubnetRouteTableAssociation(
self,
"PrivateSubnetARouteTableAssociation",
subnet_id=self.private_subnet_a.ref,
route_table_id=self.private_route_table.ref,
)
ec2.CfnSubnetRouteTableAssociation(
self,
"PrivateSubnetBRouteTableAssociation",
subnet_id=self.private_subnet_b.ref,
route_table_id=self.private_route_table.ref,
)
# SSM endpoint
self.ssm_endpoint = self.vpc.add_interface_endpoint(
"SSMEndpoint",
service=ec2.InterfaceVpcEndpointAwsService.SSM,
subnets=ec2.SubnetSelection(subnets=[self.private_subnet_a]),
)
# SSM Messages endpoint
self.ssm_messages_endpoint = self.vpc.add_interface_endpoint(
"SSMMessagesEndpoint",
service=ec2.InterfaceVpcEndpointAwsService.SSM_MESSAGES,
subnets=ec2.SubnetSelection(subnets=[self.private_subnet_a]),
)
# EC2 Messages endpoint
self.ec2_messages_endpoint = self.vpc.add_interface_endpoint(
"EC2MessagesEndpoint",
service=ec2.InterfaceVpcEndpointAwsService.EC2_MESSAGES,
subnets=ec2.SubnetSelection(subnets=[self.private_subnet_a]),
)
Possible Solution
No response
Additional Information/Context
requirements.txt has the following versions:
aws-cdk-lib>=2.239.0,<3.0.0
constructs>=10.5.0,<11.0.0
AWS CDK Library version (aws-cdk-lib)
2.241.0
AWS CDK CLI version
2.1107.0 (build e51b1ae)
Node.js Version
v24.11.1
OS
Ubuntu-24.04 running in windows subsystem for linux
Language
Python
Language Version
3.10.19
Other information
No response