<commit_before># stacks/load-balancers.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: >
  Creates application load balancers that can be reused for multiple
  applications, using host- and path-based routing rules.
Conditions:
  CreateStagingResources: !Equals [!Ref EnvironmentType, Staging]
  CreateProductionResources: !Equals [!Ref EnvironmentType, Production]
Parameters:
  EnvironmentType:
    Type: String
  EnvironmentTypeAbbreviation:
    Type: String
  VPC:
    Type: "AWS::EC2::VPC::Id"
  VPCSubnet1:
    Type: "AWS::EC2::Subnet::Id"
  VPCSubnet2:
    Type: "AWS::EC2::Subnet::Id"
  VPCSubnet3:
    Type: "AWS::EC2::Subnet::Id"
  VPCCertificateArn:
    Type: String
  OpsWarnMessagesSnsTopicArn:
    Type: String
  OpsErrorMessagesSnsTopicArn:
    Type: String
Resources:
  PlatformSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Allow web and SSH traffic to the ALB
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
        - CidrIpv6: ::/0
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
        - CidrIpv6: ::/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - CidrIpv6: ::/0
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
      Tags:
        - Key: Project
          Value: platform.prx.org
        - Key: Environment
          Value: !Ref EnvironmentType
        - Key: Name
          Value: !Sub Platform-${EnvironmentType}-LB-web_ssh
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
  PlatformALBDefaultTargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      HealthCheckIntervalSeconds: 10
      HealthyThresholdCount: 3
      HealthCheckPath: "/ecs-health-check"
      Name: !Sub default-${EnvironmentTypeAbbreviation}-${VPC}
      Port: 80
      Protocol: HTTP
      Tags:
        - Key: Project
          Value: platform.prx.org
        - Key: Environment
          Value: !Ref EnvironmentType
        - Key: Name
          Value: !Sub Platform-${EnvironmentType}
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
      VpcId: !Ref VPC
  PlatformALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    DependsOn:
      - PlatformALBLogsBucketPolicy
    Properties:
      IpAddressType: dualstack
      LoadBalancerAttributes:
        # https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes
        - Key: idle_timeout.timeout_seconds
          Value: "150"
        - Key: access_logs.s3.enabled
          Value: "true"
        - Key: access_logs.s3.bucket
          Value: !Ref PlatformALBLogsBucket
      Scheme: internet-facing
      SecurityGroups:
        - !Ref PlatformSecurityGroup
      Subnets:
        - !Ref VPCSubnet1
        - !Ref VPCSubnet2
        - !Ref VPCSubnet3
      Tags:
        - Key: Project
          Value: platform.prx.org
        - Key: Environment
          Value: !Ref EnvironmentType
        - Key: Name
          Value: !Sub Platform-${EnvironmentType}
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
  PlatformALBHTTPListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      LoadBalancerArn: !Ref PlatformALB
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - FixedResponseConfig:
            StatusCode: "404"
          Type: fixed-response
  PlatformALBHTTPSListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      Certificates:
        - CertificateArn: !Ref VPCCertificateArn
      LoadBalancerArn: !Ref PlatformALB
      Port: 443
      Protocol: HTTPS
      DefaultActions:
        - FixedResponseConfig:
            StatusCode: "404"
          Type: fixed-response
  # Logging
  PlatformALBLogsBucket:
    Type: "AWS::S3::Bucket"
    DeletionPolicy: Retain
    Properties:
      LifecycleConfiguration:
        Rules:
          - ExpirationInDays: 3
            Status: Enabled
      Tags:
        - Key: Project
          Value: Infrastructure
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
      VersioningConfiguration:
        Status: Suspended
  PlatformALBLogsBucketPolicy:
    # https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref PlatformALBLogsBucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: ELBLogWriteAccess
            Action:
              - "s3:PutObject"
            Effect: Allow
            Principal:
              AWS:
                - "127311923021" # The us-east-1 account ID of ELB
            Resource:
              - !Sub ${PlatformALBLogsBucket.Arn}/*
  # CloudWatch Alarms
  PlatformALB5XXAlarm:
    Type: "AWS::CloudWatch::Alarm"
    Condition: CreateProductionResources
    Properties:
      ActionsEnabled: true
      AlarmName: !Sub "[${VPC}][ALB][Error] LB 5XX"
      AlarmActions:
        - !Ref OpsErrorMessagesSnsTopicArn
      InsufficientDataActions:
        - !Ref OpsErrorMessagesSnsTopicArn
      OKActions:
        - !Ref OpsErrorMessagesSnsTopicArn
      AlarmDescription: >
        5XX server errors originating from the Platform ALB exceeded 0
      ComparisonOperator: GreaterThanThreshold
      EvaluationPeriods: 5
      MetricName: HTTPCode_ELB_5XX_Count
      Namespace: AWS/ApplicationELB
      Period: 60
      Statistic: Sum
      Threshold: 5
      TreatMissingData: notBreaching
      Dimensions:
        - Name: LoadBalancer
          Value: !GetAtt PlatformALB.LoadBalancerFullName
  PlatformALBResponseTimeP95Alarm:
    Type: "AWS::CloudWatch::Alarm"
    Condition: CreateProductionResources
    Properties:
      ActionsEnabled: true
      AlarmName: !Sub "[${VPC}][ALB][TargetResponseTime] P90 unusually slow"
      AlarmActions:
        - !Ref OpsWarnMessagesSnsTopicArn
      InsufficientDataActions:
        - !Ref OpsWarnMessagesSnsTopicArn
      OKActions:
        - !Ref OpsWarnMessagesSnsTopicArn
      AlarmDescription: >
        Target response time value for platform load balancer targets at 90th
        percentile higher than expected
      ComparisonOperator: GreaterThanOrEqualToThreshold
      EvaluationPeriods: 3
      ExtendedStatistic: p90
      MetricName: TargetResponseTime
      Namespace: AWS/ApplicationELB
      Period: 60
      Threshold: 1.0
      TreatMissingData: notBreaching
      Dimensions:
        - Name: LoadBalancer
          Value: !GetAtt PlatformALB.LoadBalancerFullName
Outputs:
  PlatformALBArn:
    Description: The ARN for the application load balancer
    Value: !Ref PlatformALB
  PlatformALBDNSName:
    Description: The DNS name for the application load balancer
    Value: !GetAtt PlatformALB.DNSName
  PlatformALBDualstackDNSName:
    Description: The dualstack DNS name for the application load balancer
    Value: !Sub dualstack.${PlatformALB.DNSName}
  PlatformALBFullName:
    Description: The full name for the application load balancer
    Value: !GetAtt PlatformALB.LoadBalancerFullName
  PlatformALBDefaultTargetGroupArn:
    Description: The ARN for the default target group
    Value: !Ref PlatformALBDefaultTargetGroup
  PlatformALBCanonicalHostedZoneID:
    Description: The hosted zone ID for the application load balancer
    Value: !GetAtt PlatformALB.CanonicalHostedZoneID
  PlatformALBHTTPListenerArn:
    Description: The ARN for the HTTP listener
    Value: !Ref PlatformALBHTTPListener
  PlatformALBHTTPSListenerArn:
    Description: The ARN for the HTTPS listener
    Value: !Ref PlatformALBHTTPSListener
<commit_msg>Upgrade all HTTP requests on platform ALB<commit_after># stacks/load-balancers.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: >
  Creates application load balancers that can be reused for multiple
  applications, using host- and path-based routing rules.
Conditions:
  CreateStagingResources: !Equals [!Ref EnvironmentType, Staging]
  CreateProductionResources: !Equals [!Ref EnvironmentType, Production]
Parameters:
  EnvironmentType:
    Type: String
  EnvironmentTypeAbbreviation:
    Type: String
  VPC:
    Type: "AWS::EC2::VPC::Id"
  VPCSubnet1:
    Type: "AWS::EC2::Subnet::Id"
  VPCSubnet2:
    Type: "AWS::EC2::Subnet::Id"
  VPCSubnet3:
    Type: "AWS::EC2::Subnet::Id"
  VPCCertificateArn:
    Type: String
  OpsWarnMessagesSnsTopicArn:
    Type: String
  OpsErrorMessagesSnsTopicArn:
    Type: String
Resources:
  PlatformSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Allow web and SSH traffic to the ALB
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
        - CidrIpv6: ::/0
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
        - CidrIpv6: ::/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - CidrIpv6: ::/0
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
      Tags:
        - Key: Project
          Value: platform.prx.org
        - Key: Environment
          Value: !Ref EnvironmentType
        - Key: Name
          Value: !Sub Platform-${EnvironmentType}-LB-web_ssh
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
  PlatformALBDefaultTargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      HealthCheckIntervalSeconds: 10
      HealthyThresholdCount: 3
      HealthCheckPath: "/ecs-health-check"
      Name: !Sub default-${EnvironmentTypeAbbreviation}-${VPC}
      Port: 80
      Protocol: HTTP
      Tags:
        - Key: Project
          Value: platform.prx.org
        - Key: Environment
          Value: !Ref EnvironmentType
        - Key: Name
          Value: !Sub Platform-${EnvironmentType}
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
      VpcId: !Ref VPC
  PlatformALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    DependsOn:
      - PlatformALBLogsBucketPolicy
    Properties:
      IpAddressType: dualstack
      LoadBalancerAttributes:
        # https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes
        - Key: idle_timeout.timeout_seconds
          Value: "150"
        - Key: access_logs.s3.enabled
          Value: "true"
        - Key: access_logs.s3.bucket
          Value: !Ref PlatformALBLogsBucket
      Scheme: internet-facing
      SecurityGroups:
        - !Ref PlatformSecurityGroup
      Subnets:
        - !Ref VPCSubnet1
        - !Ref VPCSubnet2
        - !Ref VPCSubnet3
      Tags:
        - Key: Project
          Value: platform.prx.org
        - Key: Environment
          Value: !Ref EnvironmentType
        - Key: Name
          Value: !Sub Platform-${EnvironmentType}
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
  PlatformALBHTTPListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      LoadBalancerArn: !Ref PlatformALB
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - FixedResponseConfig:
            StatusCode: "404"
          Type: fixed-response
  PlatformALBHTTPUpgradeRedirectListenerRule:
    Type: "AWS::ElasticLoadBalancingV2::ListenerRule"
    Properties:
      Actions:
        - RedirectConfig:
            Host: '#{host}'
            Path: '#{path}'
            Port: '#{port}'
            Protocol: HTTPS
            Query: '#{query}'
            StatusCode: HTTP_301
          Type: redirect
      Conditions:
        - Field: path-pattern
          Values:
            - '*'
      ListenerArn: !Ref PlatformALBHTTPListener
      Priority: 1
  PlatformALBHTTPSListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      Certificates:
        - CertificateArn: !Ref VPCCertificateArn
      LoadBalancerArn: !Ref PlatformALB
      Port: 443
      Protocol: HTTPS
      DefaultActions:
        - FixedResponseConfig:
            StatusCode: "404"
          Type: fixed-response
  # Logging
  PlatformALBLogsBucket:
    Type: "AWS::S3::Bucket"
    DeletionPolicy: Retain
    Properties:
      LifecycleConfiguration:
        Rules:
          - ExpirationInDays: 3
            Status: Enabled
      Tags:
        - Key: Project
          Value: Infrastructure
        - Key: "prx:cloudformation:stack-name"
          Value: !Ref AWS::StackName
        - Key: "prx:cloudformation:stack-id"
          Value: !Ref AWS::StackId
      VersioningConfiguration:
        Status: Suspended
  PlatformALBLogsBucketPolicy:
    # https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref PlatformALBLogsBucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: ELBLogWriteAccess
            Action:
              - "s3:PutObject"
            Effect: Allow
            Principal:
              AWS:
                - "127311923021" # The us-east-1 account ID of ELB
            Resource:
              - !Sub ${PlatformALBLogsBucket.Arn}/*
  # CloudWatch Alarms
  PlatformALB5XXAlarm:
    Type: "AWS::CloudWatch::Alarm"
    Condition: CreateProductionResources
    Properties:
      ActionsEnabled: true
      AlarmName: !Sub "[${VPC}][ALB][Error] LB 5XX"
      AlarmActions:
        - !Ref OpsErrorMessagesSnsTopicArn
      InsufficientDataActions:
        - !Ref OpsErrorMessagesSnsTopicArn
      OKActions:
        - !Ref OpsErrorMessagesSnsTopicArn
      AlarmDescription: >
        5XX server errors originating from the Platform ALB exceeded 0
      ComparisonOperator: GreaterThanThreshold
      EvaluationPeriods: 5
      MetricName: HTTPCode_ELB_5XX_Count
      Namespace: AWS/ApplicationELB
      Period: 60
      Statistic: Sum
      Threshold: 5
      TreatMissingData: notBreaching
      Dimensions:
        - Name: LoadBalancer
          Value: !GetAtt PlatformALB.LoadBalancerFullName
  PlatformALBResponseTimeP95Alarm:
    Type: "AWS::CloudWatch::Alarm"
    Condition: CreateProductionResources
    Properties:
      ActionsEnabled: true
      AlarmName: !Sub "[${VPC}][ALB][TargetResponseTime] P90 unusually slow"
      AlarmActions:
        - !Ref OpsWarnMessagesSnsTopicArn
      InsufficientDataActions:
        - !Ref OpsWarnMessagesSnsTopicArn
      OKActions:
        - !Ref OpsWarnMessagesSnsTopicArn
      AlarmDescription: >
        Target response time value for platform load balancer targets at 90th
        percentile higher than expected
      ComparisonOperator: GreaterThanOrEqualToThreshold
      EvaluationPeriods: 3
      ExtendedStatistic: p90
      MetricName: TargetResponseTime
      Namespace: AWS/ApplicationELB
      Period: 60
      Threshold: 1.0
      TreatMissingData: notBreaching
      Dimensions:
        - Name: LoadBalancer
          Value: !GetAtt PlatformALB.LoadBalancerFullName
Outputs:
  PlatformALBArn:
    Description: The ARN for the application load balancer
    Value: !Ref PlatformALB
  PlatformALBDNSName:
    Description: The DNS name for the application load balancer
    Value: !GetAtt PlatformALB.DNSName
  PlatformALBDualstackDNSName:
    Description: The dualstack DNS name for the application load balancer
    Value: !Sub dualstack.${PlatformALB.DNSName}
  PlatformALBFullName:
    Description: The full name for the application load balancer
    Value: !GetAtt PlatformALB.LoadBalancerFullName
  PlatformALBDefaultTargetGroupArn:
    Description: The ARN for the default target group
    Value: !Ref PlatformALBDefaultTargetGroup
  PlatformALBCanonicalHostedZoneID:
    Description: The hosted zone ID for the application load balancer
    Value: !GetAtt PlatformALB.CanonicalHostedZoneID
  PlatformALBHTTPListenerArn:
    Description: The ARN for the HTTP listener
    Value: !Ref PlatformALBHTTPListener
  PlatformALBHTTPSListenerArn:
    Description: The ARN for the HTTPS listener
    Value: !Ref PlatformALBHTTPSListener

{'fraction_non_alphanumeric': 0.07887275041953591, 'fraction_numerical': 0.01649210115155373, 'mean_word_length': 2.449500998003992, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '782757', 'n_tokens_mistral': 5356, 'n_tokens_neox': 5022, 'n_words': 1185}