From f7573f6d5dc74325f8070053958ccebe6f444e30 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Tue, 4 Jun 2024 18:08:10 +0200 Subject: [PATCH 01/12] initial implementation (without downstream service) --- scenario_groups.yml | 1 + tests/appsec/test_asm_standalone.py | 90 +++++++++++++++++++++++++++++ utils/_context/_scenarios.py | 7 +++ 3 files changed, 98 insertions(+) create mode 100644 tests/appsec/test_asm_standalone.py diff --git a/scenario_groups.yml b/scenario_groups.yml index 7731fa83c3..f6e6de6225 100644 --- a/scenario_groups.yml +++ b/scenario_groups.yml @@ -17,6 +17,7 @@ APPSEC_SCENARIOS: &appsec_scenarios - APPSEC_API_SECURITY - APPSEC_API_SECURITY_NO_RESPONSE_BODY - APPSEC_AUTO_EVENTS_EXTENDED + - APPSEC_STANDALONE # Scenarios covering Remote Configuration REMOTE_CONFIG_SCENARIOS: &remote_config_scenarios diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py new file mode 100644 index 0000000000..3b08bb0275 --- /dev/null +++ b/tests/appsec/test_asm_standalone.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +from utils import weblog, interfaces, scenarios, features +from utils._context.header_tag_vars import * + + +class Test_AppSecPropagation: + """APM correctly propagates AppSec events in distributing tracing.""" + + def setup_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-tags": "_dd.p.other=1", + }, + ) + + @scenarios.appsec_standalone + def test_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): + for _, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == -1 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert "_dd.p.appsec" not in span["meta"] + + def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-tags": "_dd.p.other=1", + "User-Agent": "Arachni/v1", + }, + ) + + @scenarios.appsec_standalone + def test_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): + for _, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 2 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + + def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "2", + "x-datadog-tags": "_dd.p.appsec=1", + }, + ) + + @scenarios.appsec_standalone + def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): + for x, y, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 2 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + + def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "1", + "User-Agent": "Arachni/v1", + }, + ) + + @scenarios.appsec_standalone + def test_trace_any_upstream_propagation_with_attack_raises_priority(self): + for _, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 2 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" diff --git a/utils/_context/_scenarios.py b/utils/_context/_scenarios.py index 4ad2006ddf..20ab4f7d2c 100644 --- a/utils/_context/_scenarios.py +++ b/utils/_context/_scenarios.py @@ -1722,6 +1722,13 @@ def all_endtoend_scenarios(test_object): scenario_groups=[ScenarioGroup.APPSEC], ) + appsec_standalone = EndToEndScenario( + "APPSEC_STANDALONE", + weblog_env={"DD_APPSEC_ENABLED": "true", "DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED": "true"}, + doc="Appsec standalone mode (APM opt out)", + scenario_groups=[ScenarioGroup.APPSEC], + ) + # Remote config scenarios # library timeout is set to 100 seconds # default polling interval for tracers is very low (5 seconds) From 72014d382ed276988f9991c7b4ae3df8a54d7093 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 5 Jun 2024 13:01:52 +0200 Subject: [PATCH 02/12] assert datadog-client-computed-stats header --- tests/appsec/test_asm_standalone.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 3b08bb0275..d04008e8c5 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python3 from utils import weblog, interfaces, scenarios, features from utils._context.header_tag_vars import * +@scenarios.appsec_standalone class Test_AppSecPropagation: """APM correctly propagates AppSec events in distributing tracing.""" @@ -19,13 +19,14 @@ def setup_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): }, ) - @scenarios.appsec_standalone def test_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): - for _, _, span in interfaces.library.get_spans(request=self.r): + for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == -1 assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] + assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): trace_id = 1212121212121212121 parent_id = 34343434 @@ -40,13 +41,14 @@ def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): }, ) - @scenarios.appsec_standalone def test_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): - for _, _, span in interfaces.library.get_spans(request=self.r): + for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): trace_id = 1212121212121212121 parent_id = 34343434 @@ -61,13 +63,14 @@ def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): }, ) - @scenarios.appsec_standalone def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): - for x, y, span in interfaces.library.get_spans(request=self.r): + for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): trace_id = 1212121212121212121 parent_id = 34343434 @@ -82,9 +85,10 @@ def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): }, ) - @scenarios.appsec_standalone def test_trace_any_upstream_propagation_with_attack_raises_priority(self): - for _, _, span in interfaces.library.get_spans(request=self.r): + for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + + assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] From d8c1c69a1ad7bd12b65cbdab2127098f01abf9a5 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 5 Jun 2024 13:08:44 +0200 Subject: [PATCH 03/12] add upstream drop priority test --- tests/appsec/test_asm_standalone.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index d04008e8c5..74c66071fc 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -92,3 +92,25 @@ def test_trace_any_upstream_propagation_with_attack_raises_priority(self): assert span["meta"]["_dd.p.appsec"] == "1" assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + + def setup_trace_drop_upstream_propagation_with_attack_raises_priority(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "-1", + "User-Agent": "Arachni/v1", + }, + ) + + def test_trace_drop_upstream_propagation_with_attack_raises_priority(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 2 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + + assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] From b6b114d45f276ae230a0d34de5c7719f77617ec2 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 5 Jun 2024 14:50:13 +0200 Subject: [PATCH 04/12] support for tracers that send true --- tests/appsec/test_asm_standalone.py | 50 ++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 74c66071fc..7a21aa4d92 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -25,7 +25,15 @@ def test_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] - assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + # Some tracers use true while others use yes + assert any( + [ + "Datadog-Client-Computed-Stats", + trueish, + ] + in data["request"]["headers"] + for trueish in ["yes", "true"] + ) def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): trace_id = 1212121212121212121 @@ -47,7 +55,15 @@ def test_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + # Some tracers use true while others use yes + assert any( + [ + "Datadog-Client-Computed-Stats", + trueish, + ] + in data["request"]["headers"] + for trueish in ["yes", "true"] + ) def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): trace_id = 1212121212121212121 @@ -69,7 +85,15 @@ def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + # Some tracers use true while others use yes + assert any( + [ + "Datadog-Client-Computed-Stats", + trueish, + ] + in data["request"]["headers"] + for trueish in ["yes", "true"] + ) def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): trace_id = 1212121212121212121 @@ -91,7 +115,15 @@ def test_trace_any_upstream_propagation_with_attack_raises_priority(self): assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + # Some tracers use true while others use yes + assert any( + [ + "Datadog-Client-Computed-Stats", + trueish, + ] + in data["request"]["headers"] + for trueish in ["yes", "true"] + ) def setup_trace_drop_upstream_propagation_with_attack_raises_priority(self): trace_id = 1212121212121212121 @@ -113,4 +145,12 @@ def test_trace_drop_upstream_propagation_with_attack_raises_priority(self): assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - assert ["Datadog-Client-Computed-Stats", "yes"] in data["request"]["headers"] + # Some tracers use true while others use yes + assert any( + [ + "Datadog-Client-Computed-Stats", + trueish, + ] + in data["request"]["headers"] + for trueish in ["yes", "true"] + ) From ce308721f4d06662883a5b6041a4ae42d258a48c Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 6 Jun 2024 16:29:40 +0200 Subject: [PATCH 05/12] improve tests --- tests/appsec/test_asm_standalone.py | 46 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 7a21aa4d92..533d782253 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -1,11 +1,45 @@ from utils import weblog, interfaces, scenarios, features from utils._context.header_tag_vars import * +import time @scenarios.appsec_standalone class Test_AppSecPropagation: """APM correctly propagates AppSec events in distributing tracing.""" + def setup_trace_no_upstream_no_attack_is_kept_by_rate_limiter_minimum(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + # Ensure this is the first span received in 60 seconds + time.sleep(60) + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-tags": "_dd.p.other=1", + }, + ) + + def test_trace_no_upstream_no_attack_is_kept_by_rate_limiter_minimum(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] >= 1 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert "_dd.p.appsec" not in span["meta"] + assert "_dd.p.other" not in span["meta"] + assert span["trace_id"] != 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + [ + "Datadog-Client-Computed-Stats", + trueish, + ] + in data["request"]["headers"] + for trueish in ["yes", "true"] + ) + def setup_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): trace_id = 1212121212121212121 parent_id = 34343434 @@ -23,6 +57,7 @@ def test_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == -1 assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["trace_id"] != 1212121212121212121 assert "_dd.p.appsec" not in span["meta"] # Some tracers use true while others use yes @@ -54,6 +89,8 @@ def test_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + # A new distributed trace is created because of no appsec upstream + assert span["trace_id"] != 1212121212121212121 # Some tracers use true while others use yes assert any( @@ -84,6 +121,7 @@ def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + assert span["trace_id"] == 1212121212121212121 # Some tracers use true while others use yes assert any( @@ -114,6 +152,8 @@ def test_trace_any_upstream_propagation_with_attack_raises_priority(self): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + # A new distributed trace is created because of no appsec upstream + assert span["trace_id"] != 1212121212121212121 # Some tracers use true while others use yes assert any( @@ -125,7 +165,7 @@ def test_trace_any_upstream_propagation_with_attack_raises_priority(self): for trueish in ["yes", "true"] ) - def setup_trace_drop_upstream_propagation_with_attack_raises_priority(self): + def setup_trace_drop_upstream_propagation_with_attack_is_not_honored(self): trace_id = 1212121212121212121 parent_id = 34343434 self.r = weblog.get( @@ -139,11 +179,13 @@ def setup_trace_drop_upstream_propagation_with_attack_raises_priority(self): }, ) - def test_trace_drop_upstream_propagation_with_attack_raises_priority(self): + def test_trace_drop_upstream_propagation_with_attack_is_not_honored(self): for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" + # A new distributed trace is created because of no appsec upstream + assert span["trace_id"] != 1212121212121212121 # Some tracers use true while others use yes assert any( From cd2d0a8461b919d5bab7d2715f17984a545b6927 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Fri, 7 Jun 2024 11:15:03 +0200 Subject: [PATCH 06/12] fix lint --- tests/appsec/test_asm_standalone.py | 42 +++++------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 533d782253..112c1359bd 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -32,12 +32,7 @@ def test_trace_no_upstream_no_attack_is_kept_by_rate_limiter_minimum(self): # Some tracers use true while others use yes assert any( - [ - "Datadog-Client-Computed-Stats", - trueish, - ] - in data["request"]["headers"] - for trueish in ["yes", "true"] + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) def setup_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): @@ -62,12 +57,7 @@ def test_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): # Some tracers use true while others use yes assert any( - [ - "Datadog-Client-Computed-Stats", - trueish, - ] - in data["request"]["headers"] - for trueish in ["yes", "true"] + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): @@ -94,12 +84,7 @@ def test_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): # Some tracers use true while others use yes assert any( - [ - "Datadog-Client-Computed-Stats", - trueish, - ] - in data["request"]["headers"] - for trueish in ["yes", "true"] + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): @@ -125,12 +110,7 @@ def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): # Some tracers use true while others use yes assert any( - [ - "Datadog-Client-Computed-Stats", - trueish, - ] - in data["request"]["headers"] - for trueish in ["yes", "true"] + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): @@ -157,12 +137,7 @@ def test_trace_any_upstream_propagation_with_attack_raises_priority(self): # Some tracers use true while others use yes assert any( - [ - "Datadog-Client-Computed-Stats", - trueish, - ] - in data["request"]["headers"] - for trueish in ["yes", "true"] + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) def setup_trace_drop_upstream_propagation_with_attack_is_not_honored(self): @@ -189,10 +164,5 @@ def test_trace_drop_upstream_propagation_with_attack_is_not_honored(self): # Some tracers use true while others use yes assert any( - [ - "Datadog-Client-Computed-Stats", - trueish, - ] - in data["request"]["headers"] - for trueish in ["yes", "true"] + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) From ee273a3934bdea03f97ba0d33969138e7c07cab9 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Fri, 7 Jun 2024 12:32:39 +0200 Subject: [PATCH 07/12] extend coverage, fix tests --- tests/appsec/test_asm_standalone.py | 221 ++++++++++++++++++++++++---- utils/_features.py | 10 ++ 2 files changed, 201 insertions(+), 30 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 112c1359bd..457b32ed45 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -1,41 +1,70 @@ -from utils import weblog, interfaces, scenarios, features +from utils import weblog, interfaces, scenarios, features, rfc from utils._context.header_tag_vars import * -import time +@rfc("https://docs.google.com/document/d/12NBx-nD-IoQEMiCRnJXneq4Be7cbtSc6pJLOFUWTpNE/edit") +@features.appsec_standalone @scenarios.appsec_standalone -class Test_AppSecPropagation: +class Test_AppSecStandalone_UpstreamPropagation: """APM correctly propagates AppSec events in distributing tracing.""" - def setup_trace_no_upstream_no_attack_is_kept_by_rate_limiter_minimum(self): + # TODO downstream propagation + + def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_minus_1(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-sampling-priority": "-1", + "x-datadog-origin": "rum", + "x-datadog-tags": "_dd.p.other=1", + }, + ) + + def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_minus_1(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert "_dd.p.appsec" not in span["meta"] + assert "_dd.p.other" in span["meta"] + assert span["trace_id"] == 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] + ) + + def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_0(self): trace_id = 1212121212121212121 parent_id = 34343434 - # Ensure this is the first span received in 60 seconds - time.sleep(60) self.r = weblog.get( "/waf/", headers={ "x-datadog-trace-id": str(trace_id), "x-datadog-parent-id": str(parent_id), + "x-datadog-sampling-priority": "0", "x-datadog-origin": "rum", "x-datadog-tags": "_dd.p.other=1", }, ) - def test_trace_no_upstream_no_attack_is_kept_by_rate_limiter_minimum(self): + def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_0(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] >= 1 + assert span["metrics"]["_sampling_priority_v1"] == 1 assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] - assert "_dd.p.other" not in span["meta"] - assert span["trace_id"] != 1212121212121212121 + assert "_dd.p.other" in span["meta"] + assert span["trace_id"] == 1212121212121212121 # Some tracers use true while others use yes assert any( ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) - def setup_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): + def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_1(self): trace_id = 1212121212121212121 parent_id = 34343434 self.r = weblog.get( @@ -43,24 +72,26 @@ def setup_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): headers={ "x-datadog-trace-id": str(trace_id), "x-datadog-parent-id": str(parent_id), + "x-datadog-sampling-priority": "1", "x-datadog-origin": "rum", "x-datadog-tags": "_dd.p.other=1", }, ) - def test_trace_no_upstream_appsec_propagation_no_attack_is_dropped(self): + def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_1(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == -1 + assert span["metrics"]["_sampling_priority_v1"] == 1 assert span["metrics"]["_dd.apm.enabled"] == 0 - assert span["trace_id"] != 1212121212121212121 assert "_dd.p.appsec" not in span["meta"] + assert "_dd.p.other" in span["meta"] + assert span["trace_id"] == 1212121212121212121 # Some tracers use true while others use yes assert any( ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) - def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): + def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_2(self): trace_id = 1212121212121212121 parent_id = 34343434 self.r = weblog.get( @@ -68,26 +99,132 @@ def setup_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): headers={ "x-datadog-trace-id": str(trace_id), "x-datadog-parent-id": str(parent_id), + "x-datadog-sampling-priority": "2", "x-datadog-origin": "rum", "x-datadog-tags": "_dd.p.other=1", + }, + ) + + def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_2(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert "_dd.p.appsec" not in span["meta"] + assert "_dd.p.other" in span["meta"] + assert span["trace_id"] == 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] + ) + + def setup_no_upstream_appsec_propagation__with_attack__is_kept_with_priority_2__from_minus_1(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "-1", + "x-datadog-tags": "_dd.p.other=1", "User-Agent": "Arachni/v1", }, ) - def test_trace_no_upstream_appsec_propagation_with_attack_is_kept(self): + def test_no_upstream_appsec_propagation__with_attack__is_kept_with_priority_2__from_minus_1(self): for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - # A new distributed trace is created because of no appsec upstream - assert span["trace_id"] != 1212121212121212121 + assert span["trace_id"] == 1212121212121212121 # Some tracers use true while others use yes assert any( ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) - def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): + def setup_no_upstream_appsec_propagation__with_attack__is_kept_with_priority_2__from_0(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "0", + "x-datadog-tags": "_dd.p.other=1", + "User-Agent": "Arachni/v1", + }, + ) + + def test_no_upstream_appsec_propagation__with_attack__is_kept_with_priority_2__from_0(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 2 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + assert span["trace_id"] == 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] + ) + + def setup_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_0(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "0", + "x-datadog-tags": "_dd.p.appsec=1", + }, + ) + + def test_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_0(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 0 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + assert span["trace_id"] == 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] + ) + + def setup_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_1(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "1", + "x-datadog-tags": "_dd.p.appsec=1", + }, + ) + + def test_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_1(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + assert span["trace_id"] == 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] + ) + + def setup_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_2(self): trace_id = 1212121212121212121 parent_id = 34343434 self.r = weblog.get( @@ -101,7 +238,7 @@ def setup_trace_upstream_appsec_propagation_no_attack_is_propagated(self): }, ) - def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): + def test_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_2(self): for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 @@ -113,7 +250,7 @@ def test_trace_upstream_appsec_propagation_no_attack_is_propagated(self): ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) - def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): + def setup_any_upstream_propagation__with_attack__raises_priority_to_2__from_minus_1(self): trace_id = 1212121212121212121 parent_id = 34343434 self.r = weblog.get( @@ -122,25 +259,24 @@ def setup_trace_any_upstream_propagation_with_attack_raises_priority(self): "x-datadog-trace-id": str(trace_id), "x-datadog-parent-id": str(parent_id), "x-datadog-origin": "rum", - "x-datadog-sampling-priority": "1", + "x-datadog-sampling-priority": "-1", "User-Agent": "Arachni/v1", }, ) - def test_trace_any_upstream_propagation_with_attack_raises_priority(self): + def test_any_upstream_propagation__with_attack__raises_priority_to_2__from_minus_1(self): for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - # A new distributed trace is created because of no appsec upstream - assert span["trace_id"] != 1212121212121212121 + assert span["trace_id"] == 1212121212121212121 # Some tracers use true while others use yes assert any( ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] ) - def setup_trace_drop_upstream_propagation_with_attack_is_not_honored(self): + def setup_any_upstream_propagation__with_attack__raises_priority_to_2__from_0(self): trace_id = 1212121212121212121 parent_id = 34343434 self.r = weblog.get( @@ -149,18 +285,43 @@ def setup_trace_drop_upstream_propagation_with_attack_is_not_honored(self): "x-datadog-trace-id": str(trace_id), "x-datadog-parent-id": str(parent_id), "x-datadog-origin": "rum", - "x-datadog-sampling-priority": "-1", + "x-datadog-sampling-priority": "0", "User-Agent": "Arachni/v1", }, ) - def test_trace_drop_upstream_propagation_with_attack_is_not_honored(self): + def test_any_upstream_propagation__with_attack__raises_priority_to_2__from_0(self): for data, _, span in interfaces.library.get_spans(request=self.r): assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" - # A new distributed trace is created because of no appsec upstream - assert span["trace_id"] != 1212121212121212121 + assert span["trace_id"] == 1212121212121212121 + + # Some tracers use true while others use yes + assert any( + ["Datadog-Client-Computed-Stats", trueish,] in data["request"]["headers"] for trueish in ["yes", "true"] + ) + + def setup_any_upstream_propagation__with_attack__raises_priority_to_2__from_1(self): + trace_id = 1212121212121212121 + parent_id = 34343434 + self.r = weblog.get( + "/waf/", + headers={ + "x-datadog-trace-id": str(trace_id), + "x-datadog-parent-id": str(parent_id), + "x-datadog-origin": "rum", + "x-datadog-sampling-priority": "0", + "User-Agent": "Arachni/v1", + }, + ) + + def test_any_upstream_propagation__with_attack__raises_priority_to_2__from_1(self): + for data, _, span in interfaces.library.get_spans(request=self.r): + assert span["metrics"]["_sampling_priority_v1"] == 2 + assert span["metrics"]["_dd.apm.enabled"] == 0 + assert span["meta"]["_dd.p.appsec"] == "1" + assert span["trace_id"] == 1212121212121212121 # Some tracers use true while others use yes assert any( diff --git a/utils/_features.py b/utils/_features.py index 5a9b515ef5..9626cfb789 100644 --- a/utils/_features.py +++ b/utils/_features.py @@ -2186,3 +2186,13 @@ def rasp_span_tags(test_object): """ pytest.mark.features(feature_id=298)(test_object) return test_object + + @staticmethod + def appsec_standalone(test_object): + """ + Appsec Standalone Billing + + https://feature-parity.us1.prod.dog/#/?feature=305 + """ + pytest.mark.features(feature_id=305)(test_object) + return test_object From 9fb53c1f7d8c731cc67e038c56f3b95b2feb603d Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Fri, 7 Jun 2024 13:47:09 +0200 Subject: [PATCH 08/12] loosen sampling priority result --- tests/appsec/test_asm_standalone.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 457b32ed45..521c1af4fd 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -26,7 +26,7 @@ def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_minus_1(s def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_minus_1(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_sampling_priority_v1"] < 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] assert "_dd.p.other" in span["meta"] @@ -53,7 +53,7 @@ def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_0(self): def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_0(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_sampling_priority_v1"] < 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] assert "_dd.p.other" in span["meta"] @@ -80,7 +80,7 @@ def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_1(self): def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_1(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_sampling_priority_v1"] < 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] assert "_dd.p.other" in span["meta"] @@ -107,7 +107,7 @@ def setup_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_2(self): def test_no_appsec_upstream__no_attack__is_kept_with_priority_1__from_2(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_sampling_priority_v1"] < 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert "_dd.p.appsec" not in span["meta"] assert "_dd.p.other" in span["meta"] From 0b2f2dff4847469fef40af181b074c1d87dc20c0 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Fri, 7 Jun 2024 15:39:40 +0200 Subject: [PATCH 09/12] updated to latest changes --- tests/appsec/test_asm_standalone.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/appsec/test_asm_standalone.py b/tests/appsec/test_asm_standalone.py index 521c1af4fd..3f566e1514 100644 --- a/tests/appsec/test_asm_standalone.py +++ b/tests/appsec/test_asm_standalone.py @@ -188,7 +188,7 @@ def setup_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_0(s def test_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_0(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == 0 + assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" assert span["trace_id"] == 1212121212121212121 @@ -214,7 +214,7 @@ def setup_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_1(s def test_upstream_appsec_propagation__no_attack__is_propagated_as_is__being_1(self): for data, _, span in interfaces.library.get_spans(request=self.r): - assert span["metrics"]["_sampling_priority_v1"] == 1 + assert span["metrics"]["_sampling_priority_v1"] == 2 assert span["metrics"]["_dd.apm.enabled"] == 0 assert span["meta"]["_dd.p.appsec"] == "1" assert span["trace_id"] == 1212121212121212121 From fb0c6de12db2966350565fbe40e2b027522c565d Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Mon, 10 Jun 2024 09:30:20 +0200 Subject: [PATCH 10/12] add test to manifest --- manifests/cpp.yml | 1 + manifests/dotnet.yml | 2 ++ manifests/golang.yml | 2 ++ manifests/java.yml | 2 ++ manifests/nodejs.yml | 2 ++ manifests/python.yml | 2 ++ 6 files changed, 11 insertions(+) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 3ad483a8bd..ddbe60641e 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -66,6 +66,7 @@ tests/: test_telemetry.py: irrelevant (ASM is not implemented in C++) test_PII.py: irrelevant (ASM is not implemented in C++) test_alpha.py: irrelevant (ASM is not implemented in C++) + test_asm_standalone.py: irrelevant (ASM is not implemented in C++) test_automated_login_events.py: irrelevant (ASM is not implemented in C++) test_blocking_addresses.py: irrelevant (ASM is not implemented in C++) test_client_ip.py: irrelevant (ASM is not implemented in C++) diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index b1e40f842d..554b8650d7 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -170,6 +170,8 @@ tests/: Test_Scrubbing: missing_feature test_alpha.py: Test_Basic: v1.28.6 + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: v2.32.0 Test_Login_Events_Extended: v2.33.0 diff --git a/manifests/golang.yml b/manifests/golang.yml index 3e537747d3..2fd4988152 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -241,6 +241,8 @@ tests/: chi: v1.36.0 echo: v1.36.0 gin: v1.37.0 + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: missing_feature Test_Login_Events_Extended: missing_feature diff --git a/manifests/java.yml b/manifests/java.yml index b2a8533c53..c4df3187d6 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -576,6 +576,8 @@ tests/: '*': v0.87.0 akka-http: v1.22.0 spring-boot-3-native: missing_feature (GraalVM. Tracing support only) + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: missing_feature Test_Login_Events_Extended: missing_feature diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 01406a850d..110c9e405f 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -269,6 +269,8 @@ tests/: Test_Scrubbing: missing_feature test_alpha.py: Test_Basic: v2.0.0 + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: '*': *ref_4_4_0 diff --git a/manifests/python.yml b/manifests/python.yml index c4c95967fc..a6e97538db 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -343,6 +343,8 @@ tests/: Test_Basic: '*': v1.1.0rc2.dev fastapi: v2.4.0.dev1 + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: '*': v2.10.0.dev From 6effcf0fef1688d4e6ceb0dcd7063d91840cfaf3 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Mon, 10 Jun 2024 14:43:07 +0200 Subject: [PATCH 11/12] add scenario to end-to-end workflow --- .github/workflows/run-end-to-end.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/run-end-to-end.yml b/.github/workflows/run-end-to-end.yml index 2d568fa6ae..8f80fc7377 100644 --- a/.github/workflows/run-end-to-end.yml +++ b/.github/workflows/run-end-to-end.yml @@ -269,6 +269,11 @@ jobs: run: ./run.sh APPSEC_RASP env: DD_API_KEY: ${{ secrets.DD_API_KEY }} + - name: Run APPSEC_STANDALONE scenario + if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_STANDALONE"') + run: ./run.sh APPSEC_STANDALONE + env: + DD_API_KEY: ${{ secrets.DD_API_KEY }} - name: Run SAMPLING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"SAMPLING"') run: ./run.sh SAMPLING From 83081eab7791c826c04fd2a6d8e65ec83cc579b6 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Mon, 10 Jun 2024 18:09:46 +0200 Subject: [PATCH 12/12] php and ruby manifests --- manifests/php.yml | 2 ++ manifests/ruby.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/manifests/php.yml b/manifests/php.yml index 0855b00677..bd71a5039d 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -160,6 +160,8 @@ tests/: Test_TelemetryMetrics: missing_feature test_PII.py: Test_Scrubbing: missing_feature + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: v0.89.0 Test_Login_Events_Extended: v0.89.0 diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 7f67c61d30..853c89de25 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -148,6 +148,8 @@ tests/: Test_TelemetryMetrics: missing_feature test_PII.py: Test_Scrubbing: missing_feature + test_asm_standalone.py: + Test_AppSecStandalone_UpstreamPropagation: missing_feature test_automated_login_events.py: Test_Login_Events: '*': v1.13.0