--- AWSTemplateFormatVersion: "2010-09-09" Description: "VPC" # takes about 6-minute # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html Parameters: Id: Type: String Description: Unique identifier, prefix for all resources created below. VpcCidr: Type: String Default: 10.0.0.0/16 AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Description: IP range (CIDR notation) for VPC, must be a valid (RFC 1918) CIDR range (from 10.0.0.0 to 10.0.255.255) PublicSubnetCidr1: Type: String Default: 10.0.64.0/19 AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Description: CIDR block for public subnet 1 within the VPC (from 10.0.64.0 to 10.0.95.255) PublicSubnetCidr2: Type: String Default: 10.0.128.0/19 AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Description: CIDR block for public subnet 2 within the VPC (from 10.0.128.0 to 10.0.159.255) PublicSubnetCidr3: Type: String Default: 10.0.192.0/19 AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Description: CIDR block for public subnet 2 within the VPC (from 10.0.192.0 to 10.0.223.255) IngressIpv4Range: Type: String Default: 0.0.0.0/0 AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Description: IP range for SSH/HTTP inbound traffic HttpPort: Type: Number Default: 9650 Description: HTTP port StakingPort: Type: Number Default: 9651 Description: HTTP port Conditions: Has2Azs: Fn::Or: - Fn::Equals: - { Ref: "AWS::Region" } - ap-south-1 - Fn::Equals: - { Ref: "AWS::Region" } - ap-northeast-2 - Fn::Equals: - { Ref: "AWS::Region" } - ca-central-1 - Fn::Equals: - { Ref: "AWS::Region" } - cn-north-1 - Fn::Equals: - { Ref: "AWS::Region" } - sa-east-1 - Fn::Equals: - { Ref: "AWS::Region" } - us-west-1 HasMoreThan2Azs: Fn::Not: - Condition: Has2Azs Resources: InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Join ["-", [!Ref Id, "igw"]] VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Join ["-", [!Ref Id, "vpc"]] VPCGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment DependsOn: - VPC - InternetGateway Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC PublicSubnet1: Type: AWS::EC2::Subnet DependsOn: - VPC - VPCGatewayAttachment Metadata: Comment: Public Subnet 1 Properties: AvailabilityZone: !Select [0, !GetAZs ] CidrBlock: !Ref PublicSubnetCidr1 MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: !Join ["-", [!Ref Id, "public-subnet-1"]] - Key: Network Value: Public PublicSubnet2: Type: AWS::EC2::Subnet DependsOn: - VPC - VPCGatewayAttachment Metadata: Comment: Public Subnet 2 Properties: AvailabilityZone: !Select [1, !GetAZs ] CidrBlock: !Ref PublicSubnetCidr2 MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: !Join ["-", [!Ref Id, "public-subnet-2"]] - Key: Network Value: Public PublicSubnet3: Condition: HasMoreThan2Azs Type: AWS::EC2::Subnet DependsOn: - VPC - VPCGatewayAttachment Metadata: Comment: Public Subnet 3 Properties: AvailabilityZone: !Select [2, !GetAZs ] CidrBlock: !Ref PublicSubnetCidr3 MapPublicIpOnLaunch: true VpcId: !Ref VPC Tags: - Key: Name Value: !Join ["-", [!Ref Id, "public-subnet-3"]] - Key: Network Value: Public PublicRouteTable: Type: AWS::EC2::RouteTable DependsOn: - VPC Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Join ["-", [!Ref Id, "public-round-table"]] - Key: Network Value: Public PublicRoute: Type: AWS::EC2::Route DependsOn: - VPC - VPCGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation DependsOn: - VPC - VPCGatewayAttachment - PublicSubnet1 Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable PublicSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation DependsOn: - VPC - VPCGatewayAttachment - PublicSubnet2 Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicRouteTable PublicSubnet3RouteTableAssociation: Condition: HasMoreThan2Azs Type: AWS::EC2::SubnetRouteTableAssociation DependsOn: - VPC - VPCGatewayAttachment - PublicSubnet3 Properties: SubnetId: !Ref PublicSubnet3 RouteTableId: !Ref PublicRouteTable # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html SecurityGroup: Type: AWS::EC2::SecurityGroup DependsOn: - VPC - VPCGatewayAttachment Properties: GroupName: !Join ["-", [!Ref Id, "security-group"]] GroupDescription: Secured communication VpcId: !Ref VPC # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html SshIngress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref SecurityGroup IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref IngressIpv4Range # TODO: can this be more strict HttpIngress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref SecurityGroup IpProtocol: tcp FromPort: !Ref HttpPort ToPort: !Ref HttpPort CidrIp: !Ref IngressIpv4Range # TODO: can this be more strict StakingIngress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref SecurityGroup IpProtocol: tcp FromPort: !Ref StakingPort ToPort: !Ref StakingPort CidrIp: !Ref IngressIpv4Range # TODO: can this be more strict # allow all outbound traffic Egress: Type: AWS::EC2::SecurityGroupEgress Properties: GroupId: !Ref SecurityGroup IpProtocol: "-1" FromPort: "1" ToPort: "65535" CidrIp: "0.0.0.0/0" Outputs: VpcId: Description: VPC ID Value: !Ref VPC SecurityGroupId: Description: Security group ID Value: !Ref SecurityGroup PublicSubnetIds: Description: All public subnet IDs in the VPC Value: Fn::If: - HasMoreThan2Azs - !Join [ ",", [!Ref PublicSubnet1, !Ref PublicSubnet2, !Ref PublicSubnet3], ] - !Join [",", [!Ref PublicSubnet1, !Ref PublicSubnet2]]