Description: > This template deploys a VPC, with a pair of private subnets spread across two Availability Zones. All of the VPC endpoints used for communicating to AWS services within the VPC are also deployed from this Template. Lastly, this Template deploys the VPC Endpoint Security group for restricting traffic to the VPC Endpoints. Parameters: EnvironmentName: Description: An environment name that is prefixed to resource names Type: String Default: Dev VpcCIDR: Description: Please enter the IP range (CIDR notation) for this 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])(\/([0-9]|[1-2][0-9]|3[0-2]))$' Type: String Default: 10.199.0.0/20 PrivateSubnet1CIDR: Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone 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])(\/([0-9]|[1-2][0-9]|3[0-2]))$' Type: String Default: 10.199.0.0/22 PrivateSubnet2CIDR: Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone 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])(\/([0-9]|[1-2][0-9]|3[0-2]))$' Type: String Default: 10.199.4.0/22 EndpointSGGroupName: Type: String Default: VpcEndpointSG Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCIDR EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Ref EnvironmentName PrivateSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref PrivateSubnet1CIDR MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Subnet (AZ1) PrivateSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 1, !GetAZs '' ] CidrBlock: !Ref PrivateSubnet2CIDR MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Subnet (AZ2) PrivateRouteTable1: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Routes (AZ1) PrivateSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable1 SubnetId: !Ref PrivateSubnet1 PrivateRouteTable2: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Routes (AZ2) PrivateSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable2 SubnetId: !Ref PrivateSubnet2 EC2MessagesEndpoint: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true SecurityGroupIds: - !Ref EndpointSG ServiceName: com.amazonaws.us-east-1.ec2messages SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 VpcEndpointType: Interface VpcId: !Ref VPC EC2Endpoint: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true SecurityGroupIds: - !Ref EndpointSG ServiceName: com.amazonaws.us-east-1.ec2 SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 VpcEndpointType: Interface VpcId: !Ref VPC SSMEndpoint: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true SecurityGroupIds: - !Ref EndpointSG ServiceName: com.amazonaws.us-east-1.ssm SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 VpcEndpointType: Interface VpcId: !Ref VPC SSMMessagesEndpoint: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true SecurityGroupIds: - !Ref EndpointSG ServiceName: com.amazonaws.us-east-1.ssmmessages SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 VpcEndpointType: Interface VpcId: !Ref VPC CloudWatchEndpoint: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true SecurityGroupIds: - !Ref EndpointSG ServiceName: com.amazonaws.us-east-1.logs SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 VpcEndpointType: Interface VpcId: !Ref VPC S3EndPoint: Type: AWS::EC2::VPCEndpoint Properties: RouteTableIds: - !Ref PrivateRouteTable1 - !Ref PrivateRouteTable2 ServiceName: com.amazonaws.us-east-1.s3 VpcId: !Ref VPC VpcEndpointType: Gateway EndpointSG: Type: 'AWS::EC2::SecurityGroup' Metadata: cfn_nag: rules_to_suppress: - id: W9 reason: "Supressing requirement for logging warning for testing purposes" - id: W5 reason: "Supressing requirement for name warning for testing purposes" - id: W2 reason: "Supressing requirement for name warning for testing purposes" - id: W36 reason: "Supressing requirement for name warning for testing purposes" - id: W29 reason: "Supressing requirement for name warning for testing purposes" Properties: GroupDescription: Base Security Group GroupName: !Ref EndpointSGGroupName SecurityGroupIngress: - IpProtocol: tcp CidrIp: 0.0.0.0/0 FromPort: 80 ToPort: 80 - IpProtocol: tcp CidrIp: 0.0.0.0/0 FromPort: 443 ToPort: 443 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 VpcId: !Ref VPC Outputs: VPC: Description: A reference to the created VPC Value: !Ref VPC Export: Name: Fn::Sub: "${AWS::StackName}-Cassis-VPC" VpcCIDR: Value: !Ref VpcCIDR Description: VPC CIDR Range Export: Name: !Sub '${AWS::StackName}-VpcCIDR' PrivateSubnets: Description: A list of the private subnets Value: !Join [ ",", [ !Ref PrivateSubnet1, !Ref PrivateSubnet2 ]] Export: Name: Fn::Sub: "${AWS::StackName}-PrivateSubnetList" PrivateSubnet1: Description: A reference to the private subnet in the 1st Availability Zone Value: !Ref PrivateSubnet1 Export: Name: Fn::Sub: "${AWS::StackName}-CassisPrivateSubnet1" PrivateSubnet2: Description: A reference to the private subnet in the 2nd Availability Zone Value: !Ref PrivateSubnet2 Export: Name: Fn::Sub: "${AWS::StackName}-CassisPrivateSubnet2"