LoginSignup
2
1

AWS WAF で OPTIONS Request を捌く...!

Last updated at Posted at 2023-12-07

これは グロービス Advent Calendar 2023 の7日目の記事です。

お気持ち表明

「AWS WAF のルールで Block した上で 200 で返す」と言われてパッとユースケースが思い浮かぶ方はどのくらいいるでしょうか?、割と発想がトリッキーなのでは!?と、
検索しても類似ブログが見当たらないので、他者と被っていないのであれば!と思った次第です。

前提構成

下記のような構成のプロダクトがあるかもしれません(?)
SPA 用ドメイン、とは別に API 用ドメインが用意されている場合、何もしなければ CORS 制限に引っかかります。
実際には Application (Framework)等で CORS 関連の Access Control Header を 付与して Return する事でオリジン間リソース利用可能としている構成を想定してみます。
image.png

どういう時に Block しつつ 200 を返したいか?

稀に見る WAF を使った Maintenance Mode で、下記のような時

WAF で社外アクセスを Block した際に Application まで到達せず、普段 Application が付与してる Access Control header が付与されないため、 SPA が Preflight Request 送信時に CORS Error となります。
image.png

Cloudfront に Alias で複数ドメイン設定を行っている時

Cloudfront Alias に複数 Domain 付与している時、それぞれの Domain 向けに OPTIONS Request に Return する時に Access-Control-Allow-Origin を * などで一括で大きく許可したくない時です。
MDN 「オリジンを指定します。1 つのオリジンだけを指定することができます。」
image.png

設定

  • WAF rule 優先度上位で Request Origin && Method で判定し、Custom Response を行う
  • Request Origin を条件に入れ、必要ドメイン分 Rule を追加する事で Origin 事の許可ドメインを指定する事が可能です。
resource "aws_wafv2_web_acl" "example" {
  name        = "example-acl"
  description = "example-acl"
  scope       = "REGIONAL"
  default_action {
    allow {}
  }

  # Preflight を 200 return する
  rule {
    name     = "preflight-return"
    priority = "0"
    action {
      block {
        custom_response {
          response_code = 200

          response_header {
            name  = "Access-Control-Max-Age"
            value = "3600"
          }
          response_header {
            name  = "Access-Control-Allow-Credentials"
            value = "true"
          }
          response_header {
            name  = "Access-Control-Allow-Headers"
            value = "Origin,Authorization,Accept,Content-Type"
          }
          response_header {
            name  = "Access-Control-Allow-Methods"
            value = "GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD"
          }
          response_header {
            name  = "Access-Control-Allow-Origin"
            value = "https://${SUB}.example.com"
          }
        }
      }
    }
    statement {
      and_statement {
        statement {
          byte_match_statement {
            positional_constraint = "EXACTLY"
            search_string         = "OPTIONS"

            field_to_match {
              method {}
            }

            text_transformation {
              priority = 0
              type     = "NONE"
            }
          }
        }
        statement {
          byte_match_statement {
            positional_constraint = "CONTAINS"
            search_string         = "${SUB}.example.com"

            field_to_match {
              single_header {
                name = "origin"
              }
            }

            text_transformation {
              priority = 0
              type     = "NONE"
            }
          }
        }
      }
    }
  }
}

確認

違和感がすごい(ネーミングと合わせて Preflight Requset を Block するルールの様に見える)
image.png

めげずに設定したホストにブラウザアクセスを行うと OPTIONS Request を Server awselb/2.0(正確にはELB Attache WAF) が応答しているのが確認できます。
image.png

さいごに

どうにか Origin が存在しない時でも AWS Managed Service 内で OPTIONS Request を捌けないかを考えてる時に閃いた設定です。
技術的には可能です(ただし色々大変)ですとか、技術的には可能です(ただしやって良いとは言ってない)などがあるかもです。
WAF Block request / Allow request 割合監視などを導入している場合、アラート発生となる可能性があります。
ALB 固定レスポンスで同様の事が出来ると良いのですが、現時点(2023.12)では Return Header のカスタマイズが出来ませんでした。
個人的には WAF Block 200 return...! の響き、割と気に入ってます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1