name: aws-waf
tests:
  - '{"timestamp": 1715065681272, "formatVersion": 1, "webaclId": "arn:aws:wafv2:us-east-1:618318131544:regional/webacl/waf-developement/a26da0b7-9788-4670-a842-62c05e1af09b",
  "terminatingRuleId": "blocl", "terminatingRuleType": "REGULAR", "action": "CAPTCHA",
  "terminatingRuleMatchDetails": [], "httpSourceName": "APIGW", "httpSourceId": "618318131544:1234567890:waf-stage",
  "ruleGroupList": [], "rateBasedRuleList": [], "nonTerminatingMatchingRules": [],
  "requestHeadersInserted": null, "responseCodeSent": 405, "httpRequest": {"clientIp":
  "192.168.10.1", "country": "IN", "headers": [{"name": "X-Forwarded-For", "value":
  "192.168.10.1"}, {"name": "X-Forwarded-Proto", "value": "https"}, {"name": "X-Forwarded-Port",
  "value": "443"}, {"name": "Host", "value": "1234567890.execute-api.example.com"},
  {"name": "X-Amzn-Trace-Id", "value": "Root=1-6639d351-2d4fd14a63dec6003ca523d7"},
  {"name": "sec-ch-ua", "value": "\"Chromium\";v=\"124\", \"Google Chrome\";v=\"124\",
  \"Not-A.Brand\";v=\"99\""}, {"name": "sec-ch-ua-mobile", "value": "?0"}, {"name":
  "sec-ch-ua-platform", "value": "\"macOS\""}, {"name": "upgrade-insecure-requests",
  "value": "1"}, {"name": "user-agent", "value": "Mozilla/5.0 (Macintosh; Intel Mac
  OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"},
  {"name": "accept", "value": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"},
  {"name": "sec-fetch-site", "value": "same-origin"}, {"name": "sec-fetch-mode", "value":
  "navigate"}, {"name": "sec-fetch-user", "value": "?1"}, {"name": "sec-fetch-dest",
  "value": "document"}, {"name": "referer", "value": "https://1234567890.execute-api.example.com/waf-stage"},
  {"name": "accept-encoding", "value": "gzip, deflate, br, zstd"}, {"name": "accept-language",
  "value": "en-GB,en-US;q=0.9,en;q=0.8"}, {"name": "priority", "value": "u=0, i"},
  {"name": "cookie", "value": "aws-waf-token=2e856be1-efef-4f93-a04b-a08ad8f96210:EQoAjoEwbRIDAAAA:m7gziO9zf7bQNcLt2YA++xN6pCS0F79RUU6ooc2VCZwZDtBdMIJ3fTU6qahEuhbCWQvljttnC0MZtmiqTcg25Q4Ep/tP6gNl6qIIjY6wcEf9UYRhf2sOQiZ94iIU7A4YR9adS4RU4Bjp2U4fZxUF9xV2MqiPqdADnCfReWnXi6UINK93rqa/KaX/l1XO6VmX6QqwYUnwvlbJ8rFot2no2U7885w80HlkkQl/vHNxA23lan3Gt3yJqWYFliIAiIhhyjL0yt7NPeI7PJqME2mknGkG8wOuKlWMkwlfK4IYcHo="}],
  "uri": "REDACTED", "args": "REDACTED", "httpVersion": "HTTP/1.1", "httpMethod":
  "REDACTED", "requestId": "XY30vE8-oAMEPcw="}, "captchaResponse": {"responseCode":
  405, "failureReason": "TOKEN_EXPIRED"}}'
  - '{"timestamp":1632420429309,"formatVersion":1,"webaclId":"arn:aws:wafv2:us-east-1:123456789012:regional/webacl/captcha-web-acl/585e38b5-afce-4d2a-b417-14fb08b66c67","terminatingRuleId":"Default_Action","terminatingRuleType":"REGULAR","action":"ALLOW","terminatingRuleMatchDetails":[],"httpSourceName":"APIGW","httpSourceId":"123456789012:b34myvfw0b:pen-test","ruleGroupList":[],"rateBasedRuleList":[],"nonTerminatingMatchingRules":[{"ruleId":"captcha-rule","action":"CAPTCHA","ruleMatchDetails":[],"captchaResponse":{"responseCode":0,"solveTimestamp":1632420429}}],"requestHeadersInserted":[{"name":"x-amzn-waf-test-header-name","value":"test-header-value"}],"responseCodeSent":null,"httpRequest":{"clientIp":"203.0.113.156","country":"US","headers":[{"name":"X-Forwarded-For","value":"203.0.113.156"},{"name":"X-Forwarded-Proto","value":"https"},{"name":"X-Forwarded-Port","value":"443"},{"name":"Host","value":"example.com.com"},{"name":"X-Amzn-Trace-Id","value":"Root=1-614cc24d-5ad89a09181910c43917a888"},{"name":"cache-control","value":"max-age=0"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"94\",
  \"Google Chrome\";v=\"94\", \";Not A Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"Windows\""},{"name":"upgrade-insecure-requests","value":"1"},{"name":"user-agent","value":"Mozilla/5.0
  (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54
  Safari/537.36"},{"name":"accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},{"name":"sec-fetch-site","value":"same-origin"},{"name":"sec-fetch-mode","value":"navigate"},{"name":"sec-fetch-user","value":"?1"},{"name":"sec-fetch-dest","value":"document"},{"name":"referer","value":"https://example.com.com/pen-test/pets"},{"name":"accept-encoding","value":"gzip,
  deflate, br"},{"name":"accept-language","value":"en-US,en;q=0.9"},{"name":"cookie","value":"aws-waf-token=xxxxxxxx-xx-xxxZ/J+AAQAAAAA:t9wvxbw042wva7E2Y6lgud/bS6YG0CJKVAJqaRqDZ140ythKW0Zj9wKB2O8lSkYDRqf1yONcVBFo5u0eYi0tvT4rtQCXsu+KanAardW8go4QSLw4yoED59lgV7oAhGyCalAzE7ra29j+RvvZPsQyoQuDCrtoY/TvQyMTXIXzGPDC/rKBbg=="}],"uri":"/pen-test/pets","args":"","httpVersion":"HTTP/1.1","httpMethod":"GET","requestId":"GINMHHUgoAMFxug="}}'
  - '{"timestamp":1592357192516,"formatVersion":1,"webaclId":"arn:aws:wafv2:us-east-1:123456789012:global/webacl/hello-world/5933d6d9-9dde-js82-v8aw-9ck28nv9","terminatingRuleId":"Default_Action","terminatingRuleType":"REGULAR","action":"ALLOW","terminatingRuleMatchDetails":[],"httpSourceName":"-","httpSourceId":"-","ruleGroupList":[],"rateBasedRuleList":[],"nonTerminatingMatchingRules":[{"ruleId":"TestRule","action":"COUNT","ruleMatchDetails":[{"conditionType":"SQL_INJECTION","sensitivityLevel":"HIGH","location":"HEADER","matchedData":["10","and","1"]}]}],"httpRequest":{"clientIp":"203.0.113.156","country":"US","headers":[{"name":"Host","value":"localhost:1989"},{"name":"User-Agent","value":"curl/7.61.1"},{"name":"Accept","value":"*/*"},{"name":"myHeader","myValue":"10
  AND 1=1"}],"uri":"/myUri","args":"","httpVersion":"HTTP/1.1","httpMethod":"GET","requestId":"rid"},"labels":[{"name":"value"}]}'
  - '{"timestamp":1633322211194,"formatVersion":1,"webaclId":"xxxx","terminatingRuleId":"RateBasedRule","terminatingRuleType":"RATE_BASED","action":"BLOCK","terminatingRuleMatchDetails":[],"httpSourceName":"APIGW","httpSourceId":"EXAMPLE11:rjvegx5guh:CanaryTest","ruleGroupList":[],"rateBasedRuleList":[{"rateBasedRuleId":"xxxxx","rateBasedRuleName":"RateBasedRule","limitKey":"CUSTOMKEYS","maxRateAllowed":100,"customValues":[{"key":"HEADER","name":"dogname","value":"ella"},{"key":"HEADER","name":"catname","value":"goofie"}]}],"nonTerminatingMatchingRules":[],"requestHeadersInserted":null,"responseCodeSent":null,"httpRequest":{"clientIp":"203.0.113.156","country":"FR","headers":[{"name":"X-Forwarded-For","value":"203.0.113.156"},{"name":"X-Forwarded-Proto","value":"https"},{"name":"X-Forwarded-Port","value":"443"},{"name":"Host","value":"23llbyn8v3.execute-api.eu-west-3.amazonaws.com"},{"name":"X-Amzn-Trace-Id","value":"Root=1-64556629-17ac754c2ed9f0620e0f2a0c"},{"name":"catname","value":"goofie"},{"name":"dogname","value":"ella"},{"name":"User-Agent","value":"Apache-HttpClient/UNAVAILABLE
  (Java/11.0.19)"},{"name":"Accept-Encoding","value":"gzip,deflate"}],"uri":"/CanaryTest","args":"","httpVersion":"HTTP/1.1","httpMethod":"GET","requestId":"EdzmlH5OCGYF1vQ="}}'
  - '{"timestamp":1576280412771,"formatVersion":1,"webaclId":"arn:aws:wafv2:ap-southeast-2:12345:regional/webacl/test/111","terminatingRuleId":"STMTest_SQLi_XSS","terminatingRuleType":"REGULAR","action":"BLOCK","terminatingRuleMatchDetails":[{"conditionType":"SQL_INJECTION","location":"UNKNOWN","matchedData":["10","AND","1"]}],"httpSourceName":"ALB","httpSourceId":"alb","ruleGroupList":[],"rateBasedRuleList":[],"nonTerminatingMatchingRules":[],"requestHeadersInserted":null,"responseCodeSent":null,"httpRequest":{"clientIp":"203.0.113.156","country":"AU","headers":[],"uri":"","args":"","httpVersion":"HTTP/1.1","httpMethod":"POST","requestId":"null"},"labels":[{"name":"value"}]}'
  - '{"timestamp":1576280412771,"formatVersion":1,"webaclId":"arn:aws:wafv2:ap-southeast-2:EXAMPLE12345:regional/webacl/STMTest/1EXAMPLE-2ARN-3ARN-4ARN-123456EXAMPLE","terminatingRuleId":"STMTest_SQLi_XSS","terminatingRuleType":"REGULAR","action":"BLOCK","terminatingRuleMatchDetails":[{"conditionType":"SQL_INJECTION","location":"HEADER","matchedData":["10","AND","1"]}],"httpSourceName":"-","httpSourceId":"-","ruleGroupList":[],"rateBasedRuleList":[],"nonTerminatingMatchingRules":[],"httpRequest":{"clientIp":"203.0.113.156","country":"AU","headers":[{"name":"Host","value":"localhost:1989"},{"name":"User-Agent","value":"curl/7.61.1"},{"name":"Accept","value":"*/*"},{"name":"x-stm-test","value":"10
  AND 1=1"}],"uri":"/foo","args":"","httpVersion":"HTTP/1.1","httpMethod":"GET","requestId":"rid"},"labels":[{"name":"value"}]}'
  - '{"timestamp":1592357192516,"formatVersion":1,"webaclId":"arn:aws:wafv2:us-east-1:123456789012:global/webacl/hello-world/5933d6d9-9dde-js82-v8aw-9ck28nv9","terminatingRuleId":"Default_Action","terminatingRuleType":"REGULAR","action":"ALLOW","terminatingRuleMatchDetails":[],"httpSourceName":"-","httpSourceId":"-","ruleGroupList":[],"rateBasedRuleList":[],"nonTerminatingMatchingRules":[{"ruleId":"TestRule","action":"COUNT","ruleMatchDetails":[{"conditionType":"SQL_INJECTION","location":"HEADER","matchedData":["10","and","1"]}]}],"httpRequest":{"clientIp":"203.0.113.156","country":"US","headers":[{"name":"Host","value":"localhost:1989"},{"name":"User-Agent","value":"curl/7.61.1"},{"name":"Accept","value":"*/*"},{"name":"foo","value":"10
  AND 1=1"}],"uri":"/foo","args":"","httpVersion":"HTTP/1.1","httpMethod":"GET","requestId":"rid"},"labels":[{"name":"value"}]}'
  - '{"timestamp":1592361810888,"formatVersion":1,"webaclId":"arn:aws:wafv2:us-east-1:123456789012:global/webacl/hello-world/5933d6d9-9dde-js82-v8aw-9ck28nv9","terminatingRuleId":"RG-Reference","terminatingRuleType":"GROUP","action":"BLOCK","terminatingRuleMatchDetails":[{"conditionType":"XSS","location":"HEADER","matchedData":["<","frameset"]}],"httpSourceName":"-","httpSourceId":"-","ruleGroupList":[{"ruleGroupId":"arn:aws:wafv2:us-east-1:123456789012:global/rulegroup/hello-world/c05lb698-1f11-4m41-aef4-99a506d53f4b","terminatingRule":{"ruleId":"RuleA-XSS","action":"BLOCK","ruleMatchDetails":null},"nonTerminatingMatchingRules":[{"ruleId":"RuleB-SQLi","action":"COUNT","ruleMatchDetails":[{"conditionType":"SQL_INJECTION","location":"HEADER","matchedData":["10","and","1"]}]}],"excludedRules":null}],"rateBasedRuleList":[],"nonTerminatingMatchingRules":[],"httpRequest":{"clientIp":"203.0.113.156","country":"US","headers":[{"name":"Host","value":"localhost:1989"},{"name":"User-Agent","value":"curl/7.61.1"},{"name":"Accept","value":"*/*"},{"name":"xssfoo","value":"<frameset
  onload=alert(1)>"},{"name":"bar","value":"10 AND 1=1"}],"uri":"/foo","args":"","httpVersion":"HTTP/1.1","httpMethod":"GET","requestId":"rid"},"labels":[{"name":"value"}]}'
fieldsToBeRemovedBeforeParsing: []
$schema: https://schemas.humio.com/parser/v0.2.0
script: |
  /*
      Reference: https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html
  */

  // #region PREPARSE
  /************************************************************
  ****** Parse timestamp and log headers
  ****** Extract message field for parsing
  ****** Parse structured data
  ************************************************************/
  parseJson(prefix="Vendor.", excludeEmpty="true", handleNull="discard")
  | parseTimestamp(field=Vendor.timestamp, format="milliseconds")

  // #endregion

  // #region METADATA
  /************************************************************
  ****** Static Metadata Definitions
  ************************************************************/
  | Parser.version := "1.1.0"
  | Vendor := "aws"
  | event.module := "waf"
  | ecs.version := "8.11.0"
  | Cps.version := "1.0.0"

  // #endregion

  // #region NORMALIZATION
  /************************************************************
  ****** Parse unstructured data (i.e. message field)
  ****** Normalize fields to data model
  ************************************************************/
  | event.category[0] := "web"
  | event.type[0] := "access"
  | event.action := rename(Vendor.action)
  | event.kind := "event"
  | event.action match {
      "ALLOW" => event.type[1] := "allowed";
      "BLOCK" => event.type[1] := "denied";
      * => *;
  }

  // *** source fields
  | source.ip := rename(Vendor.httpRequest.clientIp)
  | source.geo.country_iso_code := rename(Vendor.httpRequest.country)

  // *** http fields
  | http.request.id := rename(Vendor.httpRequest.requestId)
  | http.request.method := rename(Vendor.httpRequest.httpMethod)
  | Vendor.httpRequest.httpVersion = /^(?<network.protocol>\S+)\/(?<http.version>\S+)$/

  // *** network fields
  | network.protocol := lower(network.protocol)
  | case { network.protocol = "http" | network.transport := "tcp"; *}

  // *** url fields
  | url.query := rename(Vendor.httpRequest.args)
  | url.path := rename(Vendor.httpRequest.uri)

  // *** rule fields
  | rule.id := rename(Vendor.terminatingRuleId)
  | rule.ruleset := rename(Vendor.terminatingRuleType)

  // #endregion
tagFields:
  - Cps.version
  - Vendor
  - ecs.version
  - event.dataset
  - event.kind
  - event.module
  - event.outcome
  - observer.type
