# SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # SPDX-License-Identifier: MIT-0 License AWSTemplateFormatVersion: '2010-09-09' Description: >- This template creates a Multi-AZ, multi-subnet VPC infrastructure with managed NAT gateways in the public subnet for each Availability Zone. You can also create additional private subnets with dedicated custom network access control lists (ACLs). If you deploy the Quick Start in a region that doesn't support NAT gateways, NAT instances are deployed instead. **WARNING** This template creates AWS resources. You will be billed for the AWS resources used if you create a stack from this template. (qs-1qnnspaap) Metadata: QuickStartDocumentation: EntrypointName: 'Launch a New VPC' OptionalParameters: - PrivateSubnetATag1 - PrivateSubnetATag2 - PrivateSubnetATag3 - PrivateSubnetBTag1 - PrivateSubnetBTag2 - PrivateSubnetBTag3 - PublicSubnetTag1 - PublicSubnetTag2 - PublicSubnetTag3 AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Availability Zone Configuration Parameters: - AvailabilityZones - NumberOfAZs - Label: default: Network Configuration Parameters: - VPCCIDR - CreatePublicSubnets - PublicSubnet1CIDR - PublicSubnet2CIDR - PublicSubnet3CIDR - PublicSubnet4CIDR - PublicSubnetTag1 - PublicSubnetTag2 - PublicSubnetTag3 - CreatePrivateSubnets - CreateNATGateways - PrivateSubnet1ACIDR - PrivateSubnet2ACIDR - PrivateSubnet3ACIDR - PrivateSubnet4ACIDR - PrivateSubnetATag1 - PrivateSubnetATag2 - PrivateSubnetATag3 - CreateAdditionalPrivateSubnets - PrivateSubnet1BCIDR - PrivateSubnet2BCIDR - PrivateSubnet3BCIDR - PrivateSubnet4BCIDR - PrivateSubnetBTag1 - PrivateSubnetBTag2 - PrivateSubnetBTag3 - VPCTenancy - Label: default: VPC Flow Logs Configuration Parameters: - CreateVPCFlowLogsToCloudWatch - VPCFlowLogsLogFormat - VPCFlowLogsLogGroupRetention - VPCFlowLogsMaxAggregationInterval - VPCFlowLogsTrafficType - VPCFlowLogsCloudWatchKMSKey ParameterLabels: AvailabilityZones: default: Availability Zones CreateAdditionalPrivateSubnets: default: Create additional private subnets with dedicated network ACLs CreateNATGateways: default: Create NAT Gateways CreatePrivateSubnets: default: Create private subnets CreatePublicSubnets: default: Create public subnets CreateVPCFlowLogsToCloudWatch: default: Create VPC Flow Logs (CloudWatch) NumberOfAZs: default: Number of Availability Zones PrivateSubnet1ACIDR: default: Private subnet 1A CIDR PrivateSubnet1BCIDR: default: Private subnet 1B with dedicated network ACL CIDR PrivateSubnet2ACIDR: default: Private subnet 2A CIDR PrivateSubnet2BCIDR: default: Private subnet 2B with dedicated network ACL CIDR PrivateSubnet3ACIDR: default: Private subnet 3A CIDR PrivateSubnet3BCIDR: default: Private subnet 3B with dedicated network ACL CIDR PrivateSubnet4ACIDR: default: Private subnet 4A CIDR PrivateSubnet4BCIDR: default: Private subnet 4B with dedicated network ACL CIDR PrivateSubnetATag1: default: Tag for Private A Subnets PrivateSubnetATag2: default: Tag for Private A Subnets PrivateSubnetATag3: default: Tag for Private A Subnets PrivateSubnetBTag1: default: Tag for Private B Subnets PrivateSubnetBTag2: default: Tag for Private B Subnets PrivateSubnetBTag3: default: Tag for Private B Subnets PublicSubnet1CIDR: default: Public subnet 1 CIDR PublicSubnet2CIDR: default: Public subnet 2 CIDR PublicSubnet3CIDR: default: Public subnet 3 CIDR PublicSubnet4CIDR: default: Public subnet 4 CIDR PublicSubnetTag1: default: Tag for Public Subnets PublicSubnetTag2: default: Tag for Public Subnets PublicSubnetTag3: default: Tag for Public Subnets VPCCIDR: default: VPC CIDR VPCFlowLogsCloudWatchKMSKey: default: CloudWatch Logs KMS Key for VPC flow logs VPCFlowLogsLogFormat: default: VPC Flow Logs - Log Format VPCFlowLogsLogGroupRetention: default: VPC Flow Logs - Log Group Retention VPCFlowLogsMaxAggregationInterval: default: VPC Flow Logs - Max Aggregation Interval VPCFlowLogsTrafficType: default: VPC Flow Logs - Traffic Type VPCTenancy: default: VPC Tenancy Parameters: AvailabilityZones: Description: 'List of Availability Zones to use for the subnets in the VPC. Note: The logical order is preserved.' Type: List CreateAdditionalPrivateSubnets: AllowedValues: - 'true' - 'false' Default: 'false' Description: >- Set to true to create a network ACL protected subnet in each Availability Zone. If false, the CIDR parameters for those subnets will be ignored. If true, it also requires that the 'Create private subnets' parameter is also true to have any effect. Type: String CreateNATGateways: AllowedValues: - 'true' - 'false' Default: 'true' Description: Set to false when creating only private subnets. If True, both CreatePublicSubnets and CreatePrivateSubnets must also be true. Type: String CreatePublicSubnets: AllowedValues: - 'true' - 'false' Default: 'true' Description: Set to false to create only private subnets. If false, CreatePrivateSubnets must be True and the CIDR parameters for ALL public subnets will be ignored Type: String CreatePrivateSubnets: AllowedValues: - 'true' - 'false' Default: 'true' Description: Set to false to create only public subnets. If false, the CIDR parameters for ALL private subnets will be ignored. Type: String CreateVPCFlowLogsToCloudWatch: AllowedValues: - 'true' - 'false' Default: 'false' Description: Set to true to create VPC flow logs for the VPC and publish them to CloudWatch. If false, VPC flow logs will not be created. Type: String NumberOfAZs: AllowedValues: - '2' - '3' - '4' Default: '2' Description: Number of Availability Zones to use in the VPC. This must match your selections in the list of Availability Zones parameter. Type: String PrivateSubnet1ACIDR: 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.0.0.0/19 Description: CIDR block for private subnet 1A located in Availability Zone 1 Type: String PrivateSubnet1BCIDR: 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.0.192.0/21 Description: CIDR block for private subnet 1B with dedicated network ACL located in Availability Zone 1 Type: String PrivateSubnet2ACIDR: 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.0.32.0/19 Description: CIDR block for private subnet 2A located in Availability Zone 2 Type: String PrivateSubnet2BCIDR: 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.0.200.0/21 Description: CIDR block for private subnet 2B with dedicated network ACL located in Availability Zone 2 Type: String PrivateSubnet3ACIDR: 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.0.64.0/19 Description: CIDR block for private subnet 3A located in Availability Zone 3 Type: String PrivateSubnet3BCIDR: 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.0.208.0/21 Description: CIDR block for private subnet 3B with dedicated network ACL located in Availability Zone 3 Type: String PrivateSubnet4ACIDR: 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.0.96.0/19 Description: CIDR block for private subnet 4A located in Availability Zone 4 Type: String PrivateSubnet4BCIDR: 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.0.216.0/21 Description: CIDR block for private subnet 4B with dedicated network ACL located in Availability Zone 4 Type: String PrivateSubnetATag1: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: Network=Private Description: tag to add to private subnets A, in format Key=Value (Optional) Type: String PrivateSubnetATag2: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: '' Description: tag to add to private subnets A, in format Key=Value (Optional) Type: String PrivateSubnetATag3: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: '' Description: tag to add to private subnets A, in format Key=Value (Optional) Type: String PrivateSubnetBTag1: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: Network=Private Description: tag to add to private subnets B, in format Key=Value (Optional) Type: String PrivateSubnetBTag2: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: '' Description: tag to add to private subnets B, in format Key=Value (Optional) Type: String PrivateSubnetBTag3: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: '' Description: tag to add to private subnets B, in format Key=Value (Optional) Type: String PublicSubnet1CIDR: 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.0.128.0/20 Description: CIDR block for the public DMZ subnet 1 located in Availability Zone 1 Type: String PublicSubnet2CIDR: 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.0.144.0/20 Description: CIDR block for the public DMZ subnet 2 located in Availability Zone 2 Type: String PublicSubnet3CIDR: 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.0.160.0/20 Description: CIDR block for the public DMZ subnet 3 located in Availability Zone 3 Type: String PublicSubnet4CIDR: 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.0.176.0/20 Description: CIDR block for the public DMZ subnet 4 located in Availability Zone 4 Type: String PublicSubnetTag1: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: Network=Public Description: tag to add to public subnets, in format Key=Value (Optional) Type: String PublicSubnetTag2: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: '' Description: tag to add to public subnets, in format Key=Value (Optional) Type: String PublicSubnetTag3: AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: tags must be in format "Key=Value" keys can only contain [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] Default: '' Description: tag to add to public subnets, in format Key=Value (Optional) Type: String VPCCIDR: 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.0.0.0/16 Description: CIDR block for the VPC Type: String VPCFlowLogsCloudWatchKMSKey: AllowedPattern: '^$|^arn:(aws[a-zA-Z-]*)?:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$' ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' Default: '' Description: (Optional) KMS Key ARN to use for encrypting the VPC flow logs data. If empty, encryption is enabled with CloudWatch Logs managing the server-side encryption keys. Type: String VPCFlowLogsLogFormat: AllowedPattern: '^(\$\{[a-z-]+\})$|^((\$\{[a-z-]+\} )*\$\{[a-z-]+\})$' Default: '${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}' Description: The fields to include in the flow log record, in the order in which they should appear. Specify the fields using the ${field-id} format, separated by spaces. Using the Default Format as the default value. Type: String VPCFlowLogsLogGroupRetention: AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] Default: 14 Description: Number of days to retain the VPC Flow Logs in CloudWatch Type: String VPCFlowLogsMaxAggregationInterval: AllowedValues: - 60 - 600 Default: 600 Description: The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. You can specify 60 seconds (1 minute) or 600 seconds (10 minutes). Type: String VPCFlowLogsTrafficType: AllowedValues: - ACCEPT - ALL - REJECT Default: REJECT Description: The type of traffic to log. You can log traffic that the resource accepts or rejects, or all traffic. Type: String VPCTenancy: AllowedValues: - default - dedicated Default: default Description: The allowed tenancy of instances launched into the VPC Type: String Rules: NAT: RuleCondition: !Equals [!Ref CreateNATGateways, 'true'] Assertions: - Assert: !And - !Equals [!Ref CreatePrivateSubnets, 'true'] - !Equals [!Ref CreatePublicSubnets, 'true'] AssertDescription: To enable NAT gateways you must have both CreatePrivateSubnets and CreatePublicSubnets set to 'true' Subnets: Assertions: - Assert: !Or - !Equals [!Ref CreatePrivateSubnets, 'true'] - !Equals [!Ref CreatePublicSubnets, 'true'] AssertDescription: At least one of CreatePublicSubnets or CreatePrivateSubnets must be set to 'true' Conditions: 3AZCondition: !Or - !Equals [!Ref 'NumberOfAZs', '3'] - !Condition '4AZCondition' 4AZCondition: !Equals [!Ref 'NumberOfAZs', '4'] AdditionalPrivateSubnetsCondition: !And - !Equals [!Ref 'CreatePrivateSubnets', 'true'] - !Equals [!Ref 'CreateAdditionalPrivateSubnets', 'true'] AdditionalPrivateSubnets&3AZCondition: !And - !Condition 'AdditionalPrivateSubnetsCondition' - !Condition '3AZCondition' AdditionalPrivateSubnets&4AZCondition: !And - !Condition 'AdditionalPrivateSubnetsCondition' - !Condition '4AZCondition' AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition: !And - !Condition 'AdditionalPrivateSubnetsCondition' - !Condition 'PublicSubnetsCondition' - !Condition 'NATGatewaysCondition' AdditionalPrivateSubnets&PublicSubnets&NatGateways&3AZCondition: !And - !Condition 'AdditionalPrivateSubnets&3AZCondition' - !Condition 'PublicSubnetsCondition' - !Condition 'NATGatewaysCondition' AdditionalPrivateSubnets&PublicSubnets&NatGateways&4AZCondition: !And - !Condition 'AdditionalPrivateSubnets&4AZCondition' - !Condition 'PublicSubnetsCondition' - !Condition 'NATGatewaysCondition' NATGatewaysCondition: !Equals [!Ref 'CreateNATGateways', 'true'] NATGateways&PublicSubnets&PrivateSubnetsCondition: !And - !Condition 'NATGatewaysCondition' - !Condition 'PublicSubnetsCondition' - !Condition 'PrivateSubnetsCondition' NATGateways&PublicSubnets&PrivateSubnets&3AZCondition: !And - !Condition 'NATGatewaysCondition' - !Condition 'PublicSubnetsCondition' - !Condition 'PrivateSubnetsCondition' - !Condition '3AZCondition' NATGateways&PublicSubnets&PrivateSubnets&4AZCondition: !And - !Condition 'NATGatewaysCondition' - !Condition 'PublicSubnetsCondition' - !Condition 'PrivateSubnetsCondition' - !Condition '4AZCondition' NVirginiaRegionCondition: !Equals [!Ref 'AWS::Region', us-east-1] PrivateSubnetsCondition: !Equals [!Ref 'CreatePrivateSubnets', 'true'] PrivateSubnets&3AZCondition: !And - !Condition 'PrivateSubnetsCondition' - !Condition '3AZCondition' PrivateSubnets&4AZCondition: !And - !Condition 'PrivateSubnetsCondition' - !Condition '4AZCondition' PublicSubnetsCondition: !Equals [!Ref 'CreatePublicSubnets', 'true'] PublicSubnets&3AZCondition: !And - !Condition 'PublicSubnetsCondition' - !Condition '3AZCondition' PublicSubnets&4AZCondition: !And - !Condition 'PublicSubnetsCondition' - !Condition '4AZCondition' PrivateSubnetATag1Condition: !Not [!Equals [!Ref 'PrivateSubnetATag1', '']] PrivateSubnetATag2Condition: !Not [!Equals [!Ref 'PrivateSubnetATag2', '']] PrivateSubnetATag3Condition: !Not [!Equals [!Ref 'PrivateSubnetATag3', '']] PrivateSubnetBTag1Condition: !Not [!Equals [!Ref 'PrivateSubnetBTag1', '']] PrivateSubnetBTag2Condition: !Not [!Equals [!Ref 'PrivateSubnetBTag2', '']] PrivateSubnetBTag3Condition: !Not [!Equals [!Ref 'PrivateSubnetBTag3', '']] PublicSubnetTag1Condition: !Not [!Equals [!Ref 'PublicSubnetTag1', '']] PublicSubnetTag2Condition: !Not [!Equals [!Ref 'PublicSubnetTag2', '']] PublicSubnetTag3Condition: !Not [!Equals [!Ref 'PublicSubnetTag3', '']] VPCFlowLogsCloudWatchKMSKeyCondition: !Not [!Equals [!Ref VPCFlowLogsCloudWatchKMSKey, '']] VPCFlowLogsToCloudWatchCondition: !Equals [!Ref 'CreateVPCFlowLogsToCloudWatch', 'true'] Resources: DHCPOptions: Type: AWS::EC2::DHCPOptions Properties: DomainName: !If [NVirginiaRegionCondition, ec2.internal, !Sub '${AWS::Region}.compute.internal'] DomainNameServers: - AmazonProvidedDNS Tags: - Key: Name Value: !Sub ${AWS::StackName} stack DHCPOptions - Key: StackName Value: !Ref AWS::StackName VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref 'VPCCIDR' InstanceTenancy: !Ref 'VPCTenancy' EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Ref 'AWS::StackName' VPCDHCPOptionsAssociation: Type: AWS::EC2::VPCDHCPOptionsAssociation Properties: VpcId: !Ref 'VPC' DhcpOptionsId: !Ref 'DHCPOptions' InternetGateway: Condition: PublicSubnetsCondition Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Ref 'AWS::StackName' VPCGatewayAttachment: Condition: PublicSubnetsCondition Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref 'VPC' InternetGatewayId: !Ref 'InternetGateway' PrivateSubnet1A: Condition: PrivateSubnetsCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet1ACIDR' AvailabilityZone: !Select ['0', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 1A - !If - PrivateSubnetATag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag3']] - !Ref 'AWS::NoValue' PrivateSubnet1B: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet1BCIDR' AvailabilityZone: !Select ['0', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 1B - !If - PrivateSubnetBTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag3']] - !Ref 'AWS::NoValue' PrivateSubnet2A: Condition: PrivateSubnetsCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet2ACIDR' AvailabilityZone: !Select ['1', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 2A - !If - PrivateSubnetATag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag3']] - !Ref 'AWS::NoValue' PrivateSubnet2B: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet2BCIDR' AvailabilityZone: !Select ['1', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 2B - !If - PrivateSubnetBTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag3']] - !Ref 'AWS::NoValue' PrivateSubnet3A: Condition: PrivateSubnets&3AZCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet3ACIDR' AvailabilityZone: !Select ['2', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 3A - !If - PrivateSubnetATag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag3']] - !Ref 'AWS::NoValue' PrivateSubnet3B: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet3BCIDR' AvailabilityZone: !Select ['2', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 3B - !If - PrivateSubnetBTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag3']] - !Ref 'AWS::NoValue' PrivateSubnet4A: Condition: PrivateSubnets&4AZCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet4ACIDR' AvailabilityZone: !Select ['3', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 4A - !If - PrivateSubnetATag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetATag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetATag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetATag3']] - !Ref 'AWS::NoValue' PrivateSubnet4B: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PrivateSubnet4BCIDR' AvailabilityZone: !Select ['3', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Private subnet 4B - !If - PrivateSubnetBTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag1']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag1']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag2']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag2']] - !Ref 'AWS::NoValue' - !If - PrivateSubnetBTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PrivateSubnetBTag3']] Value: !Select ['1', !Split ['=', !Ref 'PrivateSubnetBTag3']] - !Ref 'AWS::NoValue' PublicSubnet1: Condition: PublicSubnetsCondition Type: AWS::EC2::Subnet Metadata: cfn_nag: rules_to_suppress: - id: W33 reason: "(W33) EC2 Subnet should not have MapPublicIpOnLaunch set to true" Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PublicSubnet1CIDR' AvailabilityZone: !Select ['0', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Public subnet 1 - !If - PublicSubnetTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag1']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag1']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag2']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag2']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag3']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag3']] - !Ref 'AWS::NoValue' MapPublicIpOnLaunch: true PublicSubnet2: Condition: PublicSubnetsCondition Type: AWS::EC2::Subnet Metadata: cfn_nag: rules_to_suppress: - id: W33 reason: "(W33) EC2 Subnet should not have MapPublicIpOnLaunch set to true" Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PublicSubnet2CIDR' AvailabilityZone: !Select ['1', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Public subnet 2 - !If - PublicSubnetTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag1']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag1']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag2']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag2']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag3']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag3']] - !Ref 'AWS::NoValue' MapPublicIpOnLaunch: true PublicSubnet3: Condition: PublicSubnets&3AZCondition Type: AWS::EC2::Subnet Metadata: cfn_nag: rules_to_suppress: - id: W33 reason: "(W33) EC2 Subnet should not have MapPublicIpOnLaunch set to true" Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PublicSubnet3CIDR' AvailabilityZone: !Select ['2', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Public subnet 3 - !If - PublicSubnetTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag1']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag1']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag2']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag2']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag3']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag3']] - !Ref 'AWS::NoValue' MapPublicIpOnLaunch: true PublicSubnet4: Condition: PublicSubnets&4AZCondition Type: AWS::EC2::Subnet Metadata: cfn_nag: rules_to_suppress: - id: W33 reason: "(W33) EC2 Subnet should not have MapPublicIpOnLaunch set to true" Properties: VpcId: !Ref 'VPC' CidrBlock: !Ref 'PublicSubnet4CIDR' AvailabilityZone: !Select ['3', !Ref 'AvailabilityZones'] Tags: - Key: Name Value: Public subnet 4 - !If - PublicSubnetTag1Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag1']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag1']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag2Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag2']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag2']] - !Ref 'AWS::NoValue' - !If - PublicSubnetTag3Condition - Key: !Select ['0', !Split ['=', !Ref 'PublicSubnetTag3']] Value: !Select ['1', !Split ['=', !Ref 'PublicSubnetTag3']] - !Ref 'AWS::NoValue' MapPublicIpOnLaunch: true PrivateSubnet1ARouteTable: Condition: PrivateSubnetsCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 1A - Key: Network Value: Private PrivateSubnet1ARoute: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet1ARouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway1' PrivateSubnet1ARouteTableAssociation: Condition: PrivateSubnetsCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet1A' RouteTableId: !Ref 'PrivateSubnet1ARouteTable' PrivateSubnet2ARouteTable: Condition: PrivateSubnetsCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 2A - Key: Network Value: Private PrivateSubnet2ARoute: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet2ARouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway2' PrivateSubnet2ARouteTableAssociation: Condition: PrivateSubnetsCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet2A' RouteTableId: !Ref 'PrivateSubnet2ARouteTable' PrivateSubnet3ARouteTable: Condition: PrivateSubnets&3AZCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 3A - Key: Network Value: Private PrivateSubnet3ARoute: Condition: NATGateways&PublicSubnets&PrivateSubnets&3AZCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet3ARouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway3' PrivateSubnet3ARouteTableAssociation: Condition: PrivateSubnets&3AZCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet3A' RouteTableId: !Ref 'PrivateSubnet3ARouteTable' PrivateSubnet4ARouteTable: Condition: PrivateSubnets&4AZCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 4A - Key: Network Value: Private PrivateSubnet4ARoute: Condition: NATGateways&PublicSubnets&PrivateSubnets&4AZCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet4ARouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway4' PrivateSubnet4ARouteTableAssociation: Condition: PrivateSubnets&4AZCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet4A' RouteTableId: !Ref 'PrivateSubnet4ARouteTable' PrivateSubnet1BRouteTable: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 1B - Key: Network Value: Private PrivateSubnet1BRoute: Condition: AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet1BRouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway1' PrivateSubnet1BRouteTableAssociation: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet1B' RouteTableId: !Ref 'PrivateSubnet1BRouteTable' PrivateSubnet1BNetworkAcl: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: NACL Protected subnet 1 - Key: Network Value: NACL Protected PrivateSubnet1BNetworkAclEntryInbound: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: false NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet1BNetworkAclEntryOutbound: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: true NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet1BNetworkAclAssociation: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref 'PrivateSubnet1B' NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' PrivateSubnet2BRouteTable: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 2B - Key: Network Value: Private PrivateSubnet2BRoute: Condition: AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet2BRouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway2' PrivateSubnet2BRouteTableAssociation: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet2B' RouteTableId: !Ref 'PrivateSubnet2BRouteTable' PrivateSubnet2BNetworkAcl: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: NACL Protected subnet 2 - Key: Network Value: NACL Protected PrivateSubnet2BNetworkAclEntryInbound: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: false NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet2BNetworkAclEntryOutbound: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: true NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet2BNetworkAclAssociation: Condition: AdditionalPrivateSubnetsCondition Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref 'PrivateSubnet2B' NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' PrivateSubnet3BRouteTable: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 3B - Key: Network Value: Private PrivateSubnet3BRoute: Condition: AdditionalPrivateSubnets&PublicSubnets&NatGateways&3AZCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet3BRouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway3' PrivateSubnet3BRouteTableAssociation: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet3B' RouteTableId: !Ref 'PrivateSubnet3BRouteTable' PrivateSubnet3BNetworkAcl: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: NACL Protected subnet 3 - Key: Network Value: NACL Protected PrivateSubnet3BNetworkAclEntryInbound: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: false NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet3BNetworkAclEntryOutbound: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: true NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet3BNetworkAclAssociation: Condition: AdditionalPrivateSubnets&3AZCondition Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref 'PrivateSubnet3B' NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' PrivateSubnet4BRouteTable: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Private subnet 4B - Key: Network Value: Private PrivateSubnet4BRoute: Condition: AdditionalPrivateSubnets&PublicSubnets&NatGateways&4AZCondition Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PrivateSubnet4BRouteTable' DestinationCidrBlock: '0.0.0.0/0' NatGatewayId: !Ref 'NATGateway4' PrivateSubnet4BRouteTableAssociation: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PrivateSubnet4B' RouteTableId: !Ref 'PrivateSubnet4BRouteTable' PrivateSubnet4BNetworkAcl: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: NACL Protected subnet 4 - Key: Network Value: NACL Protected PrivateSubnet4BNetworkAclEntryInbound: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: false NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet4BNetworkAclEntryOutbound: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::NetworkAclEntry Metadata: cfn_nag: rules_to_suppress: - id: W66 reason: "(W66) To avoid opening all ports for Allow rules, EC2 NetworkACL Entry Protocol should be either 6 (for TCP), 17 (for UDP), 1 (for ICMP), or 58 (for ICMPv6, which must include an IPv6 CIDR block, ICMP type, and code)." Properties: CidrBlock: '0.0.0.0/0' Egress: true NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' Protocol: -1 RuleAction: allow RuleNumber: 100 PrivateSubnet4BNetworkAclAssociation: Condition: AdditionalPrivateSubnets&4AZCondition Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref 'PrivateSubnet4B' NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' PublicSubnetRouteTable: Condition: PublicSubnetsCondition Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' Tags: - Key: Name Value: Public Subnets - Key: Network Value: Public PublicSubnetRoute: Condition: PublicSubnetsCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PublicSubnetRouteTable' DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref 'InternetGateway' PublicSubnet1RouteTableAssociation: Condition: PublicSubnetsCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PublicSubnet1' RouteTableId: !Ref 'PublicSubnetRouteTable' PublicSubnet2RouteTableAssociation: Condition: PublicSubnetsCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PublicSubnet2' RouteTableId: !Ref 'PublicSubnetRouteTable' PublicSubnet3RouteTableAssociation: Condition: PublicSubnets&3AZCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PublicSubnet3' RouteTableId: !Ref 'PublicSubnetRouteTable' PublicSubnet4RouteTableAssociation: Condition: PublicSubnets&4AZCondition Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref 'PublicSubnet4' RouteTableId: !Ref 'PublicSubnetRouteTable' NAT1EIP: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::EIP Properties: Domain: vpc Tags: - Key: Name Value: NAT1EIP NAT2EIP: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::EIP Properties: Domain: vpc Tags: - Key: Name Value: NAT2EIP NAT3EIP: Condition: NATGateways&PublicSubnets&PrivateSubnets&3AZCondition Type: AWS::EC2::EIP Properties: Domain: vpc Tags: - Key: Name Value: NAT3EIP NAT4EIP: Condition: NATGateways&PublicSubnets&PrivateSubnets&4AZCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::EIP Properties: Domain: vpc Tags: - Key: Name Value: NAT4EIP NATGateway1: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt 'NAT1EIP.AllocationId' SubnetId: !Ref 'PublicSubnet1' Tags: - Key: Name Value: NATGateway1 NATGateway2: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt 'NAT2EIP.AllocationId' SubnetId: !Ref 'PublicSubnet2' Tags: - Key: Name Value: NATGateway2 NATGateway3: Condition: NATGateways&PublicSubnets&PrivateSubnets&3AZCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt 'NAT3EIP.AllocationId' SubnetId: !Ref 'PublicSubnet3' Tags: - Key: Name Value: NATGateway3 NATGateway4: Condition: NATGateways&PublicSubnets&PrivateSubnets&4AZCondition DependsOn: VPCGatewayAttachment Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt 'NAT4EIP.AllocationId' SubnetId: !Ref 'PublicSubnet4' Tags: - Key: Name Value: NATGateway4 S3VPCEndpoint: Condition: PrivateSubnetsCondition Type: AWS::EC2::VPCEndpoint Properties: PolicyDocument: Version: '2012-10-17' Statement: - Action: '*' Effect: Allow Resource: '*' Principal: '*' RouteTableIds: - !Ref 'PrivateSubnet1ARouteTable' - !Ref 'PrivateSubnet2ARouteTable' - !If [PrivateSubnets&3AZCondition, !Ref 'PrivateSubnet3ARouteTable', !Ref 'AWS::NoValue'] - !If [PrivateSubnets&4AZCondition, !Ref 'PrivateSubnet4ARouteTable', !Ref 'AWS::NoValue'] - !If [AdditionalPrivateSubnetsCondition, !Ref 'PrivateSubnet1BRouteTable', !Ref 'AWS::NoValue'] - !If [AdditionalPrivateSubnetsCondition, !Ref 'PrivateSubnet2BRouteTable', !Ref 'AWS::NoValue'] - !If [AdditionalPrivateSubnets&3AZCondition, !Ref 'PrivateSubnet3BRouteTable', !Ref 'AWS::NoValue'] - !If [AdditionalPrivateSubnets&4AZCondition, !Ref 'PrivateSubnet4BRouteTable', !Ref 'AWS::NoValue'] ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3' VpcId: !Ref 'VPC' VPCFlowLogsRole: Condition: VPCFlowLogsToCloudWatchCondition Type: AWS::IAM::Role Properties: Description: Rights to Publish VPC Flow Logs to CloudWatch Logs AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - vpc-flow-logs.amazonaws.com Path: / Policies: - PolicyName: CloudWatchLogGroup PolicyDocument: Version: 2012-10-17 Statement: - Sid: CloudWatchLogs Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogGroups - logs:DescribeLogStreams Resource: !GetAtt VPCFlowLogsLogGroup.Arn VPCFlowLogsLogGroup: Condition: VPCFlowLogsToCloudWatchCondition Type: AWS::Logs::LogGroup Properties: RetentionInDays: !Ref VPCFlowLogsLogGroupRetention KmsKeyId: !If - VPCFlowLogsCloudWatchKMSKeyCondition - !Ref VPCFlowLogsCloudWatchKMSKey - !Ref AWS::NoValue VPCFlowLogsToCloudWatch: Condition: VPCFlowLogsToCloudWatchCondition Type: AWS::EC2::FlowLog Properties: LogDestinationType: cloud-watch-logs LogGroupName: !Ref VPCFlowLogsLogGroup DeliverLogsPermissionArn: !GetAtt VPCFlowLogsRole.Arn LogFormat: !Ref VPCFlowLogsLogFormat MaxAggregationInterval: !Ref VPCFlowLogsMaxAggregationInterval ResourceId: !Ref VPC ResourceType: VPC TrafficType: !Ref VPCFlowLogsTrafficType Tags: - Key: Name Value: VPC Flow Logs CloudWatch Outputs: NAT1EIP: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition Description: NAT 1 IP address Value: !Ref 'NAT1EIP' Export: Name: !Sub '${AWS::StackName}-NAT1EIP' NAT2EIP: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition Description: NAT 2 IP address Value: !Ref 'NAT2EIP' Export: Name: !Sub '${AWS::StackName}-NAT2EIP' NAT3EIP: Condition: NATGateways&PublicSubnets&PrivateSubnets&3AZCondition Description: NAT 3 IP address Value: !Ref 'NAT3EIP' Export: Name: !Sub '${AWS::StackName}-NAT3EIP' NAT4EIP: Condition: NATGateways&PublicSubnets&PrivateSubnets&4AZCondition Description: NAT 4 IP address Value: !Ref 'NAT4EIP' Export: Name: !Sub '${AWS::StackName}-NAT4EIP' NATGateway1ID: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition Description: NATGateway 1 ID Value: !Ref 'NATGateway1' Export: Name: !Sub '${AWS::StackName}-NATGateway1' NATGateway2ID: Condition: NATGateways&PublicSubnets&PrivateSubnetsCondition Description: NATGateway 2 ID Value: !Ref 'NATGateway2' Export: Name: !Sub '${AWS::StackName}-NATGateway2' NATGateway3ID: Condition: NATGateways&PublicSubnets&PrivateSubnets&3AZCondition Description: NATGateway 3 ID Value: !Ref 'NATGateway3' Export: Name: !Sub '${AWS::StackName}-NATGateway3' NATGateway4ID: Condition: NATGateways&PublicSubnets&PrivateSubnets&4AZCondition Description: NATGateway 4 ID Value: !Ref 'NATGateway4' Export: Name: !Sub '${AWS::StackName}-NATGateway4' PrivateSubnet1ACIDR: Condition: PrivateSubnetsCondition Description: Private subnet 1A CIDR in Availability Zone 1 Value: !Ref 'PrivateSubnet1ACIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet1ACIDR' PrivateSubnet1AID: Condition: PrivateSubnetsCondition Description: Private subnet 1A ID in Availability Zone 1 Value: !Ref 'PrivateSubnet1A' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet1AID' PrivateSubnet1ARouteTable: Condition: PrivateSubnetsCondition Value: !Ref 'PrivateSubnet1ARouteTable' Description: Private subnet 1A route table Export: Name: !Sub '${AWS::StackName}-PrivateSubnet1ARouteTable' PrivateSubnet1BCIDR: Condition: AdditionalPrivateSubnetsCondition Description: Private subnet 1B CIDR in Availability Zone 1 Value: !Ref 'PrivateSubnet1BCIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet1BCIDR' PrivateSubnet1BID: Condition: AdditionalPrivateSubnetsCondition Description: Private subnet 1B ID in Availability Zone 1 Value: !Ref 'PrivateSubnet1B' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet1BID' PrivateSubnet1BRouteTable: Condition: AdditionalPrivateSubnetsCondition Value: !Ref 'PrivateSubnet1BRouteTable' Description: Private subnet 1B route table Export: Name: !Sub '${AWS::StackName}-PrivateSubnet1BRouteTable' PrivateSubnet2ACIDR: Condition: PrivateSubnetsCondition Description: Private subnet 2A CIDR in Availability Zone 2 Value: !Ref 'PrivateSubnet2ACIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet2ACIDR' PrivateSubnet2AID: Condition: PrivateSubnetsCondition Description: Private subnet 2A ID in Availability Zone 2 Value: !Ref 'PrivateSubnet2A' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet2AID' PrivateSubnet2ARouteTable: Condition: PrivateSubnetsCondition Value: !Ref 'PrivateSubnet2ARouteTable' Description: Private subnet 2A route table Export: Name: !Sub '${AWS::StackName}-PrivateSubnet2ARouteTable' PrivateSubnet2BCIDR: Condition: AdditionalPrivateSubnetsCondition Description: Private subnet 2B CIDR in Availability Zone 2 Value: !Ref 'PrivateSubnet2BCIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet2BCIDR' PrivateSubnet2BID: Condition: AdditionalPrivateSubnetsCondition Description: Private subnet 2B ID in Availability Zone 2 Value: !Ref 'PrivateSubnet2B' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet2BID' PrivateSubnet2BRouteTable: Condition: AdditionalPrivateSubnetsCondition Value: !Ref 'PrivateSubnet2BRouteTable' Description: Private subnet 2B route table Export: Name: !Sub '${AWS::StackName}-PrivateSubnet2BRouteTable' PrivateSubnet3ACIDR: Condition: PrivateSubnets&3AZCondition Description: Private subnet 3A CIDR in Availability Zone 3 Value: !Ref 'PrivateSubnet3ACIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet3ACIDR' PrivateSubnet3AID: Condition: PrivateSubnets&3AZCondition Description: Private subnet 3A ID in Availability Zone 3 Value: !Ref 'PrivateSubnet3A' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet3AID' PrivateSubnet3ARouteTable: Condition: PrivateSubnets&3AZCondition Value: !Ref 'PrivateSubnet3ARouteTable' Description: Private subnet 3A route table Export: Name: !Sub '${AWS::StackName}-PrivateSubnet3ARouteTable' PrivateSubnet3BCIDR: Condition: AdditionalPrivateSubnets&3AZCondition Description: Private subnet 3B CIDR in Availability Zone 3 Value: !Ref 'PrivateSubnet3BCIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet3BCIDR' PrivateSubnet3BID: Condition: AdditionalPrivateSubnets&3AZCondition Description: Private subnet 3B ID in Availability Zone 3 Value: !Ref 'PrivateSubnet3B' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet3BID' PrivateSubnet3BRouteTable: Condition: AdditionalPrivateSubnets&3AZCondition Description: Private subnet 3B route table Value: !Ref 'PrivateSubnet3BRouteTable' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet3BRouteTable' PrivateSubnet4ACIDR: Condition: PrivateSubnets&4AZCondition Description: Private subnet 4A CIDR in Availability Zone 4 Value: !Ref 'PrivateSubnet4ACIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet4ACIDR' PrivateSubnet4AID: Condition: PrivateSubnets&4AZCondition Description: Private subnet 4A ID in Availability Zone 4 Value: !Ref 'PrivateSubnet4A' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet4AID' PrivateSubnet4ARouteTable: Condition: PrivateSubnets&4AZCondition Description: Private subnet 4A route table Value: !Ref 'PrivateSubnet4ARouteTable' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet4ARouteTable' PrivateSubnet4BCIDR: Condition: AdditionalPrivateSubnets&4AZCondition Description: Private subnet 4B CIDR in Availability Zone 4 Value: !Ref 'PrivateSubnet4BCIDR' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet4BCIDR' PrivateSubnet4BID: Condition: AdditionalPrivateSubnets&4AZCondition Description: Private subnet 4B ID in Availability Zone 4 Value: !Ref 'PrivateSubnet4B' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet4BID' PrivateSubnet4BRouteTable: Condition: AdditionalPrivateSubnets&4AZCondition Description: Private subnet 4B route table Value: !Ref 'PrivateSubnet4BRouteTable' Export: Name: !Sub '${AWS::StackName}-PrivateSubnet4BRouteTable' PublicSubnet1CIDR: Condition: PublicSubnetsCondition Description: Public subnet 1 CIDR in Availability Zone 1 Value: !Ref 'PublicSubnet1CIDR' Export: Name: !Sub '${AWS::StackName}-PublicSubnet1CIDR' PublicSubnet1ID: Condition: PublicSubnetsCondition Description: Public subnet 1 ID in Availability Zone 1 Value: !Ref 'PublicSubnet1' Export: Name: !Sub '${AWS::StackName}-PublicSubnet1ID' PublicSubnet2CIDR: Condition: PublicSubnetsCondition Description: Public subnet 2 CIDR in Availability Zone 2 Value: !Ref 'PublicSubnet2CIDR' Export: Name: !Sub '${AWS::StackName}-PublicSubnet2CIDR' PublicSubnet2ID: Condition: PublicSubnetsCondition Description: Public subnet 2 ID in Availability Zone 2 Value: !Ref 'PublicSubnet2' Export: Name: !Sub '${AWS::StackName}-PublicSubnet2ID' PublicSubnet3CIDR: Condition: PublicSubnets&3AZCondition Description: Public subnet 3 CIDR in Availability Zone 3 Value: !Ref 'PublicSubnet3CIDR' Export: Name: !Sub '${AWS::StackName}-PublicSubnet3CIDR' PublicSubnet3ID: Condition: PublicSubnets&3AZCondition Description: Public subnet 3 ID in Availability Zone 3 Value: !Ref 'PublicSubnet3' Export: Name: !Sub '${AWS::StackName}-PublicSubnet3ID' PublicSubnet4CIDR: Condition: PublicSubnets&4AZCondition Description: Public subnet 4 CIDR in Availability Zone 4 Value: !Ref 'PublicSubnet4CIDR' Export: Name: !Sub '${AWS::StackName}-PublicSubnet4CIDR' PublicSubnet4ID: Condition: PublicSubnets&4AZCondition Description: Public subnet 4 ID in Availability Zone 4 Value: !Ref 'PublicSubnet4' Export: Name: !Sub '${AWS::StackName}-PublicSubnet4ID' PublicSubnetRouteTable: Condition: PublicSubnetsCondition Description: Public subnet route table Value: !Ref 'PublicSubnetRouteTable' Export: Name: !Sub '${AWS::StackName}-PublicSubnetRouteTable' S3VPCEndpoint: Condition: PrivateSubnetsCondition Description: S3 VPC Endpoint Value: !Ref 'S3VPCEndpoint' Export: Name: !Sub '${AWS::StackName}-S3VPCEndpoint' VPCCIDR: Description: VPC CIDR Value: !Ref 'VPCCIDR' Export: Name: !Sub '${AWS::StackName}-VPCCIDR' VPCID: Description: VPC ID Value: !Ref 'VPC' Export: Name: !Sub '${AWS::StackName}-VPCID'