AWS WAFでカウントされたログ取りこぼしてませんか?

「COUNTログが出力されない」とお悩みの方、私もCOUNTログを拾ったつもりになっていました。
2022.01.21

AWS WAFのログでCOUNTされたリクエストのみを保存しようとしたときに、実はCOUNTだけではフィルタ条件として不十分だったという経験を共有しておこうと思います。

最初に三行まとめ

  • AWSマネージドルールのカウントはCOUNTではなくEXCLUDED_AS_COUNTで記録されるものもある
  • AWSコンソールからログフィルターの条件としてEXCLUDED_AS_COUNTを選択できない
  • 条件マッチのログのみ保存している場合BLOCKCOUNTだけをフィルタ条件にしてるとログを取りこぼしてる可能性ある

あくまでログフィルタを使用して条件マッチしたログのみを取得している場合です。全リクエスト分のログを取得している環境は安心して読み飛ばしてください!

COUNTログ少なくない?

AWS WAFでブロックルールを検討するために、COUNTされたリクエストのみをCloudWatch Logsに出力するつもりで以下のように設定していました。

(補足) ちなみに今回はルールグループ毎にSet all rule actions to countを設定してカウントを取得している環境になります。Override rule group actionでカウント設定している場合はCOUNTで出力されます。

とりあえずログが出力されることを確認するために自分のIPアドレスをカウントするカスタムルールを設定し、以下のようなログが出力されることを確認していました。

nonTerminatingMatchingRules.0.action	COUNT
nonTerminatingMatchingRules.0.ruleId	cm_restrict_ipset

しばらくの間、CloudWatchのメトリクスを眺めながら「ふむふむ、結構、Countedのリクエストも増えてきたな」と、この状態でログを溜めているつもりでした。

「そろそろ収穫時だな」と言わんばかりに、溜まったであろうログに対して分析をかけたところCloudWatchメトリクスで見てたようなCoutedリクエスト数ほどのログ件数がありません。。

何が起きたんでしょう??

EXCLUDED_AS_COUNTで記録される

ログの出力確認をカスタムルールを使って確認していたので、COUNTされたリクエストのログは全てCOUNTで出力されるものだと思い込んでました。

しかしながらマネージドルールでCOUNTと判断されたリクエストのログは以下のようにEXCLUDED_AS_COUNTとして出力されるものがあります。

ruleGroupList.0.excludedRules.0.exclusionType	EXCLUDED_AS_COUNT
ruleGroupList.0.excludedRules.0.ruleId	SignalKnownBotDataCenter
ruleGroupList.0.ruleGroupId	AWS#AWSManagedRulesBotControlRuleSet

マネージドルール内でも以下のようにCOUNTとして記録されるものもあるので、ある程度ログが取得できてるようにも見えてしまうのも気をつけたいポイントです。ちなみに細かい仕様は解ってないませんので、ここではCOUNTEXCLUDED_AS_COUNTの両方必要、くらいに認識していただければ良いかと思います。(細かな出力条件の違いについて知ってる方がいたら教えてください!)

ruleGroupList.4.excludedRules.0.exclusionType	EXCLUDED_AS_COUNT
ruleGroupList.4.excludedRules.0.ruleId	SignalKnownBotDataCenter
ruleGroupList.4.ruleGroupId	AWS#AWSManagedRulesBotControlRuleSet
ruleGroupList.5.nonTerminatingMatchingRules.0.action	COUNT
ruleGroupList.5.nonTerminatingMatchingRules.0.ruleId	AWSManagedReconnaissanceList
ruleGroupList.5.ruleGroupId	AWS#AWSManagedRulesAmazonIpReputationList

また、なぜEXCLUDED_AS_COUNTの存在に気づかなかったというと確認方法を横着したというのもありますが、一番の理由はログフィルターの条件としてEXCLUDED_AS_COUNTWebコンソールからは選択できない(見えない)ことだと思います。。

この選択肢を見てしまうとCOUNTでOKなんだ、と思いますよね。。なので、「これは同じように事故ってる人いるかもな、、」と思い今回記事にしました。

AWS CLIを使ってログフィルターを設定する

EXCLUDED_AS_COUNTをフィルタ条件に追加するにはAWS CLIなどから設定が必要です。

まず既存のログフィルターを確認しましょう。今回はCloudFront向けのWebACLだったので--scope=CLOUDFRONT--region=us-east-1を指定していますが、CloudFront以外の場合は--scope=REGIONALを指定します。

$ aws wafv2 list-logging-configurations --scope=CLOUDFRONT --region=us-east-1
LoggingConfigurations:
- LogDestinationConfigs:
  - arn:aws:logs:us-east-1:XXXXXXXXXXXX:log-group:aws-waf-logs-test-webacl
  LoggingFilter:
    DefaultBehavior: DROP
    Filters:
    - Behavior: KEEP
      Conditions:
      - ActionCondition:
          Action: BLOCK
      - ActionCondition:
          Action: COUNT
      Requirement: MEETS_ANY
  ManagedByFirewallManager: false
  ResourceArn: arn:aws:wafv2:us-east-1:XXXXXXXXXXXX:global/webacl/test_webacl/701xxxxx-xxxx-xxxx-xxxx-d60exxxxxxxx

$ aws wafv2 get-logging-configuration --resource-arn arn:aws:wafv2:us-east-1:XXXXXXXXXXXX:global/webacl/test_webacl/701xxxxx-xxxx-xxxx-xxxx-d60exxxxxxxx --region=us-east-1
LoggingConfiguration:
  LogDestinationConfigs:
  - arn:aws:logs:us-east-1:XXXXXXXXXXXX:log-group:aws-waf-logs-test-webacl
  LoggingFilter:
    DefaultBehavior: DROP
    Filters:
    - Behavior: KEEP
      Conditions:
      - ActionCondition:
          Action: BLOCK
      - ActionCondition:
          Action: COUNT
      Requirement: MEETS_ANY
  ManagedByFirewallManager: false
  ResourceArn: arn:aws:wafv2:us-east-1:XXXXXXXXXXXX:global/webacl/test_webacl/701xxxxx-xxxx-xxxx-xxxx-d60exxxxxxxx

get-logging-configurationの出力をベースに以下のようにEXCLUDED_AS_COUNT条件を加えて設定ファイルを作成します。

logging.yaml

$ vi logging.yaml

LoggingConfiguration:
  LogDestinationConfigs:
  - arn:aws:logs:us-east-1:XXXXXXXXXXXX:log-group:aws-waf-logs-test-webacl
  LoggingFilter:
    DefaultBehavior: DROP
    Filters:
    - Behavior: KEEP
      Conditions:
      - ActionCondition:
          Action: BLOCK
      - ActionCondition:
          Action: COUNT
      - ActionCondition:
          Action: EXCLUDED_AS_COUNT
      Requirement: MEETS_ANY
  ManagedByFirewallManager: false
  ResourceArn: arn:aws:wafv2:us-east-1:XXXXXXXXXXXX:global/webacl/test_webacl/701xxxxx-xxxx-xxxx-xxxx-d60exxxxxxxx

設定ファイルが準備できましたら、put-logging-configurationで設定ファイルを渡してログフィルターの設定が完了します。

$ aws wafv2 put-logging-configuration --cli-input-yaml file://logging.yaml --region=us-east-1
LoggingConfiguration:
  LogDestinationConfigs:
  - arn:aws:logs:us-east-1:XXXXXXXXXXXX:log-group:aws-waf-logs-test-webacl
  LoggingFilter:
    DefaultBehavior: DROP
    Filters:
    - Behavior: KEEP
      Conditions:
      - ActionCondition:
          Action: BLOCK
      - ActionCondition:
          Action: COUNT
      - ActionCondition:
          Action: EXCLUDED_AS_COUNT
      Requirement: MEETS_ANY
  ManagedByFirewallManager: false
  ResourceArn: arn:aws:wafv2:us-east-1:XXXXXXXXXXXX:global/webacl/test_webacl/701xxxxx-xxxx-xxxx-xxxx-d60exxxxxxxx

これでマネージドルールによってCOUNTされたすべてのログ出力が拾えるようになります!

まとめ

  • AWS WAFのマネージドルールでカウントされたログはEXCLUDED_AS_COUNTとして記録されるものもあります
  • そのため、ログフィルターの条件をBLOCKCOUNTのみ設定しているとカウントされたリクエストログを取りこぼしている可能性があります
  • AWS管理コンソールからはログフィルターの条件にEXCLUDED_AS_COUNTを選択できません
  • EXCLUDED_AS_COUNTをフィルタ条件に設定する場合はAWS CLIなどを使用します
  • そもそもコスト的な懸念がなければフィルタリングすることなく全量ログを保存しておけば安心