|
12 | 12 | from typing import Set |
13 | 13 | from typing import Tuple |
14 | 14 | from typing import Union |
| 15 | +import weakref |
15 | 16 |
|
16 | 17 | from ddtrace.appsec import _asm_request_context |
17 | 18 | from ddtrace.appsec._capabilities import _appsec_rc_file_is_not_static |
@@ -126,6 +127,7 @@ class AppSecSpanProcessor(SpanProcessor): |
126 | 127 | ) |
127 | 128 | _addresses_to_keep: Set[str] = dataclasses.field(default_factory=set) |
128 | 129 | _rate_limiter: RateLimiter = dataclasses.field(default_factory=_get_rate_limiter) |
| 130 | + _span_to_waf_ctx: weakref.WeakKeyDictionary = dataclasses.field(default_factory=weakref.WeakKeyDictionary) |
129 | 131 |
|
130 | 132 | @property |
131 | 133 | def enabled(self): |
@@ -220,7 +222,7 @@ def on_span_start(self, span: Span) -> None: |
220 | 222 | _asm_request_context.register(span, new_asm_context) |
221 | 223 |
|
222 | 224 | ctx = self._ddwaf._at_request_start() |
223 | | - |
| 225 | + self._span_to_waf_ctx[span] = ctx |
224 | 226 | peer_ip = _asm_request_context.get_ip() |
225 | 227 | headers = _asm_request_context.get_headers() |
226 | 228 | headers_case_sensitive = _asm_request_context.get_headers_case_sensitive() |
@@ -407,3 +409,19 @@ def on_span_finish(self, span: Span) -> None: |
407 | 409 | finally: |
408 | 410 | # release asm context if it was created by the span |
409 | 411 | _asm_request_context.unregister(span) |
| 412 | + |
| 413 | + if span.span_type != SpanTypes.WEB: |
| 414 | + return |
| 415 | + |
| 416 | + to_delete = [] |
| 417 | + for iterspan, ctx in self._span_to_waf_ctx.items(): |
| 418 | + # delete all the ddwaf ctxs associated with this span or finished or deleted ones |
| 419 | + if iterspan == span or iterspan.finished: |
| 420 | + # so we don't change the dictionary size on iteration |
| 421 | + to_delete.append(iterspan) |
| 422 | + |
| 423 | + for s in to_delete: |
| 424 | + try: |
| 425 | + del self._span_to_waf_ctx[s] |
| 426 | + except Exception: # nosec B110 |
| 427 | + pass |
0 commit comments