【AWS】WAF のルールの構造について

WAF のルールの基本構造

AWS WAF は HTTPリクエストに対して、優先順位順に条件を評価するルールエンジン です。

JSON を利用して条件分岐を書きますが、そのものというより、ルールの構造をAWSへ渡すための表現形式です。TerraformならHCL、CloudFormationならYAMLでも同じロジックを定義できます。

ちなみに GUI でもある程度は条件分岐ができますが、階層が浅いです。

WAFの基本構造

WAF のルールは、プログラムに置き換えると、おおよそ次のように考えられます。

if 条件A:
    ラベルを付ける
    Countする

if ラベルAが付いている and 除外条件に該当しない:
    Blockする

どのルールでも処理が確定しなければ:
    Web ACLのDefaultActionを適用する

実際のWAFは、次の順番で動きます。

HTTPリクエスト
      ↓
Priorityの小さいルールから評価
      ↓
Statementで条件判定
      ↓
一致したらラベル追加やAction実行
      ↓
終了アクションなら評価終了
      ↓
終了しなければ次のルールへ
      ↓
最後まで到達したらDefaultAction

WAFはPriorityの数値が小さい(0→1→2→3)ルールから評価します。BlockAllowなどの終了アクションが実行されると、その時点でWeb ACLの評価が終了します。一方、Countは基本的に評価を継続するため、後続ルールと組み合わせられます。

JSON部分は「条件式」

たとえば、次のようなWAFのJSONは、

{
  "AndStatement": {
    "Statements": [
      {
        "LabelMatchStatement": {
          "Scope": "LABEL",
          "Key": "awswaf:managed:aws:sql-database:SQLi_URIPath"
        }
      },
      {
        "NotStatement": {
          "Statement": {
            "ByteMatchStatement": {
              "SearchString": "/health",
              "FieldToMatch": {
                "UriPath": {}
              },
              "PositionalConstraint": "EXACTLY",
              "TextTransformations": [
                {
                  "Priority": 0,
                  "Type": "NONE"
                }
              ]
            }
          }
        }
      }
    ]
  }
}

プログラム風に表すと、

if SQLi_URIPathラベルが付いている
   and URIが「/health」ではない:
       条件一致

というロジックです。

主に次の論理条件を組み合わせます。

AndStatement    → A かつ B
OrStatement     → A または B
NotStatement    → A ではない

その内側に具体的な検査条件を入れます。

ByteMatchStatement          文字列一致
RegexMatchStatement         正規表現一致
IPSetReferenceStatement     IPアドレス一致
GeoMatchStatement           国・地域一致
SqliMatchStatement          SQLi検知
XssMatchStatement           XSS検知
LabelMatchStatement         ラベル一致
RateBasedStatement          リクエスト数超過

つまり、WAFを理解する中心は確かに、Statementを使った条件式の組み立てです。