Lambda-School-Labs/prismatopia

View on GitHub
aws/app-network.cf.yaml

Summary

Maintainability
Test Coverage
AWSTemplateFormatVersion: '2010-09-09'
Description: A very simple VPC for hosting an application

Parameters:
  ApplicationName:
    Type: String
    Description: The name of the application
    AllowedPattern: ^[a-z0-9\-]*$

  VPCCidrBlock:
    Type: String
    AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}'
    Default: 10.0.0.0/16

  ApplicationDomainNamespace:
    Type: String
    Description: The DNS domain namespace for the application (e.g. mycoolapplication.com)
    AllowedPattern: ^[a-z0-9\-\.]*$

  ApolloServicePort:
    Type: Number
    Description: The port that the Apollo service will be listening on

  PrismaServicePort:
    Type: Number
    Description: The port that the Prisma service will be listening on

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidrBlock
      EnableDnsHostnames: true
      EnableDnsSupport: true

  FlowLogsLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      RetentionInDays: 14

  FlowLog:
    Type: AWS::EC2::FlowLog
    Properties:
      DeliverLogsPermissionArn:
        Fn::ImportValue: !Sub ${ApplicationName}-LoggingRoleArn
      LogGroupName: !Ref FlowLogsLogGroup
      ResourceId: !Ref VPC
      ResourceType: VPC
      TrafficType: ALL

  CloudTrailBucket:
    Type: AWS::S3::Bucket
    Properties:
      LifecycleConfiguration:
        Rules:
          - Status: Enabled
            ExpirationInDays: 14

  CloudTrailBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: CloudTrailBucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: 'AWSCloudTrailAclCheck'
            Effect: 'Allow'
            Principal:
              Service: 'cloudtrail.amazonaws.com'
            Action: 's3:GetBucketAcl'
            Resource: !Sub arn:aws:s3:::${CloudTrailBucket}
          - Sid: 'AWSCloudTrailWrite'
            Effect: 'Allow'
            Principal:
              Service: 'cloudtrail.amazonaws.com'
            Action: 's3:PutObject'
            Resource: !Sub arn:aws:s3:::${CloudTrailBucket}/AWSLogs/${AWS::AccountId}/*
            Condition:
              StringEquals:
                s3:x-amz-acl: 'bucket-owner-full-control'

  CloudTrailLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      RetentionInDays: 14

  CloudTrail:
    Type: AWS::CloudTrail::Trail
    DependsOn:
      - CloudTrailBucketPolicy
    Properties:
      S3BucketName: !Ref CloudTrailBucket
      CloudWatchLogsLogGroupArn: !GetAtt CloudTrailLogGroup.Arn
      CloudWatchLogsRoleArn:
        Fn::ImportValue: !Sub ${ApplicationName}-LoggingRoleArn
      IsLogging: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    DependsOn: VPC

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: '10.0.10.0/24'
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref 'AWS::Region'
      Tags:
        - Key: Name
          Value: Public01

  PublicSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: '10.0.20.0/24'
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref 'AWS::Region'
      Tags:
        - Key: Name
          Value: Public02

  PublicSubnetNACL:
    Type: AWS::EC2::NetworkAcl
    Properties:
      VpcId: !Ref VPC

  PublicSubnetNACLIngressHTTP:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PublicSubnetNACL
      RuleNumber: 1000
      Protocol: 6
      RuleAction: allow
      Egress: false
      CidrBlock: 0.0.0.0/0
      PortRange:
        From: 80
        To: 80

  PublicSubnetNACLIngressHTTPS:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PublicSubnetNACL
      RuleNumber: 2000
      Protocol: 6
      RuleAction: allow
      Egress: false
      CidrBlock: 0.0.0.0/0
      PortRange:
        From: 443
        To: 443

  PublicSubnetNACLEntryEphemeralWithNAT:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PublicSubnetNACL
      RuleNumber: 200
      Protocol: 6
      RuleAction: allow
      Egress: false
      CidrBlock: 0.0.0.0/0
      PortRange:
        From: 1024
        To: 65535

  PublicSubnetNACLEntryEgressToVPC:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PublicSubnetNACL
      RuleNumber: 1000
      Protocol: -1
      RuleAction: allow
      Egress: true
      CidrBlock: 0.0.0.0/0
      PortRange:
        From: 0
        To: 65535

  PublicSubnet01NACLAssociation:
    Type: AWS::EC2::SubnetNetworkAclAssociation
    Properties:
      SubnetId: !Ref PublicSubnet01
      NetworkAclId: !Ref PublicSubnetNACL

  PublicSubnet02NACLAssociation:
    Type: AWS::EC2::SubnetNetworkAclAssociation
    Properties:
      SubnetId: !Ref PublicSubnet02
      NetworkAclId: !Ref PublicSubnetNACL

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Public

  PublicRoute01:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet01RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet01
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet02RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet02
      RouteTableId: !Ref PublicRouteTable

  EIP:
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  NATGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt 'EIP.AllocationId'
      SubnetId: !Ref PublicSubnet01

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Private

  PrivateRoute01:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NATGateway

  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: '10.0.30.0/24'
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref 'AWS::Region'
      Tags:
        - Key: Name
          Value: Private01

  PrivateSubnet01RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet01
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: '10.0.40.0/24'
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref 'AWS::Region'
      Tags:
        - Key: Name
          Value: Private02

  PrivateSubnet02RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet02
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnetNACL:
    Type: AWS::EC2::NetworkAcl
    Properties:
      VpcId: !Ref VPC

  PrivateSubnetNACLEntryIngressFromVPC:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PrivateSubnetNACL
      RuleNumber: 100
      Protocol: 6
      RuleAction: allow
      Egress: false
      CidrBlock: !GetAtt VPC.CidrBlock
      PortRange:
        From: 0
        To: 65535

  PrivateSubnetNACLEntryIngressEphemeralWithNAT:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PrivateSubnetNACL
      RuleNumber: 200
      Protocol: 6
      RuleAction: allow
      Egress: false
      CidrBlock: 0.0.0.0/0
      PortRange:
        From: 1024
        To: 65535

  PrivateSubnetNACLEntryEgress:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: !Ref PrivateSubnetNACL
      RuleNumber: 1000
      Protocol: 6
      RuleAction: allow
      Egress: true
      CidrBlock: 0.0.0.0/0
      PortRange:
        From: 0
        To: 65535

  PrivateSubnet01NACLAssociation:
    Type: AWS::EC2::SubnetNetworkAclAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet01
      NetworkAclId: !Ref PrivateSubnetNACL

  PrivateSubnet02NACLAssociation:
    Type: AWS::EC2::SubnetNetworkAclAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet02
      NetworkAclId: !Ref PrivateSubnetNACL

  ServiceSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security Group for the Mission Control API ELB
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - CidrIp: !GetAtt VPC.CidrBlock
          IpProtocol: 'tcp'
          FromPort: !Ref ApolloServicePort
          ToPort: !Ref ApolloServicePort
        - CidrIp: !GetAtt VPC.CidrBlock
          IpProtocol: 'tcp'
          FromPort: !Ref PrismaServicePort
          ToPort: !Ref PrismaServicePort

  ProductionHostedZone:
    Type: 'AWS::Route53::HostedZone'
    Properties:
      HostedZoneConfig:
        Comment: !Sub Hosted zone for the production environment of ${ApplicationName}
      Name: !Ref ApplicationDomainNamespace

  PrivateNamespace:
    Type: AWS::ServiceDiscovery::PrivateDnsNamespace
    Properties:
      Name: !Sub private.${ApplicationDomainNamespace}
      Vpc: !Ref VPC

Outputs:
  VPCID:
    Description: The ID of the VPC
    Value: !Ref VPC
    Export:
      Name: !Sub ${ApplicationName}-VPCID

  VPCCIDR:
    Description: The CIDR block for the VPC
    Value: !GetAtt VPC.CidrBlock
    Export:
      Name: !Sub ${ApplicationName}-VPCCIDR

  PublicSubnet01:
    Description: ID for public subnet 01
    Value: !Ref PublicSubnet01
    Export:
      Name: !Sub ${ApplicationName}-PublicSubnet01

  PublicSubnet02:
    Description: ID for public subnet 02
    Value: !Ref PublicSubnet02
    Export:
      Name: !Sub ${ApplicationName}-PublicSubnet02

  PrivateSubnet01:
    Description: ID for private subnet 01
    Value: !Ref PrivateSubnet01
    Export:
      Name: !Sub ${ApplicationName}-PrivateSubnet01

  PrivateSubnet02:
    Description: ID for private subnet 02
    Value: !Ref PrivateSubnet02
    Export:
      Name: !Sub ${ApplicationName}-PrivateSubnet02

  ServiceSG:
    Description: Security group for ECS services
    Value: !Ref ServiceSG
    Export:
      Name: !Sub ${ApplicationName}-ServiceSG

  ProductionHostedZone:
    Description: HostedZone ID for the production hosted zone
    Value: !Ref ProductionHostedZone
    Export:
      Name: !Sub ${ApplicationName}-production-HostedZone

  ProductionPrivateNamespace:
    Description: Private namespace for the production environment
    Value: !Ref PrivateNamespace
    Export:
      Name: !Sub ${ApplicationName}-production-PrivateNamespace