S3 にエクスポートされた AWS WAF v2 ログを Athena で検索する
目次
概要
やりたいこと
S3 にエクスポートした AWS WAF ログを Athena で検索する。
AWS WAF ログサンプル
S3 に保存されたログを確認すると、以下のようログがきていた。
{ "timestamp": 1589519024297, "formatVersion": 1, "webaclId": "arn:aws:wafv2:ap-northeast-1:111111111111:regional/webacl/ExampleWebACL/8f31247c-27a2-471d-8388-7fa4d7ab424f", "terminatingRuleId": "Default_Action", "terminatingRuleType": "REGULAR", "action": "ALLOW", "terminatingRuleMatchDetails": [], "httpSourceName": "ALB", "httpSourceId": "111122223333-app/webserver-alb/39ba02e250f5a76a", "ruleGroupList": [ { "ruleGroupId": "AWS#AWSManagedRulesCommonRuleSet", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": [ { "exclusionType": "EXCLUDED_AS_COUNT", "ruleId": "NoUserAgent_HEADER" } ] }, { "ruleGroupId": "AWS#AWSManagedRulesKnownBadInputsRuleSet", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": null }, { "ruleGroupId": "AWS#AWSManagedRulesAmazonIpReputationList", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": null }, { "ruleGroupId": "AWS#AWSManagedRulesAnonymousIpList", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": null }, { "ruleGroupId": "AWS#AWSManagedRulesSQLiRuleSet", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": null }, { "ruleGroupId": "AWS#AWSManagedRulesLinuxRuleSet", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": null }, { "ruleGroupId": "AWS#AWSManagedRulesUnixRuleSet", "terminatingRule": null, "nonTerminatingMatchingRules": [], "excludedRules": null } ], "rateBasedRuleList": [], "nonTerminatingMatchingRules": [], "httpRequest": { "clientIp": "184.105.247.252", "country": "US", "headers": [ { "name": "Host", "value": "54.250.130.19" } ], "uri": "REDACTED", "args": "REDACTED", "httpVersion": "HTTP/1.1", "httpMethod": "REDACTED", "requestId": null } }
AWS WAF ログのテーブル
AWS WAF ログのテーブル定義のカラムの説明。
No | 項目 | 説明 |
---|---|---|
1 | timestamp | タイムスタンプ (ミリ秒) |
2 | formatversion | ログの形式バージョン |
3 | webaclid | ウェブ ACL の GUID |
4 | terminatingruleid | リクエストを終了したルールの ID。リクエストを終了したものがない場合、この値は Default_Action となる |
5 | terminatingruletype | リクエストを終了したルールのタイプ。可能な値: RATE_BASED, REGULAR、GROUP, MANAGED_RULE_GROUP |
6 | action | アクション。可能な値 : ALLOW, BLOCK |
7 | terminatingrulematchdetails | リクエストのどの場所(ヘッダ/クエリストリング/Body等)でどの値が検知に影響したか |
8 | httpsourcename | リクエストの送信元。有効な値: CF(CloudFormation), APIGW(API Gateway), ALB (Application Load Balancer) |
9 | httpsourceid | ソース ID。 Amazon CloudFront ディストリビューションの ID、API Gateway の REST API、または Application Load Balancer の名前 |
10 | rulegrouplist | このリクエストで動作したルールグループのリスト |
11 | ratebasedrulelist | ルールグループの IDルールがリクエストをブロックした場合、ruleGroupID の ID は、terminatingRuleId の ID と同じ |
12 | nonterminatingmatchingrules | リクエストに一致するルールグループ内の終了しないルールのリスト。これは常に COUNT ルール (一致する終了しないルール) となる |
13 | httprequest | リクエストに関するメタデータ |
コンソールから設定
Athena でテーブルを作成
公式 : Querying AWS WAF Logs。
S3 バケット waf-test-cross-account に対してテーブルを作成するクエリ。結果 waf_logs というテーブルが作成される。
CREATE EXTERNAL TABLE `waf_logs`( `timestamp` bigint, `formatversion` int, `webaclid` string, `terminatingruleid` string, `terminatingruletype` string, `action` string, `terminatingrulematchdetails` array< struct< conditiontype:string, location:string, matcheddata:array<string> > >, `httpsourcename` string, `httpsourceid` string, `rulegrouplist` array<string>, `ratebasedrulelist` array< struct< ratebasedruleid:string, limitkey:string, maxrateallowed:int > >, `nonterminatingmatchingrules` array< struct< ruleid:string, action:string > >, `httprequest` struct< clientip:string, country:string, headers:array< struct< name:string, value:string > >, uri:string, args:string, httpversion:string, httpmethod:string, requestid:string > ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ( 'paths'='action,formatVersion,httpRequest,httpSourceId,httpSourceName,nonTerminatingMatchingRules,rateBasedRuleList,ruleGroupList,terminatingRuleId,terminatingRuleMatchDetails,terminatingRuleType,timestamp,webaclId') STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://waf-test-cross-account/'
Athena より検索クエリを実行し、結果が返ることを確認。

パーティションを区切ったテーブルを作成
S3 に保存されている形式。2020/05/15/12 というパーティション分割できる。
今回は日にちまでの 2020/05/15 でパーティションを区切る。

パーティションを区切ったテーブルを作成。
CREATE EXTERNAL TABLE `waf_logs`( `timestamp` bigint, `formatversion` int, `webaclid` string, `terminatingruleid` string, `terminatingruletype` string, `action` string, `terminatingrulematchdetails` array< struct< conditiontype:string, location:string, matcheddata:array<string> > >, `httpsourcename` string, `httpsourceid` string, `rulegrouplist` array<string>, `ratebasedrulelist` array< struct< ratebasedruleid:string, limitkey:string, maxrateallowed:int > >, `nonterminatingmatchingrules` array< struct< ruleid:string, action:string > >, `httprequest` struct< clientip:string, country:string, headers:array< struct< name:string, value:string > >, uri:string, args:string, httpversion:string, httpmethod:string, requestid:string > ) PARTITIONED BY (year int, month int, day int) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ( 'paths'='action,formatVersion,httpRequest,httpSourceId,httpSourceName,nonTerminatingMatchingRules,rateBasedRuleList,ruleGroupList,terminatingRuleId,terminatingRuleMatchDetails,terminatingRuleType,timestamp,webaclId') STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://waf-test-cross-account/'
パーティションで区切れるテーブルが作成されたので、実際にパーティションを区切ってみる。2020/05/15 と 2020/05/16 の2つ。
ALTER TABLE waf_logs ADD IF NOT EXISTS PARTITION (year=2020, month=5, day=15) location 's3://waf-test-cross-account/2020/05/15/'; ALTER TABLE waf_logs ADD IF NOT EXISTS PARTITION (year=2020, month=5, day=16) location 's3://waf-test-cross-account/2020/05/16/';
パーティション状況を確認。「year=2020/month=5/day=15」という結果が返ってき、パーティションが区切られたことを確認できる。
SHOW PARTITIONS waf_logs;
パーティションで絞り込んでスキャンを行う。スキャン量が違うことを確認。
SELECT * FROM waf_logs WHERE year=2020 AND month=5 AND day=15; SELECT * FROM waf_logs WHERE year=2020 AND month=5 AND day=16;
パーティションを削除する場合。
ALTER TABLE waf_logs DROP IF EXISTS PARTITION (year=2020, month=5, day=16);
ディスカッション
コメント一覧
まだ、コメントがありません