Skip to content

JULIO-12: prototype for the datadog-lambda-extension LLD (do not merge) - #1512

Draft
Julio-Guerra wants to merge 6 commits into
mainfrom
agent/software-engineer/45724177d887
Draft

Julio-Guerra wants to merge 6 commits into
mainfrom
agent/software-engineer/45724177d887

Conversation

@Julio-Guerra

@Julio-Guerra Julio-Guerra commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Warning

Throwaway prototype for the datadog-lambda-extension LLD of the RFC "CADR for AWS Lambda" (Jira APPSEC-71674, Multica JULIO-12). Do not merge. It backs the LLD tab of the RFC and will be closed. The real change follows at build time, after design_gate.

Problem

CADR links an attack across AAP, Workload Protection and Cloud SIEM. Every correlation starts from a Workload Protection signal, and Workload Protection does not run on AWS Lambda. The execution environment's AWS access key ID can join an AAP signal to the CloudTrail userIdentity.accessKeyId of the calls made with those credentials. That works only if the invocation span carries the key ID. Today, on the extension AppSec path (Go, .NET, Node.js), it does not.

This PR

When DD_SERVERLESS_APPSEC_ENABLED=true and the new DD_APPSEC_AWS_ACCESS_KEY_ID_TAG_ENABLED=true (default false), the extension adds aws.lambda.access_key_id to every aws.lambda span it has an AppSec context for, whether or not AppSec raised an event, unless the span already carries a tracer's value.

  • config/aws.rs: aws_access_key_id_from_env() reads only AWS_ACCESS_KEY_ID, never the secret or the session token, and accepts only ^(ASIA|AKIA)[A-Z0-9]{16}$.
  • config/mod.rs: new key appsec_aws_access_key_id_tag_enabled.
  • appsec/processor/aws_access_key.rs (new): reads the value once, at the first monitored invocation, and caches it, or caches its absence, for the life of the process. On SnapStart that read happens after restore.
  • appsec/processor/{mod,context}.rs: the cached value goes into the context's tags as a new TagValue::IfAbsent. The extension writes the tag only when the final aws.lambda span does not carry it yet, counting the meta merged from a tracer placeholder (add_tracer_span), and never overwrites a tracer's value (RFC revision 2, D5).
  • On a SnapStart restore (AWS_LAMBDA_INITIALIZATION_TYPE=snap-start) the processor holds no reader, so the value is never read and no tag is set (RFC revision 2, D2).
  • benches/appsec_access_key_id.rs (new, criterion dev-dependency): T14, one monitored invocation with the key on against off.

Known limit, accepted in RFC revision 2 (D2): .NET SnapStart functions get no tag.

The activation key was renamed from DD_APPSEC_AWS_ACCESS_KEY_ID_ENABLED to DD_APPSEC_AWS_ACCESS_KEY_ID_TAG_ENABLED (design change on JULIO-10, 2026-11-12). The first commit's title still has the old name.

Testing

Test 1: unit and processor tests

Steps

  1. cargo nextest run --workspace (in a rust:1.93.1 container)

Result

797 passed, 1 skipped. The new tests cover the tag on a normal invocation and next to a crs-930-120 event, no tag when the key is off, missing, malformed, or the trigger is not monitored, and a single read across invocations.

Test 2: RFC revision 2 D5, the tracer's value is kept

Steps

  1. cargo nextest run --workspace -E 'test(/access_key_id_keeps|access_key_id_set_when/)'

Result

4 passed: a tracer-built span (Python, Node.js); a placeholder merge (Java, Ruby) before and after the extension's write; a placeholder with no tag (Go, .NET), where the extension adds its own value. With overwrite semantics put back, the tracer-built and merge-before-write tests fail, as they should.

Test 3: T14 micro benchmark

Steps

  1. cargo bench --bench appsec_access_key_id (criterion, 200 samples, 20 s per variant, aarch64 Linux container on a laptop)
  2. Each variant again on its own, alternating order: on, off, off, on

Result

Mean per monitored invocation: key off 81.5, 78.6, 79.8 µs; key on 83.5, 79.5, 79.4 µs. The difference stays under the ±1 µs run-to-run noise. The 2 µs gap in the first run came from run order. The RFC budget is +100 µs at p99.

Test 4: lint and format

Steps

  1. cargo fmt --all -- --check
  2. cargo clippy --workspace --all-targets --features default
  3. cargo clippy --workspace --all-targets --features default,test-mode

Result

Clean. The --no-default-features --features fips variant did not build locally (aws-lc-fips-sys needs Go in the container); CI runs it.

🤖 Generated with Claude Code

Julio-Guerra and others added 2 commits November 12, 2026 13:07
… AWS_ACCESS_KEY_ID read

Prototype for the JULIO-12 LLD (CADR for AWS Lambda, APPSEC-71674). Do not merge.

The new read touches only AWS_ACCESS_KEY_ID, never the secret or the
session token, and accepts only ^(ASIA|AKIA)[A-Z0-9]{16}$.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
…ey_id

Prototype for the JULIO-12 LLD (CADR for AWS Lambda, APPSEC-71674). Do not merge.

When DD_APPSEC_AWS_ACCESS_KEY_ID_ENABLED is on, the AppSec processor reads
the execution environment's access key ID once, at the first monitored
invocation (so after restore on SnapStart), and adds it to every span it
has an AppSec context for, with or without an AppSec event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Pipelines

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 17f5fc8 | Docs | View more details | Give us feedback!

Julio-Guerra and others added 4 commits November 12, 2026 21:26
…NABLED

Prototype for the JULIO-12 LLD (CADR for AWS Lambda, APPSEC-71674). Do not merge.

Design change on JULIO-10 (2026-11-12). The old name has no effect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
…RFC rev 2 D5)

Prototype for the JULIO-12 LLD (CADR for AWS Lambda, APPSEC-71674). Do not merge.

The extension now writes the tag only when the final invocation span does
not carry it yet, counting the meta merged from a tracer placeholder span.
Tests cover a tracer-built span (Python, Node.js) and the placeholder merge
(Java, Ruby) before and after the extension's write. Also drops the config
test that still set the pre-rename key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Prototype for the JULIO-12 LLD (CADR for AWS Lambda, APPSEC-71674). Do not merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
…ev 2 D2)

Prototype for the JULIO-12 LLD (CADR for AWS Lambda, APPSEC-71674). Do not merge.

On snap-start the variable is absent or belongs to the snapshotted
environment, so the processor holds no reader and sets no tag. Also adds
the trailing-newline cases of RFC rev 2 D3 to the validation test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
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