--- # Copyright 2018 widdix GmbH # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. AWSTemplateFormatVersion: '2010-09-09' Description: 'VPC: public and private subnets in four availability zones, a cloudonaut.io template' Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: 'VPC Parameters' Parameters: - ClassB Parameters: ClassB: Description: 'Class B of VPC (10.XXX.0.0/16)' Type: Number Default: 0 ConstraintDescription: 'Must be in the range [0-255]' MinValue: 0 MaxValue: 255 Resources: VPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: !Sub '10.${ClassB}.0.0/16' EnableDnsSupport: true EnableDnsHostnames: true InstanceTenancy: default Tags: - Key: Name Value: !Sub '10.${ClassB}.0.0/16' VPCCidrBlock: Type: 'AWS::EC2::VPCCidrBlock' Properties: AmazonProvidedIpv6CidrBlock: true VpcId: !Ref VPC InternetGateway: Type: 'AWS::EC2::InternetGateway' Properties: Tags: - Key: Name Value: !Sub 10.${ClassB}.0.0/16 EgressOnlyInternetGateway: Type: 'AWS::EC2::EgressOnlyInternetGateway' Properties: VpcId: !Ref VPC VPCGatewayAttachment: Type: 'AWS::EC2::VPCGatewayAttachment' Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway SubnetAPublic: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: #AssignIpv6AddressOnCreation: true # TODO can not be set if MapPublicIpOnLaunch is true as well AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.0.0/20' Ipv6CidrBlock: !Select [0, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: 'A public' - Key: Reach Value: public SubnetAPrivate: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: AssignIpv6AddressOnCreation: false AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.16.0/20' Ipv6CidrBlock: !Select [1, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] VpcId: !Ref VPC Tags: - Key: Name Value: 'A private' - Key: Reach Value: private SubnetBPublic: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: #AssignIpv6AddressOnCreation: true # TODO can not be set if MapPublicIpOnLaunch is true as well AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.32.0/20' Ipv6CidrBlock: !Select [2, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: 'B public' - Key: Reach Value: public SubnetBPrivate: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: AssignIpv6AddressOnCreation: false AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.48.0/20' Ipv6CidrBlock: !Select [3, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] VpcId: !Ref VPC Tags: - Key: Name Value: 'B private' - Key: Reach Value: private SubnetCPublic: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: #AssignIpv6AddressOnCreation: true # TODO can not be set if MapPublicIpOnLaunch is true as well AvailabilityZone: !Select [2, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.64.0/20' Ipv6CidrBlock: !Select [4, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: 'C public' - Key: Reach Value: public SubnetCPrivate: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: AssignIpv6AddressOnCreation: false AvailabilityZone: !Select [2, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.80.0/20' Ipv6CidrBlock: !Select [5, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] VpcId: !Ref VPC Tags: - Key: Name Value: 'C private' - Key: Reach Value: private SubnetDPublic: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: #AssignIpv6AddressOnCreation: true # TODO can not be set if MapPublicIpOnLaunch is true as well AvailabilityZone: !Select [3, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.96.0/20' Ipv6CidrBlock: !Select [6, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: 'D public' - Key: Reach Value: public SubnetDPrivate: DependsOn: VPCCidrBlock Type: 'AWS::EC2::Subnet' Properties: AssignIpv6AddressOnCreation: false AvailabilityZone: !Select [3, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.112.0/20' Ipv6CidrBlock: !Select [7, !Cidr [!Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'], 8, 64]] VpcId: !Ref VPC Tags: - Key: Name Value: 'D private' - Key: Reach Value: private RouteTablePublic: # should be RouteTableAPublic, but logical id was not changed for backward compatibility Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Public RouteTablePrivate: # should be RouteTableAPrivate, but logical id was not changed for backward compatibility Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Private RouteTableBPublic: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: 'B Public' RouteTableBPrivate: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: 'B Private' RouteTableCPublic: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: 'C Public' RouteTableCPrivate: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: 'C Private' RouteTableDPublic: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: 'D Public' RouteTableDPrivate: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: 'D Private' RouteTableAssociationAPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetAPublic RouteTableId: !Ref RouteTablePublic RouteTableAssociationAPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetAPrivate RouteTableId: !Ref RouteTablePrivate RouteTableAssociationBPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetBPublic RouteTableId: !Ref RouteTableBPublic RouteTableAssociationBPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetBPrivate RouteTableId: !Ref RouteTableBPrivate RouteTableAssociationCPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetCPublic RouteTableId: !Ref RouteTableCPublic RouteTableAssociationCPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetCPrivate RouteTableId: !Ref RouteTableCPrivate RouteTableAssociationDPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetDPublic RouteTableId: !Ref RouteTableDPublic RouteTableAssociationDPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetDPrivate RouteTableId: !Ref RouteTableDPrivate RouteTablePublicInternetRoute: # should be RouteTablePublicAInternetRoute, but logical id was not changed for backward compatibility Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTablePublic DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref InternetGateway RouteTablePublicAInternetRouteIPv6: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTablePublic DestinationIpv6CidrBlock: '::/0' GatewayId: !Ref InternetGateway RouteTablePrivateAInternetRouteIPv6: Type: 'AWS::EC2::Route' Properties: RouteTableId: !Ref RouteTablePrivate DestinationIpv6CidrBlock: '::/0' EgressOnlyInternetGatewayId: !Ref EgressOnlyInternetGateway RouteTablePublicBInternetRoute: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTableBPublic DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref InternetGateway RouteTablePublicBInternetRouteIPv6: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTableBPublic DestinationIpv6CidrBlock: '::/0' GatewayId: !Ref InternetGateway RouteTablePrivateBInternetRouteIPv6: Type: 'AWS::EC2::Route' Properties: RouteTableId: !Ref RouteTableBPrivate DestinationIpv6CidrBlock: '::/0' EgressOnlyInternetGatewayId: !Ref EgressOnlyInternetGateway RouteTablePublicCInternetRoute: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTableCPublic DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref InternetGateway RouteTablePublicCInternetRouteIPv6: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTableCPublic DestinationIpv6CidrBlock: '::/0' GatewayId: !Ref InternetGateway RouteTablePrivateCInternetRouteIPv6: Type: 'AWS::EC2::Route' Properties: RouteTableId: !Ref RouteTableCPrivate DestinationIpv6CidrBlock: '::/0' EgressOnlyInternetGatewayId: !Ref EgressOnlyInternetGateway RouteTablePublicDInternetRoute: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTableDPublic DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref InternetGateway RouteTablePublicDInternetRouteIPv6: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTableDPublic DestinationIpv6CidrBlock: '::/0' GatewayId: !Ref InternetGateway RouteTablePrivateDInternetRouteIPv6: Type: 'AWS::EC2::Route' Properties: RouteTableId: !Ref RouteTableDPrivate DestinationIpv6CidrBlock: '::/0' EgressOnlyInternetGatewayId: !Ref EgressOnlyInternetGateway NetworkAclPublic: Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Public NetworkAclPrivate: Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Private SubnetNetworkAclAssociationAPublic: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetAPublic NetworkAclId: !Ref NetworkAclPublic SubnetNetworkAclAssociationAPrivate: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetAPrivate NetworkAclId: !Ref NetworkAclPrivate SubnetNetworkAclAssociationBPublic: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetBPublic NetworkAclId: !Ref NetworkAclPublic SubnetNetworkAclAssociationBPrivate: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetBPrivate NetworkAclId: !Ref NetworkAclPrivate SubnetNetworkAclAssociationCPublic: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetCPublic NetworkAclId: !Ref NetworkAclPublic SubnetNetworkAclAssociationCPrivate: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetCPrivate NetworkAclId: !Ref NetworkAclPrivate SubnetNetworkAclAssociationDPublic: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetDPublic NetworkAclId: !Ref NetworkAclPublic SubnetNetworkAclAssociationDPrivate: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref SubnetDPrivate NetworkAclId: !Ref NetworkAclPrivate NetworkAclEntryInPublicAllowAll: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPublic RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: false CidrBlock: '0.0.0.0/0' NetworkAclEntryInPublicAllowAllIPv6: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPublic RuleNumber: 98 Protocol: -1 RuleAction: allow Egress: false Ipv6CidrBlock: '::/0' NetworkAclEntryOutPublicAllowAll: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPublic RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: true CidrBlock: '0.0.0.0/0' NetworkAclEntryOutPublicAllowAllIPv6: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPublic RuleNumber: 98 Protocol: -1 RuleAction: allow Egress: true Ipv6CidrBlock: '::/0' NetworkAclEntryInPrivateAllowAll: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPrivate RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: false CidrBlock: '0.0.0.0/0' NetworkAclEntryInPrivateAllowAllIPv6: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPrivate RuleNumber: 98 Protocol: -1 RuleAction: allow Egress: false Ipv6CidrBlock: '::/0' NetworkAclEntryOutPrivateAllowAll: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPrivate RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: true CidrBlock: '0.0.0.0/0' NetworkAclEntryOutPrivateAllowAllIPv6: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPrivate RuleNumber: 98 Protocol: -1 RuleAction: allow Egress: true Ipv6CidrBlock: '::/0' Outputs: TemplateID: Description: 'cloudonaut.io template id.' Value: 'vpc/vpc-4azs' TemplateVersion: Description: 'cloudonaut.io template version.' Value: '__VERSION__' StackName: Description: 'Stack name.' Value: !Sub '${AWS::StackName}' AZs: # Better name would be NumberOfAZs, but we keep the name for backward compatibility Description: 'Number of AZs' Value: 4 Export: Name: !Sub '${AWS::StackName}-AZs' AZList: # Better name would be AZs, but the name was already used Description: 'List of AZs' Value: !Join [',', [!Select [0, !GetAZs ''], !Select [1, !GetAZs ''], !Select [2, !GetAZs ''], !Select [3, !GetAZs '']]] Export: Name: !Sub '${AWS::StackName}-AZList' AZA: Description: 'AZ of A' Value: !Select [0, !GetAZs ''] Export: Name: !Sub '${AWS::StackName}-AZA' AZB: Description: 'AZ of B' Value: !Select [1, !GetAZs ''] Export: Name: !Sub '${AWS::StackName}-AZB' AZC: Description: 'AZ of C' Value: !Select [2, !GetAZs ''] Export: Name: !Sub '${AWS::StackName}-AZC' AZD: Description: 'AZ of D' Value: !Select [3, !GetAZs ''] Export: Name: !Sub '${AWS::StackName}-AZD' CidrBlock: Description: 'The set of IP addresses for the VPC.' Value: !GetAtt 'VPC.CidrBlock' Export: Name: !Sub '${AWS::StackName}-CidrBlock' CidrBlockIPv6: Description: 'The set of IPv6 addresses for the VPC.' Value: !Select [0, !GetAtt 'VPC.Ipv6CidrBlocks'] Export: Name: !Sub '${AWS::StackName}-CidrBlockIPv6' VPC: Description: 'VPC.' Value: !Ref VPC Export: Name: !Sub '${AWS::StackName}-VPC' InternetGateway: Description: 'InternetGateway.' Value: !Ref InternetGateway Export: Name: !Sub '${AWS::StackName}-InternetGateway' SubnetsPublic: Description: 'Subnets public.' Value: !Join [',', [!Ref SubnetAPublic, !Ref SubnetBPublic, !Ref SubnetCPublic, !Ref SubnetDPublic]] Export: Name: !Sub '${AWS::StackName}-SubnetsPublic' SubnetsPrivate: Description: 'Subnets private.' Value: !Join [',', [!Ref SubnetAPrivate, !Ref SubnetBPrivate, !Ref SubnetCPrivate, !Ref SubnetDPrivate]] Export: Name: !Sub '${AWS::StackName}-SubnetsPrivate' RouteTablesPrivate: Description: 'Route tables private.' Value: !Join [',', [!Ref RouteTablePrivate, !Ref RouteTableBPrivate, !Ref RouteTableCPrivate, !Ref RouteTableDPrivate]] Export: Name: !Sub '${AWS::StackName}-RouteTablesPrivate' RouteTablesPublic: Description: 'Route tables public.' Value: !Join [',', [!Ref RouteTablePublic, !Ref RouteTableBPublic, !Ref RouteTableCPublic, !Ref RouteTableDPublic]] Export: Name: !Sub '${AWS::StackName}-RouteTablesPublic' SubnetAPublic: Description: 'Subnet A public.' Value: !Ref SubnetAPublic Export: Name: !Sub '${AWS::StackName}-SubnetAPublic' RouteTableAPublic: Description: 'Route table A public.' Value: !Ref RouteTablePublic Export: Name: !Sub '${AWS::StackName}-RouteTableAPublic' SubnetAPrivate: Description: 'Subnet A private.' Value: !Ref SubnetAPrivate Export: Name: !Sub '${AWS::StackName}-SubnetAPrivate' RouteTableAPrivate: Description: 'Route table A private.' Value: !Ref RouteTablePrivate Export: Name: !Sub '${AWS::StackName}-RouteTableAPrivate' SubnetBPublic: Description: 'Subnet B public.' Value: !Ref SubnetBPublic Export: Name: !Sub '${AWS::StackName}-SubnetBPublic' RouteTableBPublic: Description: 'Route table B public.' Value: !Ref RouteTableBPublic Export: Name: !Sub '${AWS::StackName}-RouteTableBPublic' SubnetBPrivate: Description: 'Subnet B private.' Value: !Ref SubnetBPrivate Export: Name: !Sub '${AWS::StackName}-SubnetBPrivate' RouteTableBPrivate: Description: 'Route table B private.' Value: !Ref RouteTableBPrivate Export: Name: !Sub '${AWS::StackName}-RouteTableBPrivate' SubnetCPublic: Description: 'Subnet C public.' Value: !Ref SubnetCPublic Export: Name: !Sub '${AWS::StackName}-SubnetCPublic' RouteTableCPublic: Description: 'Route table C public.' Value: !Ref RouteTableCPublic Export: Name: !Sub '${AWS::StackName}-RouteTableCPublic' SubnetCPrivate: Description: 'Subnet C private.' Value: !Ref SubnetCPrivate Export: Name: !Sub '${AWS::StackName}-SubnetCPrivate' RouteTableCPrivate: Description: 'Route table C private.' Value: !Ref RouteTableCPrivate Export: Name: !Sub '${AWS::StackName}-RouteTableCPrivate' SubnetDPublic: Description: 'Subnet D public.' Value: !Ref SubnetDPublic Export: Name: !Sub '${AWS::StackName}-SubnetDPublic' RouteTableDPublic: Description: 'Route table D public.' Value: !Ref RouteTableDPublic Export: Name: !Sub '${AWS::StackName}-RouteTableDPublic' SubnetDPrivate: Description: 'Subnet D private.' Value: !Ref SubnetDPrivate Export: Name: !Sub '${AWS::StackName}-SubnetDPrivate' RouteTableDPrivate: Description: 'Route table D private.' Value: !Ref RouteTableDPrivate Export: Name: !Sub '${AWS::StackName}-RouteTableDPrivate'