CloudFrontのカスタムエラーレスポンスとWAFでメンテナンスページを表示する

CloudFrontのカスタムエラーレスポンス機能とAWS WAFと連携することで、メンテナンスページを手軽に表示することができます。


CloudFrontのカスタムエラーレスポンス機能とは

特定のhttpステータスコードの時に、指定したエラーページファイルへ遷移させ、かつhttpステータスコードの上書きができる機能のことです。

docs.aws.amazon.com


対象リソース

CloudFrontを対象としています。


仕組み

こちらで、なぜこれでメンテナンスページが実現できるのか考えてみました。

go-to-k.hatenablog.com


特徴

①フロント環境のみでメンテナンスページを表示できる

バックエンド側の実装や変更を必要とせずにメンテナンスページを表示できます。


※CloudFrontのカスタムエラーレスポンス機能を使わず、WAFのカスタムレスポンスという新機能のみでもメンテナンスページを実現することが可能です

go-to-k.hatenablog.com


API側をメンテナンスモードにする方法はこちら

go-to-k.hatenablog.com


JavaScriptなどのコード実装が必要ない

CloudFront・WAFの機能と、メンテナンスページ用ファイルさえ用意できれば、その他のコード実装・変更の必要はありません。


方法

今回もCloudFormationのテンプレートファイルをベースに説明します。

※詳細のファイルはGitHubにあります。

github.com


主な流れ

  • AWS WAFのWebACLを作成する
  • CloudFrontにWAFのアタッチとカスタムエラーレスポンスを設定する

WAFの作成

API側のメンテナンスモードのときは、WAFのカスタムレスポンス機能を使用しましたが、今回は特に使用しません。

  WAFWebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name: "Maintenance-WebACL"
      Scope: "CLOUDFRONT"
      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: !Ref WAFWebACLMetricName
        SampledRequestsEnabled: true
      DefaultAction:
        Block: {}


  • Scope
    • アタッチするリソース(CloudFront)はグローバルサービスのため、ScopeはCLOUDFRONTにする
Scope: "CLOUDFRONT"


  • VisibilityConfig
    • 監視のための設定など
    • 今回はあまり触れません
      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: !Ref WAFWebACLMetricName
        SampledRequestsEnabled: true


  • Block
    • カスタムレスポンスなどを使用せずに無条件にただブロックする場合は、Block: {}を書く
    • その場合は、httpステータスコードは403が返ります
      DefaultAction:
        Block: {}


CloudFrontのカスタムエラーレスポンスとWAFアタッチ

それ以外の部分はサンプルなので気にしないでください。

    CloudfrontForTest:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Enabled: true
          Comment: "for maintenance page test"
          PriceClass: PriceClass_200
          DefaultRootObject: index.html
          Aliases: !Ref DomainAlias
          Origins:
            - DomainName: !Sub "${TestS3Bucket}.s3-ap-northeast-1.amazonaws.com"
              Id: S3Origin
              S3OriginConfig:
                OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudfrontForTestOriginAccessIdentity}"
          IPV6Enabled: true
          HttpVersion: http2
          DefaultCacheBehavior:
            AllowedMethods:
              - HEAD
              - GET
            CachedMethods:
              - HEAD
              - GET
            Compress: false
            DefaultTTL: 86400
            MaxTTL: 31536000
            MinTTL: 0
            ForwardedValues:
              QueryString: false
              Headers:
                - Origin
                - Access-Control-Request-Headers
                - Access-Control-Request-Method
            SmoothStreaming: false
            TargetOriginId: S3Origin
            ViewerProtocolPolicy: redirect-to-https
          ViewerCertificate:
            AcmCertificateArn: !Ref AcmArn
            MinimumProtocolVersion: TLSv1.2_2018
            SslSupportMethod: sni-only
          # カスタムエラーレスポンス
          CustomErrorResponses:
          - ErrorCode: '403'
            ResponsePagePath: "/maintenance.html"
            ResponseCode: '503'
          # WAFのアタッチ
          WebACLId: !Ref WAFWebACL


  • CustomErrorResponses
    • 先程のWAFをアタッチすると無条件で403が返るので、「403が返ってきた時に503に変更して、/maintenance.htmlに遷移する」設定にする
      • メンテナンス時のhttpステータスコードは503のケースが多いため
      • ※メンテナンスページとして実際に表示するmaintenance.htmlを用意しておく必要があります
        • ここではHTMLファイルの内容には触れません。お好きなデザインをご用意ください。
          CustomErrorResponses:
          - ErrorCode: '403'
            ResponsePagePath: "/maintenance.html"
            ResponseCode: '503'


  • WebACLId
    • WebAclパラメータに先程作成したWAFのWebACLのARNを指定する
          WebACLId: !Ref WAFWebACL


まとめ

CloudFrontのカスタムエラーレスポンスAWS WAFを組み合わせて、フロント環境のみでメンテナンスページを表示する方法についてでした。