AWSTemplateFormatVersion: '2010-09-09'
Description: External, public facing load balancer, for forwarding public traffic to containers.
Parameters:
  EnvironmentName:
    Type: String
    Default: production
    Description: The name of the environment to add this load balancer to
Resources:
  EcsSecurityGroupIngressFromPublicALB:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      Description: Ingress from the public ALB
      GroupId:
        Fn::ImportValue: !Sub ${EnvironmentName}:ContainerSecurityGroup
      IpProtocol: -1
      SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'

  # Public load balancer, hosted in public subnets that is accessible
  # to the public, and is intended to route traffic to one or more public
  # facing services. This is used for accepting traffic from the public
  # internet and directing it to public facing microservices
  PublicLoadBalancerSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the public facing load balancer
      VpcId:
        Fn::ImportValue: !Sub ${EnvironmentName}:VpcId
      SecurityGroupIngress:
          # Allow access to ALB from anywhere on the internet
          - CidrIp: 0.0.0.0/0
            IpProtocol: -1
  PublicLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      LoadBalancerAttributes:
      - Key: idle_timeout.timeout_seconds
        Value: '30'
      Subnets:
        # The load balancer is placed into the public subnets, so that traffic
        # from the internet can reach the load balancer directly via the internet gateway
        - Fn::ImportValue: !Sub ${EnvironmentName}:PublicSubnetOne
        - Fn::ImportValue: !Sub ${EnvironmentName}:PublicSubnetTwo
      SecurityGroups: [!Ref 'PublicLoadBalancerSG']
  # A dummy target group is used to setup the ALB to just drop traffic
  # initially, before any real service target groups have been added.
  DummyTargetGroupPublic:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 6
      HealthCheckPath: /
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      Port: 80
      Protocol: HTTP
      UnhealthyThresholdCount: 2
      VpcId:
        Fn::ImportValue: !Sub ${EnvironmentName}:VpcId
  PublicLoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref 'DummyTargetGroupPublic'
          Type: 'forward'
      LoadBalancerArn: !Ref 'PublicLoadBalancer'
      Port: 80
      Protocol: HTTP

Outputs:
  PublicListener:
    Description: The ARN of the public load balancer's Listener
    Value: !Ref PublicLoadBalancerListener
    Export:
      Name: !Sub ${EnvironmentName}:PublicListener
  ExternalUrl:
    Description: The url of the external load balancer
    Value: !Sub http://${PublicLoadBalancer.DNSName}
    Export:
      Name: !Sub ${EnvironmentName}:ExternalUrl
