From e6c98f7b74efcd51697277eabcc5d095166c7d71 Mon Sep 17 00:00:00 2001 From: Jordan Gonzalez <30836115+duncanista@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:02:53 -0400 Subject: [PATCH 1/3] feat(agent-config): add dd_org_uuid for delegated auth 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. --- crates/datadog-agent-config/src/lib.rs | 5 +++ .../datadog-agent-config/src/sources/env.rs | 42 +++++++++++++++++++ .../datadog-agent-config/src/sources/yaml.rs | 7 ++++ 3 files changed, 54 insertions(+) diff --git a/crates/datadog-agent-config/src/lib.rs b/crates/datadog-agent-config/src/lib.rs index f671293..f79aa63 100644 --- a/crates/datadog-agent-config/src/lib.rs +++ b/crates/datadog-agent-config/src/lib.rs @@ -42,6 +42,10 @@ use crate::{ pub struct Config { pub site: String, pub api_key: String, + /// Datadog organization UUID. When set, enables delegated authentication + /// against the Datadog SaaS auth tier without requiring an api_key in some + /// flows. Sourced from `DD_ORG_UUID` / `org_uuid` in datadog.yaml. + pub dd_org_uuid: String, pub log_level: LogLevel, // Timeout for the request to flush data to Datadog endpoint @@ -160,6 +164,7 @@ impl Default for Config { Self { site: String::default(), api_key: String::default(), + dd_org_uuid: String::default(), log_level: LogLevel::default(), flush_timeout: 30, diff --git a/crates/datadog-agent-config/src/sources/env.rs b/crates/datadog-agent-config/src/sources/env.rs index 6fb96a1..baa3813 100644 --- a/crates/datadog-agent-config/src/sources/env.rs +++ b/crates/datadog-agent-config/src/sources/env.rs @@ -35,6 +35,13 @@ pub struct EnvConfig { /// The Datadog API key used to submit telemetry to Datadog #[serde(deserialize_with = "deserialize_optional_string")] pub api_key: Option, + /// @env `DD_ORG_UUID` + /// + /// The Datadog organization UUID. When set, enables delegated auth so the + /// agent can submit telemetry without a long-lived API key. Accepts a + /// string or numeric form for backwards compatibility. + #[serde(deserialize_with = "deserialize_string_or_int")] + pub org_uuid: Option, /// @env `DD_LOG_LEVEL` /// /// Minimum log level of the Datadog Agent. @@ -372,6 +379,7 @@ fn merge_config(config: &mut Config, env_config: &EnvConf // Basic fields merge_string!(config, env_config, site); merge_string!(config, env_config, api_key); + merge_string!(config, dd_org_uuid, env_config, org_uuid); merge_option_to_value!(config, env_config, log_level); merge_option_to_value!(config, env_config, flush_timeout); @@ -688,6 +696,7 @@ mod tests { let string_env_vars: &[(&str, &str)] = &[ ("DD_SITE", "custom-site.example.com"), ("DD_API_KEY", "test-api-key-12345"), + ("DD_ORG_UUID", "00000000-0000-0000-0000-000000000001"), ("DD_PROXY_HTTPS", "https://proxy.example.com"), ("DD_HTTP_PROTOCOL", "http1"), ("DD_TLS_CERT_FILE", "/opt/ca-cert.pem"), @@ -770,6 +779,7 @@ mod tests { // String fields (merge_string! → Config String) expected.site = "custom-site.example.com".to_string(); expected.api_key = "test-api-key-12345".to_string(); + expected.dd_org_uuid = "00000000-0000-0000-0000-000000000001".to_string(); expected.dd_url = "https://custom-metrics.example.com".to_string(); expected.url = "https://custom-app.example.com".to_string(); expected.logs_config_logs_dd_url = "https://custom-logs.example.com".to_string(); @@ -954,6 +964,7 @@ mod tests { let expected_config = Config { site: "test-site".to_string(), api_key: "test-api-key".to_string(), + dd_org_uuid: String::default(), log_level: LogLevel::Debug, compression_level: 4, flush_timeout: 42, @@ -1112,6 +1123,37 @@ mod tests { }); } + #[test] + fn test_dd_org_uuid_from_env() { + figment::Jail::expect_with(|jail| { + jail.clear_env(); + jail.set_env("DD_ORG_UUID", "11111111-2222-3333-4444-555555555555"); + + let mut config: Config = Config::default(); + EnvConfigSource + .load(&mut config) + .expect("Failed to load config"); + + assert_eq!(config.dd_org_uuid, "11111111-2222-3333-4444-555555555555"); + Ok(()) + }); + } + + #[test] + fn test_dd_org_uuid_default_empty_when_unset() { + figment::Jail::expect_with(|jail| { + jail.clear_env(); + + let mut config: Config = Config::default(); + EnvConfigSource + .load(&mut config) + .expect("Failed to load config"); + + assert!(config.dd_org_uuid.is_empty()); + Ok(()) + }); + } + #[test] fn test_dogstatsd_config_defaults_to_none() { figment::Jail::expect_with(|jail| { diff --git a/crates/datadog-agent-config/src/sources/yaml.rs b/crates/datadog-agent-config/src/sources/yaml.rs index 933a9fd..2c5b14d 100644 --- a/crates/datadog-agent-config/src/sources/yaml.rs +++ b/crates/datadog-agent-config/src/sources/yaml.rs @@ -29,6 +29,9 @@ pub struct YamlConfig { pub site: Option, #[serde(deserialize_with = "deserialize_optional_string")] pub api_key: Option, + /// Datadog organization UUID; see env.rs for full docs. + #[serde(deserialize_with = "deserialize_string_or_int")] + pub org_uuid: Option, #[serde(deserialize_with = "deserialize_with_default")] pub log_level: Option, @@ -410,6 +413,7 @@ fn merge_config(config: &mut Config, yaml_config: &YamlCo // Basic fields merge_string!(config, yaml_config, site); merge_string!(config, yaml_config, api_key); + merge_string!(config, dd_org_uuid, yaml_config, org_uuid); merge_option_to_value!(config, yaml_config, log_level); merge_option_to_value!(config, yaml_config, flush_timeout); @@ -747,6 +751,7 @@ mod tests { # Basic fields — string fields get valid non-default values site: "custom-site.example.com" api_key: "test-api-key-12345" +org_uuid: "00000000-0000-0000-0000-000000000001" log_level: [1, 2, 3] flush_timeout: [1, 2, 3] compression_level: [1, 2, 3] @@ -858,6 +863,7 @@ otlp_config: let mut expected: Config = Config::default(); expected.site = "custom-site.example.com".to_string(); expected.api_key = "test-api-key-12345".to_string(); + expected.dd_org_uuid = "00000000-0000-0000-0000-000000000001".to_string(); expected.dd_url = "https://custom-metrics.example.com".to_string(); expected.logs_config_logs_dd_url = "https://custom-logs.example.com".to_string(); expected.apm_dd_url = "https://custom-apm.example.com".to_string(); @@ -1024,6 +1030,7 @@ otlp_config: let expected_config = Config { site: "test-site".to_string(), api_key: "test-api-key".to_string(), + dd_org_uuid: String::default(), log_level: LogLevel::Debug, flush_timeout: 42, compression_level: 4, From 1d35f6c46e1dddacf63f2dfc3f3d0656762f9119 Mon Sep 17 00:00:00 2001 From: Jordan Gonzalez <30836115+duncanista@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:08:08 -0400 Subject: [PATCH 2/3] docs(agent-config): self-contained YAML doc for org_uuid 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. --- crates/datadog-agent-config/src/sources/yaml.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/datadog-agent-config/src/sources/yaml.rs b/crates/datadog-agent-config/src/sources/yaml.rs index 2c5b14d..86dad84 100644 --- a/crates/datadog-agent-config/src/sources/yaml.rs +++ b/crates/datadog-agent-config/src/sources/yaml.rs @@ -29,7 +29,10 @@ pub struct YamlConfig { pub site: Option, #[serde(deserialize_with = "deserialize_optional_string")] pub api_key: Option, - /// Datadog organization UUID; see env.rs for full docs. + /// YAML key: `org_uuid`. Datadog organization UUID. When set, enables + /// 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")] pub org_uuid: Option, #[serde(deserialize_with = "deserialize_with_default")] From d4d6fd8e639c1ad89aca02d4b5d483d6fafd4d4e Mon Sep 17 00:00:00 2001 From: Jordan Gonzalez <30836115+duncanista@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:09:49 -0400 Subject: [PATCH 3/3] fix(agent-config): use deserialize_optional_string for org_uuid 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. --- crates/datadog-agent-config/src/sources/env.rs | 5 ++--- crates/datadog-agent-config/src/sources/yaml.rs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/datadog-agent-config/src/sources/env.rs b/crates/datadog-agent-config/src/sources/env.rs index baa3813..9523a66 100644 --- a/crates/datadog-agent-config/src/sources/env.rs +++ b/crates/datadog-agent-config/src/sources/env.rs @@ -38,9 +38,8 @@ pub struct EnvConfig { /// @env `DD_ORG_UUID` /// /// The Datadog organization UUID. When set, enables delegated auth so the - /// agent can submit telemetry without a long-lived API key. Accepts a - /// string or numeric form for backwards compatibility. - #[serde(deserialize_with = "deserialize_string_or_int")] + /// agent can submit telemetry without a long-lived API key. + #[serde(deserialize_with = "deserialize_optional_string")] pub org_uuid: Option, /// @env `DD_LOG_LEVEL` /// diff --git a/crates/datadog-agent-config/src/sources/yaml.rs b/crates/datadog-agent-config/src/sources/yaml.rs index 86dad84..75c1a08 100644 --- a/crates/datadog-agent-config/src/sources/yaml.rs +++ b/crates/datadog-agent-config/src/sources/yaml.rs @@ -31,9 +31,8 @@ pub struct YamlConfig { pub api_key: Option, /// YAML key: `org_uuid`. Datadog organization UUID. When set, enables /// 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")] + /// API key. Merges into the resolved config field `dd_org_uuid`. + #[serde(deserialize_with = "deserialize_optional_string")] pub org_uuid: Option, #[serde(deserialize_with = "deserialize_with_default")] pub log_level: Option,