Skip to content

feat(aws): add CloudTrail to ECS v8.0.0 transforms (core + comprehensive) - #33

Open
behobu wants to merge 3 commits into
mainfrom
feat/cloudtrail-ecs-v8.0
Open

feat(aws): add CloudTrail to ECS v8.0.0 transforms (core + comprehensive)#33
behobu wants to merge 3 commits into
mainfrom
feat/cloudtrail-ecs-v8.0

Conversation

@behobu

@behobu behobu commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What

Adds the same two AWS CloudTrail → ECS transforms retargeted to ECS v8.0.0, for deployments still on the 8.0 line:

  • ecs/v8.0.0/aws/aws-cloudtrail-core.yaml
  • ecs/v8.0.0/aws/aws-cloudtrail-comprehensive.yaml

Relationship to the v8.11.0 PR

Same jq logic as the v8.11.0 pair (#32) — a clean version bump, no field surgery. This branch is based on main and is independent of #32, so the two can review/merge separately. The two trees are byte-identical apart from their version strings, verified by diffing with version lines filtered out.

Every ECS field used exists in 8.0.0. Verified programmatically against Elastic's generated field list for v8.0.0 — all 27 emitted ECS fields are present, and the event.category / event.type values used (authentication, iam, configuration / start, access, creation, deletion, change, info) are all in 8.0.0's allowed-value sets. No field needs version-specific treatment, which is why the logic can be identical.

Validation

37 real CloudTrail records run through both files, from two sources. No failures on either file. ecs.version is 8.0.0 throughout — confirmed no cross-contamination from the 8.11.0 tree.

1. Live pipeline records (30)

Pulled off the input node of the live cloudtrail input in the jfrog demo orguse_synthetic_data: false, real S3 bucket, and an organization trail (4 distinct recipientAccountIds, 6 regions including us-east-1).

  • 30/30 pass on each file. 20 distinct eventName across 12 distinct eventSource.
  • Records arrive as flat single events (no Records wrapper), confirming the connector contract.
  • All 25 ECS-namespace output paths are valid ECS fields in 8.0.0. Plus 59 aws.cloudtrail.* vendor paths.

Real-world shapes verified to map correctly: userIdentity.type AssumedRole (8+) and AWSService (1 → user block pruned), tlsDetails (3 → tls.version/cipher/client.server_name), resources[] (2 → ARNarn, accountIdaccount_id), non-IP sourceIPAddress (3 → is_ip guard holds, source.ip omitted), sessionContext (8).

2. Real failure records (7)

The live pipeline sample contained no failed calls, so these were sourced separately from CloudTrail Event History (lookup-events) rather than through the connector — genuine InternalFailure records on CreateServiceLinkedChannel, all carrying an errorMessage.

  • 7/7 pass, event.outcome: "failure" on all.
  • error.code 7/7 and error.message 7/7 populated in comprehensive.
  • Also covers the creation event type.

Combined live branch coverage: outcomes success + failure; categories configuration, iam, authentication; types access, change, creation.

3. Synthetic matrix

17 cases for shapes real traffic doesn't produce: empty object, missing/null eventName, by_size envelope, IPv6 and service-name sourceIPAddress, ConsoleLogin success/failure/no-response, assumed-role name fallback, readOnly, resources, and each category/type branch. 0 failures.

Fixes found during validation

  1. eventName guard (e67123f). $category and $type piped $r.eventName straight into test(), which hard-errors when eventName is absent or null. Realistic trigger: feeding aws-sqs-s3-cloudtrail's default by_size output in without exploding .Records[] first. Now guarded with // ""; output on records carrying eventName is byte-identical before and after.

  2. userIdentity.onBehalfOf mapping (63b6d68). Live records carried this field and the comprehensive transform dropped it. AWS sets it for IAM Identity Center callers — the only attribution for SSO-initiated activity. Now mapped to aws.cloudtrail.user_identity.on_behalf_of (user_id, identity_store_arn), field names per AWS's userIdentity reference. Absent → pruned, no empty object.

  3. Header comment corrected: aws-sqs-s3-cloudtrail's Chunking Mode decides the shape — per_record needs nothing extra, only by_size (the default) needs the .Records[] explode.

Known coverage limits

  • ConsoleLogin is not testable in our AWS org. Monad authenticates via IAM Identity Center, which doesn't emit ConsoleLogin in the target account — confirmed zero such events across 4 accounts over a 7-day window. That branch is covered synthetically only; it remains correct for customers using IAM console sign-in.
  • The deletion event type is likewise synthetic-only — no delete calls appeared in the sampled window.

Note on version choice

ECS is currently at v9.4.0, and this repo otherwise only carries a v8.11.0 tree — so this PR adds an older version directory. Worth confirming there's a consumer actually pinned to the 8.0 line before merging; otherwise a v9.x variant would likely serve more users.

Refs: CS-135

Retarget the AWS CloudTrail normalization templates (core + comprehensive)
to ECS v8.0.0, for the many deployments still on the 8.0 line. Same jq
logic as the v8.11.0 pair — every fieldset used (event, cloud, user,
source, user_agent, related, error, tls, and the aws.cloudtrail.* vendor
namespace) is present in ECS 8.0.0, verified against Elastic's 8.0 field
reference — so this is a clean version bump with no field surgery.

Validated locally with jq against a 5-record matrix (S3 data event, IAM
assumed-role, console-login failure, access-denied, service event)
covering the success/failure, authentication/iam/configuration, and
access/creation/deletion/change/start/info branches.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@behobu behobu self-assigned this Jul 21, 2026
behobu added 2 commits July 30, 2026 11:04
Mirrors the same fix on the v8.11.0 pair so the two version trees stay
identical apart from their version strings.

The $category and $type branches piped $r.eventName straight into
test(), which hard-errors on a record where eventName is absent or null.
$r.eventSource two lines away was already guarded with // "".

The realistic trigger is feeding the aws-sqs-s3-cloudtrail connector's
default by_size output in without exploding .Records[] first — that
envelope has no top-level eventName, so the transform died on a cryptic
jq error instead of degrading.

Output on records that do carry eventName is byte-identical before and
after. Verified across the same 17-case matrix; ecs.version stays
8.0.0 throughout.

Also corrects the header comment about aws-sqs-s3-cloudtrail: its
Chunking Mode decides the shape. per_record already emits one bare
event; only by_size (the default) needs the .Records[] explode.
Live CloudTrail records from the jfrog demo org carried
userIdentity.onBehalfOf, which the comprehensive transform dropped
despite its description promising full CloudTrail field coverage. AWS
sets it when the caller is an IAM Identity Center user
(userIdentity.type "IdentityCenterUser"), and it is the only thing in
the record that identifies which Identity Center user the call was made
on behalf of — so losing it loses attribution for SSO-initiated
activity.

Mapped into the vendor namespace as
aws.cloudtrail.user_identity.on_behalf_of with the two documented
subfields, snake_cased to match the surrounding style:

  userId           -> user_id
  identityStoreArn -> identity_store_arn

Field names taken from the AWS userIdentity reference. Records without
onBehalfOf are unaffected: $ui.onBehalfOf is null, both subfields
resolve to null, and prune drops the empty object rather than emitting
an empty on_behalf_of. Verified against a record carrying the full
object, one carrying only userId, one with no onBehalfOf at all, and an
empty record, plus the full 17-case matrix.

Core is deliberately unchanged — it has no vendor namespace.
@behobu
behobu marked this pull request as ready for review July 30, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant