Skip to content

fix(logs_monitoring): read the API key from the region in its ARN - #1192

Open
ppulec-make wants to merge 1 commit into
DataDog:masterfrom
ppulec-make:fix/cross-region-api-key-secret
Open

fix(logs_monitoring): read the API key from the region in its ARN#1192
ppulec-make wants to merge 1 commit into
DataDog:masterfrom
ppulec-make:fix/cross-region-api-key-secret

Conversation

@ppulec-make

Copy link
Copy Markdown

What does this PR do?

Passes the region parsed out of the ARN to the Secrets Manager and SSM clients that fetch the Datadog API key in aws/logs_monitoring/settings.py, so a secret or parameter stored in a different region than the Forwarder can be read.

  • get_region_from_arn() returns the region field of an ARN, or None when the value is not an ARN.
  • boto3.client("secretsmanager", region_name=..., ...) for DD_API_KEY_SECRET_ARN.
  • boto3.client("ssm", region_name=..., ...) for DD_API_KEY_SSM_NAME.
  • DdApiKeySsmParameterName accepts a full SSM ARN in addition to a parameter path. Its AllowedPattern rejected colons, so without this the SSM half of the fix is unreachable from CloudFormation. The SSM statement in the execution role already grants Resource: "*", so no IAM change is needed.

Passing region_name=None is equivalent to omitting it, so a plain SSM parameter name (/datadog/api-key) keeps the existing default region resolution. Both clients are unchanged for same-region configurations.

Motivation

Both clients were created without a region, so botocore resolved one from the environment — on Lambda that is AWS_REGION, always the region the Forwarder runs in. Neither Secrets Manager nor SSM redirects a request based on the ARN it carries: the secretsmanager endpoint ruleset takes only Region, UseDualStack, UseFIPS and Endpoint, and the service model defines no contextParam binding SecretId to the endpoint. A cross-region ARN was therefore sent to the local region's endpoint and came back ResourceNotFoundException.

The failure mode is severe: the lookup runs at settings import time and only json.JSONDecodeError is caught, so the ClientError propagates out of the import and fails Lambda initialization rather than degrading. It also reads as a permissions problem when it is not — the role's secretsmanager:GetSecretValue statement is scoped to !Sub "${DdApiKeySecretArn}*", which does grant the cross-region secret.

This affects a single Secrets Manager secret shared by Forwarders in several regions, which is otherwise a supported way to hold one API key.

Not changed

DD_KMS_API_KEY still requires a KMS key in the Forwarder's region. Its input is a base64 ciphertext blob with no ARN to parse, so supporting a cross-region key would mean adding a new parameter for the key's region. That is left out to keep this a bug fix; the constraint is now stated in the README.

Testing Guidelines

New cases in aws/logs_monitoring/tests/test_settings.py:

  • get_region_from_arn() over a full secret ARN, a partial secret ARN, an SSM parameter ARN, a non-commercial partition ARN, a plain parameter name, a secret friendly name, an ARN with an empty region field, and a truncated ARN.
  • Reloading settings with a patched boto3 asserts the client is built with region_name="eu-west-1" for a cross-region secret ARN, region_name="us-west-2" for a cross-region SSM ARN, and region_name=None for a parameter name.

Verified locally on Python 3.14 with the CI commands: python -m unittest discover ./aws/logs_monitoring/ (190 tests, OK), flake8 --select=E9,F --ignore=F824, black --check, and cfn-lint -i E3030 -t aws/logs_monitoring/template.yaml all clean. The AllowedPattern regex was checked against parameter paths and aws, aws-us-gov and aws-cn SSM ARNs, and against values it must keep rejecting.

Additional Notes

Unrelated latent bug noticed while writing the tests, not addressed here: when a plaintext secret parses as non-object JSON — an all-digit string, which a 32-character hex API key can be — json.loads returns an int and "DD_API_KEY" in secret_json raises TypeError: argument of type 'int' is not a container or iterable. Only json.JSONDecodeError is caught. Happy to send a separate PR guarding on isinstance(secret_json, dict).

Types of changes

  • Bug fix
  • New feature
  • Breaking change
  • Misc (docs, refactoring, dependency upgrade, etc.)

Check all that apply

  • This PR's description is comprehensive
  • This PR contains breaking changes that are documented in the description
  • This PR introduces new APIs or parameters that are documented and unlikely to change in the foreseeable future
  • This PR impacts documentation, and it has been updated (or a ticket has been logged)
  • This PR's changes are covered by the automated tests
  • This PR collects user input/sensitive content into Datadog
  • This PR passes the integration tests (ask a Datadog member to run the tests)
  • This PR passes the unit tests
  • This PR passes the installation tests (ask a Datadog member to run the tests)

🤖 Generated with Claude Code

The Secrets Manager and SSM clients were built without a region, so boto3
resolved one from the environment, which on Lambda is always the region the
Forwarder runs in. Neither service redirects a request based on the ARN it
carries, so a secret or parameter in another region was unreachable and the
lookup failed during module import, taking the whole init down with it.

Pass the region parsed out of the ARN to both clients. Values that are not
ARNs, such as a plain SSM parameter name, keep the default resolution.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ppulec-make
ppulec-make requested review from a team as code owners August 4, 2026 12:54
@ppulec-make

ppulec-make commented Aug 5, 2026

Copy link
Copy Markdown
Author

Hello @rtrieu, thank you for approving this change.

Could you please help me to get an approval from the aws-integrations team?

Thank you!

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.

2 participants