CloudFormation Template
I have received cloud formation template from AWS Professional service to create a VPC which creates subnet in 3 AZ with 3 TGW attachment and also attach it Transit gateway.
Customer requires a VPC which should have 3 CIDRS and one CIDR for each AZ . Is this possible via CFT. Please help .
Below is the template:
---
# Creates a VPC. Supports various patterns through Conditions.
# This template is hardcoded to use 3 AZs.
# Depends on SNTO being active, as well as the Subnet Calculator solution.
AWSTemplateFormatVersion: 2010-09-09
Description: Standard VPC network
##############
# Parameters #
##############
Parameters:
VPCName:
Description: Text to prefix in the VPC resource names
Type: String
VPCPattern:
Description: VPC pattern to create
Type: String
Default: 1 public, 1 private, with Transit Gateway
AllowedValues:
- 1 public, 1 private, with Transit Gateway, dedicated NAT gateways
- 1 public, 1 private, no Transit Gateway, dedicated NAT gateways
- 1 public, 2 private, no Transit Gateway, dedicated NAT gateways
- 1 public, 1 private, with Transit Gateway
- 1 public, 2 private, with Transit Gateway
- No public, 1 private in 3 AZs, with Transit Gateway
- No public, 2 private in 3 AZs, with Transit Gateway
VPCNetwork:
Description: Network (WITHOUT the /prefix) to assign to the created VPC, eg. 10.123.0.0
Type: String
AllowedPattern: ^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$
CIDRPrefix:
Description: "VPC CIDR prefix. Approximate IPs: /24: 150 IPs -- /23: 350 IPs -- /22: 750 IPs -- /21: 1500 IPs -- /20: 3000 IPs"
Type: Number
Default: 24
AllowedValues:
- 24
- 23
- 22
- 21
- 20
TransitGatewayConnectivity:
Description: Connectivity requirements, configures the Transit Gateway route tables.
Type: String
AllowedValues:
# For the Mappings to work, we can only have alphanumeric chars, -, and .
# No spaces.
- "None"
- "Standard"
- "Inspection"
# Add more as needed.
Default: "Standard"
SSMEndpoints:
Description: Create SSM VPC interface endpoints? This allows using Session Manager to access the instance without a public subnet.
Type: String
Default: "No"
AllowedValues:
- "Yes"
- "No"
PrivateDomainName:
Description: Private hosted zone DNS name for this VPC
Type: String
Default: awslocal
# Advanced options:
Private1SubnetMask:
Description: >
(Advanced) Override automatic subnet prefix selection.
If this is set, all subnet masks below need to be specified.
Set to 0 if subnet does not exist for the pattern.
Type: String
Default: Automatic
AllowedValues: [ Automatic, 0, 23, 24, 25, 26, 27, 28 ]
Private2SubnetMask:
Description: (Advanced) Override automatic subnet mask selection.
Type: String
Default: Automatic
AllowedValues: [ Automatic, 0, 23, 24, 25, 26, 27, 28 ]
Private3SubnetMask:
Description: (Advanced) Override automatic subnet mask selection.
Type: String
Default: Automatic
AllowedValues: [ Automatic, 0, 23, 24, 25, 26, 27, 28 ]
PublicSubnetMask:
Description: (Advanced) Override automatic subnet mask selection.
Type: String
Default: Automatic
AllowedValues: [ Automatic, 0, 23, 24, 25, 26, 27, 28 ]
# For informational purposes only, for users calculating the available space themselves:
TGWSubnetMask: # Not used
Description: (Advanced) Override automatic subnet mask selection.
Type: String
Default: "28"
AllowedValues: [ "28" ]
Private1SubnetLabel:
Description: Name for the first private subnet
Type: String
Default: "Private Subnet 1"
Private2SubnetLabel:
Description: (if applicable) Name for the second private subnet
Type: String
Default: "Private Subnet 2"
Private3SubnetLabel:
Description: (if applicable) Name for the third private subnet
Type: String
Default: "Private Subnet 3"
PublicSubnetLabel:
Description: Name for the public subet
Type: String
Default: "Public Subnet"
Rules:
NoTransitGatewayPattern:
RuleCondition: !Or
- !Equals [ !Ref VPCPattern, "1 public, 1 private, no Transit Gateway, dedicated NAT gateways" ]
- !Equals [ !Ref VPCPattern, "1 public, 2 private, no Transit Gateway, dedicated NAT gateways" ]
Assertions:
- Assert: !Equals [ !Ref TransitGatewayConnectivity, "None" ]
AssertDescription: 'VPC pattern has no Transit Gateway'
HasTransitGatewayPattern:
RuleCondition: !Not
- !Or
- !Equals [ !Ref VPCPattern, "1 public, 1 private, no Transit Gateway, dedicated NAT gateways" ]
- !Equals [ !Ref VPCPattern, "1 public, 2 private, no Transit Gateway, dedicated NAT gateways" ]
Assertions:
- Assert: !Not [ !Equals [ !Ref TransitGatewayConnectivity, "None" ] ]
AssertDescription: 'Transit Gateway pattern required for given pattern.'
Mappings:
#############
# Variables #
#############
Variables:
TransitGatewayID:
Value: tgw-01bb62fb90cf083e5
VPCFlowLogBucket:
Value: controltower-vpc-flow-logs-124669510339-ap-southeast-2
VPCFlowLogPrefix:
Value: vpc-flow-logs
NetworkAccountID:
Value: "124669510339"
################################
# Transit Gateway route tables #
###############################
# These are based on Conditions that looks at !Ref TransitGatewayConnectivity
TransitGatewayRouteTablePatterns:
"Standard":
AssociateWith: "Standard"
PropagateTo: "Inspection,On-premises"
"Inspection":
AssociateWith: "Inspection"
PropagateTo: "Inspection,On-premises"
"None":
AssociateWith: ""
PropagateTo: ""
# Default VPC Prefix to subnet prefix mapping
# Subnet prefix needs to take into account 3 x /28 for TGW
"24":
OneSubnet:
Private1: 26
TwoSubnets:
Private1: 27
PublicOrPrivate2: 27
ThreeSubnets:
Private1: 27
Private2: 28
PublicOrPrivate3: 28
"23":
OneSubnet:
Private1: 25
TwoSubnets:
Private1: 26
PublicOrPrivate2: 26
ThreeSubnets:
Private1: 26
Private2: 27
PublicOrPrivate3: 27
"22":
OneSubnet:
Private1: 24
TwoSubnets:
Private1: 25
PublicOrPrivate2: 25
ThreeSubnets:
Private1: 25
Private2: 25
PublicOrPrivate3: 26
"21":
OneSubnet:
Private1: 23
TwoSubnets:
Private1: 24
PublicOrPrivate2: 24
ThreeSubnets:
Private1: 24
Private2: 24
PublicOrPrivate3: 25
"20":
OneSubnet:
Private1: 22
TwoSubnets:
Private1: 23
PublicOrPrivate2: 23
ThreeSubnets:
Private1: 23
Private2: 23
PublicOrPrivate3: 24
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Required configuiraion
Parameters:
- VPCName
- VPCNetwork
- CIDRPrefix
- Label:
default: Networking configuration
Parameters:
- VPCPattern
- TransitGatewayConnectivity
- Label:
default: Subnet naming
Parameters:
- Private1SubnetLabel
- Private2SubnetLabel
- Private3SubnetLabel
- PublicSubnetLabel
- Label:
default: Advanced configuration
Parameters:
- Private1SubnetMask
- Private2SubnetMask
- Private3SubnetMask
- PublicSubnetMask
- TGWSubnetMask
ParameterLabels:
VPCNetwork:
default: VPC IP network
CIDRPrefix:
default: VPC prefix/size
VPCName:
default: Name of the VPC. "VPC" will be appended to this name.
VPCPattern:
default: VPC pattern and subnets to create
PrivateDomainName:
default: Private DNS name
TransitGatewayConnectivity:
default: Transit Gateway connectivity requirements
##############
# Conditions #
##############
Conditions:
AutomaticCidr: !Equals [ !Ref VPCNetwork, 'Automatic' ]
SSMEndpoints: !Equals [ !Ref SSMEndpoints, "Yes" ]
ConnectToTransitGateway: !Not
- !Or
- !Equals [ !Ref VPCPattern, '1 public, 1 private, no Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, no Transit Gateway, dedicated NAT gateways' ]
UseDedicatedNATGateways: !Or
- !Equals [ !Ref VPCPattern, '1 public, 1 private, with Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 1 private, no Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, no Transit Gateway, dedicated NAT gateways' ]
HaveNATGatewaysPerAZ: !Or
- !Equals [ !Ref VPCPattern, '1 public, 1 private, with Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 1 private, no Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, no Transit Gateway, dedicated NAT gateways' ]
# These count the number of subnet sets (not counting TGW subnets)
OneSubnet: !Equals [ !Ref VPCPattern, 'No public, 1 private in 3 AZs, with Transit Gateway' ]
TwoSubnets: !Or
- !Equals [ !Ref VPCPattern, '1 public, 1 private, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, '1 public, 1 private, with Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, 'No public, 2 private in 3 AZs, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, '1 public, 1 private, no Transit Gateway, dedicated NAT gateways' ]
# ThreeSubnets: Any other patter not matching the above.
CreatePrivate2Subnets: !Or
- !Equals [ !Ref VPCPattern, 'No public, 2 private in 3 AZs, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, 'No public, 3 private in 3 AZs, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, no Transit Gateway, dedicated NAT gateways' ]
CreatePrivate3Subnets: !Equals [ !Ref VPCPattern, 'No public, 3 private in 3 AZs, with Transit Gateway' ]
CreatePublicSubnets: !Or
- !Equals [ !Ref VPCPattern, '1 public, 1 private, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, '1 public, 1 private, with Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, with Transit Gateway' ]
- !Equals [ !Ref VPCPattern, '1 public, 1 private, no Transit Gateway, dedicated NAT gateways' ]
- !Equals [ !Ref VPCPattern, '1 public, 2 private, no Transit Gateway, dedicated NAT gateways' ]
# Check if the subnet masks were overridden
ManualSubnetMaskPrivate1: !Not [ !Equals [ !Ref Private1SubnetMask, 'Automatic' ] ]
ManualSubnetMaskPrivate2: !Not [ !Equals [ !Ref Private2SubnetMask, 'Automatic' ] ]
ManualSubnetMaskPrivate3: !Not [ !Equals [ !Ref Private3SubnetMask, 'Automatic' ] ]
ManualSubnetMaskPublic: !Not [ !Equals [ !Ref PublicSubnetMask, 'Automatic' ] ]
# Negative conditions:
UseSharedNATGateways: !Not [ !Condition UseDedicatedNATGateways ]
UserDefinedCidr: !Not [ !Condition AutomaticCidr ]
# Compound Conditions:
UseDedicatedNATGateways&HaveNATGatewaysPerAZ: !And
- !Condition 'UseDedicatedNATGateways'
- !Condition 'HaveNATGatewaysPerAZ'
CreatePrivate2Subnets&UseDedicatedNATGateways: !And
- !Condition 'CreatePrivate2Subnets'
- !Condition 'UseDedicatedNATGateways'
CreatePrivate2Subnets&UseDedicatedNATGateways&HaveNATGatewaysPerAZ: !And
- !Condition 'CreatePrivate2Subnets'
- !Condition 'UseDedicatedNATGateways'
- !Condition 'HaveNATGatewaysPerAZ'
CreatePrivate2Subnets&UseSharedNATGateways: !And
- !Condition 'CreatePrivate2Subnets'
- !Condition 'UseSharedNATGateways'
CreatePrivate3Subnets&ConnectToTransitGateway: !And
- !Condition 'CreatePrivate3Subnets'
- !Condition 'ConnectToTransitGateway'
Resources:
#######
# VPC #
#######
# This Custom resource reads the list of Subnets Labels+prefixes given, and returns a dictionary
# with a key of the Label given, and the value of an array of 3 CIDRs (one for each AZ).
# If the Prefix is set to 0, it's as though the prefix was not listed.
# The custom resource lambda runs in the network account, exposed via SNS.
SubnetCalculator:
Type: Custom::SubnetCalculator
Properties:
ServiceToken: !Sub
- arn:aws:sns:${AWS::Region}:${NetworkAccountID}:SubnetCalculatorV1
- NetworkAccountID: !FindInMap [ Variables, NetworkAccountID, Value ]
VPCNetwork: !GetAtt VPC.CidrBlock
AZs: 3
Subnets:
# Always calculate the TGW subnet, so that it is easy to migrate from
# a non-TGW pattern to a TGW one. It does not need to be used for non-TGW patterns.
- Label: TGW
Prefix: 28
- Label: Private1
Prefix: !If
- ManualSubnetMaskPrivate1
# Then:
- !Ref Private1SubnetMask
# Else, automatic selection based on Mapping:
- !If
- OneSubnet
- !FindInMap [ !Ref CIDRPrefix, "OneSubnet", Private1 ]
- !If
- TwoSubnets
- !FindInMap [ !Ref CIDRPrefix, "TwoSubnets", Private1 ]
# Else:
- !FindInMap [ !Ref CIDRPrefix, "ThreeSubnets", Private1 ]
- !If
- CreatePrivate2Subnets
- Label: Private2
Prefix: !If
- ManualSubnetMaskPrivate2
# Then:
- !Ref Private2SubnetMask
# Else, automatic selection based on Mapping:
- !If
- TwoSubnets
- !FindInMap [ !Ref CIDRPrefix, "TwoSubnets", PublicOrPrivate2 ]
# Else
- !FindInMap [ !Ref CIDRPrefix, "ThreeSubnets", Private2 ]
# If not CreatePrivate2Subnets, skip this section:
- !Ref AWS::NoValue
- !If
- CreatePrivate3Subnets
- Label: Private3
Prefix: !If
- ManualSubnetMaskPrivate3
# Then:
- !Ref Private3SubnetMask
# Else, automatic selection based on Mapping:
- !FindInMap [ !Ref CIDRPrefix, "ThreeSubnets", PublicOrPrivate3 ]
# If not CreatePrivate3Subnets, skip this section:
- !Ref AWS::NoValue
- !If
- CreatePublicSubnets
- Label: Public
Prefix: !If
- ManualSubnetMaskPublic
# Then:
- !Ref PublicSubnetMask
# Else, automatic selection based on Mapping:
- !If
- TwoSubnets
- !FindInMap [ !Ref CIDRPrefix, "TwoSu