2

我按照这些说明将我的 AWS WAF 数据放入 Athena 表中。

我想查询数据以查找具有 BLOCK 操作的最新请求。此查询有效:

SELECT
  from_unixtime(timestamp / 1000e0) AS date,
  action,
  httprequest.clientip AS ip,
  httprequest.uri AS request,
  httprequest.country as country,
  terminatingruleid,
  rulegrouplist
FROM waf_logs
WHERE action='BLOCK'
ORDER BY date DESC
LIMIT 100;

我的问题是清楚地识别“终止规则”——请求被阻止的原因。例如,一个结果有

terminatingrule = AWS-AWSManagedRulesCommonRuleSet

rulegrouplist = [
  {
    "nonterminatingmatchingrules": [],
    "rulegroupid": "AWS#AWSManagedRulesAmazonIpReputationList",
    "terminatingrule": "null",
    "excludedrules": "null"
  },
  {
    "nonterminatingmatchingrules": [],
    "rulegroupid": "AWS#AWSManagedRulesKnownBadInputsRuleSet",
    "terminatingrule": "null",
    "excludedrules": "null"
  },
  {
    "nonterminatingmatchingrules": [],
    "rulegroupid": "AWS#AWSManagedRulesLinuxRuleSet",
    "terminatingrule": "null",
    "excludedrules": "null"
  },
  {
    "nonterminatingmatchingrules": [],
    "rulegroupid": "AWS#AWSManagedRulesCommonRuleSet",
    "terminatingrule": {
      "rulematchdetails": "null",
      "action": "BLOCK",
      "ruleid": "NoUserAgent_HEADER"
    },
    "excludedrules":"null"
  }
]

我想分成一列的数据是rulegrouplist[terminatingrule].ruleid它的值NoUserAgent_HEADER

AWS 提供了有关查询嵌套 Athena 数组的有用信息,但我一直无法获得我想要的结果。

我已将此作为一个 AWS 问题进行框定,但由于 Athena 使用 SQL 查询,因此任何具有良好 SQL 技能的人都可以解决这个问题。

4

2 回答 2

4

我并不完全清楚你想要什么,但我会假设你在数组元素后面terminatingrule不是"null"(我也会假设如果有多个你想要第一个)。

您链接的文档说该rulegrouplist列的类型是array<string>. 它是string复杂类型而不是复杂类型的原因是因为该列似乎有多种不同的模式,一个例子是terminatingrule属性是string "null"或 struct/object - 这是无法使用 Athena 的类型描述的系统。

然而,这不是问题。在处理 JSON 时,可以使用一整套JSON 函数。这是一种json_extract结合使用filterelement_at删除terminatingrule属性为字符串“null”的数组元素的方法,然后选择剩余元素中的第一个:

SELECT
  element_at(
    filter(
      rulegrouplist,
      rulegroup -> json_extract(rulegroup, '$.terminatingrule') <> CAST('null' AS JSON)
    ),
    1
  ) AS first_non_null_terminatingrule
FROM waf_logs
WHERE action = 'BLOCK'
ORDER BY date DESC

你说你想要“最新的”,这对我来说是模棱两可的,可能意味着第一个非空元素和最后一个非空元素。上面的查询将返回第一个非空元素,如果您想要最后一个,您可以将第二个参数更改element_at为 -1(Athena 的数组索引从 1 开始,-1 从末尾开始计数)。

要返回 json 的单个 ruleid 元素:

SELECT from_unixtime(timestamp / 1000e0) AS date, action, httprequest.clientip AS ip, httprequest.uri AS request, httprequest.country as country, terminatingruleid, json_extract(element_at(filter(rulegrouplist,rulegroup -> json_extract(rulegroup, '$.terminatingrule') <> CAST('null' AS JSON)  ),1), '$.terminatingrule.ruleid') AS ruleid
FROM waf_logs
WHERE action='BLOCK'
ORDER BY date DESC
于 2020-07-23T17:53:45.867 回答
3

我遇到了同样的问题,但 Theo 发布的解决方案对我不起作用,即使该表是根据原始帖子中链接的说明创建的。

这对我有用,与 Theo 的解决方案基本相同,但没有 json 转换:

SELECT
  from_unixtime(timestamp / 1000e0) AS date,
  action,
  httprequest.clientip AS ip,
  httprequest.uri AS request,
  httprequest.country as country,
  terminatingruleid,
  rulegrouplist,
  element_at(filter(ruleGroupList, ruleGroup -> ruleGroup.terminatingRule IS NOT NULL),1).terminatingRule.ruleId AS ruleId
FROM waf_logs
WHERE action='BLOCK'
ORDER BY date DESC
LIMIT 100;
于 2021-02-22T14:34:01.023 回答