Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Cloudformation template for a VPC with ipv6, with public and private subnets, calculating the subnet ipv6 CIDR blocks on the fly.
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Public VPC and subnets
Resources:
#
# Public VPC
#
PublicVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 172.31.0.0/16
InstanceTenancy: default
Tags:
- Key: Name
Value: Public VPC
IPv6CidrBlock:
Type: AWS::EC2::VPCCidrBlock
Properties:
VpcId: !Ref PublicVpc
AmazonProvidedIpv6CidrBlock: true
#
# Internet gateways (ipv4, and egress for ipv6)
#
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: Public VPC Internet Access
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref PublicVpc
InternetGatewayId: !Ref InternetGateway
EgressOnlyInternetGateway:
Type: AWS::EC2::EgressOnlyInternetGateway
Properties:
VpcId: !Ref PublicVpc
#
# Routing - public subnets
#
PublicSubnetRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref PublicVpc
Tags:
- Key: Name
Value: Route Table for Public Subnets in Public VPC
PublicSubnetDefaultRoute:
DependsOn: InternetGatewayAttachment
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: 0.0.0.0/0
RouteTableId: !Ref PublicSubnetRouteTable
GatewayId: !Ref InternetGateway
PublicSubnetDefaultIpv6Route:
Type: AWS::EC2::Route
Properties:
DestinationIpv6CidrBlock: ::/0
RouteTableId: !Ref PublicSubnetRouteTable
EgressOnlyInternetGatewayId: !Ref EgressOnlyInternetGateway
#
# Routing - private subnets
#
PrivateSubnetRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref PublicVpc
Tags:
- Key: Name
Value: Route Table for Private Subnets in Public VPC
PrivateSubnetDefaultIpv6Route:
Type: AWS::EC2::Route
Properties:
DestinationIpv6CidrBlock: ::/0
RouteTableId: !Ref PrivateSubnetRouteTable
EgressOnlyInternetGatewayId: !Ref EgressOnlyInternetGateway
#
# Access control
#
PrivateSubnetsNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref PublicVpc
Tags:
- Key: Name
Value: Private Subnet on Public VPC ACL
PrivateSubnetsNetworkAclInboundEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateSubnetsNetworkAcl
RuleNumber: 1
PortRange:
From: 22 # SSH
To: 22
Protocol: 6 # TCP
RuleAction: allow
Egress: false
CidrBlock: 172.31.0.0/16
PrivateSubnetsNetworkAclIpv6OutboundEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateSubnetsNetworkAcl
RuleNumber: 1
Protocol: -1
RuleAction: allow
Egress: true
Ipv6CidrBlock: ::/0
PrivateSubnetsNetworkAclOutboundEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateSubnetsNetworkAcl
RuleNumber: 2
Protocol: -1
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
#
# Public subnet A
#
PublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 172.31.0.0/20
Ipv6CidrBlock:
Fn::Sub:
- "${VpcPart}${SubnetPart}"
- SubnetPart: '01::/64'
VpcPart: !Select [ 0, !Split [ '00::/56', !Select [ 0, !GetAtt PublicVpc.Ipv6CidrBlocks ]]]
AvailabilityZone: !Select [ 0, !GetAZs '' ]
VpcId: !Ref PublicVpc
MapPublicIpOnLaunch: 'true'
Tags:
- Key: Name
Value: Public Subnet A
PublicSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicSubnetRouteTable
SubnetId: !Ref PublicSubnetA
#
# Private subnet A
#
PrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 172.31.48.0/20
Ipv6CidrBlock:
Fn::Sub:
- "${VpcPart}${SubnetPart}"
- SubnetPart: 'a1::/64'
VpcPart: !Select [ 0, !Split [ '00::/56', !Select [ 0, !GetAtt PublicVpc.Ipv6CidrBlocks ]]]
AssignIpv6AddressOnCreation: true
AvailabilityZone: !Select [ 0, !GetAZs '' ]
VpcId: !Ref PublicVpc
Tags:
- Key: Name
Value: Private Subnet A in Public VPC
PrivateSubnetAAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
NetworkAclId: !Ref PrivateSubnetsNetworkAcl
SubnetId: !Ref PrivateSubnetA
PrivateSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateSubnetRouteTable
SubnetId: !Ref PrivateSubnetA
@milesjordan

This comment has been minimized.

Copy link
Owner Author

commented Dec 22, 2017

This doesn't currently work due to an issue in cloudformation that prevents Egress Only Internet Gateways from routing properly. Let's hope it's fixed soon!

@jghaines

This comment has been minimized.

Copy link

commented Aug 16, 2018

The routing issue looks to fixed now.

@jghaines

This comment has been minimized.

Copy link

commented Aug 16, 2018

I suggest adding DependsOn: IPv6CidrBlock to the AWS::EC2::Subnet resources.

Otherwise you can get a race condition with the Subnet failing on the GetAtt VPC.Ipv6CidrBlocks operation.

@drobern

This comment has been minimized.

Copy link

commented Aug 28, 2018

Thanks for this post!

@thyme-87

This comment has been minimized.

Copy link

commented Dec 18, 2018

Thanks for your work! I based my own template on it and found !Cidr ( https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-cidr.html) to make the subnet calculation more simple for a scenario with multiple subnets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.