# Following example shows how to implement AWS Gateway Load Balancer (GWLB) # integrated with AWS Transit Gateway for centralized architecture using AWS # CloudFormation. It uses nested stacks and deploys entire architecture as # 1-click deployment. # For architecture details refer to blog: # https://aws.amazon.com/blogs/networking-and-content-delivery/centralized-inspection-architecture-with-aws-gateway-load-balancer-and-aws-transit-gateway/ # This is the primary template. Primar template launches: # - Appliance VPC template to configure Application VPC # - Spoke VPC template to configure to Spoke VPCs: Spoke 1 and 2. # - Transit Gateway template to configure Transti Gateway. AWSTemplateFormatVersion: "2010-09-09" Description: >- AWS CloudFormation Sample Template For deploying AWS Gateway Load Balancer (GWLB) in centralized architecture. This primary template, using nested stacks, creates appropriate resources arcoss 2 AZs. **WARNING** This template creates one or more Amazon EC2 instances, GWLB, GWLB endpints, NAT gateways and Transit Gateway. You will be billed for the AWS resources used if you create a stack from this template. Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Availability Zone Configuration Parameters: - AvailabilityZone1 - AvailabilityZone2 - Label: default: Generice EC2 - Configuration Parameters: - EC2InstanceType - EC2InstanceAmiId - EC2InstanceDiskSize - KeyPairName - AccessLocation - Label: default: Appliance VPC - Network Configuration Parameters: - ApplianceVpcCidr - ApplianceVpcTgwAttachSubnet1Cidr - ApplianceVpcApplianceSubnet1Cidr - ApplianceVpcNatgwSubnet1Cidr - ApplianceVpcTgwAttachSubnet2Cidr - ApplianceVpcApplianceSubnet2Cidr - ApplianceVpcNatgwSubnet2Cidr - Label: default: Appliance VPC - Gateway Load Balancer Configuration Parameters: - ApplianceVpcGwlbName - ApplianceVpcTargetGroupName - ApplianceVpcHealthPort - ApplianceVpcHealthProtocol - Label: default: Spoke 1 VPC - Network Configuration Parameters: - Spoke1VpcCidr - Spoke1VpcApplicationSubnet1Cidr - Spoke1VpcTgwAttachSubnet1Cidr - Spoke1VpcBastionSubnet1Cidr - Spoke1VpcApplicationSubnet2Cidr - Spoke1VpcTgwAttachSubnet2Cidr - Spoke1VpcBastionSubnet2Cidr - Label: default: Spoke 2 VPC - Network Configuration Parameters: - Spoke2VpcCidr - Spoke2VpcApplicationSubnet1Cidr - Spoke2VpcTgwAttachSubnet1Cidr - Spoke2VpcBastionSubnet1Cidr - Spoke2VpcApplicationSubnet2Cidr - Spoke2VpcTgwAttachSubnet2Cidr - Spoke2VpcBastionSubnet2Cidr ParameterLabels: AvailabilityZone1: default: Availability Zone 1 AvailabilityZone2: default: Availability Zone 2 EC2InstanceType: default: Ec2 Instance Type EC2InstanceAmiId: default: Latest AMI ID for EC2 intance EC2InstanceDiskSize: default: Appliance Instance Size in GB KeyPairName: default: KeyPair required for accessing Appliance instance AccessLocation: default: Network CIDR to access Appliance instance ApplianceVpcCidr: default: Appliance VPC - Network CIDR for VPC ApplianceVpcTgwAttachSubnet1Cidr: default: Appliance VPC - TGW Attachment Subnet 1 CIDR in AZ1 ApplianceVpcApplianceSubnet1Cidr: default: Appliance VPC - Appliance Subnet 1 CIDR in AZ1 ApplianceVpcNatgwSubnet1Cidr: default: Appliance VPC - NAT GW Subnet 1 CIDR in AZ1 ApplianceVpcTgwAttachSubnet2Cidr: default: Appliance VPC - TGW Attachment Subnet 2 CIDR in AZ2 ApplianceVpcApplianceSubnet2Cidr: default: Appliance VPC - Appliance Subnet 2 CIDR in AZ2 ApplianceVpcNatgwSubnet2Cidr: default: Appliance VPC - NAT GW Subnet 2 CIDR in AZ2 ApplianceVpcGwlbName: default: Appliance VPC - Gateway Load Balancer Name ApplianceVpcTargetGroupName: default: Appliance VPC - Target Group Name ApplianceVpcHealthPort: default: Appliance VPC - Health Check Port ApplianceVpcHealthProtocol: default: Appliance VPC - Health Check Protocol Spoke1VpcCidr: default: Spoke1 VPC - VPC CIDR Spoke1VpcApplicationSubnet1Cidr: default: Spoke1 VPC - Application Subnet 1 CIDR Spoke1VpcTgwAttachSubnet1Cidr: default: Spoke1 VPC - TGW Attachment Subnet 1 CIDR Spoke1VpcBastionSubnet1Cidr: default: Spoke1 VPC - Bastion Subnet 1 CIDR Spoke1VpcApplicationSubnet2Cidr: default: Spoke1 VPC - Application Subnet 2 CIDR Spoke1VpcTgwAttachSubnet2Cidr: default: Spoke1 VPC - TGW Attachment Subnet 2 CIDR Spoke1VpcBastionSubnet2Cidr: default: Spoke1 VPC - Bastion Subnet 2 CIDR Spoke2VpcCidr: default: Spoke2 VPC - VPC CIDR Spoke2VpcApplicationSubnet1Cidr: default: Spoke2 VPC - Application Subnet 1 CIDR Spoke2VpcTgwAttachSubnet1Cidr: default: Spoke2 VPC - TGW Attachment Subnet 1 CIDR Spoke2VpcBastionSubnet1Cidr: default: Spoke2 VPC - Bastion Subnet 1 CIDR Spoke2VpcApplicationSubnet2Cidr: default: Spoke2 VPC - Application Subnet 2 CIDR Spoke2VpcTgwAttachSubnet2Cidr: default: Spoke2 VPC - TGW Attachment Subnet 2 CIDR Spoke2VpcBastionSubnet2Cidr: default: Spoke2 VPC - Bastion Subnet 2 CIDR Parameters: # Generic Parameters: AvailabilityZone1: Description: Availability Zone 1 Type: AWS::EC2::AvailabilityZone::Name ConstraintDescription: Valid Availability Zone Id AvailabilityZone2: Description: Availability Zone 2 Type: AWS::EC2::AvailabilityZone::Name ConstraintDescription: Valid Availability Zone Id EC2InstanceType: Description: Select EC2 instance type. Default is set to t2.micro Default: t2.micro AllowedValues: - t2.micro Type: String EC2InstanceAmiId: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' EC2InstanceDiskSize: Description: EC2 instance disk size in GB. Default is set to 8GB Default: 8 AllowedValues: [8] Type: Number ConstraintDescription: Should be a valid instance size in GB KeyPairName: Description: EC2 KeyPair required for accessing EC2 instance Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: Must be the name of an existing EC2 KeyPair AccessLocation: Description: >- Enter desired Network CIDR to allow traffic to EC2 instance. Default is set to access from anywhere and it is not recommended AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" MinLength: "9" MaxLength: "18" Default: 0.0.0.0/0 Type: String ConstraintDescription: Must be a valid Network CIDR of the form x.x.x.x/y # Appliance VPC specific parameters: ApplianceVpcCidr: 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]))$" Default: 192.168.1.0/24 Description: Appliance VPC - CIDR block for the VPC Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/y # AZ1: ApplianceVpcTgwAttachSubnet1Cidr: 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]))$" Default: 192.168.1.0/28 Description: Appliance VPC - TGW Attachment Subnet 1 CIDR in AZ1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 ApplianceVpcApplianceSubnet1Cidr: 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]))$" Default: 192.168.1.16/28 Description: Appliance VPC - Appliance Subnet 1 CIDR in AZ1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 ApplianceVpcNatgwSubnet1Cidr: 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]))$" Default: 192.168.1.32/28 Description: Appliance VPC - NAT GW Subnet 1 CIDR in AZ1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 # AZ2: ApplianceVpcTgwAttachSubnet2Cidr: 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]))$" Default: 192.168.1.48/28 Description: Appliance VPC - TGW Attachment Subnet 2 CIDR in AZ2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 ApplianceVpcApplianceSubnet2Cidr: 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]))$" Default: 192.168.1.64/28 Description: Appliance VPC - Appliance Subnet 2 CIDR in AZ2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 ApplianceVpcNatgwSubnet2Cidr: 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]))$" Default: 192.168.1.80/28 Description: Appliance VPC - NAT GW Subnet 2 CIDR in AZ2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 ApplianceVpcGwlbName: Description: >- Gateway Load Balancer name. This name must be unique within your AWS account and can have a maximum of 32 alphanumeric characters and hyphens. A name cannot begin or end with a hyphen. Type: String Default: gwlb1 ConstraintDescription: Must be a valid GWLB Name ApplianceVpcTargetGroupName: Description: Target Group Name Type: String Default: gwlb1-tg1 ConstraintDescription: Must be a valid target group name ApplianceVpcHealthProtocol: Description: >- The protocol GWLB uses when performing health checks on targets. Default is HTTP. Type: String Default: HTTP AllowedValues: ['TCP', 'HTTP', 'HTTPS'] ConstraintDescription: Must be a valid health check protocol ApplianceVpcHealthPort: Description: >- The port the load balancer uses when performing health checks on targets. Default is 80. Type: String Default: '80' ConstraintDescription: Must be a valid health check port # Spoke1 VPC specific parameters: Spoke1VpcCidr: 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]))$" Default: 10.0.0.0/24 Description: Spoke1 VPC - CIDR block for the VPC Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 # AZ1: Spoke1VpcApplicationSubnet1Cidr: 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]))$" Default: 10.0.0.0/28 Description: Spoke1 VPC - Application Subnet 1 CIDR in Availability Zone 1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 Spoke1VpcTgwAttachSubnet1Cidr: 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]))$" Default: 10.0.0.16/28 Description: Spoke1 VPC - TGW Attachment Subnet 1 CIDR in Availability Zone 1 Type: String ConstraintDescription: Subnet CIDR parameter must be in the form x.x.x.x/16-28 Spoke1VpcBastionSubnet1Cidr: 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]))$" Default: 10.0.0.64/28 Description: Spoke1 VPC - Bastion Subnet 1 CIDR in Availability Zone 1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 # AZ2: Spoke1VpcApplicationSubnet2Cidr: 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]))$" Default: 10.0.0.32/28 Description: Spoke1 VPC - Application Subnet 2 CIDR in Availability Zone 2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 Spoke1VpcTgwAttachSubnet2Cidr: 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]))$" Default: 10.0.0.48/28 Description: Spoke1 VPC - TGW Attachment Subnet 2 CIDR in Availability Zone 1 Type: String ConstraintDescription: Subnet CIDR parameter must be in the form x.x.x.x/16-28 Spoke1VpcBastionSubnet2Cidr: 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]))$" Default: 10.0.0.80/28 Description: Spoke1 VPC - Bastion Subnet 2 CIDR in Availability Zone 2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 # Spoke2 VPC specific parameters: Spoke2VpcCidr: 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]))$" Default: 10.0.1.0/24 Description: Spoke2 VPC - CIDR block for the VPC Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 # AZ1: Spoke2VpcApplicationSubnet1Cidr: 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]))$" Default: 10.0.1.0/28 Description: Spoke2 VPC - Application Subnet 1 CIDR in Availability Zone 1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 Spoke2VpcTgwAttachSubnet1Cidr: 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]))$" Default: 10.0.1.16/28 Description: Spoke2 VPC - TGW Attachment Subnet 1 CIDR in Availability Zone 1 Type: String ConstraintDescription: Subnet CIDR parameter must be in the form x.x.x.x/16-28 Spoke2VpcBastionSubnet1Cidr: 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]))$" Default: 10.0.1.64/28 Description: Spoke2 VPC - Bastion Subnet 1 CIDR in Availability Zone 1 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 # AZ2: Spoke2VpcApplicationSubnet2Cidr: 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]))$" Default: 10.0.1.32/28 Description: Spoke2 VPC - Application Subnet 2 CIDR in Availability Zone 2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 Spoke2VpcTgwAttachSubnet2Cidr: 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]))$" Default: 10.0.1.48/28 Description: Spoke2 VPC - TGW Attachment Subnet 2 CIDR in Availability Zone 1 Type: String ConstraintDescription: Subnet CIDR parameter must be in the form x.x.x.x/16-28 Spoke2VpcBastionSubnet2Cidr: 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]))$" Default: 10.0.1.80/28 Description: Spoke2 VPC - Bastion Subnet 2 CIDR in Availability Zone 2 Type: String ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 Resources: ApplianceVpcStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: 'https://s3-us-west-2.amazonaws.com/tech-content-us-west-2/aws-gwlb-cloudformation-samples/centralized-architecture/nested-stack/ApplianceVpc2Az.yaml' Parameters: VpcCidr: !Ref ApplianceVpcCidr AvailabilityZone1: !Ref AvailabilityZone1 TgwAttachSubnet1Cidr: !Ref ApplianceVpcTgwAttachSubnet1Cidr ApplianceSubnet1Cidr: !Ref ApplianceVpcApplianceSubnet1Cidr NatgwSubnet1Cidr: !Ref ApplianceVpcNatgwSubnet1Cidr AvailabilityZone2: !Ref AvailabilityZone2 TgwAttachSubnet2Cidr: !Ref ApplianceVpcTgwAttachSubnet2Cidr ApplianceSubnet2Cidr: !Ref ApplianceVpcApplianceSubnet2Cidr NatgwSubnet2Cidr: !Ref ApplianceVpcNatgwSubnet2Cidr ApplianceInstanceType: !Ref EC2InstanceType ApplianceInstanceAmiId: !Ref EC2InstanceAmiId ApplianceInstanceDiskSize: !Ref EC2InstanceDiskSize KeyPairName: !Ref KeyPairName AccessLocation: !Ref AccessLocation Spoke1VpcCidr: !Ref Spoke1VpcCidr Spoke2VpcCidr: !Ref Spoke2VpcCidr GwlbName: !Ref ApplianceVpcGwlbName TargetGroupName: !Ref ApplianceVpcTargetGroupName HealthPort: !Ref ApplianceVpcHealthPort HealthProtocol: !Ref ApplianceVpcHealthProtocol Spoke1VpcStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: 'https://s3-us-west-2.amazonaws.com/tech-content-us-west-2/aws-gwlb-cloudformation-samples/centralized-architecture/nested-stack/SpokeVpc2Az.yaml' Parameters: VpcCidr: !Ref Spoke1VpcCidr AvailabilityZone1: !Ref AvailabilityZone1 BastionSubnet1Cidr: !Ref Spoke1VpcBastionSubnet1Cidr ApplicationSubnet1Cidr: !Ref Spoke1VpcApplicationSubnet1Cidr TgwAttachSubnet1Cidr: !Ref Spoke1VpcTgwAttachSubnet1Cidr AvailabilityZone2: !Ref AvailabilityZone2 BastionSubnet2Cidr: !Ref Spoke1VpcBastionSubnet2Cidr ApplicationSubnet2Cidr: !Ref Spoke1VpcApplicationSubnet2Cidr TgwAttachSubnet2Cidr: !Ref Spoke1VpcTgwAttachSubnet2Cidr ApplicationInstanceType: !Ref EC2InstanceType ApplicationInstanceAmiId: !Ref EC2InstanceAmiId ApplicationInstanceDiskSize: !Ref EC2InstanceDiskSize KeyPairName: !Ref KeyPairName AccessLocation: !Ref AccessLocation Spoke2VpcStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: 'https://s3-us-west-2.amazonaws.com/tech-content-us-west-2/aws-gwlb-cloudformation-samples/centralized-architecture/nested-stack/SpokeVpc2Az.yaml' Parameters: VpcCidr: !Ref Spoke2VpcCidr AvailabilityZone1: !Ref AvailabilityZone1 BastionSubnet1Cidr: !Ref Spoke2VpcBastionSubnet1Cidr ApplicationSubnet1Cidr: !Ref Spoke2VpcApplicationSubnet1Cidr TgwAttachSubnet1Cidr: !Ref Spoke2VpcTgwAttachSubnet1Cidr AvailabilityZone2: !Ref AvailabilityZone2 BastionSubnet2Cidr: !Ref Spoke2VpcBastionSubnet2Cidr ApplicationSubnet2Cidr: !Ref Spoke2VpcApplicationSubnet2Cidr TgwAttachSubnet2Cidr: !Ref Spoke2VpcTgwAttachSubnet2Cidr ApplicationInstanceType: !Ref EC2InstanceType ApplicationInstanceAmiId: !Ref EC2InstanceAmiId ApplicationInstanceDiskSize: !Ref EC2InstanceDiskSize KeyPairName: !Ref KeyPairName AccessLocation: !Ref AccessLocation TgwStack: Type: AWS::CloudFormation::Stack DependsOn: ['ApplianceVpcStack', 'Spoke1VpcStack', 'Spoke2VpcStack' ] Properties: TemplateURL: 'https://s3-us-west-2.amazonaws.com/tech-content-us-west-2/aws-gwlb-cloudformation-samples/centralized-architecture/nested-stack/Tgw.yaml' Parameters: ApplianceVpcId: !GetAtt - ApplianceVpcStack - Outputs.ApplianceVpcId ApplianceVpcTgwAttachSubnet1Id: !GetAtt ['ApplianceVpcStack', 'Outputs.ApplianceTgwAttachSubnet1Id'] ApplianceVpcTgwAttachSubnet2Id: !GetAtt ['ApplianceVpcStack', 'Outputs.ApplianceTgwAttachSubnet2Id'] ApplianceVpcApplianceRtb1Id: !GetAtt ['ApplianceVpcStack', 'Outputs.ApplianceRtb1Id'] ApplianceVpcApplianceRtb2Id: !GetAtt ['ApplianceVpcStack', 'Outputs.ApplianceRtb2Id'] Spoke1VpcId: !GetAtt ['Spoke1VpcStack', 'Outputs.SpokeVpcId'] Spoke1VpcCidr: !GetAtt ['Spoke1VpcStack', 'Outputs.SpokeVpcCidr'] Spoke1VpcTgwAttachSubnet1Id: !GetAtt ['Spoke1VpcStack', 'Outputs.SpokeTgwAttachSubnet1Id'] Spoke1VpcTgwAttachSubnet2Id: !GetAtt ['Spoke1VpcStack', 'Outputs.SpokeTgwAttachSubnet2Id'] Spoke1VpcRtb1Id: !GetAtt ['Spoke1VpcStack', 'Outputs.SpokeApplicationRouteTableId'] Spoke2VpcId: !GetAtt ['Spoke2VpcStack', 'Outputs.SpokeVpcId'] Spoke2VpcCidr: !GetAtt ['Spoke2VpcStack', 'Outputs.SpokeVpcCidr'] Spoke2VpcTgwAttachSubnet1Id: !GetAtt ['Spoke2VpcStack', 'Outputs.SpokeTgwAttachSubnet1Id'] Spoke2VpcTgwAttachSubnet2Id: !GetAtt ['Spoke2VpcStack', 'Outputs.SpokeTgwAttachSubnet2Id'] Spoke2VpcRtb1Id: !GetAtt ['Spoke2VpcStack', 'Outputs.SpokeApplicationRouteTableId'] AccessLocation: !Ref AccessLocation