feat(agent-config): add dd_org_uuid for delegated auth#137
Conversation
Adds first-class `dd_org_uuid: String` field to the top-level `Config` struct, sourced from `DD_ORG_UUID` (env) and `org_uuid` (datadog.yaml). Belongs upstream because delegated auth is a generic Datadog SaaS auth-tier concept, not a Lambda-specific one. Currently re-implemented inside `LambdaConfig` in datadog-lambda-extension; this lets the extension drop its local definition in a follow-up. - Accepts string or numeric form via `deserialize_string_or_int` for backwards compatibility with legacy callers. - Source field name (`org_uuid`) matches the env var / yaml key; merges into the config field `dd_org_uuid` to match the existing convention the lambda extension was already using.
|
superseeds #112 tysm @jchrostek-dd |
There was a problem hiding this comment.
Pull request overview
Adds first-class support for Datadog Org UUID–based delegated authentication in datadog-agent-config by introducing a new resolved config field and wiring it up to existing env/YAML sources.
Changes:
- Introduces
Config::dd_org_uuid: String(default empty) on the top-level resolved config. - Adds
org_uuidsupport to both env (DD_ORG_UUID) and YAML (org_uuid) sources and merges intodd_org_uuid. - Updates/extends env and YAML tests to cover the new field (including default + env override cases).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| crates/datadog-agent-config/src/lib.rs | Adds dd_org_uuid to the top-level Config struct and default initialization. |
| crates/datadog-agent-config/src/sources/env.rs | Adds DD_ORG_UUID → org_uuid parsing and merges into Config::dd_org_uuid, with new tests. |
| crates/datadog-agent-config/src/sources/yaml.rs | Adds YAML org_uuid parsing and merges into Config::dd_org_uuid, updating YAML fixtures/expectations. |
Address Copilot review: replace the "see env.rs" pointer with the full explanation inline so users reading the YAML source can understand the key without cross-referencing.
| /// delegated auth so the agent can submit telemetry without a long-lived | ||
| /// API key. Accepts a string or numeric form for backwards compatibility. | ||
| /// Merges into the resolved config field `dd_org_uuid`. | ||
| #[serde(deserialize_with = "deserialize_string_or_int")] |
There was a problem hiding this comment.
Nit: could we clarify why we’re using deserialize_string_or_int instead of deserialize_optional_string here?
There was a problem hiding this comment.
good question — it is a carry-over. the field was first added in bottlecap by #1112 (john, delegated auth) with deserialize_string_or_int, and i preserved it verbatim when moving it upstream. the introducing pr does not explain the choice; it looks copy-pasted from the env/service/version pattern (those genuinely need string_or_int because users do set them to numeric values like "1.2").
for a uuid it makes no sense — uuids are hex + dashes, there is no numeric form. tightening to deserialize_optional_string also fail-fasts on misconfiguration instead of silently coercing. fixed in d4d6fd8.
A UUID is hex + dashes; there is no legitimate numeric form a user would supply. The previous deserializer (deserialize_string_or_int) was a carry-over from the bottlecap copy, where it appears to have been copy-pasted from the env/service/version pattern. Tightening to deserialize_optional_string fail-fasts on misconfiguration instead of silently coercing.
…_enabled) (#1267) ## Summary Bumps the \`datadog-agent-config\` / \`dogstatsd\` / \`datadog-fips\` pin to \`8ce37eb\`, which contains two recently-merged upstream features: - [serverless-components#137](DataDog/serverless-components#137) — adds \`Config::dd_org_uuid: String\` (\`DD_ORG_UUID\` / yaml \`org_uuid\`) - [serverless-components#138](DataDog/serverless-components#138) — adds \`Config::logs_enabled: bool\` (\`DD_LOGS_ENABLED\` / yaml \`logs_enabled\`) ## What changes in bottlecap ### dd_org_uuid Drops the now-redundant local copy from \`LambdaConfig\`: - \`LambdaConfig\`: removed \`dd_org_uuid: String\`. - \`LambdaConfigSource\`: removed \`org_uuid: Option<String>\` and the \`merge_string!(self, dd_org_uuid, source, org_uuid)\` source-to-config renaming call in \`merge_from\`. - Consumers (\`secrets/decrypt.rs\`, \`secrets/delegated_auth/client.rs\`) switch from \`config.ext.dd_org_uuid\` → \`config.dd_org_uuid\`. - Tests assert on the upstream field. ### logs_enabled The lambda extension's existing OR-merge contract for log shipping is preserved **exactly**. The legacy semantics are: | \`DD_SERVERLESS_LOGS_ENABLED\` | \`DD_LOGS_ENABLED\` | resolved \`serverless_logs_enabled\` | |---|---|---| | unset | unset | **true** (default kept) | | any | true | true | | true | any | true | | false | false | false | | **unset** | **false** | **false** (alias alone can override default) | | false | unset | false | To preserve "was \`DD_LOGS_ENABLED\` explicitly set?" the alias source field is **retained** on \`LambdaConfigSource\` and the OR-merge in \`merge_from\` is kept. The upstream parsing of the same env var into \`config.logs_enabled\` runs in parallel — that field exists for any non-lambda consumer of the crate, but the lambda extension continues to gate log shipping on \`config.ext.serverless_logs_enabled\`. A regression test was added for the alias-only-false case (the trickiest invariant), so a future refactor that breaks it fails loudly. ## Why two PRs in one Both upstream PRs are merged and \`8ce37eb\` contains them as a single SHA. Bundling lets us bump once and avoid a transitional state where main is pinned to a SHA that has \`logs_enabled\` upstream but the lambda extension's source field still aliases it. ## Test plan - [x] \`cargo test --workspace --features default\` — all pass (lambda_config_tests now at 40, +2 for the new logs_enabled coverage) - [x] \`cargo clippy --workspace --all-targets --features default\` — clean - [x] \`cargo fmt -- --check\` — clean - [x] Regression test \`logs_enabled_alias_only_false_overrides_default\` exercises the invariant that \`DD_LOGS_ENABLED=false\` alone disables logs (overriding the default-true) - [x] No behavior change for customers — same env vars, same resolved field at lambda call sites
Summary
Adds a first-class `dd_org_uuid: String` field to the top-level `Config` struct in `datadog-agent-config`, sourced from the `DD_ORG_UUID` env var and the `org_uuid` key in `datadog.yaml`.
Why
Delegated auth via Datadog Org UUID is a generic Datadog SaaS auth-tier concept — it lets a component submit telemetry without a long-lived API key, by binding to an org rather than authenticating per call. It is not Lambda-specific.
Today `datadog-lambda-extension` carries this field inside its `LambdaConfig` extension. As more agents/embedders adopt this crate, every one of them would need to redefine the same field. Putting it upstream lets the lambda extension (and any future consumer) drop the local copy.
Behavior
Test plan
Follow-up
Once this lands and is pinned in `datadog-lambda-extension`, the extension can drop `dd_org_uuid` and `org_uuid` from its `LambdaConfig` / `LambdaConfigSource` and the local `merge_string!(self, dd_org_uuid, source, org_uuid)` call.