AWSTemplateFormatVersion: '2010-09-09' Description: 'Cloudformation Template to create a VPC with public and private subnets in 3 AZs' Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: 'VPC Parameters' Parameters: - ClassB ParameterLabels: ClassB: default: ClassB 2nd Octet Parameters: ClassB: Description: 'Specify the 2nd Octet of IPv4 CIDR block for the VPC (10.XXX.0.0/16) in the range [0-255]' 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 '${AWS::StackName}-VPC' InternetGateway: Type: 'AWS::EC2::InternetGateway' Properties: Tags: - Key: Name Value: !Sub '10.${ClassB}.0.0/16' VPCGatewayAttachment: Type: 'AWS::EC2::VPCGatewayAttachment' Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway NATEIPA: DependsOn: VPCGatewayAttachment Type: AWS::EC2::EIP Properties: Domain: vpc NATEIPB: DependsOn: VPCGatewayAttachment Type: AWS::EC2::EIP Properties: Domain: vpc NATEIPC: DependsOn: VPCGatewayAttachment Type: AWS::EC2::EIP Properties: Domain: vpc SubnetAPublic: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.0.0/20' MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [0, !GetAZs ''] - 'Public' - Key: Reach Value: public SubnetAPrivate: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.16.0/20' VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [0, !GetAZs ''] - 'Private' - Key: Reach Value: private SubnetBPublic: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.32.0/20' MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [1, !GetAZs ''] - 'Public' - Key: Reach Value: public SubnetBPrivate: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.48.0/20' VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [1, !GetAZs ''] - 'Private' - Key: Reach Value: private SubnetCPublic: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select [2, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.64.0/20' MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [2, !GetAZs ''] - 'Public' - Key: Reach Value: public SubnetCPrivate: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select [2, !GetAZs ''] CidrBlock: !Sub '10.${ClassB}.80.0/20' VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [2, !GetAZs ''] - 'Private' - Key: Reach Value: private RouteTablePublic: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - 'Public' RouteTableAPrivate: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [0, !GetAZs ''] - 'Private' RouteTableBPrivate: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [1, !GetAZs ''] - 'Private' RouteTableCPrivate: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [2, !GetAZs ''] - 'Private' RouteTableAssociationAPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetAPublic RouteTableId: !Ref RouteTablePublic RouteTableAssociationAPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetAPrivate RouteTableId: !Ref RouteTableAPrivate RouteTableAssociationBPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetBPublic RouteTableId: !Ref RouteTablePublic RouteTableAssociationBPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetBPrivate RouteTableId: !Ref RouteTableBPrivate RouteTableAssociationCPublic: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetCPublic RouteTableId: !Ref RouteTablePublic RouteTableAssociationCPrivate: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref SubnetCPrivate RouteTableId: !Ref RouteTableCPrivate RouteTablePublicInternetRoute: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref RouteTablePublic DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref InternetGateway NetworkAclPublic: Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - 'NACL' - 'Public' NetworkAclPrivate: Type: 'AWS::EC2::NetworkAcl' Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - 'NACL' - '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 NetworkAclEntryInPublicAllowAll: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPublic RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: false CidrBlock: '0.0.0.0/0' NetworkAclEntryOutPublicAllowAll: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPublic RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: true CidrBlock: '0.0.0.0/0' NetworkAclEntryInPrivateAllowVPC: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPrivate RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: false CidrBlock: '0.0.0.0/0' NetworkAclEntryOutPrivateAllowVPC: Type: 'AWS::EC2::NetworkAclEntry' Properties: NetworkAclId: !Ref NetworkAclPrivate RuleNumber: 99 Protocol: -1 RuleAction: allow Egress: true CidrBlock: '0.0.0.0/0' NATGatewayA: DependsOn: VPC Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt [NATEIPA,AllocationId] SubnetId: !Ref SubnetAPublic Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [0, !GetAZs ''] - 'NGW' NATGatewayB: DependsOn: VPC Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt [NATEIPB,AllocationId] SubnetId: !Ref SubnetBPublic Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [1, !GetAZs ''] - 'NGW' NATGatewayC: DependsOn: VPC Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt [NATEIPC,AllocationId] SubnetId: !Ref SubnetCPublic Tags: - Key: Name Value: !Join - '_' - - !Sub '10.${ClassB}.0.0/16' - !Select [2, !GetAZs ''] - 'NGW' RouteTablePrivateANATRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref RouteTableAPrivate DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NATGatewayA RouteTablePrivateBNATRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref RouteTableBPrivate DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NATGatewayB RouteTablePrivateCNATRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref RouteTableCPrivate DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NATGatewayC S3VPCEndpoint: Type: 'AWS::EC2::VPCEndpoint' Properties: PolicyDocument: Version: 2012-10-17 Statement: - Action: '*' Effect: Allow Resource: '*' Principal: '*' RouteTableIds: - !Ref RouteTableAPrivate - !Ref RouteTableBPrivate - !Ref RouteTableCPrivate ServiceName: !Join - '' - - com.amazonaws. - !Ref 'AWS::Region' - .s3 VpcId: !Ref VPC Outputs: TemplateID: Description: 'Template ID' Value: 'VPC-3AZs' StackName: Description: 'Stack name' Value: !Sub '${AWS::StackName}' VPC: Description: 'VPC' Value: !Ref VPC Export: Name: !Sub '${AWS::StackName}-VPC' ClassB: Description: 'Class B' Value: !Ref ClassB Export: Name: !Sub '${AWS::StackName}-ClassB' CidrBlock: Description: 'The set of IP addresses for the VPC' Value: !GetAtt 'VPC.CidrBlock' Export: Name: !Sub '${AWS::StackName}-CidrBlock' AZs: Description: 'AZs' Value: 3 Export: Name: !Sub '${AWS::StackName}-AZs' 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' SubnetsPublic: Description: 'Subnets public' Value: !Join [',', [!Ref SubnetAPublic, !Ref SubnetBPublic, !Ref SubnetCPublic]] Export: Name: !Sub '${AWS::StackName}-SubnetsPublic' SubnetsPrivate: Description: 'Subnets private' Value: !Join [',', [!Ref SubnetAPrivate, !Ref SubnetBPrivate, !Ref SubnetCPrivate]] Export: Name: !Sub '${AWS::StackName}-SubnetsPrivate' RouteTablesPublic: Description: 'Route tables public' Value: !Ref RouteTablePublic Export: Name: !Sub '${AWS::StackName}-RouteTablePublic' RouteTablesPrivate: Description: 'Route tables private' Value: !Join [',', [!Ref RouteTableAPrivate, !Ref RouteTableBPrivate, !Ref RouteTableCPrivate]] Export: Name: !Sub '${AWS::StackName}-RouteTablesPrivate' SubnetAPublic: Description: 'Subnet A public' Value: !Ref SubnetAPublic Export: Name: !Sub '${AWS::StackName}-SubnetAPublic' SubnetAPrivate: Description: 'Subnet A private' Value: !Ref SubnetAPrivate Export: Name: !Sub '${AWS::StackName}-SubnetAPrivate' RouteTableAPrivate: Description: 'Route table A private' Value: !Ref RouteTableAPrivate Export: Name: !Sub '${AWS::StackName}-RouteTableAPrivate' SubnetBPublic: Description: 'Subnet B public' Value: !Ref SubnetBPublic Export: Name: !Sub '${AWS::StackName}-SubnetBPublic' 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' 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' S3VPCEndpoint: Description: S3 VPC Endpoint Value: !Ref S3VPCEndpoint Export: Name: !Sub '${AWS::StackName}-S3VPCEndpoint'