概要
やりたいこと
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);
コメント