-
-
Save milesjordan/d86942718f8d4dc20f9f331913e7367a to your computer and use it in GitHub Desktop.
| --- | |
| 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 |
I suggest adding
DependsOn: IPv6CidrBlockto theAWS::EC2::Subnetresources.Otherwise you can get a race condition with the Subnet failing on the
GetAtt VPC.Ipv6CidrBlocksoperation.
+1
I suggest using intrinsic function Fn::Cidr to break the /48 VPC Cidr block into /64 rather than hard coding the SubnetPart.
I suggest using intrinsic function Fn::Cidr to break the /48 VPC Cidr block into /64 rather than hard coding the SubnetPart.
Indeed, it looks like the docs for this function have an example of doing exactly this (search for "Creating an IPv6 enabled VPC"): https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-cidr.html
Thanks for the suggestions! Indeed, using the newer Fn::Cidr function and adding DependsOn would be a nice addition. I'm glad this helped some of you out!
Thanks for this post it really helped me !!!