---
AWSTemplateFormatVersion: 2010-09-09
Description: Provides networking configuration for a VFX Production VPC
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Region Configuration
        Parameters:
          - pAvailabilityZones

      - Label:
          default: Network Configuration
        Parameters:
          - pProductionVPCName
          - pProductionVpcCIDR
          - pProdAppPrivateSubnetACIDR
          - pProdAppPrivateSubnetBCIDR

    ParameterLabels:
      pAvailabilityZones:
        default: Select two Availability Zones

      pProductionVPCName:
        default: Name of Production VPC

      pProductionVpcCIDR:
        default: Production VPC CIDR block

      pProdAppPrivateSubnetACIDR:
        default: CIDR block of Production Application Subnet A (private)

      pProdAppPrivateSubnetBCIDR:
        default: CIDR block of Production Application Subnet B (private)

Parameters:
  pAvailabilityZones:
    Description: The list of Availability Zones to use for the subnets in the VPC.
      This template uses two Availability Zones from your list and preserves the logical order you specify.
    Type: List<AWS::EC2::AvailabilityZone::Name>

  pProductionVPCName:
    Default: Production-1-VPC
    Description: Production VPC Name
    Type: String

  pProductionVpcCIDR:
    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]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.100.0.0/16
    Description: CIDR block for Production VPC
    Type: String

  pProdAppPrivateSubnetACIDR:
    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]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.100.0.0/19
    Description: CIDR block of Production Application Subnet A (private)
    Type: String

  pProdAppPrivateSubnetBCIDR:
    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]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.100.32.0/19
    Description: CIDR block of Production Application Subnet B (private)
    Type: String

  pEnvironment:
    AllowedValues:
      - DEV
      - TEST
      - PROD
    Default: DEV
    Description: Environment (Dev, Test or Prod)
    Type: String

Resources:
  # -- Create VPC -- #
  rVPCProduction:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref pProductionVpcCIDR
      InstanceTenancy: default
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref pProductionVPCName
        - Key: Environment
          Value: !Ref pEnvironment

  # -- Create Private Subnets -- #
  rProdAppPrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref pProdAppPrivateSubnetACIDR
      AvailabilityZone: !Select [0, !Ref pAvailabilityZones]
      VpcId: !Ref rVPCProduction
      Tags:
        - Key: Name
          Value: Production-1 App Subnet A
        - Key: Environment
          Value: !Ref pEnvironment

  rProdAppPrivateSubnetB:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref pProdAppPrivateSubnetBCIDR
      AvailabilityZone: !Select [1, !Ref pAvailabilityZones]
      VpcId: !Ref rVPCProduction
      Tags:
        - Key: Name
          Value: Production-1 App Subnet B
        - Key: Environment
          Value: !Ref pEnvironment

  # -- Create the Route Table for the Private Subnets -- #
  rRouteTableProdPrivateA:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref rVPCProduction
      Tags:
        - Key: Name
          Value: Production-1 Private Route A

  rRouteTableProdPrivateB:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref rVPCProduction
      Tags:
        - Key: Name
          Value: Production-1 Private Route B

  rProdAppPrivateSubnetAssociationA:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref rRouteTableProdPrivateA
      SubnetId: !Ref rProdAppPrivateSubnetA

  rProdAppPrivateSubnetAssociationB:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref rRouteTableProdPrivateB
      SubnetId: !Ref rProdAppPrivateSubnetB

  # -- Create FlowLogs and CloudWatch Logs Group including Service Role policy. -- #
  rProdVpcFlowLogsServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: AllowFlowLogs
            Effect: Allow
            Principal:
              Service: vpc-flow-logs.amazonaws.com
            Action: sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: cloudwatchlogsrole
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                  - logs:DescribeLogGroups
                  - logs:DescribeLogStreams
                Effect: Allow
                Resource: '*'

  rProdVpcFlowLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      RetentionInDays: 90

  rProdVpcFlowLog:
    Type: AWS::EC2::FlowLog
    Properties:
      DeliverLogsPermissionArn: !GetAtt rProdVpcFlowLogsServiceRole.Arn
      LogGroupName: !Ref rProdVpcFlowLogGroup
      ResourceId: !Ref rVPCProduction
      ResourceType: VPC
      TrafficType: ALL

Outputs:
  rVPCProduction:
    Value: !Ref rVPCProduction

  pProductionVpcCIDR:
    Value: !Ref pProductionVpcCIDR

  pProductionVPCName:
    Value: !Ref pProductionVPCName

  rProdAppPrivateSubnetA:
    Value: !Ref rProdAppPrivateSubnetA

  rProdAppPrivateSubnetB:
    Value: !Ref rProdAppPrivateSubnetB

  rRouteTableProdPrivateA:
    Value: !Ref rRouteTableProdPrivateA

  rRouteTableProdPrivateB:
    Value: !Ref rRouteTableProdPrivateB

  rProdVpcFlowLogGroup:
    Value: !Ref rProdVpcFlowLogGroup