[AWS]ALBのHTTPtoHTTPSリダイレクトをCloudFormationで実装する

コンニチハ、千葉です。

ALBの機能を利用することで、HTTPをHTTPSにリダイレクトが可能です。

[新機能]Webサーバでの実装不要!ALBだけでリダイレクト出来るようになりました!

今回、リダイレクトの設定をCloudFormationを使って構築したので残しておきます。

やってみた

まずは手動で設定してみる

どのパラメータを指定すればいいかわからなかったので、まずは手動で設定してみました。 HTTPからHTTPSへリダイレクトする、リスナールールを設定します。

最終的にリスナールールが https://#{host}:443/#{path}?#{query}、ステータスコードがHTTP_301となっていればよさそうです。

CloudFormationを書く

まずはポート番号80の定義です。ロードバランサーのリスナーの設定箇所で、デフォルトアクションにリダイレクトの定義を追加します。 Type: redirectにて、リダイレクトを指定します。RedirectConfigにて詳細なパラメータを指定します。 https://#{host}:443/#{path}?#{query}、ステータスコードがHTTP_301になるように指定します。 ポイントは、Pathだと/が必要だったり、Queryだと?の指定が不要だったりします。

参考:

Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
  Port: 80
  Protocol: HTTP
  DefaultActions:
    - Type: redirect
      RedirectConfig:
        Host: '#{host}'
        Path: '/#{path}'
        Port: 443
        Protocol: HTTPS
        Query: '#{query}'
        StatusCode: HTTP_301
  LoadBalancerArn: #ALBのARNを指定

次に、ポート番号443のリスナー設定です。プロトコルにHTTPSを指定して、証明書も指定しましょう。

Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
  Port: 443
  Protocol: HTTPS
  Certificates:
    - CertificateArn: #ACMのARNを指定
  DefaultActions:
    - TargetGroupArn: #ターゲットグループのARNを指定
      Type: forward
  LoadBalancerArn:  #ALBのARNを指定

Cloudformationで構築してみた

実際にCloudFormationスタックでELBを構築してみて、リダイレクトされるか確認してみました。 80番のリスナーは、想定通りのパラメータで作成されています。

実際にアクセスしてみて、リダイレクトされるか確認してみました。

問題なくHTTPからHTTPSへリダイレクトされました!

CloudFormationの全体

コピペ用です。ロードバランサー、リスナー、ターゲットグループを作成します。また、HTTPからHTTPSへリダイレクトします。 Mappingsに適宜パラメータ指定してご利用ください。

前提

CloudFormationを流す前提を書いておきます。

  • VPCが作成済みであること
  • ELB用のセキュリティグループが作成済みであること
  • ACMにて証明書で発行し、有効になっていること
  • ロードバランサーにアタッチするEC2が構築済みであること

作成されるリソース

このテンプレートで作成されるリソースは以下です。

  • ターゲットグループ
  • インターネットフェイシングのALB
  • HTTPリスナー
  • HTTPSリスナー

コード

AWSTemplateFormatVersion: '2010-09-09'
Description: This CloudFormation template to create ELB.

Mappings:
  prd:
    VPC:             { ID: vpc-xxx }
    PublicSubnet1a:  { ID: subnet-xxx }
    PublicSubnet1c:  { ID: subnet-xxx }
    AlbSecurityGroup: { ID: sg-xxx }
    Web1Ec2Instance:    { ID: i-xxx }
    Web2Ec2Instance:    { ID: i-xxx }
    Certificate:      { ARN: 'arn:aws:acm:ap-northeast-1:xxxx:certificate/xxxx' }

Parameters:
  Environment:
    Description: Type of this environment.
    Type: String
    Default: prd
    AllowedValues:
      - prd
      - stg
  SystemName:
    Description: Name of this system.
    Type: String
    Default: chiba-lb
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: Environment Configuration
      Parameters:
        - SystemName
        - Environment

Resources:
  # ALB
  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub ${Environment}-${SystemName}-alb
      Type: application
      Scheme: internet-facing
      IpAddressType: ipv4
      SecurityGroups:
        - !FindInMap [ !Ref Environment, AlbSecurityGroup, ID ]
      Subnets:
        - !FindInMap [ !Ref Environment, PublicSubnet1a, ID ]
        - !FindInMap [ !Ref Environment, PublicSubnet1c, ID ]
      Tags:
        - Key: Name
          Value: !Sub ${Environment}-${SystemName}-alb
  ApplicationLoadBalancerListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - Type: redirect
          RedirectConfig:
            Host: '#{host}'
            Path: '/#{path}'
            Port: 443
            Protocol: HTTPS
            Query: '#{query}'
            StatusCode: HTTP_301
      LoadBalancerArn: !Ref ApplicationLoadBalancer
  ApplicationLoadBalancerListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Port: 443
      Protocol: HTTPS
      Certificates:
        - CertificateArn: !FindInMap [ !Ref Environment, Certificate, ARN ]
      DefaultActions:
        - TargetGroupArn: !Ref AlbTargetGroup
          Type: forward
      LoadBalancerArn: !Ref ApplicationLoadBalancer

  # ALB Target group
  AlbTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub ${Environment}-${SystemName}-web-tg
      Port: 80
      Protocol: HTTP
      Targets:
        - Id: !FindInMap [ !Ref Environment, Web1Ec2Instance, ID ]
          Port: 80
        - Id: !FindInMap [ !Ref Environment, Web2Ec2Instance, ID ]
          Port: 80
      # Health check
      HealthCheckProtocol: HTTP
      HealthyThresholdCount: 5
      UnhealthyThresholdCount: 2
      HealthCheckTimeoutSeconds: 5
      HealthCheckIntervalSeconds: 30
      Matcher:
        HttpCode: 200
      VpcId: !FindInMap [ !Ref Environment, VPC, ID ]
      Tags:
        - Key: Name
          Value: !Sub ${Environment}-${SystemName}-web-tg

Outputs:
  AlbEndpoint:
    Value: !GetAtt ApplicationLoadBalancer.DNSName

最後に

CloudFormationを使って、HTTPをHTTPSへリダイレクトするELBを作りました。コード管理しておくと、何かと便利なのでコピペ用に置いておきます!

参考

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html