Skip to content

Commit 5ad5469

Browse files
chore(aap): appsec tests in appsec files (#15155)
## Description - remove appsec/iast references from non appsec/iast tests when it's not useful - ensuring appsec tests are in files clearly identified as owned by appsec team. - move appsec related tests from non appsec files to appsec files (rarely duplicate a test, with/without appsec) - add asm ownership to clearly identify tests files containing appsec/iast tests for mixed test files. Basically, making sure we are accountable for ASM/AAP. This PR will be followed by another one on the same topic (to not create huge PR) APPSEC-59813 --------- Co-authored-by: Alberto Vara <alberto.vara@datadoghq.com>
1 parent acd8a7d commit 5ad5469

File tree

9 files changed

+245
-169
lines changed

9 files changed

+245
-169
lines changed

.github/CODEOWNERS

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ tests/utils.py @DataDog/python-guild
4747
tests/suitespec.yml @DataDog/python-guild @DataDog/apm-core-python
4848
tests/suitespec.py @DataDog/python-guild @DataDog/apm-core-python
4949
scripts/bump_ddtrace.py @DataDog/python-guild
50+
tests/smoke_test.py @DataDog/python-guild
5051

5152
# Core / Language Platform
5253
tests/internal @DataDog/apm-core-python
@@ -125,10 +126,9 @@ ddtrace/internal/iast/ @DataDog/asm-python
125126
tests/appsec/ @DataDog/asm-python
126127
tests/contrib/subprocess @DataDog/asm-python
127128
tests/snapshots/tests*appsec*.json @DataDog/asm-python
128-
tests/contrib/*/test*appsec*.py @DataDog/asm-python
129-
tests/contrib/*/test*iast*.py @DataDog/asm-python
130129
scripts/iast/* @DataDog/asm-python
131130

131+
132132
# Profiling
133133
ddtrace/profiling @DataDog/profiling-python
134134
ddtrace/internal/settings/profiling.py @DataDog/profiling-python
@@ -240,7 +240,7 @@ tests/contrib/azure_functions @DataDog/serverless
240240
tests/contrib/azure_functions_eventhubs @DataDog/serverless @DataDog/apm-serverless
241241
tests/contrib/azure_functions_servicebus @DataDog/serverless @DataDog/apm-serverless
242242
tests/contrib/azure_servicebus @DataDog/serverless @DataDog/apm-serverless
243-
tests/internal/test_serverless.py @DataDog/apm-core-python @DataDog/apm-serverless
243+
tests/internal/test_serverless.py @DataDog/apm-core-python @DataDog/apm-serverless @DataDog/asm-python
244244
tests/snapshots/tests.contrib.aws_lambda.*. @DataDog/apm-serverless
245245
tests/snapshots/tests.contrib.azure_eventhubs.* @DataDog/serverless @DataDog/apm-serverless
246246
tests/snapshots/tests.contrib.azure_functions.* @DataDog/serverless @DataDog/apm-serverless
@@ -251,3 +251,8 @@ tests/snapshots/tests.contrib.azure_servicebus.* @DataDog/serverless
251251
# Data Streams Monitoring
252252
ddtrace/internal/datastreams @DataDog/data-streams-monitoring
253253
tests/datastreams @DataDog/data-streams-monitoring
254+
255+
# ASM (order matters)
256+
tests/**/*appsec* @DataDog/asm-python
257+
tests/**/*iast* @DataDog/asm-python
258+
tests/tracer/test_propagation.py @DataDog/apm-sdk-capabilities-python @DataDog/asm-python

tests/integration/test_integration_snapshots.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ def test_flush_spans_before_writer_recreate():
4646
long_running_span = tracer.trace("long_running_operation")
4747

4848
writer = tracer._span_aggregator.writer
49-
# Enable appsec to trigger the recreation of the agent writer
50-
tracer.configure(appsec_enabled=True)
49+
# Enable compute stats to trigger the recreation of the agent writer
50+
tracer._recreate(reset_buffer=False)
5151
assert tracer._span_aggregator.writer is not writer, "Writer should be recreated"
5252
# Finish the long running span after the writer has been recreated
5353
long_running_span.finish()

tests/tracer/test_endpoint_config.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def mock_getresponse_enabled_after_4_retries(self):
2323
response.status = 500
2424
response.reason = "KO"
2525
else:
26-
response.read.return_value = b'{"dd_iast_enabled": true}'
26+
response.read.return_value = b'{"dd_product_enabled": true}'
2727
response.status = 200
2828
response.reason = "OK"
2929
response.fp = BytesIO(response.read.return_value)
@@ -34,7 +34,7 @@ def mock_getresponse_enabled_after_4_retries(self):
3434

3535
def mock_getresponse_enabled(self):
3636
response = mock.Mock(spec=HTTPResponse)
37-
response.read.return_value = b'{"dd_iast_enabled": true}'
37+
response.read.return_value = b'{"dd_product_enabled": true}'
3838
response.status = 200
3939
response.reason = "OK"
4040
response.chunked = False
@@ -46,7 +46,7 @@ def mock_getresponse_enabled(self):
4646

4747
def mock_getresponse_403(self):
4848
response = mock.Mock(spec=HTTPResponse)
49-
response.read.return_value = b'{"dd_iast_enabled": true}'
49+
response.read.return_value = b'{"dd_product_enabled": true}'
5050
response.status = 403
5151
response.reason = "KO"
5252
response.chunked = False
@@ -58,7 +58,7 @@ def mock_getresponse_403(self):
5858

5959
def mock_getresponse_500(self):
6060
response = mock.Mock(spec=HTTPResponse)
61-
response.read.return_value = b'{"dd_iast_enabled": true}'
61+
response.read.return_value = b'{"dd_product_enabled": true}'
6262
response.status = 500
6363
response.reason = "KO"
6464
response.chunked = False
@@ -99,7 +99,7 @@ def test_set_config_endpoint_enabled(caplog):
9999
), mock.patch.object(
100100
HTTPConnection, "getresponse", new=mock_getresponse_enabled
101101
):
102-
assert fetch_config_from_endpoint() == {"dd_iast_enabled": True}
102+
assert fetch_config_from_endpoint() == {"dd_product_enabled": True}
103103
if caplog.text:
104104
assert "Configuration endpoint not set. Skipping fetching configuration." not in caplog.text
105105
assert "Failed to fetch configuration from endpoint" not in caplog.text
@@ -181,4 +181,4 @@ def test_set_config_endpoint_retries(caplog):
181181
), mock.patch(
182182
"ddtrace.internal.settings.endpoint_config._get_retries", return_value=5
183183
):
184-
assert fetch_config_from_endpoint() == {"dd_iast_enabled": True}
184+
assert fetch_config_from_endpoint() == {"dd_product_enabled": True}

tests/tracer/test_processors.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def test_aggregator_reset_apm_opt_out_preserves_sampling():
178178
def test_aggregator_reset_with_args(writer_class):
179179
"""
180180
Validates that the span aggregator can reset trace buffers, sampling processor,
181-
user processors/filters and trace api version (when ASM is enabled)
181+
user processors/filters.
182182
"""
183183

184184
dd_proc = DummyProcessor()
@@ -204,12 +204,12 @@ def test_aggregator_reset_with_args(writer_class):
204204
assert aggr.sampling_processor.apm_opt_out is False
205205
assert aggr.sampling_processor._compute_stats_enabled is False
206206
# Reset the aggregator with new args and new user processors and expect the new values to be set
207-
aggr.reset(user_processors=[], compute_stats=True, apm_opt_out=True, appsec_enabled=True, reset_buffer=False)
207+
aggr.reset(user_processors=[], compute_stats=True, reset_buffer=False)
208208
assert aggr.user_processors == []
209209
assert dd_proc in aggr.dd_processors
210-
assert aggr.sampling_processor.apm_opt_out is True
210+
assert aggr.sampling_processor.apm_opt_out is False
211211
assert aggr.sampling_processor._compute_stats_enabled is True
212-
assert aggr.writer._api_version == "v0.4"
212+
assert aggr.writer._api_version == "v0.5"
213213
assert span.trace_id in aggr._traces
214214
assert len(aggr._span_metrics["spans_created"]) == 1
215215

tests/tracer/test_trace_utils.py

Lines changed: 0 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
from ddtrace._trace.pin import Pin
1818
from ddtrace.contrib.internal import trace_utils
1919
from ddtrace.contrib.internal.trace_utils import _get_request_header_client_ip
20-
from ddtrace.ext import SpanTypes
2120
from ddtrace.ext import http
22-
from ddtrace.ext import net
2321
from ddtrace.internal.compat import ensure_text
2422
from ddtrace.internal.settings._config import Config
2523
from ddtrace.internal.settings.integration import IntegrationConfig
@@ -28,7 +26,6 @@
2826
from ddtrace.propagation.http import HTTPPropagator
2927
from ddtrace.trace import Context
3028
from ddtrace.trace import Span
31-
from tests.appsec.utils import asm_context
3229
from tests.utils import override_global_config
3330

3431

@@ -389,128 +386,6 @@ def test_set_http_meta_with_http_header_tags_config():
389386
assert response_span.get_tag("third-header") == "value3"
390387

391388

392-
@pytest.mark.parametrize("appsec_enabled", [False, True])
393-
@pytest.mark.parametrize("span_type", [SpanTypes.WEB, SpanTypes.HTTP, None])
394-
@pytest.mark.parametrize(
395-
"method,url,status_code,status_msg,query,request_headers,response_headers,uri,path_params,cookies,target_host",
396-
[
397-
("GET", "http://localhost/", 0, None, None, None, None, None, None, None, "localhost"),
398-
("GET", "http://localhost/", 200, "OK", None, None, None, None, None, None, "localhost"),
399-
(None, None, None, None, None, None, None, None, None, None, None),
400-
(
401-
"GET",
402-
"http://localhost/",
403-
200,
404-
"OK",
405-
None,
406-
{"my-header": "value1"},
407-
{"resp-header": "val"},
408-
"http://localhost/",
409-
None,
410-
None,
411-
"localhost",
412-
),
413-
(
414-
"GET",
415-
"http://localhost/",
416-
200,
417-
"OK",
418-
"q=test+query&q2=val",
419-
{"my-header": "value1"},
420-
{"resp-header": "val"},
421-
"http://localhost/search?q=test+query&q2=val",
422-
{"id": "val", "name": "vlad"},
423-
None,
424-
"localhost",
425-
),
426-
("GET", "http://user:pass@localhost/", 0, None, None, None, None, None, None, None, None),
427-
("GET", "http://user@localhost/", 0, None, None, None, None, None, None, None, None),
428-
("GET", "http://user:pass@localhost/api?q=test", 0, None, None, None, None, None, None, None, None),
429-
("GET", "http://localhost/api@test", 0, None, None, None, None, None, None, None, None),
430-
("GET", "http://localhost/?api@test", 0, None, None, None, None, None, None, None, None),
431-
],
432-
)
433-
def test_set_http_meta(
434-
span,
435-
int_config,
436-
method,
437-
url,
438-
target_host,
439-
status_code,
440-
status_msg,
441-
query,
442-
request_headers,
443-
response_headers,
444-
uri,
445-
path_params,
446-
cookies,
447-
appsec_enabled,
448-
span_type,
449-
):
450-
int_config.myint.http.trace_headers(["my-header"])
451-
int_config.myint.http.trace_query_string = True
452-
span.span_type = span_type
453-
with asm_context(config={"_asm_enabled": appsec_enabled}):
454-
trace_utils.set_http_meta(
455-
span,
456-
int_config.myint,
457-
method=method,
458-
url=url,
459-
target_host=target_host,
460-
status_code=status_code,
461-
status_msg=status_msg,
462-
query=query,
463-
raw_uri=uri,
464-
request_headers=request_headers,
465-
response_headers=response_headers,
466-
request_cookies=cookies,
467-
request_path_params=path_params,
468-
)
469-
if method is not None:
470-
assert span.get_tag(http.METHOD) == method
471-
else:
472-
assert http.METHOD not in span.get_tags()
473-
474-
if target_host is not None:
475-
assert span.get_tag(net.TARGET_HOST) == target_host
476-
else:
477-
assert net.TARGET_HOST not in span.get_tags()
478-
479-
if url is not None:
480-
if url.startswith("http://user"):
481-
# Remove any userinfo that may be in the original url
482-
expected_url = url[: url.index(":")] + "://" + url[url.index("@") + 1 :]
483-
else:
484-
expected_url = url
485-
486-
if query and int_config.myint.http.trace_query_string:
487-
assert span.get_tag(http.URL) == str(expected_url + "?" + query)
488-
else:
489-
assert span.get_tag(http.URL) == str(expected_url)
490-
else:
491-
assert http.URL not in span.get_tags()
492-
493-
if status_code is not None:
494-
assert span.get_tag(http.STATUS_CODE) == str(status_code)
495-
if 500 <= int(status_code) < 600:
496-
assert span.error == 1
497-
else:
498-
assert span.error == 0
499-
else:
500-
assert http.STATUS_CODE not in span.get_tags()
501-
502-
if status_msg is not None:
503-
assert span.get_tag(http.STATUS_MSG) == str(status_msg)
504-
505-
if query is not None and int_config.myint.http.trace_query_string:
506-
assert span.get_tag(http.QUERY_STRING) == query
507-
508-
if request_headers is not None:
509-
for header, value in request_headers.items():
510-
tag = "http.request.headers." + header
511-
assert span.get_tag(tag) == value
512-
513-
514389
@mock.patch("ddtrace.internal.settings._config.log")
515390
@pytest.mark.parametrize(
516391
"error_codes,status_code,error,log_call",

tests/tracer/test_tracer.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
from ddtrace.ext import user
3232
import ddtrace.internal
3333
from ddtrace.internal.compat import PYTHON_VERSION_INFO
34-
from ddtrace.internal.rate_limiter import RateLimiter
3534
from ddtrace.internal.serverless import has_aws_lambda_agent_extension
3635
from ddtrace.internal.serverless import in_aws_lambda
3736
from ddtrace.internal.settings._config import Config
@@ -51,7 +50,6 @@ class TracerTestCases(TracerTestCase):
5150
@pytest.fixture(autouse=True)
5251
def inject_fixtures(self, tracer, caplog):
5352
self._caplog = caplog
54-
self._tracer_appsec = tracer
5553

5654
def test_tracer_vars(self):
5755
span = self.trace("a", service="s", resource="r", span_type="t")
@@ -1842,33 +1840,6 @@ def test_top_level(tracer):
18421840
assert child_span2._is_top_level
18431841

18441842

1845-
@pytest.mark.parametrize("sca_enabled", ["true", "false"])
1846-
@pytest.mark.parametrize("appsec_enabled", [True, False])
1847-
@pytest.mark.parametrize("iast_enabled", [True, False])
1848-
def test_asm_standalone_configuration(sca_enabled, appsec_enabled, iast_enabled):
1849-
if not appsec_enabled and not iast_enabled and sca_enabled == "false":
1850-
pytest.skip("SCA, AppSec or IAST must be enabled")
1851-
1852-
with override_env({"DD_APPSEC_SCA_ENABLED": sca_enabled}):
1853-
ddtrace.config._reset()
1854-
tracer = DummyTracer()
1855-
tracer.configure(appsec_enabled=appsec_enabled, iast_enabled=iast_enabled, apm_tracing_disabled=True)
1856-
if sca_enabled == "true":
1857-
assert bool(ddtrace.config._sca_enabled) is True
1858-
assert tracer.enabled is False
1859-
1860-
assert isinstance(tracer._sampler.limiter, RateLimiter)
1861-
assert tracer._sampler.limiter.rate_limit == 1
1862-
assert tracer._sampler.limiter.time_window == 60e9
1863-
1864-
assert tracer._span_aggregator.sampling_processor._compute_stats_enabled is False
1865-
1866-
# reset tracer values
1867-
with override_env({"DD_APPSEC_SCA_ENABLED": "false"}):
1868-
ddtrace.config._reset()
1869-
tracer.configure(appsec_enabled=False, iast_enabled=False, apm_tracing_disabled=False)
1870-
1871-
18721843
def test_gc_not_used_on_root_spans():
18731844
gc.freeze()
18741845

0 commit comments

Comments
 (0)