Build an AWS Transit Gateway using CloudFormation

Build an AWS Transit Gateway using CloudFormation

AWS VPCs are a beautiful thing. So much more than just networking, I think of them as the top-level technical container for many other AWS resources. They are so flexible, so convenient that you should — and can — build your entire AWS environment and development process around them.

There was just one fly in the ointment: when you wanted traffic to flow between VPCs, you had to peer them in a mesh network. And transitive routing was a no-no, making a hub and spoke environment harder to build.

Last fall at re:Invent 2018, AWS fixed this with a major new VPC feature. The elegant Transit Gateway capability solves for all the issues that made scaling VPCs hard. Now, it’s both possible and desirable to churn out VPCs like M&Ms.

Recently, I developed a transit gateway template for a client and I thought that generalizing it might make it a useful sample for others to base their network designs on. In the JSON and YAML templates that follow,  you’ll find the outline of a transit gateway along with a couple of VPCs and associated resources that could be the model for your environment as well.

Here’s a visual of what the template produces. The JSON and YAML versions are identical and produce the same outputs.

The design underlying this example of a transit gateway has the following attributes:

  • I assume that the first VPC (MgmtVPC) will have access to all subnets in all VPCs. It’s where you would put monitoring and management resources.
  • App1VPC is one of what would probably be many VPCs added to the transit gateway.  I create route tables and a security group that permits out-of-VPC traffic only to the management VPC’s first subnet.

The idea is that you could use this template for the basic networking infrastructure in an ever-expanding VPC environment, each of which would be connected to the virtual gateway. You could simply add each additional VPC and update the CloudFormation stack by replacing the entire template. As you probably know, exisiting VPCs, route tables, security groups and, of course, the transit gateway itself would not be affected. You’d only add the additional VPCs.

This way, you’d be able to design and implement in code an auditable, verifiable network environment using transit gateways. Of course, you need to adjust the addressing, routes and security groups for your design.

I hope this transit gateway example and template is helpful to you. The template is provided first as a YAML template, followed by a JSON version. Both produce identical resources.

Updated: 2021-08-19. This template could fail if you run it in an AWS region in which your account has been assigned fewer than three AZs. It now only distributes subnets between AZs 0 and 1.

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Creates a transit gateway two VPCs each with two private subnets and routes
  for each subnet to the TGW. A security group permitting all traffic to/from
  the MgmtVPC is created and an SG that permits inbound traffic from MgmtVPC to
  App1VPC is also created. MgmtVPC would have all of the necessary monitoring
  and management tools. App1VPC is a model of just one of many possible App1VPC 
  Alex Neihaus 2019-08-17 (c) 2019 Air11 Technology LLC -- licensed under the
  Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0
Metadata:
  'AWS::CloudFormation::Interface':
    ParameterGroups:
      - Label:
          default: VPC and Transit Gateway configuration parameters
        Parameters:
          - MgmtVPCCIDR
          - MgmtVPCSubnet1CIDR
          - MgmtVPCSubnet2CIDR
          - App1VPCCIDR
          - App1VPCSubnet1CIDR
          - App1VPCSubnet2CIDR
          - TransitGatewayASN
          - TransitGatewayRoute
    ParameterLabels:
      TransitGatewayRoute:
        default: >-
          Enter the CIDR that contains ALL VPCs that can be routed through the
          Transit Gateway (probably a /16)
      TransitGatewayASN:
        default: Enter the ASN of the transit gateway
      MgmtVPCCIDR:
        default: Enter CIDR of management VPC
      MgmtVPCSubnet1CIDR:
        default: Enter CIDR of the first private subnet in the management VPC
      MgmtVPCSubnet2CIDR:
        default: Enter CIDR of the second private subnet in the management VPC
      App1VPCCIDR:
        default: Enter the CIDR of the App1 VPC
      App1VPCSubnet1CIDR:
        default: Enter the CIDR of the first private subnet in the App1 VPC
      App1VPCSubnet2CIDR:
        default: Enter the CIDR of the second private subnet in the App1 VPC
Parameters:
  TransitGatewayRoute:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.0.0/16
    Description: CIDR block for address range that contains ALL VPCs.
    Type: String
  MgmtVPCCIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.0.0/17
    Description: CIDR block for Management VPC
    Type: String
  App1VPCCIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.128.0/17
    Description: CIDR block for App1 VPC
    Type: String
  MgmtVPCSubnet1CIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.0.0/24
    Description: CIDR block for the first management VPC subnet
    Type: String
  MgmtVPCSubnet2CIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.1.0/24
    Description: CIDR block for the second management VPC subnet
    Type: String
  App1VPCSubnet1CIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.128.0/24
    Description: CIDR block for the first private subnet in the App1 VPC
    Type: String
  App1VPCSubnet2CIDR:
    AllowedPattern: >-
      ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.10.129.0/24
    Description: CIDR block for the second private subnet in the App1 VPC
    Type: String
  TransitGatewayASN:
    Default: '64612'
    ConstraintDescription: Must be an integer between 64512 and 65534
    Description: The ASN for the AWS Transit Gateway
    Type: Number
    MinValue: '64512'
    MaxValue: '65534'
Mappings: {}
Resources:
  TransitGateway:
    Type: 'AWS::EC2::TransitGateway'
    Properties:
      AmazonSideAsn: !Ref TransitGatewayASN
      Description: VPC transit gateway
      AutoAcceptSharedAttachments: enable
      DefaultRouteTableAssociation: enable
      DnsSupport: enable
      VpnEcmpSupport: enable
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - TransitGateway-
              - !Ref TransitGatewayASN
  MgmtVPC:
    Type: 'AWS::EC2::VPC'
    Properties:
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      CidrBlock: !Ref MgmtVPCCIDR
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPC-
              - !Ref MgmtVPCCIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
    DependsOn: TransitGateway
  MgmtVPCTGWAttachment:
    Type: 'AWS::EC2::TransitGatewayAttachment'
    Properties:
      SubnetIds:
        - !Ref MgmtVPCSubnet1
        - !Ref MgmtVPCSubnet2
      TransitGatewayId: !Ref TransitGateway
      VpcId: !Ref MgmtVPC
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPCAttachment-
              - !Ref MgmtVPCCIDR
  MgmtVPCSubnet1:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref MgmtVPC
      CidrBlock: !Ref MgmtVPCSubnet1CIDR
      AvailabilityZone: !Select 
        - '1'
        - !GetAZs ''
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPCSubnet1-
              - !Ref MgmtVPCSubnet1CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  MgmtVPCSubnet1RouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref MgmtVPC
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPCSubnet1RouteTable-
              - !Ref MgmtVPCSubnet1CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  MgmtVPCSubnet1TGWRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: MgmtVPCTGWAttachment
    Properties:
      RouteTableId: !Ref MgmtVPCSubnet1RouteTable
      DestinationCidrBlock: !Ref TransitGatewayRoute
      TransitGatewayId: !Ref TransitGateway
  MgmtSubnet1RouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref MgmtVPCSubnet1
      RouteTableId: !Ref MgmtVPCSubnet1RouteTable
  MgmtVPCSubnet2:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref MgmtVPC
      CidrBlock: !Ref MgmtVPCSubnet2CIDR
      AvailabilityZone: !Select 
        - '0'
        - !GetAZs ''
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPCSubnet2-
              - !Ref MgmtVPCSubnet2CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  MgmtVPCSubnet2RouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref MgmtVPC
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPCSubnet2RouteTable-
              - !Ref MgmtVPCSubnet2CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  MgmtVPCSubnet2TGWRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: MgmtVPCTGWAttachment
    Properties:
      RouteTableId: !Ref MgmtVPCSubnet2RouteTable
      DestinationCidrBlock: !Ref TransitGatewayRoute
      TransitGatewayId: !Ref TransitGateway
  MgmtSubnet2RouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref MgmtVPCSubnet2
      RouteTableId: !Ref MgmtVPCSubnet2RouteTable
  MgmtVPCSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      VpcId: !Ref MgmtVPC
      GroupDescription: Allow all traffic to TGW-connected VPCs
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '0'
          ToPort: '1024'
          CidrIp: !Ref TransitGatewayRoute
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: '0'
          ToPort: '1024'
          CidrIp: !Ref TransitGatewayRoute
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - MgmtVPCSecurityGroup-
              - !Ref MgmtVPC
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  App1VPC:
    Type: 'AWS::EC2::VPC'
    DependsOn: TransitGateway
    Properties:
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      CidrBlock: !Ref App1VPCCIDR
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1VPC-
              - !Ref App1VPCCIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  App1VPCTGWAttachment:
    Type: 'AWS::EC2::TransitGatewayAttachment'
    Properties:
      SubnetIds:
        - !Ref App1VPCSubnet1
        - !Ref App1VPCSubnet2
      TransitGatewayId: !Ref TransitGateway
      VpcId: !Ref App1VPC
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1Attachment-
              - !Ref App1VPCCIDR
  App1VPCSubnet1:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref App1VPC
      CidrBlock: !Ref App1VPCSubnet1CIDR
      AvailabilityZone: !Select 
        - '1'
        - !GetAZs ''
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1VPCSubnet1-
              - !Ref App1VPCSubnet1CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  App1VPCSubnet1RouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref App1VPC
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1VPCSubnet1RouteTable-
              - !Ref App1VPCSubnet1CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  App1VPCSubnet1TGWRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: App1VPCTGWAttachment
    Properties:
      RouteTableId: !Ref App1VPCSubnet1RouteTable
      DestinationCidrBlock: !Ref MgmtVPCSubnet1CIDR
      TransitGatewayId: !Ref TransitGateway
  App1Subnet1RouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref App1VPCSubnet1
      RouteTableId: !Ref App1VPCSubnet1RouteTable
  App1VPCSubnet2:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref App1VPC
      CidrBlock: !Ref App1VPCSubnet2CIDR
      AvailabilityZone: !Select 
        - '0'
        - !GetAZs ''
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1VPCSubnet2-
              - !Ref App1VPCSubnet2CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  App1VPCSubnet2RouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref App1VPC
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1VPCSubnet2RouteTable-
              - !Ref App1VPCSubnet2CIDR
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
  App1VPCSubnet2TGWRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: App1VPCTGWAttachment
    Properties:
      RouteTableId: !Ref App1VPCSubnet2RouteTable
      DestinationCidrBlock: !Ref MgmtVPCSubnet1CIDR
      TransitGatewayId: !Ref TransitGateway
  App1Subnet2RouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref App1VPCSubnet2
      RouteTableId: !Ref App1VPCSubnet2RouteTable
  App1VPCSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      VpcId: !Ref App1VPC
      GroupDescription: Allow all traffic to MgmtVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '0'
          ToPort: '1024'
          CidrIp: !Ref MgmtVPCCIDR
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: '0'
          ToPort: '1024'
          CidrIp: !Ref MgmtVPCSubnet1CIDR
      Tags:
        - Key: Name
          Value: !Join 
            - ''
            - - App1VPCSecurityGroup-
              - !Ref App1VPC
        - Key: CloudFormationStack
          Value: !Ref 'AWS::StackId'
Outputs:
  TransitGateway:
    Description: Transit Gateway
    Value: !Ref TransitGateway
    Export:
      Name: !Sub '${AWS::StackName}-TransitGateway'
  MgmtVPCTGWAttachment:
    Description: Attachment ID of management VPC to Transit Gateway
    Value: !Ref MgmtVPCTGWAttachment
  MgmtVPCID:
    Description: VPCID of the management VPC
    Value: !Ref MgmtVPC
    Export:
      Name: !Sub '${AWS::StackName}-MgmtVPC'
  MgmtVPCSubnet1:
    Description: SubnetId of the first subnet in the management VPC
    Value: !Ref MgmtVPCSubnet1
  MgmtVPCSubnet1RouteTable:
    Description: Route table ID of the first subnet in the management VPC
    Value: !Ref MgmtVPCSubnet1RouteTable
  MgmtVPCSubnet2:
    Description: SubnetId of the second subnet in the management VPC
    Value: !Ref MgmtVPCSubnet2
  MgmtVPCSubnet2RouteTable:
    Description: Route table ID of the second subnet in the management VPC
    Value: !Ref MgmtVPCSubnet2RouteTable
  App1VPCID:
    Description: VPCID of the App1 VPC
    Value: !Ref App1VPC
    Export:
      Name: !Sub '${AWS::StackName}-App1VPC'
  App1VPCSubnet1:
    Description: SubnetId of the first subnet in the App1 VPC
    Value: !Ref App1VPCSubnet1
  App1VPCSubnet1RouteTable:
    Description: Route table ID of the first subnet in the App1 VPC
    Value: !Ref App1VPCSubnet1RouteTable
  App1VPCSubnet2:
    Description: SubnetId of the second subnet in the App1 VPC
    Value: !Ref App1VPCSubnet2
  App1VPCSubnet2RouteTable:
    Description: Route table ID of the second subnet in the App1 VPC
    Value: !Ref App1VPCSubnet2RouteTable
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Creates a transit gateway two VPCs each with two private subnets and routes for each subnet to the TGW. A security group permitting all traffic to/from the MgmtVPC is created and an SG that permits inbound traffic from MgmtVPC to App1VPC is also created. MgmtVPC would have all of the necessary monitoring and management tools. App1VPC is a model of just one of many possible App1VPC  Alex Neihaus 2019-08-17 (c) 2019 Air11 Technology LLC -- licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0",
    "Metadata": {
        "AWS::CloudFormation::Interface": {
            "ParameterGroups": [
                {
                    "Label": {
                        "default": "VPC and Transit Gateway configuration parameters"
                    },
                    "Parameters": [
                        "MgmtVPCCIDR",
                        "MgmtVPCSubnet1CIDR",
                        "MgmtVPCSubnet2CIDR",
                        "App1VPCCIDR",
                        "App1VPCSubnet1CIDR",
                        "App1VPCSubnet2CIDR",
                        "TransitGatewayASN",
                        "TransitGatewayRoute"
                    ]
                }
            ],
            "ParameterLabels": {
                "TransitGatewayRoute": {
                    "default": "Enter the CIDR that contains ALL VPCs that can be routed through the Transit Gateway (probably a /16)"
                },
                "TransitGatewayASN": {
                    "default": "Enter the ASN of the transit gateway"
                },
                "MgmtVPCCIDR": {
                    "default": "Enter CIDR of management VPC"
                },
                "MgmtVPCSubnet1CIDR": {
                    "default": "Enter CIDR of the first private subnet in the management VPC"
                },
                "MgmtVPCSubnet2CIDR": {
                    "default": "Enter CIDR of the second private subnet in the management VPC"
                },
                "App1VPCCIDR": {
                    "default": "Enter the CIDR of the App1 VPC"
                },
                "App1VPCSubnet1CIDR": {
                    "default": "Enter the CIDR of the first private subnet in the App1 VPC"
                },
                "App1VPCSubnet2CIDR": {
                    "default": "Enter the CIDR of the second private subnet in the App1 VPC"
                }
            }
        }
    },
    "Parameters": {
        "TransitGatewayRoute": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.0.0/16",
            "Description": "CIDR block for address range that contains ALL VPCs.",
            "Type": "String"
        },
        "MgmtVPCCIDR": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.0.0/17",
            "Description": "CIDR block for Management VPC",
            "Type": "String"
        },
        "App1VPCCIDR": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.128.0/17",
            "Description": "CIDR block for App1 VPC",
            "Type": "String"
        },
        "MgmtVPCSubnet1CIDR": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.0.0/24",
            "Description": "CIDR block for the first management VPC subnet",
            "Type": "String"
        },
        "MgmtVPCSubnet2CIDR": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.1.0/24",
            "Description": "CIDR block for the second management VPC subnet",
            "Type": "String"
        },
        "App1VPCSubnet1CIDR": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.128.0/24",
            "Description": "CIDR block for the first private subnet in the App1 VPC",
            "Type": "String"
        },
        "App1VPCSubnet2CIDR": {
            "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$",
            "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28",
            "Default": "10.10.129.0/24",
            "Description": "CIDR block for the second private subnet in the App1 VPC",
            "Type": "String"
        },
        "TransitGatewayASN": {
            "Default": "64612",
            "ConstraintDescription": "Must be an integer between 64512 and 65534",
            "Description": "The ASN for the AWS Transit Gateway",
            "Type": "Number",
            "MinValue": "64512",
            "MaxValue": "65534"
        }
    },
    "Mappings": {},
    "Resources": {
        "TransitGateway": {
            "Type": "AWS::EC2::TransitGateway",
            "Properties": {
                "AmazonSideAsn": {
                    "Ref": "TransitGatewayASN"
                },
                "Description": "VPC transit gateway",
                "AutoAcceptSharedAttachments": "enable",
                "DefaultRouteTableAssociation": "enable",
                "DnsSupport": "enable",
                "VpnEcmpSupport": "enable",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "TransitGateway-",
                                    {
                                        "Ref": "TransitGatewayASN"
                                    }
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "MgmtVPC": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "EnableDnsSupport": "true",
                "EnableDnsHostnames": "true",
                "CidrBlock": {
                    "Ref": "MgmtVPCCIDR"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPC-",
                                    {
                                        "Ref": "MgmtVPCCIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            },
            "DependsOn": "TransitGateway"
        },
        "MgmtVPCTGWAttachment": {
            "Type": "AWS::EC2::TransitGatewayAttachment",
            "Properties": {
                "SubnetIds": [
                    {
                        "Ref": "MgmtVPCSubnet1"
                    },
                    {
                        "Ref": "MgmtVPCSubnet2"
                    }
                ],
                "TransitGatewayId": {
                    "Ref": "TransitGateway"
                },
                "VpcId": {
                    "Ref": "MgmtVPC"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPCAttachment-",
                                    {
                                        "Ref": "MgmtVPCCIDR"
                                    }
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "MgmtVPCSubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "MgmtVPC"
                },
                "CidrBlock": {
                    "Ref": "MgmtVPCSubnet1CIDR"
                },
                "AvailabilityZone": {
                    "Fn::Select": [
                        "1",
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPCSubnet1-",
                                    {
                                        "Ref": "MgmtVPCSubnet1CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "MgmtVPCSubnet1RouteTable": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "MgmtVPC"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPCSubnet1RouteTable-",
                                    {
                                        "Ref": "MgmtVPCSubnet1CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "MgmtVPCSubnet1TGWRoute": {
            "Type": "AWS::EC2::Route",
            "DependsOn": "MgmtVPCTGWAttachment",
            "Properties": {
                "RouteTableId": {
                    "Ref": "MgmtVPCSubnet1RouteTable"
                },
                "DestinationCidrBlock": {
                    "Ref": "TransitGatewayRoute"
                },
                "TransitGatewayId": {
                    "Ref": "TransitGateway"
                }
            }
        },
        "MgmtSubnet1RouteTableAssociation": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "MgmtVPCSubnet1"
                },
                "RouteTableId": {
                    "Ref": "MgmtVPCSubnet1RouteTable"
                }
            }
        },
        "MgmtVPCSubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "MgmtVPC"
                },
                "CidrBlock": {
                    "Ref": "MgmtVPCSubnet2CIDR"
                },
                "AvailabilityZone": {
                    "Fn::Select": [
                        "0",
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPCSubnet2-",
                                    {
                                        "Ref": "MgmtVPCSubnet2CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "MgmtVPCSubnet2RouteTable": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "MgmtVPC"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPCSubnet2RouteTable-",
                                    {
                                        "Ref": "MgmtVPCSubnet2CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "MgmtVPCSubnet2TGWRoute": {
            "Type": "AWS::EC2::Route",
            "DependsOn": "MgmtVPCTGWAttachment",
            "Properties": {
                "RouteTableId": {
                    "Ref": "MgmtVPCSubnet2RouteTable"
                },
                "DestinationCidrBlock": {
                    "Ref": "TransitGatewayRoute"
                },
                "TransitGatewayId": {
                    "Ref": "TransitGateway"
                }
            }
        },
        "MgmtSubnet2RouteTableAssociation": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "MgmtVPCSubnet2"
                },
                "RouteTableId": {
                    "Ref": "MgmtVPCSubnet2RouteTable"
                }
            }
        },
        "MgmtVPCSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "VpcId": {
                    "Ref": "MgmtVPC"
                },
                "GroupDescription": "Allow all traffic to TGW-connected VPCs",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "0",
                        "ToPort": "1024",
                        "CidrIp": {
                            "Ref": "TransitGatewayRoute"
                        }
                    }
                ],
                "SecurityGroupEgress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "0",
                        "ToPort": "1024",
                        "CidrIp": {
                            "Ref": "TransitGatewayRoute"
                        }
                    }
                ],
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "MgmtVPCSecurityGroup-",
                                    {
                                        "Ref": "MgmtVPC"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "App1VPC": {
            "Type": "AWS::EC2::VPC",
            "DependsOn": "TransitGateway",
            "Properties": {
                "EnableDnsSupport": "true",
                "EnableDnsHostnames": "true",
                "CidrBlock": {
                    "Ref": "App1VPCCIDR"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1VPC-",
                                    {
                                        "Ref": "App1VPCCIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "App1VPCTGWAttachment": {
            "Type": "AWS::EC2::TransitGatewayAttachment",
            "Properties": {
                "SubnetIds": [
                    {
                        "Ref": "App1VPCSubnet1"
                    },
                    {
                        "Ref": "App1VPCSubnet2"
                    }
                ],
                "TransitGatewayId": {
                    "Ref": "TransitGateway"
                },
                "VpcId": {
                    "Ref": "App1VPC"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1Attachment-",
                                    {
                                        "Ref": "App1VPCCIDR"
                                    }
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "App1VPCSubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "App1VPC"
                },
                "CidrBlock": {
                    "Ref": "App1VPCSubnet1CIDR"
                },
                "AvailabilityZone": {
                    "Fn::Select": [
                        "1",
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1VPCSubnet1-",
                                    {
                                        "Ref": "App1VPCSubnet1CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "App1VPCSubnet1RouteTable": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "App1VPC"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1VPCSubnet1RouteTable-",
                                    {
                                        "Ref": "App1VPCSubnet1CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "App1VPCSubnet1TGWRoute": {
            "Type": "AWS::EC2::Route",
            "DependsOn": "App1VPCTGWAttachment",
            "Properties": {
                "RouteTableId": {
                    "Ref": "App1VPCSubnet1RouteTable"
                },
                "DestinationCidrBlock": {
                    "Ref": "MgmtVPCSubnet1CIDR"
                },
                "TransitGatewayId": {
                    "Ref": "TransitGateway"
                }
            }
        },
        "App1Subnet1RouteTableAssociation": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "App1VPCSubnet1"
                },
                "RouteTableId": {
                    "Ref": "App1VPCSubnet1RouteTable"
                }
            }
        },
        "App1VPCSubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "App1VPC"
                },
                "CidrBlock": {
                    "Ref": "App1VPCSubnet2CIDR"
                },
                "AvailabilityZone": {
                    "Fn::Select": [
                        "0",
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1VPCSubnet2-",
                                    {
                                        "Ref": "App1VPCSubnet2CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "App1VPCSubnet2RouteTable": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "App1VPC"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1VPCSubnet2RouteTable-",
                                    {
                                        "Ref": "App1VPCSubnet2CIDR"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        },
        "App1VPCSubnet2TGWRoute": {
            "Type": "AWS::EC2::Route",
            "DependsOn": "App1VPCTGWAttachment",
            "Properties": {
                "RouteTableId": {
                    "Ref": "App1VPCSubnet2RouteTable"
                },
                "DestinationCidrBlock": {
                    "Ref": "MgmtVPCSubnet1CIDR"
                },
                "TransitGatewayId": {
                    "Ref": "TransitGateway"
                }
            }
        },
        "App1Subnet2RouteTableAssociation": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "App1VPCSubnet2"
                },
                "RouteTableId": {
                    "Ref": "App1VPCSubnet2RouteTable"
                }
            }
        },
        "App1VPCSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "VpcId": {
                    "Ref": "App1VPC"
                },
                "GroupDescription": "Allow all traffic to MgmtVPC",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "0",
                        "ToPort": "1024",
                        "CidrIp": {
                            "Ref": "MgmtVPCCIDR"
                        }
                    }
                ],
                "SecurityGroupEgress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "0",
                        "ToPort": "1024",
                        "CidrIp": {
                            "Ref": "MgmtVPCSubnet1CIDR"
                        }
                    }
                ],
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "",
                                [
                                    "App1VPCSecurityGroup-",
                                    {
                                        "Ref": "App1VPC"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "CloudFormationStack",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ]
            }
        }
    },
    "Outputs": {
        "TransitGateway": {
            "Description": "Transit Gateway",
            "Value": {
                "Ref": "TransitGateway"
            },
            "Export": {
                "Name": {
                    "Fn::Sub": "${AWS::StackName}-TransitGateway"
                }
            }
        },
        "MgmtVPCTGWAttachment": {
            "Description": "Attachment ID of management VPC to Transit Gateway",
            "Value": {
                "Ref": "MgmtVPCTGWAttachment"
            }
        },
        "MgmtVPCID": {
            "Description": "VPCID of the management VPC",
            "Value": {
                "Ref": "MgmtVPC"
            },
            "Export": {
                "Name": {
                    "Fn::Sub": "${AWS::StackName}-MgmtVPC"
                }
            }
        },
        "MgmtVPCSubnet1": {
            "Description": "SubnetId of the first subnet in the management VPC",
            "Value": {
                "Ref": "MgmtVPCSubnet1"
            }
        },
        "MgmtVPCSubnet1RouteTable": {
            "Description": "Route table ID of the first subnet in the management VPC",
            "Value": {
                "Ref": "MgmtVPCSubnet1RouteTable"
            }
        },
        "MgmtVPCSubnet2": {
            "Description": "SubnetId of the second subnet in the management VPC",
            "Value": {
                "Ref": "MgmtVPCSubnet2"
            }
        },
        "MgmtVPCSubnet2RouteTable": {
            "Description": "Route table ID of the second subnet in the management VPC",
            "Value": {
                "Ref": "MgmtVPCSubnet2RouteTable"
            }
        },
        "App1VPCID": {
            "Description": "VPCID of the App1 VPC",
            "Value": {
                "Ref": "App1VPC"
            },
            "Export": {
                "Name": {
                    "Fn::Sub": "${AWS::StackName}-App1VPC"
                }
            }
        },
        "App1VPCSubnet1": {
            "Description": "SubnetId of the first subnet in the App1 VPC",
            "Value": {
                "Ref": "App1VPCSubnet1"
            }
        },
        "App1VPCSubnet1RouteTable": {
            "Description": "Route table ID of the first subnet in the App1 VPC",
            "Value": {
                "Ref": "App1VPCSubnet1RouteTable"
            }
        },
        "App1VPCSubnet2": {
            "Description": "SubnetId of the second subnet in the App1 VPC",
            "Value": {
                "Ref": "App1VPCSubnet2"
            }
        },
        "App1VPCSubnet2RouteTable": {
            "Description": "Route table ID of the second subnet in the App1 VPC",
            "Value": {
                "Ref": "App1VPCSubnet2RouteTable"
            }
        }
    }
}
Techmandra Avatar

Leave a Reply

Your email address will not be published. Required fields are marked *