From 69cb43a586dc77501cf632c89c3da0b721745085 Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Thu, 13 Mar 2025 17:04:47 -0400 Subject: [PATCH 1/6] use region from secrets manager arn --- datadog_lambda/api.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/datadog_lambda/api.py b/datadog_lambda/api.py index 03135912..29df9a2f 100644 --- a/datadog_lambda/api.py +++ b/datadog_lambda/api.py @@ -64,8 +64,8 @@ def get_api_key() -> str: DD_KMS_API_KEY = os.environ.get("DD_KMS_API_KEY", "") DD_API_KEY = os.environ.get("DD_API_KEY", os.environ.get("DATADOG_API_KEY", "")) - REGION = os.environ.get("AWS_REGION", "") - is_gov_region = REGION.startswith("us-gov-") + LAMBDA_REGION = os.environ.get("AWS_REGION", "") + is_gov_region = LAMBDA_REGION.startswith("us-gov-") if is_gov_region: logger.debug( "Govcloud region detected. Using FIPs endpoints for secrets management." @@ -73,13 +73,18 @@ def get_api_key() -> str: if DD_API_KEY_SECRET_ARN: # Secrets manager endpoints: https://docs.aws.amazon.com/general/latest/gr/asm.html - fips_endpoint = ( - f"https://secretsmanager-fips.{REGION}.amazonaws.com" + try: + secrets_region = DD_API_KEY_SECRET_ARN.split(":")[3] + except Exception as e: + logger.debug("Invalid secret arn in DD_API_KEY_SECRET_ARN. Unable to get API key.") + return "" + endpoint_url = ( + f"https://secretsmanager-fips.{secrets_region}.amazonaws.com" if is_gov_region - else None + else f"https://secretsmanager.{secrets_region}.amazonaws.com" ) secrets_manager_client = boto3.client( - "secretsmanager", endpoint_url=fips_endpoint + "secretsmanager", endpoint_url=endpoint_url ) api_key = secrets_manager_client.get_secret_value( SecretId=DD_API_KEY_SECRET_ARN @@ -87,7 +92,7 @@ def get_api_key() -> str: elif DD_API_KEY_SSM_NAME: # SSM endpoints: https://docs.aws.amazon.com/general/latest/gr/ssm.html fips_endpoint = ( - f"https://ssm-fips.{REGION}.amazonaws.com" if is_gov_region else None + f"https://ssm-fips.{LAMBDA_REGION}.amazonaws.com" if is_gov_region else None ) ssm_client = boto3.client("ssm", endpoint_url=fips_endpoint) api_key = ssm_client.get_parameter( @@ -96,7 +101,7 @@ def get_api_key() -> str: elif DD_KMS_API_KEY: # KMS endpoints: https://docs.aws.amazon.com/general/latest/gr/kms.html fips_endpoint = ( - f"https://kms-fips.{REGION}.amazonaws.com" if is_gov_region else None + f"https://kms-fips.{LAMBDA_REGION}.amazonaws.com" if is_gov_region else None ) kms_client = boto3.client("kms", endpoint_url=fips_endpoint) api_key = decrypt_kms_api_key(kms_client, DD_KMS_API_KEY) From b5af010642494494e03f628939ce94c0e3b225d9 Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Thu, 13 Mar 2025 17:04:53 -0400 Subject: [PATCH 2/6] unit tests --- tests/test_api.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/test_api.py b/tests/test_api.py index a69f4382..af88a71b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -29,7 +29,7 @@ def test_secrets_manager_fips_endpoint(self, mock_boto3_client): mock_boto3_client.return_value = mock_client os.environ["AWS_REGION"] = "us-gov-east-1" - os.environ["DD_API_KEY_SECRET_ARN"] = "test-secrets-arn" + os.environ["DD_API_KEY_SECRET_ARN"] = "arn:aws:secretsmanager:us-gov-east-1:1234567890:secret:key-name-123ABC" api_key = api.get_api_key() @@ -39,6 +39,23 @@ def test_secrets_manager_fips_endpoint(self, mock_boto3_client): ) self.assertEqual(api_key, "test-api-key") + @patch("boto3.client") + def test_secrets_manager_different_region(self, mock_boto3_client): + mock_client = MagicMock() + mock_client.get_secret_value.return_value = {"SecretString": "test-api-key"} + mock_boto3_client.return_value = mock_client + + os.environ["AWS_REGION"] = "us-east-1" + os.environ["DD_API_KEY_SECRET_ARN"] = "arn:aws:secretsmanager:us-west-1:1234567890:secret:key-name-123ABC" + + api_key = api.get_api_key() + + mock_boto3_client.assert_called_with( + "secretsmanager", + endpoint_url="https://secretsmanager.us-west-1.amazonaws.com", + ) + self.assertEqual(api_key, "test-api-key") + @patch("boto3.client") def test_ssm_fips_endpoint(self, mock_boto3_client): mock_client = MagicMock() From c69271321d7356571cb0ce2a0b9bb0409d2020f6 Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Thu, 13 Mar 2025 17:08:56 -0400 Subject: [PATCH 3/6] lint --- datadog_lambda/api.py | 4 +++- tests/test_api.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/datadog_lambda/api.py b/datadog_lambda/api.py index 29df9a2f..88c59310 100644 --- a/datadog_lambda/api.py +++ b/datadog_lambda/api.py @@ -76,7 +76,9 @@ def get_api_key() -> str: try: secrets_region = DD_API_KEY_SECRET_ARN.split(":")[3] except Exception as e: - logger.debug("Invalid secret arn in DD_API_KEY_SECRET_ARN. Unable to get API key.") + logger.debug( + "Invalid secret arn in DD_API_KEY_SECRET_ARN. Unable to get API key." + ) return "" endpoint_url = ( f"https://secretsmanager-fips.{secrets_region}.amazonaws.com" diff --git a/tests/test_api.py b/tests/test_api.py index af88a71b..0efbf1c5 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -46,7 +46,9 @@ def test_secrets_manager_different_region(self, mock_boto3_client): mock_boto3_client.return_value = mock_client os.environ["AWS_REGION"] = "us-east-1" - os.environ["DD_API_KEY_SECRET_ARN"] = "arn:aws:secretsmanager:us-west-1:1234567890:secret:key-name-123ABC" + os.environ[ + "DD_API_KEY_SECRET_ARN" + ] = "arn:aws:secretsmanager:us-west-1:1234567890:secret:key-name-123ABC" api_key = api.get_api_key() From 925726bcb2b168c0e97ae95dcfa50d7abd14bf0a Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Thu, 13 Mar 2025 17:22:56 -0400 Subject: [PATCH 4/6] create secrets manager client with correct region (no need to specify endpoint now) --- datadog_lambda/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datadog_lambda/api.py b/datadog_lambda/api.py index 88c59310..85ca0a23 100644 --- a/datadog_lambda/api.py +++ b/datadog_lambda/api.py @@ -83,10 +83,10 @@ def get_api_key() -> str: endpoint_url = ( f"https://secretsmanager-fips.{secrets_region}.amazonaws.com" if is_gov_region - else f"https://secretsmanager.{secrets_region}.amazonaws.com" + else None ) secrets_manager_client = boto3.client( - "secretsmanager", endpoint_url=endpoint_url + "secretsmanager", endpoint_url=endpoint_url, region_name=secrets_region ) api_key = secrets_manager_client.get_secret_value( SecretId=DD_API_KEY_SECRET_ARN From 7df118a5720837eb3315373cb9b5658236649a16 Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Thu, 13 Mar 2025 17:24:31 -0400 Subject: [PATCH 5/6] lint --- datadog_lambda/api.py | 2 +- tests/test_api.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/datadog_lambda/api.py b/datadog_lambda/api.py index 85ca0a23..ad860873 100644 --- a/datadog_lambda/api.py +++ b/datadog_lambda/api.py @@ -75,7 +75,7 @@ def get_api_key() -> str: # Secrets manager endpoints: https://docs.aws.amazon.com/general/latest/gr/asm.html try: secrets_region = DD_API_KEY_SECRET_ARN.split(":")[3] - except Exception as e: + except Exception: logger.debug( "Invalid secret arn in DD_API_KEY_SECRET_ARN. Unable to get API key." ) diff --git a/tests/test_api.py b/tests/test_api.py index 0efbf1c5..b2d6f10a 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -29,7 +29,9 @@ def test_secrets_manager_fips_endpoint(self, mock_boto3_client): mock_boto3_client.return_value = mock_client os.environ["AWS_REGION"] = "us-gov-east-1" - os.environ["DD_API_KEY_SECRET_ARN"] = "arn:aws:secretsmanager:us-gov-east-1:1234567890:secret:key-name-123ABC" + os.environ[ + "DD_API_KEY_SECRET_ARN" + ] = "arn:aws:secretsmanager:us-gov-east-1:1234567890:secret:key-name-123ABC" api_key = api.get_api_key() From 1fec486fd9ff9f72b7d1ce645c74c7b737534690 Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Thu, 13 Mar 2025 17:30:02 -0400 Subject: [PATCH 6/6] fix test --- tests/test_api.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index b2d6f10a..c7facb43 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -38,6 +38,7 @@ def test_secrets_manager_fips_endpoint(self, mock_boto3_client): mock_boto3_client.assert_called_with( "secretsmanager", endpoint_url="https://secretsmanager-fips.us-gov-east-1.amazonaws.com", + region_name="us-gov-east-1", ) self.assertEqual(api_key, "test-api-key") @@ -56,7 +57,8 @@ def test_secrets_manager_different_region(self, mock_boto3_client): mock_boto3_client.assert_called_with( "secretsmanager", - endpoint_url="https://secretsmanager.us-west-1.amazonaws.com", + endpoint_url=None, + region_name="us-west-1", ) self.assertEqual(api_key, "test-api-key") @@ -103,8 +105,12 @@ def test_no_fips_for_standard_regions(self, mock_boto3_client): os.environ.clear() os.environ["AWS_REGION"] = "us-west-2" - os.environ["DD_API_KEY_SECRET_ARN"] = "test-arn" + os.environ[ + "DD_API_KEY_SECRET_ARN" + ] = "arn:aws:secretsmanager:us-west-2:1234567890:secret:key-name-123ABC" api.get_api_key() - mock_boto3_client.assert_called_with("secretsmanager", endpoint_url=None) + mock_boto3_client.assert_called_with( + "secretsmanager", endpoint_url=None, region_name="us-west-2" + )