diff --git a/ddtrace/appsec/_constants.py b/ddtrace/appsec/_constants.py index 246ecd54461..929db7cf722 100644 --- a/ddtrace/appsec/_constants.py +++ b/ddtrace/appsec/_constants.py @@ -121,6 +121,7 @@ class APPSEC(metaclass=Constant_Class): RASP_ERROR: Literal["_dd.appsec.rasp.error"] = "_dd.appsec.rasp.error" ERROR_TYPE: Literal["_dd.appsec.error.type"] = "_dd.appsec.error.type" ERROR_MESSAGE: Literal["_dd.appsec.error.message"] = "_dd.appsec.error.message" + UNSUPPORTED_EVENT_TYPE: Literal["_dd.appsec.unsupported_event_type"] = "_dd.appsec.unsupported_event_type" TELEMETRY_OFF_NAME = "OFF" diff --git a/ddtrace/appsec/_processor.py b/ddtrace/appsec/_processor.py index 63fec15679b..1eb0ecda59e 100644 --- a/ddtrace/appsec/_processor.py +++ b/ddtrace/appsec/_processor.py @@ -14,6 +14,9 @@ from typing import Tuple from typing import Union +from ddtrace.ext import SpanTypes +from ddtrace.internal import core + if TYPE_CHECKING: import ddtrace.appsec._ddwaf as ddwaf @@ -181,6 +184,16 @@ def on_span_start(self, span: Span) -> None: if span.span_type not in asm_config._asm_processed_span_types: return + if span.span_type == SpanTypes.SERVERLESS: + skip_event = core.get_item("appsec_skip_next_lambda_event") + if skip_event: + core.discard_item("appsec_skip_next_lambda_event") + log.debug( + "appsec: ignoring unsupported lamdba event", + ) + span.set_metric(APPSEC.UNSUPPORTED_EVENT_TYPE, 1.0) + return + ctx = self._ddwaf._at_request_start() _asm_request_context.start_context(span, ctx.rc_products if ctx is not None else "") peer_ip = _asm_request_context.get_ip() diff --git a/ddtrace/settings/asm.py b/ddtrace/settings/asm.py index 98843f237af..e6b6ec9fb76 100644 --- a/ddtrace/settings/asm.py +++ b/ddtrace/settings/asm.py @@ -177,6 +177,7 @@ class ASMConfig(DDConfig): "_asm_static_rule_file", "_asm_obfuscation_parameter_key_regexp", "_asm_obfuscation_parameter_value_regexp", + "_asm_processed_span_types", "_apm_tracing_enabled", "_bypass_instrumentation_for_waf", "_iast_enabled", diff --git a/tests/appsec/appsec/test_processor.py b/tests/appsec/appsec/test_processor.py index 09fd5e724ce..ed79a7c0bcd 100644 --- a/tests/appsec/appsec/test_processor.py +++ b/tests/appsec/appsec/test_processor.py @@ -767,3 +767,28 @@ def test_ephemeral_addresses(mock_run, persistent, ephemeral): WAF_DATA_NAMES[ephemeral]: {"key_2": "value_3"}, } assert (span._local_root or span).get_tag(APPSEC.RC_PRODUCTS) == "[ASM:1] u:1 r:1" + + +@pytest.mark.parametrize("skip_event", [True, False]) +def test_lambda_unsupported_event(tracer, skip_event): + """ + Test that the processor correctly handles the appsec_skip_next_lambda_event flag. + """ + if skip_event: + core.set_item("appsec_skip_next_lambda_event", True) + + config = { + "_asm_enabled": True, + "_asm_processed_span_types": {SpanTypes.SERVERLESS}, + } + + with asm_context(tracer=tracer, config=config, span_type=SpanTypes.SERVERLESS) as span: + pass + + if skip_event: + # When skip_event is True, the metric should be set and context item should be discarded + assert span.get_metric(APPSEC.UNSUPPORTED_EVENT_TYPE) == 1.0 + assert core.get_item("appsec_skip_next_lambda_event") is None + else: + # When skip_event is False, the metric should not be set + assert span.get_metric(APPSEC.UNSUPPORTED_EVENT_TYPE) is None diff --git a/tests/appsec/utils.py b/tests/appsec/utils.py index 47911aa76c5..d97691bc333 100644 --- a/tests/appsec/utils.py +++ b/tests/appsec/utils.py @@ -53,6 +53,7 @@ def get_waf_addresses(address: str) -> typing.Optional[typing.Any]: def asm_context( tracer=None, span_name: str = "", + span_type: str = SpanTypes.WEB, ip_addr: typing.Optional[str] = None, headers_case_sensitive: bool = False, headers: typing.Optional[typing.Dict[str, str]] = None, @@ -80,7 +81,7 @@ def asm_context( headers=headers, block_request_callable=block_request_callable, service=service, - ), tracer.trace(span_name or "test", span_type=SpanTypes.WEB, service=service) as span: + ), tracer.trace(span_name or "test", span_type=span_type, service=service) as span: yield span unpatch_for_waf_addresses()