avalanche-ops 0.6.8

avalanche-ops spec
---
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)

  # limit this to your IP
  SshPortIngressIpv4Range:
    Type: String
    Default: 0.0.0.0/0
    AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}'
    Description: IP range for SSH inbound traffic

  # limit this to your IP
  HttpPortIngressIpv4Range:
    Type: String
    Default: 0.0.0.0/0
    AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}'
    Description: IP range for HTTP inbound traffic

  HttpPort:
    Type: Number
    Default: 9650
    Description: HTTP port

  StakingPortIngressIpv4Range:
    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

  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

  # The instances must be in a subnet with outbound internet access.
  # Can be a public subnet with an auto-assigned public ipv4 address.
  # Or it can be a private subnet with a NAT Gateway.
  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 SshPortIngressIpv4Range

  HttpIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SecurityGroup
      IpProtocol: tcp
      FromPort: !Ref HttpPort
      ToPort: !Ref HttpPort
      CidrIp: !Ref HttpPortIngressIpv4Range

  StakingIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SecurityGroup
      IpProtocol: tcp
      FromPort: !Ref StakingPort
      ToPort: !Ref StakingPort
      CidrIp: !Ref StakingPortIngressIpv4Range

  # 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]]

  PublicSubnetId1Az:
    Description: AZ.
    Value:
      Fn::Select:
        - 0
        - Fn::GetAZs: ""

  PublicSubnetId2Az:
    Description: AZ.
    Value:
      Fn::Select:
        - 1
        - Fn::GetAZs: ""

  PublicSubnetId3Az:
    Description: AZ.
    Value:
      Fn::If:
        - HasMoreThan2Azs
        - Fn::Select:
            - 2
            - Fn::GetAZs: ""
        - ""