🖥

AWS WAF でメンテナンスモードの開始・解除を実現する ( +特定のIPアドレスだけはアクセスを許可する )

2024/07/10に公開1

概要

サービスメンテナンス中に、レスポンスコード 503 Service Temporarily Unavailable と、メンテナンス表示用のHTMLをユーザーに返したい

ALBとの比較

ALBでやる欠点は

  • 構成によってはALBで実現しようとすると作業が煩雑だったり、困難だったりする。
  • 特定のIPアドレスだけ許可しようとしても、1ルールあたりのIPアドレス設定の上限があり、やりづらい。
  • 1ルールの中でレスポンスヘッダが指定できないので、キャッシュコントロールがしづらい。

思い出してほしい。ALBは「バランサー」である。

メンテナンスモードに限らず、WAFでもALBでも実現できる動作はあるが、あくまでALBはパスに対してのリソースの振り分けに徹した方が良いと思った。

WAFの設定手順

STEP 1 . WAFにカスタムレスポンスを作成しておく

AWS WAF > Web ACLs > ACL名 > Custom Response Bodies から

  • 文字化けしないようにHTMLで文字コード系の指定をしておく
  • キャッシュが問題にならないようにキャッシュコントロールのmetaタグを指定しておく
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="UTF-8">
<meta http-equiv="content-language" content="ja">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<title>メンテナンス中 </title>

</head>
<body>
ただいまメンテナンス中です
</body>
</html>

STEP 2. WAF ルールの追加

登録開始

AWS WAF > Web ACLs > ACL名 > Rules > Add my own rules and rule groups を選ぶ

CleanShot 2024-07-03 at 14 18 50@2x

Actions の指定

  • Blockを選ぶ
  • カスタムレスポンスを利用する
  • レスポンスコードは503
  • ヘッダに Cache-Control no-cache を指定する ( メンテナンスモードを解除しても、ユーザ端末のキャッシュによって解除されていないように見えるのを防ぐ )

ルール同士の優先順位を決めてSaveする

設定すべき優先順位は構成による

STEP 3. 特別に許可するIPアドレスの設定

必要な場合は、STEP2と同じWAFのルールに、メンテナンスモードでもアクセスできるIPアドレスを設定する

まずは事前にWAFでIPセットを登録しておく

単一のIPセットを許可する場合は
「リクエストのIPアドレスが、IPセット1のものでない場合」にルールを適用するという条件を設定すれば良い

CleanShot 2024-07-05 at 08 10 35@2x

複数のIPセットを許可対象にする場合は
「リクエストのIPアドレスが、IPセット1のものでなく、なおかつ、IPセットのものでもない2場合」にルールを適用する条件を設定すれば良い

CleanShot 2024-07-05 at 08 05 57@2x

STEP 4. WAF ルールの削除

メンテナンスが終わったらWAFのルールを削除するだけ

STEP 5. 再度メンテナンスモードにする時

AWSからの直接登録だと、メンテナンスをする時に1回ずつが面倒だと思うが、どうするか

JSONで設定する

JSONでルールを保持できるようなので、それを次の登録時にも使うと良いだろう

ただし今回のようにAWS上の他のリソース (カスタムレスポンスのBODYやIPセット)も参照する形だと、ひとつのAWSアカウントのJSONは、他のAWSアカウントの環境では使えないので注意

優先順位で工夫する

ルール自体は削除せず保持したまま、他のルールとの優先順位の入れ替えでも簡単な切り替えを実現できるかもしれないが、未検証

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

プロフィール・経歴

https://github.com/YumaInaura/YumaInaura

公開日時

2024-07-05

https://qiita.com/YumaInaura/items/8a37876d0df6a88300e0

Discussion

rakiraki

思い出してほしい。ALBは「バランサー」である。

思い出してほしい。WAFは「ファイヤーウォール」である。

CloudFront や ALB に横付けするのがWAFであり、別料金がかかる。
L7で処理できるALB(のリスナールール)のほうが柔軟な対応ができる(場合がある)。

既にWAFを利用していて、IPアドレス以外の条件では分岐を行わず、ALBのリスナールールが既に十分複雑である(から弄りたくない)場合、はWAFを使う選択もありだと思うが、それ以外はALBのリスナールールを採用したほうが総合的に楽。

そもそもパスベースのルーティングで管理画面のアクセス制限する時もALBで実現できる。
メンテモードはこのパス指定がないのと同じ(全てのパスで指定のIPアドレスの時に既存のターゲットグループに流す)なので、メンテモードのメンテナンスも楽。

AWSからの直接登録だと、メンテナンスをする時に1回ずつが面倒だと思うが、どうするか

WAFでもALBでも管理を terraform や cdk などの IaC を活用していれば適用も復元も問題ないと思われる。
手作業で json 管理は勧められない。

ちなみにALBでやるなら優先度を変えるだけで条件をとっておいても大丈夫(実際に処理されないように最後に持っていく。使う時に優先度を上げることで処理されるようにする)な点もWAFよりALBを採用する理由にできると思う。