こんにちは、AWSグループの平原です。
皆様は、ダーツという室内競技をプレイしたことがあるでしょうか?
ダーツは円形のボードにアローを投げ、得点を競う室内競技です。
ゲームの種類は、シンプルに得点を競うカウントアップや特定の点数からカウントを減らしていくゼロワン、的のエリアを取り合うクリケットなどがあります。
最近では、ダーツバーやアミューズメント施設などで気軽に楽しむことができます。
私は会社のイベントなどで楽しむ程度ですが、とても面白い競技だと感じています。
皆様も機会があればぜひ挑戦してみてはいかがでしょうか。
といったところで今回は、AWS WAF Web ACL Rule の"Allow"と"Count"の違いを検証しつつ理解した時のことを記事にします。
はじめに
今回は業務で Amazon API Gateway の Rest API に Web ACL を設定した時に、Rule の "Allow"と"Count"の違いが個人的に理解できていなかったので、その際に調査し、検証した時の内容となります。
AWS WAF とは
AWS WAFは、保護されたウェブアプリケーションリソースに転送される HTTP(S) リクエストをモニタリングできるウェブアプリケーションファイアウォールです。
以下のリソースタイプを保護できます。
- Amazon CloudFront ディストリビューション
- Amazon API Gateway REST API
- Application Load Balancer
- AWS AppSync GraphQL API
- Amazon Cognito ユーザープール
- AWS App Runner サービス
- AWS Verified Access インスタンス
- AWS Amplify
Rule アクションの種類
Rule アクションの種類(設定時に選択できるオプション)は、以下です。
Allow
AWS WAF リクエストを保護された AWS リソースに転送して処理および応答できるようにします。これは終了アクションです。
定義したRuleでは、リクエストを保護されたリソースに転送する前に、カスタムヘッダーを挿入できます。Block
リクエストを AWS WAF ブロックします。これは終了アクションです。
デフォルトでは、保護された AWS リソースは HTTP 403 (Forbidden)ステータスコードで応答します。Count
リクエストを AWS WAF カウントしますが、許可するかブロックするかは決定しません。 これは非終了アクションです。
AWS WAF がウェブ ACL の残りのRuleの処理を継続します。CAPTCHA および Challenge
CAPTCHA パズルとサイレントチャレンジ AWS WAF を使用して、リクエストがボットから送信されていないことを確認し、トークン AWS WAF を使用して最近成功したクライアントレスポンスを追跡します。
実際に検証してみた
上述のように、"Allow" はその Rule で処理が終了する「終了アクション」、"Count" は処理を続けて次の Rule も評価する「非終了アクション」です。
Web ACLs を設定する
AWS API Gateway - AWS Lambda 構成の API Gateway RestAPI にWeb ACLs を設定します。
(AWS API Gateway - AWS Lambda の構築については、省略します)
- AWS マネージメントコンソールにログインし、AWS WAFのページに遷移後、左ペインの Web ACLs をクリック
Web ACLs を作成するリージョンを選択し、「Create Web ACL」をクリック
下記のように設定し、「Next」をクリック
・Resource type: Regional resources
・Region: Web ACL を設定するリソースのリージョン(今回の場合はAPI Gatewayのリージョン)
・Name: 任意の Web ACL名
・Description: 任意
・CloudWatch metric name: 自動的に"Name"と同じ値が入る(変更可能)
・「Add resources」をクリックし、Web ACL を設定するリソースを選択
「Add rule」>「Add my own rules and rule groups」をクリック
※ 検証のための Rule として、今回は Header でフィルタリングする設定を行います下記のように設定し、「Add rule」をクリック
・Rule type: Rule builder
・Name: 任意の Rule名
・Type: Regular rule
・If a request: matches the statement
・Inspect: Single header
・Header field name: 任意のカスタム Headerキー
・Match type: Exactly matches string
・String to match: 任意のカスタム Headerの値
・Text transformation: None
・Action: Count ※この設定を変更しながら検証します
4, 5の手順を再度実施し、2つ目のRuleを追加
以下3つを1つ目のRuleと異なる値で設定
・Name: 任意の Rule名
・Header field name: 任意のカスタム Headerキー
・String to match: 任意のカスタム Headerの値元ページに遷移後、下記のように設定し、「Next」をクリック
・Default action: Allow
1つ目のRule の priority が上位となるように設定し、「Next」をクリック
下記のように設定し、「Next」をクリック
・Rules: 2つの Rule にチェック
・CloudWatch metric name: 任意のメトリクス名
・Options: Enable sampled requests
設定内容を確認し、「Create Web ACL」をクリック
API を実行する
Web ACLを設定した API GatewayのURLに対して、下記のように Header をつけてリクエストを実行します。
curl -H 'x-custom-header01:hogehoge01' -H 'x-custom-header02:hogehoge02' \ https://<API Gateway ID>.execute-api.ap-northeast-1.amazonaws.com/dev/hello
初期設定の状態で実行
1つ目のRuleのアクション: Count
2つ目のRuleのアクション: Count
レスポンス
{"message": "hello world"}
この場合は、Ruleが2つとも処理され、アクションがCountの為、正常レスポンスが返されます。
CloudWatchメトリクスを確認すると、2つのRuleアクションがCountであることが確認できます。
1つ目のRuleのアクションをAllowに変更して実行
1つ目のRuleのアクション: Allow
2つ目のRuleのアクション: Count
レスポンス
{"message": "hello world"}
この場合は、1つ目のRuleのみが処理され、アクションがAllowの為、正常レスポンスが返されます。
1つ目のRuleが終了アクションのAllowなので、2つ目のRuleは処理されません。
CloudWatchメトリクスを確認すると、1つ目のRuleアクションのAllowのみであることが確認できます。
2つ目のRuleのアクションをAllowに変更して実行
1つ目のRuleのアクション: Count
2つ目のRuleのアクション: Allow
レスポンス
{"message": "hello world"}
この場合は、Ruleが2つとも処理され、2つ目のRuleのアクションがAllowの為、正常レスポンスが返されます。
2つ目のRuleが終了アクションのAllowなので、2つ目のRuleまで処理されます。
CloudWatchメトリクスを確認すると、1つ目のRuleアクションはCountで、2つ目のRuleアクションはAllowであることが確認できます。
1つ目のRuleのアクションをBlockに変更して実行(おまけ)
1つ目のRuleのアクション: Block
2つ目のRuleのアクション: Count
レスポンス
{ "message": "403 waf-filter" }
この場合は、1つ目のRuleのみが処理され、アクションがBlockの為、エラーレスポンスが返されます。
1つ目のRuleが終了アクションのBlockなので、2つ目のRuleは処理されません。
CloudWatchメトリクスを確認すると、1つ目のRuleアクションのBlockのみであることが確認できます。
補足ですが、レスポンスのメッセージは、API Gatewayの"ゲートウェイのレスポンス"で設定したものとなります。
さいごに
AWS WAF Web ACL Ruleの "Allow" と "Count" の違いについて検証を踏まえ確認できました。
調査・検証を進める中で疑問に思ったのですが、"Count"アクションは評価のみで、許可やブロックは行わないので、何のために必要なのかと感じました。
"Count"アクションは、Rule を試験的に設定する際などによく使われます。いわゆる「経過観察期間」です。
これは、商用環境などでいきなり "Allow" もしくは "Block" アクションに設定して誤検知が発生した場合に、サービスに悪い影響を与えないようにするためです。
私と同様に "Allow" と "Count" の違いがいまいち理解できていない方などの参考になると幸いです。