AWSTemplateFormatVersion: 2010-09-09 Description: >- This template creates a Multi-AZ, multisubnet 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 an AWS 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: LICENSE: Apache License, Version 2.0 QuickStartDocumentation: EntrypointName: Launch a new VPC 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 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 pair 1 for private A subnets PrivateSubnetATag2: default: Tag pair 2 for private A subnets PrivateSubnetATag3: default: Tag pair 3 for private A subnets PrivateSubnetBTag1: default: Tag pair 1 for private B subnets PrivateSubnetBTag2: default: Tag pair 2 for private B subnets PrivateSubnetBTag3: default: Tag pair 3 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 pair 1 for public subnets PublicSubnetTag2: default: Tag pair 2 for public subnets PublicSubnetTag3: default: Tag pair 3 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: Type: List Description: >- Availability Zones to use for the subnets in the VPC. The specified logical order is preserved. CreateAdditionalPrivateSubnets: Type: String Description: >- Choose true to create additional private subnets with dedicated network ACLs in each Availability Zone. If false, the CIDR parameters for those subnets will be ignored. If true, the CreatePrivateSubnets parameter must also be true to have any effect. AllowedValues: - 'true' - 'false' Default: 'false' CreateNATGateways: Type: String Description: >- Choose false when creating only private subnets. If true, both CreatePublicSubnets and CreatePrivateSubnets must also be true. AllowedValues: - 'true' - 'false' Default: 'true' CreatePublicSubnets: Type: String Description: >- Choose false to create only private subnets. If false, CreatePrivateSubnets must be true, and the CIDR parameters for all public subnets will be ignored. AllowedValues: - 'true' - 'false' Default: 'true' CreatePrivateSubnets: Type: String Description: >- Choose false to create only public subnets. If false, the CIDR parameters for all private subnets will be ignored. AllowedValues: - 'true' - 'false' Default: 'true' CreateVPCFlowLogsToCloudWatch: Type: String Description: >- Choose true to create VPC flow logs for the VPC and publish them to CloudWatch. If false, VPC flow logs will not be created. AllowedValues: - 'true' - 'false' Default: 'false' NumberOfAZs: Type: String Description: >- Number of Availability Zones to use in the VPC. This must match your selections in the AvailabilityZones parameter. AllowedValues: - '2' - '3' - '4' Default: '2' PrivateSubnet1ACIDR: Type: String Description: >- CIDR block for private subnet 1A located in Availability Zone 1. 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 PrivateSubnet1BCIDR: Type: String Description: >- CIDR block for private subnet 1B with dedicated network ACL located in Availability Zone 1. 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 PrivateSubnet2ACIDR: Type: String Description: >- CIDR block for private subnet 2A located in Availability Zone 2. 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 PrivateSubnet2BCIDR: Type: String Description: >- CIDR block for private subnet 2B with dedicated network ACL located in Availability Zone 2. 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 PrivateSubnet3ACIDR: Type: String Description: >- CIDR block for private subnet 3A located in Availability Zone 3. 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 PrivateSubnet3BCIDR: Type: String Description: >- CIDR block for private subnet 3B with dedicated network ACL located in Availability Zone 3. 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 PrivateSubnet4ACIDR: Type: String Description: >- CIDR block for private subnet 4A located in Availability Zone 4. 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 PrivateSubnet4BCIDR: Type: String Description: >- CIDR block for private subnet 4B with dedicated network ACL located in Availability Zone 4. 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 PrivateSubnetATag1: Type: String Description: >- (Optional) Tag to add to private subnets A, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: Network=Private PrivateSubnetATag2: Type: String Description: >- (Optional) Tag to add to private subnets A, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: '' PrivateSubnetATag3: Type: String Description: >- (Optional) Tag to add to private subnets A, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: '' PrivateSubnetBTag1: Type: String Description: >- (Optional) Tag to add to private subnets B, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: Network=Private PrivateSubnetBTag2: Type: String Description: >- (Optional) Tag to add to private subnets B, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: '' PrivateSubnetBTag3: Type: String Description: >- (Optional) Tag to add to private subnets B, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: '' PublicSubnet1CIDR: Type: String Description: >- CIDR block for the public DMZ subnet 1 located in Availability Zone 1. 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 PublicSubnet2CIDR: Type: String Description: >- CIDR block for the public DMZ subnet 2 located in Availability Zone 2. 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 PublicSubnet3CIDR: Type: String Description: >- CIDR block for the public DMZ subnet 3 located in Availability Zone 3. 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 PublicSubnet4CIDR: Type: String Description: >- CIDR block for the public DMZ subnet 4 located in Availability Zone 4. 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 PublicSubnetTag1: Type: String Description: >- (Optional) Tag to add to public subnets, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: Network=Public PublicSubnetTag2: Type: String Description: >- (Optional) Tag to add to public subnets, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: '' PublicSubnetTag3: Type: String Description: >- (Optional) Tag to add to public subnets, in format 'key=value'. AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ ConstraintDescription: >- Tags must be in format 'key=value'. Keys can contain only [a-zA-Z0-9+\-._:/@]. Values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}]. Default: '' VPCCIDR: Type: String Description: CIDR block for the VPC. 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 VPCFlowLogsCloudWatchKMSKey: Type: String 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. AllowedPattern: ^$|^arn:aws(-cn)?: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: >- Invalid KMS ARN or attempting to use in GovCloud. The AWS::Logs::LogGroup CloudFormation resource does not yet support the KmsKeyId property in GovCloud. Key ARN example: 'arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'. Default: '' VPCFlowLogsLogFormat: Type: String 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. The default format is used as the default value. 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} VPCFlowLogsLogGroupRetention: Type: String Description: Number of days to retain the VPC flow logs in CloudWatch. AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] Default: 14 VPCFlowLogsMaxAggregationInterval: Type: String 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). AllowedValues: - 60 - 600 Default: 600 VPCFlowLogsTrafficType: Type: String Description: >- The type of traffic to log. You can log traffic that the resource accepts or rejects, or all traffic. AllowedValues: - ACCEPT - ALL - REJECT Default: REJECT VPCTenancy: Type: String Description: The allowed tenancy of instances launched into the VPC. AllowedValues: - default - dedicated Default: default Rules: NAT: RuleCondition: !Equals [!Ref CreateNATGateways, 'true'] Assertions: - Assert: !And - !Equals [!Ref CreatePrivateSubnets, 'true'] - !Equals [!Ref CreatePublicSubnets, 'true'] AssertDescription: >- To enable NAT gateways, both CreatePrivateSubnets and CreatePublicSubnets must be 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 Metadata: cfn-lint: config: ignore_checks: - EIAMPolicyActionWildcard - EPolicyWildcardPrincipal ignore_reasons: EIAMPolicyActionWildcard: >- This is based on AWS documentation- filtering via bucket policy is generally preferred. EIAMPolicyWildcardResource: >- This is based on AWS documentation- filtering via bucket policy is generally preferred. 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 Description: Private subnet 1A route table. Value: !Ref PrivateSubnet1ARouteTable 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 Description: Private subnet 1B route table. Value: !Ref PrivateSubnet1BRouteTable 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 Description: Private subnet 2B route table. Value: !Ref PrivateSubnet2BRouteTable 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 Description: Private subnet 3A route table. Value: !Ref PrivateSubnet3ARouteTable 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