Lambda-School-Labs/prismatopia

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

Summary

Maintainability
Test Coverage
AWSTemplateFormatVersion: "2010-09-09"
Description: Environment specific AWS resources

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

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

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

Conditions:
  IsProductionEnvironment: !Equals [ !Ref EnvironmentName, production ]

Resources:
  PublicLoadBalancerSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security Group for the load balancer
      VpcId:
        Fn::ImportValue:
            !Sub ${ApplicationName}-VPCID
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: "tcp"
          FromPort: 80
          ToPort: 80
        - CidrIp: 0.0.0.0/0
          IpProtocol: "tcp"
          FromPort: 443
          ToPort: 443

  PrismaLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Type: application
      Scheme: internet-facing
      LoadBalancerAttributes:
      - Key: idle_timeout.timeout_seconds
        Value: '30'
      Subnets:
        - Fn::ImportValue:
            !Sub ${ApplicationName}-PublicSubnet01
        - Fn::ImportValue:
            !Sub ${ApplicationName}-PublicSubnet02
      SecurityGroups:
        - !Ref PublicLoadBalancerSG
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-${EnvironmentName}-prisma

  ApolloLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Type: application
      Scheme: internet-facing
      LoadBalancerAttributes:
      - Key: idle_timeout.timeout_seconds
        Value: '30'
      Subnets:
        - Fn::ImportValue:
            !Sub ${ApplicationName}-PublicSubnet01
        - Fn::ImportValue:
            !Sub ${ApplicationName}-PublicSubnet02
      SecurityGroups:
        - !Ref PublicLoadBalancerSG
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-${EnvironmentName}-apollo

  PrismaTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 6
      HealthCheckPath: /status
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      Port: 80
      Protocol: HTTP
      UnhealthyThresholdCount: 2
      VpcId:
        Fn::ImportValue:
            !Sub ${ApplicationName}-VPCID
      TargetType: 'ip'
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: '10'
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-${EnvironmentName}-prisma

  ApolloTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 6
      HealthCheckPath: /.well-known/apollo/server-health
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      Port: 80
      Protocol: HTTP
      UnhealthyThresholdCount: 2
      VpcId:
        Fn::ImportValue:
            !Sub ${ApplicationName}-VPCID
      TargetType: 'ip'
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: '10'
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-${EnvironmentName}-apollo

  PrismaLoadBalancerListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: redirect
          RedirectConfig:
            Protocol: HTTPS
            Port: '443'
            Host: '#{host}'
            Path: '/#{path}'
            Query: '#{query}'
            StatusCode: HTTP_301
      LoadBalancerArn: !Ref 'PrismaLoadBalancer'
      Protocol: HTTP
      Port: 80

  ApolloLoadBalancerListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: redirect
          RedirectConfig:
            Protocol: HTTPS
            Port: '443'
            Host: '#{host}'
            Path: '/#{path}'
            Query: '#{query}'
            StatusCode: HTTP_301
      LoadBalancerArn: !Ref 'ApolloLoadBalancer'
      Protocol: HTTP
      Port: 80

  PrismaLoadBalancerListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Certificates:
        - CertificateArn:
            Fn::ImportValue:
              !Sub ${ApplicationName}-${EnvironmentName}-Certificate
      DefaultActions:
        - TargetGroupArn: !Ref 'PrismaTargetGroup'
          Type: 'forward'
      LoadBalancerArn: !Ref 'PrismaLoadBalancer'
      Protocol: HTTPS
      Port: 443

  ApolloLoadBalancerListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Certificates:
        - CertificateArn:
            Fn::ImportValue:
              !Sub ${ApplicationName}-${EnvironmentName}-Certificate
      DefaultActions:
        - TargetGroupArn: !Ref 'ApolloTargetGroup'
          Type: 'forward'
      LoadBalancerArn: !Ref 'ApolloLoadBalancer'
      Protocol: HTTPS
      Port: 443

  ARecordApolloPublicAPI:
    Type: AWS::Route53::RecordSet
    Properties:
      Comment: !Sub Apollo API A record for the ${EnvironmentName} environment of ${ApplicationName}
      HostedZoneId:
        Fn::ImportValue:
            !Sub ${ApplicationName}-${EnvironmentName}-HostedZone
      # Environment A records are added to a subdomain, production records are on the application domain
      Name: !If [IsProductionEnvironment, !Sub "apollo.${ApplicationDomainNamespace}", !Sub "apollo.${EnvironmentName}.${ApplicationDomainNamespace}"]
      Type: A
      AliasTarget:
        DNSName: !GetAtt ApolloLoadBalancer.DNSName
        HostedZoneId: !GetAtt ApolloLoadBalancer.CanonicalHostedZoneID

  ARecordPrismaPublicAPI:
    Type: AWS::Route53::RecordSet
    Properties:
      Comment: !Sub Prisma API A record for the ${EnvironmentName} environment of ${ApplicationName}
      HostedZoneId:
        Fn::ImportValue:
            !Sub ${ApplicationName}-${EnvironmentName}-HostedZone
      # Environment A records are added to a subdomain, production records are on the application domain
      Name: !If [IsProductionEnvironment, !Sub "prisma.${ApplicationDomainNamespace}", !Sub "prisma.${EnvironmentName}.${ApplicationDomainNamespace}"]
      Type: A
      AliasTarget:
        DNSName: !GetAtt PrismaLoadBalancer.DNSName
        HostedZoneId: !GetAtt PrismaLoadBalancer.CanonicalHostedZoneID

  ECSCluster:
    Type: "AWS::ECS::Cluster"
    Properties:
      ClusterName: !Sub ${ApplicationName}-${EnvironmentName}

Outputs:
  PrismaTargetGroup:
    Description: The target group for the Prisma service
    Value: !Ref PrismaTargetGroup
    Export:
      Name: !Sub ${ApplicationName}-${EnvironmentName}-PrismaTargetGroup

  ApolloTargetGroup:
    Description: The target group for the Apollo service
    Value: !Ref ApolloTargetGroup
    Export:
      Name: !Sub ${ApplicationName}-${EnvironmentName}-ApolloTargetGroup

  ECSCluster:
    Description: The ECS cluster
    Value: !Ref ECSCluster
    Export:
      Name: !Sub ${ApplicationName}-${EnvironmentName}-ECSCluster