🔥

AWS/WAFでメンテナンスページを表示する

2023/07/27に公開

はじめに

今回はAWSのWAFでメンテナンスページを表示させてみました。
アクセス許可したIPはコンテンツを閲覧でき、それ以外のIPはWAFで設定したメンテナンスページに案内するという構成です。

最初はs3にHTMLファイル配置して、そこにアクセスさせる方法か?
と思っていたのですが、WAFで完結できると知り試してみた次第です。
楽ちんでうれしいです。

https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-custom-request-response.html

検証イメージ図

この構成のメリット

  • s3等にメンテナンスページを配置する必要がない
    • WAFのみで完結する
  • 許可したIPは動作確認などでページを閲覧可能

前提

CloudFront+s3でホスティングされた静的サイト、WAFによるIP制限機能が実装されていることを前提とします。
こちらの記事でWAFのIP制限機能を説明していますので、よかったら見て下さい。
https://zenn.dev/not75743/articles/67a04861519846

要件

  • 許可したいIP:サイト閲覧可能
  • それ以外のIP:メンテナンスページに誘導
    • メンテナンスページはステータスコード503を返却する
  • オンオフが簡単にできる

検証

この流れですすめていきます。

  • IPSetのIPをallow、デフォルトアクションがblockであることを確認する
  • web aclのCustom response bodiesから返却したいレスポンスを作成
  • Default web ACL action for requests that don't match any rulesの項目で↑で作成したレスポンス、ステータスコードを指定
  • 動作確認

カスタムレスポンスを作成する

webaclのCustom response bodiesより作成が可能です。

Content Type,Response bodyを設定します。
今回はHTMLを使います。

<h1>maintenance</h1>

ルールに合致しないリクエストにカスタムレスポンスを適用する

Default web ACL action for requests that don't match any rulesから先程作成したカスタムレスポンスを選びます。
エラーコードもここで設定します。

動作確認

リクエストを送って想定通りの挙動となるか確認します。
許可された端末は

$ curl -I https://<endpoint>
HTTP/2 200 

問題なく通信できます。

許可されていない端末は

$ curl https://<endpoint>
<h1>at maintenance</h1>

$ curl -I https://<endpoint>
HTTP/2 503 

指定したレスポンスボディ、ステータスコードが返却されました。
OKです!

メンテナンスページの適用解除

カスタムレスポンス設定のEnableからチェックを外せばよいです。
簡単です。

Terraform化

今後楽できるようにTerraform化しました。
カスタムレスポンスは以下の様に作成出来ます。

resource "aws_wafv2_web_acl" "web_acl" {
// 略
  custom_response_body {
    key          = "maintenance"
    content      = "<h1>maintenance</h1>"
    content_type = "TEXT_HTML"
  }

ですが適用させる手段まで調べきれませんでした。
頻繁に行う設定ではないため、メンテナンスページ表示の際は手動かawscliで対応したいと思います。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl#custom_response_body-block

2023年7月29日追記

以下のように設定すれば作成したカスタムレスポンスを、ルールに合致しないリクエストに適用させることができました。

resource "aws_wafv2_web_acl" "web_acl" {
// 略
  custom_response_body {
    key          = "maintenance"
    content      = "<h1>maintenance</h1>"
    content_type = "TEXT_HTML"
  }

  default_action {
    block {
      custom_response {
        response_code = 503
        custom_response_body_key = "maintenance"
      }
    }
  }

おわりに

WAFだけで完結するのがとても嬉しいですね。
s3にファイル置いて〜、などのアクションが不要なのはとても助かります。

余裕ができたらawscliでカスタムレスポンス適用を対応できるようにしたいですね。

参考

https://qiita.com/mitzi2funk/items/7dfd07ec00b916b8dfc6
https://www.fourier.jp/techblog/articles/maintenance-aws-laravel/
https://dev.classmethod.jp/articles/aws-waf-custom-response_bodies_html/
https://kenzo0107.github.io/2022/03/12/2022-03-13-maintenance-mode-for-alb-or-cloudfront/

Discussion