Skip to content

Commit 3b56d9f

Browse files
tylfinwatson
andauthored
Excluding PII identifiers should work for DI tracers (#4564)
Co-authored-by: Thomas Watson <[email protected]>
1 parent 1689a73 commit 3b56d9f

File tree

10 files changed

+82
-23
lines changed

10 files changed

+82
-23
lines changed

manifests/cpp_nginx.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ tests/:
5353
Test_Debugger_InProduct_Enablement_Exception_Replay: irrelevant
5454
test_debugger_pii.py:
5555
Test_Debugger_PII_Redaction: irrelevant
56+
Test_Debugger_PII_Redaction_Excluded_Identifiers: irrelevant
5657
test_debugger_probe_budgets.py:
5758
Test_Debugger_Probe_Budgets: irrelevant
5859
test_debugger_probe_snapshot.py:

manifests/dotnet.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ tests/:
430430
Test_Debugger_InProduct_Enablement_Exception_Replay: missing_feature
431431
test_debugger_pii.py:
432432
Test_Debugger_PII_Redaction: v2.50.0
433+
Test_Debugger_PII_Redaction_Excluded_Identifiers: v2.50.0
433434
test_debugger_probe_budgets.py:
434435
Test_Debugger_Probe_Budgets: v2.53.0
435436
test_debugger_probe_snapshot.py:

manifests/golang.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ tests/:
513513
Test_Debugger_InProduct_Enablement_Exception_Replay: missing_feature
514514
test_debugger_pii.py:
515515
Test_Debugger_PII_Redaction: missing_feature (feature not implented)
516+
Test_Debugger_PII_Redaction_Excluded_Identifiers: missing_feature (feature not implented)
516517
test_debugger_probe_budgets.py:
517518
Test_Debugger_Probe_Budgets: missing_feature (feature not implented)
518519
test_debugger_probe_snapshot.py:

manifests/java.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,15 @@ tests/:
17471747
spring-boot-undertow: v1.38.0
17481748
spring-boot-wildfly: v1.38.0
17491749
uds-spring-boot: v1.33.0
1750+
Test_Debugger_PII_Redaction_Excluded_Identifiers:
1751+
'*': missing_feature
1752+
spring-boot: v1.49.0
1753+
spring-boot-jetty: v1.49.0
1754+
spring-boot-openliberty: v1.49.0
1755+
spring-boot-payara: v1.49.0
1756+
spring-boot-undertow: v1.49.0
1757+
spring-boot-wildfly: v1.49.0
1758+
uds-spring-boot: v1.49.0
17501759
test_debugger_probe_budgets.py:
17511760
Test_Debugger_Probe_Budgets:
17521761
'*': missing_feature

manifests/nodejs.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,11 @@ tests/:
829829
express4: v5.39.0
830830
express4-typescript: v5.39.0
831831
uds-express4: v5.39.0
832+
Test_Debugger_PII_Redaction_Excluded_Identifiers:
833+
'*': irrelevant
834+
express4: v5.39.0
835+
express4-typescript: v5.39.0
836+
uds-express4: v5.39.0
832837
test_debugger_probe_budgets.py:
833838
Test_Debugger_Probe_Budgets: missing_feature
834839
test_debugger_probe_snapshot.py:

manifests/php.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ tests/:
417417
Test_Debugger_InProduct_Enablement_Exception_Replay: missing_feature
418418
test_debugger_pii.py:
419419
Test_Debugger_PII_Redaction: missing_feature
420+
Test_Debugger_PII_Redaction_Excluded_Identifiers: missing_feature
420421
test_debugger_probe_budgets.py:
421422
Test_Debugger_Probe_Budgets: missing_feature
422423
test_debugger_probe_snapshot.py:

manifests/python.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,11 @@ tests/:
761761
flask-poc: v2.11.0
762762
uds-flask: v2.11.0
763763
uwsgi-poc: v2.11.0
764+
Test_Debugger_PII_Redaction_Excluded_Identifiers:
765+
'*': missing_feature
766+
flask-poc: v3.7.0
767+
uds-flask: v3.7.0
768+
uwsgi-poc: v3.7.0
764769
test_debugger_probe_budgets.py:
765770
Test_Debugger_Probe_Budgets:
766771
'*': missing_feature

manifests/ruby.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ tests/:
585585
rails70: v2.8.0
586586
rails80: v2.8.0
587587
uds-rails: v2.12.0
588+
Test_Debugger_PII_Redaction_Excluded_Identifiers: missing_feature
588589
test_debugger_probe_budgets.py:
589590
Test_Debugger_Probe_Budgets:
590591
"*": irrelevant

tests/debugger/test_debugger_pii.py

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@
111111

112112

113113
@features.debugger_pii_redaction
114-
@scenarios.debugger_pii_redaction
115-
class Test_Debugger_PII_Redaction(debugger.BaseDebuggerTest):
114+
class BaseDebuggerPIIRedactionTest(debugger.BaseDebuggerTest):
116115
############ setup ############
117116
def _setup(self, *, line_probe=False):
118117
self.initialize_weblog_remote_config()
@@ -129,31 +128,34 @@ def _setup(self, *, line_probe=False):
129128
self.wait_for_all_probes(statuses=["EMITTING"])
130129

131130
############ assert ############
132-
def _assert(self, redacted_keys, redacted_types, *, line_probe=False):
131+
def _assert(self, excluded_identifiers=None, *, line_probe=False):
133132
self.collect()
134133
self.assert_setup_ok()
135134
self.assert_rc_state_not_error()
136135
self.assert_all_probes_are_emitting()
137136
self.assert_all_weblog_responses_ok()
138137

139-
self._validate_pii_keyword_redaction(redacted_keys, line_probe)
138+
self._validate_pii_keyword_redaction(excluded_identifiers, line_probe)
140139
if context.library != "nodejs": # Node.js does not support type redacting
141-
self._validate_pii_type_redaction(redacted_types, line_probe)
140+
self._validate_pii_type_redaction(line_probe)
142141

143-
def _validate_pii_keyword_redaction(self, should_redact_field_names, line_probe):
142+
def _validate_pii_keyword_redaction(self, excluded_identifiers, line_probe):
144143
not_redacted = []
145-
not_found = list(set(should_redact_field_names))
144+
not_found = list(set(REDACTED_KEYS))
145+
improperly_redacted = []
146+
excluded_identifiers = excluded_identifiers if excluded_identifiers else []
146147

147148
for probe_id in self.probe_ids:
148149
base = self.probe_snapshots[probe_id][0]
149150
snapshot = base.get("debugger", {}).get("snapshot") or base["debugger.snapshot"]
150151

151-
for field_name in should_redact_field_names:
152-
if line_probe:
153-
fields = snapshot["captures"]["lines"]["64"]["locals"]["pii"]["fields"]
154-
else:
155-
fields = snapshot["captures"]["return"]["locals"]["pii"]["fields"]
152+
if line_probe:
153+
fields = snapshot["captures"]["lines"]["64"]["locals"]["pii"]["fields"]
154+
else:
155+
fields = snapshot["captures"]["return"]["locals"]["pii"]["fields"]
156156

157+
# Check if fields that should be redacted are properly redacted
158+
for field_name in set(REDACTED_KEYS):
157159
if context.library == "ruby":
158160
check_field_name = "@" + field_name
159161
else:
@@ -162,29 +164,40 @@ def _validate_pii_keyword_redaction(self, should_redact_field_names, line_probe)
162164
if check_field_name in fields:
163165
not_found.remove(field_name)
164166

165-
if "value" in fields[check_field_name]:
167+
# Fields not included in excluded_identifiers should not have values
168+
if "value" in fields[check_field_name] and field_name not in excluded_identifiers:
166169
not_redacted.append(field_name)
167170

168-
error_message = ""
171+
# Fields included in excluded_identifiers should have values
172+
if "value" not in fields[check_field_name] and field_name in excluded_identifiers:
173+
improperly_redacted.append(field_name)
174+
175+
error_message = []
169176
if not_redacted:
170177
not_redacted.sort()
171-
error_message = "Fields not properly redacted: " + "".join([f"{item}, " for item in not_redacted])
178+
error_message.append("Fields not properly redacted: " + "".join([f"{item}, " for item in not_redacted]))
172179

173180
if not_found:
174181
not_found.sort()
175-
error_message += ". Fields not found: " + "".join([f"{item}, " for item in not_found])
182+
error_message.append("Fields not found: " + "".join([f"{item}, " for item in not_found]))
176183

177-
if error_message != "":
178-
raise ValueError(error_message)
184+
if improperly_redacted:
185+
improperly_redacted.sort()
186+
error_message.append(
187+
"Excluded fields improperly redacted: " + "".join([f"{item}, " for item in improperly_redacted])
188+
)
179189

180-
def _validate_pii_type_redaction(self, should_redact_types, line_probe):
190+
if error_message:
191+
raise ValueError(". ".join(error_message))
192+
193+
def _validate_pii_type_redaction(self, line_probe):
181194
not_redacted = []
182195

183196
for probe_id in self.probe_ids:
184197
base = self.probe_snapshots[probe_id][0]
185198
snapshot = base.get("debugger", {}).get("snapshot") or base["debugger.snapshot"]
186199

187-
for type_name in should_redact_types:
200+
for type_name in REDACTED_TYPES:
188201
if line_probe:
189202
type_info = snapshot["captures"]["lines"]["64"]["locals"][type_name]
190203
else:
@@ -196,11 +209,14 @@ def _validate_pii_type_redaction(self, should_redact_types, line_probe):
196209
error_message = ""
197210
if not_redacted:
198211
not_redacted.sort()
199-
error_message = "Types not properly redacted: " + "".join([f"{item}, " for item in not_redacted])
212+
error_message += "Types not properly redacted: " + "".join([f"{item}, " for item in not_redacted])
200213

201214
if error_message != "":
202215
raise ValueError(error_message)
203216

217+
218+
@scenarios.debugger_pii_redaction
219+
class Test_Debugger_PII_Redaction(BaseDebuggerPIIRedactionTest):
204220
############ test ############
205221
### method ###
206222
def setup_pii_redaction_method_full(self):
@@ -215,11 +231,25 @@ def setup_pii_redaction_method_full(self):
215231
)
216232
@missing_feature(context.library == "nodejs", reason="Not yet implemented", force_skip=True)
217233
def test_pii_redaction_method_full(self):
218-
self._assert(REDACTED_KEYS, REDACTED_TYPES)
234+
self._assert()
219235

220236
### line ###
221237
def setup_pii_redaction_line_full(self):
222238
self._setup(line_probe=True)
223239

224240
def test_pii_redaction_line_full(self):
225-
self._assert(REDACTED_KEYS, REDACTED_TYPES, line_probe=True)
241+
self._assert(line_probe=True)
242+
243+
244+
@scenarios.tracing_config_nondefault_4
245+
class Test_Debugger_PII_Redaction_Excluded_Identifiers(BaseDebuggerPIIRedactionTest):
246+
### excluded identifiers ###
247+
def setup_pii_redaction_excluded_identifiers(self):
248+
self._setup(line_probe=True)
249+
250+
@bug(context.library == "java", reason="DEBUG-3745")
251+
@bug(context.library == "ruby", reason="DEBUG-3747")
252+
@bug(context.library == "python", reason="DEBUG-3746")
253+
def test_pii_redaction_excluded_identifiers(self):
254+
excluded_identifiers = ["_2fa", "cookie", "sessionid"]
255+
self._assert(excluded_identifiers, line_probe=True)

utils/_context/_scenarios/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,10 +644,15 @@ class _Scenarios:
644644
tracing_config_nondefault_4 = EndToEndScenario(
645645
"TRACING_CONFIG_NONDEFAULT_4",
646646
weblog_env={
647+
"DD_DYNAMIC_INSTRUMENTATION_ENABLED": "true",
648+
"DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS": "customidentifier1,customidentifier2",
649+
"DD_DYNAMIC_INSTRUMENTATION_REDACTED_TYPES": "weblog.Models.Debugger.CustomPii,com.datadoghq.system_tests.springboot.CustomPii,CustomPii", # noqa: E501
650+
"DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS": "_2fa,cookie,sessionid",
647651
"DD_LOGS_INJECTION": "true",
648652
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": "false",
649653
},
650654
doc="",
655+
rc_api_enabled=True,
651656
)
652657

653658
parametric = ParametricScenario("PARAMETRIC", doc="WIP")

0 commit comments

Comments
 (0)