Skip to content

Commit 71b64fa

Browse files
authored
Use FIPs endpoints in Govcloud regions (#575)
1 parent 6e2e5d5 commit 71b64fa

File tree

2 files changed

+117
-3
lines changed

2 files changed

+117
-3
lines changed

datadog_lambda/api.py

+28-3
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,41 @@ def get_api_key() -> str:
6464
DD_KMS_API_KEY = os.environ.get("DD_KMS_API_KEY", "")
6565
DD_API_KEY = os.environ.get("DD_API_KEY", os.environ.get("DATADOG_API_KEY", ""))
6666

67+
REGION = os.environ.get("AWS_REGION", "")
68+
is_gov_region = REGION.startswith("us-gov-")
69+
if is_gov_region:
70+
logger.debug(
71+
"Govcloud region detected. Using FIPs endpoints for secrets management."
72+
)
73+
6774
if DD_API_KEY_SECRET_ARN:
68-
api_key = boto3.client("secretsmanager").get_secret_value(
75+
# Secrets manager endpoints: https://docs.aws.amazon.com/general/latest/gr/asm.html
76+
fips_endpoint = (
77+
f"https://secretsmanager-fips.{REGION}.amazonaws.com"
78+
if is_gov_region
79+
else None
80+
)
81+
secrets_manager_client = boto3.client(
82+
"secretsmanager", endpoint_url=fips_endpoint
83+
)
84+
api_key = secrets_manager_client.get_secret_value(
6985
SecretId=DD_API_KEY_SECRET_ARN
7086
)["SecretString"]
7187
elif DD_API_KEY_SSM_NAME:
72-
api_key = boto3.client("ssm").get_parameter(
88+
# SSM endpoints: https://docs.aws.amazon.com/general/latest/gr/ssm.html
89+
fips_endpoint = (
90+
f"https://ssm-fips.{REGION}.amazonaws.com" if is_gov_region else None
91+
)
92+
ssm_client = boto3.client("ssm", endpoint_url=fips_endpoint)
93+
api_key = ssm_client.get_parameter(
7394
Name=DD_API_KEY_SSM_NAME, WithDecryption=True
7495
)["Parameter"]["Value"]
7596
elif DD_KMS_API_KEY:
76-
kms_client = boto3.client("kms")
97+
# KMS endpoints: https://docs.aws.amazon.com/general/latest/gr/kms.html
98+
fips_endpoint = (
99+
f"https://kms-fips.{REGION}.amazonaws.com" if is_gov_region else None
100+
)
101+
kms_client = boto3.client("kms", endpoint_url=fips_endpoint)
77102
api_key = decrypt_kms_api_key(kms_client, DD_KMS_API_KEY)
78103
else:
79104
api_key = DD_API_KEY

tests/test_api.py

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import os
2+
import unittest
3+
from unittest.mock import patch, MagicMock
4+
5+
import datadog_lambda.api as api
6+
7+
8+
class TestDatadogLambdaAPI(unittest.TestCase):
9+
def setUp(self):
10+
api.api_key = None
11+
self.env_patcher = patch.dict(
12+
os.environ,
13+
{
14+
"DD_API_KEY_SECRET_ARN": "",
15+
"DD_API_KEY_SSM_NAME": "",
16+
"DD_KMS_API_KEY": "",
17+
"DD_API_KEY": "",
18+
"DATADOG_API_KEY": "",
19+
"AWS_REGION": "",
20+
},
21+
clear=True,
22+
)
23+
self.env_patcher.start()
24+
25+
@patch("boto3.client")
26+
def test_secrets_manager_fips_endpoint(self, mock_boto3_client):
27+
mock_client = MagicMock()
28+
mock_client.get_secret_value.return_value = {"SecretString": "test-api-key"}
29+
mock_boto3_client.return_value = mock_client
30+
31+
os.environ["AWS_REGION"] = "us-gov-east-1"
32+
os.environ["DD_API_KEY_SECRET_ARN"] = "test-secrets-arn"
33+
34+
api_key = api.get_api_key()
35+
36+
mock_boto3_client.assert_called_with(
37+
"secretsmanager",
38+
endpoint_url="https://secretsmanager-fips.us-gov-east-1.amazonaws.com",
39+
)
40+
self.assertEqual(api_key, "test-api-key")
41+
42+
@patch("boto3.client")
43+
def test_ssm_fips_endpoint(self, mock_boto3_client):
44+
mock_client = MagicMock()
45+
mock_client.get_parameter.return_value = {
46+
"Parameter": {"Value": "test-api-key"}
47+
}
48+
mock_boto3_client.return_value = mock_client
49+
50+
os.environ["AWS_REGION"] = "us-gov-west-1"
51+
os.environ["DD_API_KEY_SSM_NAME"] = "test-ssm-param"
52+
53+
api_key = api.get_api_key()
54+
55+
mock_boto3_client.assert_called_with(
56+
"ssm", endpoint_url="https://ssm-fips.us-gov-west-1.amazonaws.com"
57+
)
58+
self.assertEqual(api_key, "test-api-key")
59+
60+
@patch("boto3.client")
61+
@patch("datadog_lambda.api.decrypt_kms_api_key")
62+
def test_kms_fips_endpoint(self, mock_decrypt_kms, mock_boto3_client):
63+
mock_client = MagicMock()
64+
mock_boto3_client.return_value = mock_client
65+
mock_decrypt_kms.return_value = "test-api-key"
66+
67+
os.environ["AWS_REGION"] = "us-gov-west-1"
68+
os.environ["DD_KMS_API_KEY"] = "encrypted-api-key"
69+
70+
api_key = api.get_api_key()
71+
72+
mock_boto3_client.assert_called_with(
73+
"kms", endpoint_url="https://kms-fips.us-gov-west-1.amazonaws.com"
74+
)
75+
self.assertEqual(api_key, "test-api-key")
76+
77+
@patch("boto3.client")
78+
def test_no_fips_for_standard_regions(self, mock_boto3_client):
79+
mock_client = MagicMock()
80+
mock_client.get_secret_value.return_value = {"SecretString": "test-api-key"}
81+
mock_boto3_client.return_value = mock_client
82+
83+
os.environ.clear()
84+
os.environ["AWS_REGION"] = "us-west-2"
85+
os.environ["DD_API_KEY_SECRET_ARN"] = "test-arn"
86+
87+
api.get_api_key()
88+
89+
mock_boto3_client.assert_called_with("secretsmanager", endpoint_url=None)

0 commit comments

Comments
 (0)