feat(secrets): auto-extract API key from JSON-structured Secrets Manager secrets - #1146
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds support for JSON-structured Secrets Manager secrets by introducing a new DD_API_KEY_SECRET_JSON_KEY environment variable. When set alongside DD_API_KEY_SECRET_ARN, the extension parses the secret value as JSON and extracts the named field as the API key, addressing the need for teams that store secrets in key/value format (e.g., {"apiKey": "<key>"}).
Changes:
- Added JSON extraction logic to
decrypt_aws_sm()function that parses secrets as JSON whenjson_keyis provided - Added
api_key_secret_json_keyfield to all three config layers (Config,EnvConfig,YamlConfig) with proper merge logic - Added three unit tests covering successful extraction, missing key error handling, and backward compatibility with plain secrets
- Updated configuration examples in YAML and environment config tests
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| bottlecap/src/secrets/decrypt.rs | Added JSON extraction logic with new json_key parameter; includes three new unit tests |
| bottlecap/src/config/mod.rs | Added api_key_secret_json_key field to Config struct and its Default impl |
| bottlecap/src/config/env.rs | Added api_key_secret_json_key field to EnvConfig with documentation; updated merge logic and test fixtures |
| bottlecap/src/config/yaml.rs | Added api_key_secret_json_key field to YamlConfig; updated merge logic, example YAML config, and test fixtures |
duncanista
left a comment
There was a problem hiding this comment.
Honestly, not super happy about having a new env var just for this, we should talk as a team if this is something we want to actually support
I think the user makes a valid point for below reasons:
Without introducing a new key, I do not think there is a better candidate for this. |
055a5f2 to
d5c7644
Compare
72de1a9 to
1a00156
Compare
…ger secrets When DD_API_KEY_SECRET_ARN is set and the fetched secret is a JSON object, automatically extract the value of the hardcoded "dd_api_key" field as the API key. Falls back to using the raw secret string if the value is not valid JSON or the "dd_api_key" field is absent, preserving existing behavior for plain-string secrets. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1a00156 to
fb78f3b
Compare
…ger secrets (#1305) https://datadoghq.atlassian.net/browse/SVLS-9488 ## Overview AWS's [Managed Rotation for Datadog API Key](https://docs.aws.amazon.com/secretsmanager/latest/userguide/mes-partner-DatadogApiKey.html) Secrets Manager secret type stores the API key under the field `apiKey` (alongside `apiKeyId`), not our own `dd_api_key` convention added in #1146. As a result, `DD_API_KEY_SECRET_ARN` couldn't consume that AWS-managed secret type. `extract_secret_string` now checks `dd_api_key` first (unchanged), then falls back to `apiKey`, before falling back to treating the secret as a raw string. Fixes #1304 ## Testing - Added `test_json_secret_dd_api_key_takes_precedence_over_api_key` — when both fields are present, `dd_api_key` wins. - Existing tests (`test_json_secret_extraction`, `test_json_secret_missing_key_falls_back_to_raw`, `test_plain_secret_unaffected`, `test_malformed_json_secret_falls_back_to_raw`) continue to pass unchanged. - `cargo test --lib secrets::decrypt` — 11/11 passing. - `cargo clippy` — clean on the changed file. - Added `test_json_secret_extraction_api_key` — secret shaped like AWS's managed-rotation type (`{"apiKey":"...","apiKeyId":"..."}`) extracts the API key. ([sample function](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/functions/tianning-li-20260716-1213-sample-function/versions/5?subtab=envVars&tab=testing) with [sample log](https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/$252Faws$252Flambda$252Ftianning-li-20260716-1213-sample-function/log-events/2026$252F07$252F16$252F$255B5$255D7aeb509a15c7467699d15ac4db9c9122)) <img width="1046" height="632" alt="image" src="https://github.com/user-attachments/assets/f93b217e-8d4d-4100-ad36-cd7b34d02578" />
Summary
DD_API_KEY_SECRET_ARNis set and the fetched secret is a JSON object, automatically extract thedd_api_keyfield as the API keydd_api_keyfield is absent — preserving existing behavior for plain-string secretsdd_api_keyTest Plan
dd_api_keypresent), fallback to raw (key absent), and plain string secrets{"dd_api_key": "<your-key>"}