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

CloudFormationを使って、一発でロードバランサーを作成します。また、HTTPをHTTPSへリダイレクトする設定が追加されます。
2019.02.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンニチハ、千葉です。

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

https://dev.classmethod.jp/cloud/aws/alb-redirects/

今回、リダイレクトの設定を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