[akamai] Fix ingest pipeline failures and malformed geo codes in siem - #20969
Open
smnschndr wants to merge 2 commits into
Open
[akamai] Fix ingest pipeline failures and malformed geo codes in siem#20969smnschndr wants to merge 2 commits into
smnschndr wants to merge 2 commits into
Conversation
Three defects in the `siem` ingest pipeline caused Akamai security events
to be indexed as `event.kind: pipeline_error` with all parsed fields lost,
or to carry malformed values. All three are reproducible with
`POST _ingest/pipeline/_simulate`.
1. `script_base64_decode_attackData_rule_573db939` threw a NullPointerException
in two cases:
- `ctx.akamai.siem.rules = rules_array` assumed `akamai.siem` existed, but
that object is only created by the KV processors for `requestHeaders` /
`responseHeaders`. Events with attack rules but no HTTP headers (header
logging is optional in the Akamai security configuration, and an empty
string is stripped earlier by `remove_http_message_request_headers_non_kv`)
failed with "cannot access method/field [siem] from a null def reference".
- `ctx.json.attackData[key].length` assumed all seven `rule*` fields were
present. Akamai only sends the ones that apply, so a missing key failed
with "cannot access method/field [length] from a null def reference".
Because the script runs before every `attackData`, `botData`, `clientData`
and `userRiskData` rename and before `event.category` / `event.kind`, the
whole tail of the pipeline was skipped for these events.
2. `set_source_geo_region_iso_code_3a81fa3d` ran after the rename that removes
`json.geo.country`, so whenever GeoIP could not resolve the client address
the field rendered as `-NY` instead of `US-NY`. With no geo data at all the
value rendered as `-`, which is not empty and therefore not caught by
`ignore_empty_value` — every such event gained a synthetic `source.geo`
object holding only `region_iso_code: "-"`. The processor now runs before
the rename and requires both parts.
3. `set_client_10dffeb7` copied `client` from `source` without a guard.
Events without `attackData.clientIP` have no `source` object, and
`copy_from` fails on a missing path. This was masked by defect 2, which
incidentally created a `source` object; fixing 2 alone would have turned it
into a live failure.
Adds four pipeline test documents covering each path: attack rules without
headers, a missing `rule*` key, an unresolvable client address with an Akamai
geo block, and an event with no client IP. The two pre-existing expected
documents are unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014AUSnTxmZK2NCk1JuyyoiH
Contributor
ReviewersBuildkite won't run for external contributors automatically; you need to add a comment:
NOTE: https://github.com/elastic/integrations/blob/main/.buildkite/pull-requests.json contains all those details. |
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014AUSnTxmZK2NCk1JuyyoiH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed commit message
Three defects in the
siemingest pipeline caused Akamai security events to be indexed asevent.kind: pipeline_errorwith all parsed fields lost, or to carry malformed values. All three are reproducible withPOST _ingest/pipeline/_simulate, and all three are invisible to the current test fixture, whose two documents happen to avoid every affected path.1. Painless NullPointerException in
script_base64_decode_attackData_rule_573db939— two triggers:ctx.akamai.siem.rules = rules_arrayassumedakamai.siemalready existed. That object is created only by the KV processors forhttpMessage.requestHeaders/responseHeaders. Header logging is optional in the Akamai security configuration, and an empty string is stripped earlier byremove_http_message_request_headers_non_kv, so an event carrying attack rules but no headers failed withcannot access method/field [siem] from a null def reference.ctx.json.attackData[key].lengthassumed all sevenrule*fields were present. Akamai only sends the ones that apply to the event, so a missing key (e.g.ruleSelectors) failed withcannot access method/field [length] from a null def reference.The script runs before every
attackData,botData,clientDataanduserRiskDatarename and beforeevent.category/event.kind, so the entire tail of the pipeline was skipped. The document was not rejected — it was silently indexed aspipeline_errorwith an emptyakamai.siem, noconfig_id, nopolicy_id, norulesand norelated.ip, which means these attacks are invisible to detection rules and dashboards.The same defensive pattern already exists in
script_userRiskData_general_ade061bcin this file; the two scripts were simply inconsistent.2. Malformed
source.geo.region_iso_code—set_source_geo_region_iso_code_3a81fa3dbuilds its value from{{{json.geo.country}}}-{{{json.geo.regionCode}}}but ran afterrename_json_geo_country_to_source_geo_country_iso_code_66520e30, which removesjson.geo.countryprecisely when GeoIP did not resolve the address. Two wrong outcomes:geoblock →region_iso_code: "-NY"instead of"US-NY"."-", which is not empty, soignore_empty_valuedoes not skip it. Every such event gained a syntheticsource.geoobject whose only field wasregion_iso_code: "-". The trailing null-strip script removes'', not"-".The processor now runs before the rename and requires both parts to be present.
3. Unguarded
clientcopy —set_client_10dffeb7copiesclientfromsource, but events withoutattackData.clientIPhave nosourceobject andcopy_fromfails on a missing path (field [source] not present as part of path [source]). This was masked in production by defect 2, which incidentally created asourceobject; fixing 2 on its own would have converted it into a live failure. The guard is added in the same change.Testing
Added four pipeline test documents, one per affected path: attack rules without headers, a missing
rule*key, an unresolvable client address with an Akamaigeoblock, and an event with no client IP. The two pre-existing expected documents are byte-identical after regeneration, so the change is a pure addition to the expected output.Verified against a local stack:
Note: RFC 5737 documentation addresses all resolve in the Elasticsearch test GeoIP databases, so the GeoIP-miss fixture uses an RFC 1918 address — that is the only way to exercise the fallback deterministically.
The whitespace-only changes in
fields.ymland the twosiem_otelpolicy test files areelastic-package formatoutput — the package did not format cleanly before this change, andformat --fail-fastnow passes.Out of scope, found during the same review and not addressed here:
event.startis set from the collection timestamp on events withouthttpMessage.start;attackData.appliedActionis dropped and there is noevent.type/event.outcome/event.action; the CEL-eraterminateprocessor is dead code now that the CEL input is gone.Checklist
changelog.ymlfile.How to test this PR locally
To see the failures this fixes, check out the parent commit and run the same command against the new fixture documents.
🤖 Generated with Claude Code
https://claude.ai/code/session_014AUSnTxmZK2NCk1JuyyoiH