diff --git a/datadog_lambda/api.py b/datadog_lambda/api.py index fd3e2c17..5c6f7c52 100644 --- a/datadog_lambda/api.py +++ b/datadog_lambda/api.py @@ -1,6 +1,8 @@ import os import logging +from datadog_lambda.aws import current_region, running_in_gov_region + logger = logging.getLogger(__name__) KMS_ENCRYPTION_CONTEXT_KEY = "LambdaFunctionName" api_key = None @@ -62,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", "")) - LAMBDA_REGION = os.environ.get("AWS_REGION", "") - is_gov_region = LAMBDA_REGION.startswith("us-gov-") + LAMBDA_REGION = current_region() + is_gov_region = running_in_gov_region() if is_gov_region: logger.debug( "Govcloud region detected. Using FIPs endpoints for secrets management." diff --git a/datadog_lambda/aws.py b/datadog_lambda/aws.py new file mode 100644 index 00000000..89a05580 --- /dev/null +++ b/datadog_lambda/aws.py @@ -0,0 +1,9 @@ +import os + + +def current_region() -> str: + return os.environ.get("AWS_REGION", "") + + +def running_in_gov_region() -> bool: + return current_region().startswith("us-gov-") diff --git a/datadog_lambda/metric.py b/datadog_lambda/metric.py index f9c67a26..94bf93b6 100644 --- a/datadog_lambda/metric.py +++ b/datadog_lambda/metric.py @@ -11,6 +11,7 @@ from datadog_lambda.extension import should_use_extension from datadog_lambda.tags import get_enhanced_metrics_tags, dd_lambda_layer_tag +from datadog_lambda.aws import running_in_gov_region logger = logging.getLogger(__name__) @@ -76,6 +77,18 @@ def lambda_metric(metric_name, value, timestamp=None, tags=None, force_async=Fal tags.append(dd_lambda_layer_tag) if should_use_extension and timestamp is not None: + if running_in_gov_region(): + # Metrics with timestamps get shipped directly to datadog instead + # of going to the agent. We cannot guarantee from our side that + # this will be done in a FIPS-compliant way, so we disable this + # feature for now. We may revisit it in the future. + logger.warning( + "Ignoring metric submission for metric '%s' because we cannot guarantee " + "FIPS-compliance for metrics submitted directly to Datadog.", + metric_name, + ) + return + # The extension does not support timestamps for distributions so we create a # a thread stats writer to submit metrics with timestamps to the API timestamp_ceiling = int( diff --git a/tests/test_api.py b/tests/test_api.py index c98d91eb..513ccd8f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -22,6 +22,9 @@ def setUp(self): ) self.env_patcher.start() + def tearDown(self): + self.env_patcher.stop() + @patch("botocore.session.Session.create_client") def test_secrets_manager_fips_endpoint(self, mock_boto3_client): mock_client = MagicMock() diff --git a/tests/test_metric.py b/tests/test_metric.py index d10a0f0d..99dc3c87 100644 --- a/tests/test_metric.py +++ b/tests/test_metric.py @@ -58,6 +58,20 @@ def test_lambda_metric_timestamp_with_extension(self): "test_timestamp", 1, timestamp=timestamp, tags=[dd_lambda_layer_tag] ) + @patch("os.environ", {"AWS_REGION": "us-gov-west-1"}) + @patch("datadog_lambda.metric.should_use_extension", True) + def test_lambda_metric_timestamp_with_extension_in_govcloud(self): + patcher = patch("datadog_lambda.metric.extension_thread_stats") + self.mock_metric_extension_thread_stats = patcher.start() + self.addCleanup(patcher.stop) + + delta = timedelta(minutes=1) + timestamp = int((datetime.now() - delta).timestamp()) + + lambda_metric("test_timestamp", 1, timestamp) + self.mock_metric_lambda_stats.distribution.assert_not_called() + self.mock_metric_extension_thread_stats.distribution.assert_not_called() + @patch("datadog_lambda.metric.should_use_extension", True) def test_lambda_metric_datetime_with_extension(self): patcher = patch("datadog_lambda.metric.extension_thread_stats")