WAFとALBリスナールールで「メンテナンス時間帯には開発拠点からのアクセスのみ許可」を実現する

メンテナンス時間帯には一般からのアクセスには503を返しておき開発拠点からのアクセスのみ許可したいことがちょいちょいある。

WAFのルールの付け替えだけでいけるケースも多々あるが、単純なブロックではなく503をちゃんと返したい/メンテナンス画面出したいなど一旦ALBまで届かせたいケースもあるのでそういうときのメモ。

そういうときはまず同じ宛先に対して「サービス用外部ドメイン」と「メンテナンス用外部ドメイン」の2個を用意する。

サービス用外部ドメインは一般ユーザが利用するドメイン。たとえばここでは api.example.net (本番環境にのみ存在)みたいにしておく。

メンテナンス用外部ドメインは開発拠点からのアクセスのみ許可されるドメイン。証明書の量産が嫌なので開発部で一個もしくは環境別に一個ずつ基底ドメインを決めておき、個々のドメインはその基底ドメインの直下の階層に配置されるようにする。たとえばここでは基底ドメインexample.com とした場合、先ほどのサービス用外部ドメインに対応したメンテナンス用外部ドメインapi--example--net.dev.example.com (開発環境)、 api--example--net.prod.example.com (本番環境)みたいにしておく(ここでは元のドメインのドットをハイフン2個にした)。証明書は *.dev.example.com と *.prod.example.com だけ用意しておけばメンテナンス用外部ドメインについては全部まかなえることになる。

ここで、WAFを用意して「HOSTヘッダの末尾が .example.com の場合、開発拠点を示すIPセットのときのみ通過する」というルールを作ってALBに付与しておくことで、まず平時「メンテナンス用外部ドメインでアクセスしてきたときは開発拠点からのアクセスのみALBに辿り着ける。それ以外のドメインでアクセスしてきたときはみんなALBに辿り着ける」となる。

また、ALBには優先度1のリスナールールとして「HOSTヘッダが *.example.com の場合はターゲットグループにフォワードする」、デフォルトルールとして「ターゲットグループにフォワードする」を設定しておく。

このALBのルールは平時は同じ挙動なので意味がないが、メンテナンス時間帯になったら定期実行のLambdaで当該ALBに優先度900のリスナールールとして「無条件にステータス503とメンテナンス時間であることを示す静的コンテンツを返す」を付与すると、最終的に「メンテナンス時間帯に開発拠点からのアクセスは通すがそれ以外のアクセスは遮断」が実現できる。

メンテナンス時間帯が終わったら定期実行のLambdaで優先度900のリスナールールを除去すれば良い。

この設定のポイントは「ALBに辿り着く前のWAFの時点で特定のHOSTヘッダを開発拠点に制限する」「ALBでは特定のHOSTヘッダは常にフォワード、それ以外は条件によってフォワードか503をハンドリング」という2つの大きな機構が連携して機能しているところ。

ただ、API Gatewayで認証認可させるためにVPC Link+プライベートサブネット内NLBで厳密にAPI Gateway以外からのアクセスを弾く機構を入れた場合に併用できないのがつらい。