CloudFormation Template

0

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
1 Answer
0

Yes any supported VPC setup can be done through CloudFormation. You say the VPC should have 3 CIDRs, this is possible but not normally needed - usually you just need 1 VPC CIDR block which you break up into various "tiers" of subnets, each tier consisting of a subnet in each AZ. Doing it this way is best for supporting firewall rules. As for the tiers you need - at a minimum have a TGW-attach tier, a public tier, a "NAT" tier (i.e. for workloads needing outbound-only internet access) and a fully private tier.

EXPERT
answered 2 years ago
  • I currently have the template but customer is requesting for multipe CIDRs for each AZ .Anyone has sample cloudformation template.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions