diff --git a/bottlecap/src/secrets/decrypt.rs b/bottlecap/src/secrets/decrypt.rs index 37effc65f..334f96181 100644 --- a/bottlecap/src/secrets/decrypt.rs +++ b/bottlecap/src/secrets/decrypt.rs @@ -217,16 +217,22 @@ async fn decrypt_aws_sm( extract_secret_string(&v) } -// When a Secrets Manager secret is a JSON object, this key is used to extract the API key. -// Falls back to the raw secret string if the key is absent or the value is not valid JSON. +// When a Secrets Manager secret is a JSON object, these keys are used to extract the API key, +// checked in order. `dd_api_key` is our own convention; `apiKey` matches the field name used by +// AWS's Managed Rotation for Datadog API Key secret type. Falls back to the raw secret string if +// neither key is present or the value is not valid JSON. const JSON_SECRET_DD_API_KEY: &str = "dd_api_key"; +const JSON_SECRET_API_KEY: &str = "apiKey"; fn extract_secret_string(v: &Value) -> Result> { if let Some(secret_string) = v["SecretString"].as_str() { - if let Ok(parsed) = serde_json::from_str::(secret_string) - && let Some(extracted) = parsed[JSON_SECRET_DD_API_KEY].as_str() - { - return Ok(extracted.to_string()); + if let Ok(parsed) = serde_json::from_str::(secret_string) { + if let Some(extracted) = parsed[JSON_SECRET_DD_API_KEY].as_str() { + return Ok(extracted.to_string()); + } + if let Some(extracted) = parsed[JSON_SECRET_API_KEY].as_str() { + return Ok(extracted.to_string()); + } } Ok(secret_string.to_string()) } else { @@ -454,6 +460,20 @@ mod tests { assert_eq!(result, "abc123"); } + #[test] + fn test_json_secret_extraction_api_key() { + let v = make_sm_response(r#"{"apiKey":"abc123","apiKeyId":"some-uuid"}"#); + let result = extract_secret_string(&v).expect("should extract apiKey"); + assert_eq!(result, "abc123"); + } + + #[test] + fn test_json_secret_dd_api_key_takes_precedence_over_api_key() { + let v = make_sm_response(r#"{"dd_api_key":"abc123","apiKey":"def456"}"#); + let result = extract_secret_string(&v).expect("should extract dd_api_key"); + assert_eq!(result, "abc123"); + } + #[test] fn test_json_secret_missing_key_falls_back_to_raw() { let raw = r#"{"other_key":"abc123"}"#;