Skip to content

Commit ad49abc

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add SDS rule should_save_match field (#2704)
Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 69ea97c commit ad49abc

File tree

7 files changed

+346
-2
lines changed

7 files changed

+346
-2
lines changed

.generated-info

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"spec_repo_commit": "98e3371",
3-
"generated": "2025-08-27 08:47:10.789"
2+
"spec_repo_commit": "62a19e4",
3+
"generated": "2025-08-27 15:03:12.722"
44
}

.generator/schemas/v2/openapi.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39445,6 +39445,12 @@ components:
3944539445
replacement_string:
3944639446
description: Required if type == 'replacement_string'.
3944739447
type: string
39448+
should_save_match:
39449+
description: "Only valid when type == `replacement_string`. When enabled,
39450+
matches can be unmasked in logs by users with \u2018Data Scanner Unmask\u2019
39451+
permission. As a security best practice, avoid masking for highly-sensitive,
39452+
long-lived data."
39453+
type: boolean
3944839454
type:
3944939455
$ref: '#/components/schemas/SensitiveDataScannerTextReplacementType'
3945039456
type: object
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"2025-08-26T20:31:44.042Z"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
{
2+
"log": {
3+
"_recordingName": "Sensitive Data Scanner/Create Scanning Rule with should_save_match returns \"OK\" response",
4+
"creator": {
5+
"comment": "persister:fs",
6+
"name": "Polly.JS",
7+
"version": "6.0.5"
8+
},
9+
"entries": [
10+
{
11+
"_id": "01611a935e7406303c51f707c3b51e78",
12+
"_order": 0,
13+
"cache": {},
14+
"request": {
15+
"bodySize": 0,
16+
"cookies": [],
17+
"headers": [
18+
{
19+
"_fromType": "array",
20+
"name": "accept",
21+
"value": "application/json"
22+
}
23+
],
24+
"headersSize": 528,
25+
"httpVersion": "HTTP/1.1",
26+
"method": "GET",
27+
"queryString": [],
28+
"url": "https://api.datadoghq.com/api/v2/sensitive-data-scanner/config"
29+
},
30+
"response": {
31+
"bodySize": 465,
32+
"content": {
33+
"mimeType": "application/json",
34+
"size": 465,
35+
"text": "{\"data\":{\"id\":\"7957915c634d4dcb581fa154157f5ad9c2947f50be632fb5599862069f4d2d87\",\"attributes\":{},\"type\":\"sensitive_data_scanner_configuration\",\"relationships\":{\"groups\":{\"data\":[]}}},\"meta\":{\"version\":275277,\"count_limit\":250,\"group_count_limit\":20,\"is_pci_compliant\":false,\"has_highlight_enabled\":true,\"has_multi_pass_enabled\":true,\"has_cascading_enabled\":false,\"is_configuration_superseded\":false,\"is_float_sampling_rate_enabled\":false,\"min_sampling_rate\":10.0}}\n"
36+
},
37+
"cookies": [],
38+
"headers": [
39+
{
40+
"name": "content-type",
41+
"value": "application/json"
42+
}
43+
],
44+
"headersSize": 548,
45+
"httpVersion": "HTTP/1.1",
46+
"redirectURL": "",
47+
"status": 200,
48+
"statusText": "OK"
49+
},
50+
"startedDateTime": "2025-08-26T20:31:44.671Z",
51+
"time": 389
52+
},
53+
{
54+
"_id": "e6af4a2fdfda8f066f3af5528b238a9d",
55+
"_order": 0,
56+
"cache": {},
57+
"request": {
58+
"bodySize": 389,
59+
"cookies": [],
60+
"headers": [
61+
{
62+
"_fromType": "array",
63+
"name": "accept",
64+
"value": "application/json"
65+
},
66+
{
67+
"_fromType": "array",
68+
"name": "content-type",
69+
"value": "application/json"
70+
}
71+
],
72+
"headersSize": 590,
73+
"httpVersion": "HTTP/1.1",
74+
"method": "POST",
75+
"postData": {
76+
"mimeType": "application/json",
77+
"params": [],
78+
"text": "{\"data\":{\"attributes\":{\"filter\":{\"query\":\"*\"},\"is_enabled\":false,\"name\":\"my-test-group\",\"product_list\":[\"logs\"],\"samplings\":[{\"product\":\"logs\",\"rate\":100}]},\"relationships\":{\"configuration\":{\"data\":{\"id\":\"7957915c634d4dcb581fa154157f5ad9c2947f50be632fb5599862069f4d2d87\",\"type\":\"sensitive_data_scanner_configuration\"}},\"rules\":{\"data\":[]}},\"type\":\"sensitive_data_scanner_group\"},\"meta\":{}}"
79+
},
80+
"queryString": [],
81+
"url": "https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/groups"
82+
},
83+
"response": {
84+
"bodySize": 452,
85+
"content": {
86+
"mimeType": "application/json",
87+
"size": 452,
88+
"text": "{\"data\":{\"id\":\"18cc2267-f3cc-4c15-917d-d3efb15deb03\",\"attributes\":{\"name\":\"my-test-group\",\"is_enabled\":false,\"filter\":{\"query\":\"*\"},\"product_list\":[\"logs\"],\"samplings\":[{\"product\":\"logs\",\"rate\":100.0}]},\"type\":\"sensitive_data_scanner_group\",\"relationships\":{\"configuration\":{\"data\":{\"id\":\"7957915c634d4dcb581fa154157f5ad9c2947f50be632fb5599862069f4d2d87\",\"type\":\"sensitive_data_scanner_configuration\"}},\"rules\":{\"data\":[]}}},\"meta\":{\"version\":275278}}\n"
89+
},
90+
"cookies": [],
91+
"headers": [
92+
{
93+
"name": "content-type",
94+
"value": "application/json"
95+
}
96+
],
97+
"headersSize": 724,
98+
"httpVersion": "HTTP/1.1",
99+
"redirectURL": "",
100+
"status": 200,
101+
"statusText": "OK"
102+
},
103+
"startedDateTime": "2025-08-26T20:31:45.076Z",
104+
"time": 459
105+
},
106+
{
107+
"_id": "d5695745b55eb2d21a8bce6beb63aa60",
108+
"_order": 0,
109+
"cache": {},
110+
"request": {
111+
"bodySize": 468,
112+
"cookies": [],
113+
"headers": [
114+
{
115+
"_fromType": "array",
116+
"name": "accept",
117+
"value": "application/json"
118+
},
119+
{
120+
"_fromType": "array",
121+
"name": "content-type",
122+
"value": "application/json"
123+
}
124+
],
125+
"headersSize": 588,
126+
"httpVersion": "HTTP/1.1",
127+
"method": "POST",
128+
"postData": {
129+
"mimeType": "application/json",
130+
"params": [],
131+
"text": "{\"data\":{\"attributes\":{\"is_enabled\":true,\"name\":\"Test-Create_Scanning_Rule_with_should_save_match_returns_OK_response-1756240304\",\"pattern\":\"pattern\",\"priority\":1,\"tags\":[\"sensitive_data:true\"],\"text_replacement\":{\"replacement_string\":\"REDACTED\",\"should_save_match\":true,\"type\":\"replacement_string\"}},\"relationships\":{\"group\":{\"data\":{\"id\":\"18cc2267-f3cc-4c15-917d-d3efb15deb03\",\"type\":\"sensitive_data_scanner_group\"}}},\"type\":\"sensitive_data_scanner_rule\"},\"meta\":{}}"
132+
},
133+
"queryString": [],
134+
"url": "https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/rules"
135+
},
136+
"response": {
137+
"bodySize": 582,
138+
"content": {
139+
"mimeType": "application/json",
140+
"size": 582,
141+
"text": "{\"data\":{\"id\":\"0e517b8a-04c1-4ae0-b57b-22b8e081190c\",\"attributes\":{\"name\":\"Test-Create_Scanning_Rule_with_should_save_match_returns_OK_response-1756240304\",\"namespaces\":[],\"excluded_namespaces\":[],\"pattern\":\"pattern\",\"text_replacement\":{\"replacement_string\":\"REDACTED\",\"should_save_match\":true,\"type\":\"replacement_string\"},\"tags\":[\"sensitive_data:true\"],\"labels\":[],\"is_enabled\":true,\"priority\":1},\"type\":\"sensitive_data_scanner_rule\",\"relationships\":{\"group\":{\"data\":{\"id\":\"18cc2267-f3cc-4c15-917d-d3efb15deb03\",\"type\":\"sensitive_data_scanner_group\"}}}},\"meta\":{\"version\":275279}}\n"
142+
},
143+
"cookies": [],
144+
"headers": [
145+
{
146+
"name": "content-type",
147+
"value": "application/json"
148+
}
149+
],
150+
"headersSize": 730,
151+
"httpVersion": "HTTP/1.1",
152+
"redirectURL": "",
153+
"status": 200,
154+
"statusText": "OK"
155+
},
156+
"startedDateTime": "2025-08-26T20:31:45.541Z",
157+
"time": 384
158+
},
159+
{
160+
"_id": "9cb4750bc912e7e7baa631b157a5f623",
161+
"_order": 0,
162+
"cache": {},
163+
"request": {
164+
"bodySize": 11,
165+
"cookies": [],
166+
"headers": [
167+
{
168+
"_fromType": "array",
169+
"name": "accept",
170+
"value": "application/json"
171+
},
172+
{
173+
"_fromType": "array",
174+
"name": "content-type",
175+
"value": "application/json"
176+
}
177+
],
178+
"headersSize": 624,
179+
"httpVersion": "HTTP/1.1",
180+
"method": "DELETE",
181+
"postData": {
182+
"mimeType": "application/json",
183+
"params": [],
184+
"text": "{\"meta\":{}}"
185+
},
186+
"queryString": [],
187+
"url": "https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/rules/0e517b8a-04c1-4ae0-b57b-22b8e081190c"
188+
},
189+
"response": {
190+
"bodySize": 28,
191+
"content": {
192+
"mimeType": "application/json",
193+
"size": 28,
194+
"text": "{\"meta\":{\"version\":275280}}\n"
195+
},
196+
"cookies": [],
197+
"headers": [
198+
{
199+
"name": "content-type",
200+
"value": "application/json"
201+
}
202+
],
203+
"headersSize": 706,
204+
"httpVersion": "HTTP/1.1",
205+
"redirectURL": "",
206+
"status": 200,
207+
"statusText": "OK"
208+
},
209+
"startedDateTime": "2025-08-26T20:31:45.931Z",
210+
"time": 384
211+
},
212+
{
213+
"_id": "e79ae3f126edbe8515ec0a35094e9e3f",
214+
"_order": 0,
215+
"cache": {},
216+
"request": {
217+
"bodySize": 11,
218+
"cookies": [],
219+
"headers": [
220+
{
221+
"_fromType": "array",
222+
"name": "accept",
223+
"value": "application/json"
224+
},
225+
{
226+
"_fromType": "array",
227+
"name": "content-type",
228+
"value": "application/json"
229+
}
230+
],
231+
"headersSize": 628,
232+
"httpVersion": "HTTP/1.1",
233+
"method": "DELETE",
234+
"postData": {
235+
"mimeType": "application/json",
236+
"params": [],
237+
"text": "{\"meta\":{}}"
238+
},
239+
"queryString": [],
240+
"url": "https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/groups/18cc2267-f3cc-4c15-917d-d3efb15deb03"
241+
},
242+
"response": {
243+
"bodySize": 28,
244+
"content": {
245+
"mimeType": "application/json",
246+
"size": 28,
247+
"text": "{\"meta\":{\"version\":275281}}\n"
248+
},
249+
"cookies": [],
250+
"headers": [
251+
{
252+
"name": "content-type",
253+
"value": "application/json"
254+
}
255+
],
256+
"headersSize": 707,
257+
"httpVersion": "HTTP/1.1",
258+
"redirectURL": "",
259+
"status": 200,
260+
"statusText": "OK"
261+
},
262+
"startedDateTime": "2025-08-26T20:31:46.319Z",
263+
"time": 445
264+
}
265+
],
266+
"pages": [],
267+
"version": "1.2"
268+
}
269+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Create Scanning Rule with should_save_match returns "OK" response
3+
*/
4+
5+
import { client, v2 } from "@datadog/datadog-api-client";
6+
7+
const configuration = client.createConfiguration();
8+
const apiInstance = new v2.SensitiveDataScannerApi(configuration);
9+
10+
// there is a valid "scanning_group" in the system
11+
const GROUP_DATA_ID = process.env.GROUP_DATA_ID as string;
12+
13+
const params: v2.SensitiveDataScannerApiCreateScanningRuleRequest = {
14+
body: {
15+
meta: {},
16+
data: {
17+
type: "sensitive_data_scanner_rule",
18+
attributes: {
19+
name: "Example-Sensitive-Data-Scanner",
20+
pattern: "pattern",
21+
textReplacement: {
22+
type: "replacement_string",
23+
replacementString: "REDACTED",
24+
shouldSaveMatch: true,
25+
},
26+
tags: ["sensitive_data:true"],
27+
isEnabled: true,
28+
priority: 1,
29+
},
30+
relationships: {
31+
group: {
32+
data: {
33+
type: "sensitive_data_scanner_group",
34+
id: GROUP_DATA_ID,
35+
},
36+
},
37+
},
38+
},
39+
},
40+
};
41+
42+
apiInstance
43+
.createScanningRule(params)
44+
.then((data: v2.SensitiveDataScannerCreateRuleResponse) => {
45+
console.log(
46+
"API called successfully. Returned data: " + JSON.stringify(data)
47+
);
48+
})
49+
.catch((error: any) => console.error(error));

features/v2/sensitive_data_scanner.feature

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ Feature: Sensitive Data Scanner
5050
And the response "data.attributes.included_keyword_configuration.character_count" is equal to 35
5151
And the response "data.attributes.included_keyword_configuration.keywords[0]" is equal to "credit card"
5252

53+
@team:DataDog/sensitive-data-scanner
54+
Scenario: Create Scanning Rule with should_save_match returns "OK" response
55+
Given a valid "configuration" in the system
56+
And there is a valid "scanning_group" in the system
57+
And new "CreateScanningRule" request
58+
And body with value {"meta":{},"data":{"type":"sensitive_data_scanner_rule","attributes":{"name":"{{ unique }}","pattern":"pattern","text_replacement":{"type":"replacement_string","replacement_string":"REDACTED","should_save_match":true},"tags":["sensitive_data:true"],"is_enabled":true,"priority":1},"relationships":{"group":{"data":{"type":"{{ group.data.type }}","id":"{{ group.data.id }}"}}}}}
59+
When the request is sent
60+
Then the response status is 200 OK
61+
And the response "data.type" is equal to "sensitive_data_scanner_rule"
62+
And the response "data.attributes.name" is equal to "{{ unique }}"
63+
5364
@generated @skip @team:DataDog/sensitive-data-scanner
5465
Scenario: Delete Scanning Group returns "Bad Request" response
5566
Given new "DeleteScanningGroup" request

packages/datadog-api-client-v2/models/SensitiveDataScannerTextReplacement.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export class SensitiveDataScannerTextReplacement {
2020
* Required if type == 'replacement_string'.
2121
*/
2222
"replacementString"?: string;
23+
/**
24+
* Only valid when type == `replacement_string`. When enabled, matches can be unmasked in logs by users with ‘Data Scanner Unmask’ permission. As a security best practice, avoid masking for highly-sensitive, long-lived data.
25+
*/
26+
"shouldSaveMatch"?: boolean;
2327
/**
2428
* Type of the replacement text. None means no replacement.
2529
* hash means the data will be stubbed. replacement_string means that
@@ -55,6 +59,10 @@ export class SensitiveDataScannerTextReplacement {
5559
baseName: "replacement_string",
5660
type: "string",
5761
},
62+
shouldSaveMatch: {
63+
baseName: "should_save_match",
64+
type: "boolean",
65+
},
5866
type: {
5967
baseName: "type",
6068
type: "SensitiveDataScannerTextReplacementType",

0 commit comments

Comments
 (0)