Skip to content

Commit 53dd9de

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add SDS rule should_save_match field (#3089)
Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 33b7971 commit 53dd9de

11 files changed

+276
-11
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:46:33.176"
2+
"spec_repo_commit": "62a19e4",
3+
"generated": "2025-08-27 15:03:03.841"
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
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Create Scanning Rule with should_save_match returns "OK" response
2+
3+
import com.datadog.api.client.ApiClient;
4+
import com.datadog.api.client.ApiException;
5+
import com.datadog.api.client.v2.api.SensitiveDataScannerApi;
6+
import com.datadog.api.client.v2.model.SensitiveDataScannerCreateRuleResponse;
7+
import com.datadog.api.client.v2.model.SensitiveDataScannerGroup;
8+
import com.datadog.api.client.v2.model.SensitiveDataScannerGroupData;
9+
import com.datadog.api.client.v2.model.SensitiveDataScannerGroupType;
10+
import com.datadog.api.client.v2.model.SensitiveDataScannerMetaVersionOnly;
11+
import com.datadog.api.client.v2.model.SensitiveDataScannerRuleAttributes;
12+
import com.datadog.api.client.v2.model.SensitiveDataScannerRuleCreate;
13+
import com.datadog.api.client.v2.model.SensitiveDataScannerRuleCreateRequest;
14+
import com.datadog.api.client.v2.model.SensitiveDataScannerRuleRelationships;
15+
import com.datadog.api.client.v2.model.SensitiveDataScannerRuleType;
16+
import com.datadog.api.client.v2.model.SensitiveDataScannerTextReplacement;
17+
import com.datadog.api.client.v2.model.SensitiveDataScannerTextReplacementType;
18+
import java.util.Collections;
19+
20+
public class Example {
21+
public static void main(String[] args) {
22+
ApiClient defaultClient = ApiClient.getDefaultApiClient();
23+
SensitiveDataScannerApi apiInstance = new SensitiveDataScannerApi(defaultClient);
24+
25+
// there is a valid "scanning_group" in the system
26+
String GROUP_DATA_ID = System.getenv("GROUP_DATA_ID");
27+
28+
SensitiveDataScannerRuleCreateRequest body =
29+
new SensitiveDataScannerRuleCreateRequest()
30+
.meta(new SensitiveDataScannerMetaVersionOnly())
31+
.data(
32+
new SensitiveDataScannerRuleCreate()
33+
.type(SensitiveDataScannerRuleType.SENSITIVE_DATA_SCANNER_RULE)
34+
.attributes(
35+
new SensitiveDataScannerRuleAttributes()
36+
.name("Example-Sensitive-Data-Scanner")
37+
.pattern("pattern")
38+
.textReplacement(
39+
new SensitiveDataScannerTextReplacement()
40+
.type(
41+
SensitiveDataScannerTextReplacementType.REPLACEMENT_STRING)
42+
.replacementString("REDACTED")
43+
.shouldSaveMatch(true))
44+
.tags(Collections.singletonList("sensitive_data:true"))
45+
.isEnabled(true)
46+
.priority(1L))
47+
.relationships(
48+
new SensitiveDataScannerRuleRelationships()
49+
.group(
50+
new SensitiveDataScannerGroupData()
51+
.data(
52+
new SensitiveDataScannerGroup()
53+
.type(
54+
SensitiveDataScannerGroupType
55+
.SENSITIVE_DATA_SCANNER_GROUP)
56+
.id(GROUP_DATA_ID)))));
57+
58+
try {
59+
SensitiveDataScannerCreateRuleResponse result = apiInstance.createScanningRule(body);
60+
System.out.println(result);
61+
} catch (ApiException e) {
62+
System.err.println("Exception when calling SensitiveDataScannerApi#createScanningRule");
63+
System.err.println("Status code: " + e.getCode());
64+
System.err.println("Reason: " + e.getResponseBody());
65+
System.err.println("Response headers: " + e.getResponseHeaders());
66+
e.printStackTrace();
67+
}
68+
}
69+
}

src/main/java/com/datadog/api/client/v2/model/SensitiveDataScannerTextReplacement.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
@JsonPropertyOrder({
2121
SensitiveDataScannerTextReplacement.JSON_PROPERTY_NUMBER_OF_CHARS,
2222
SensitiveDataScannerTextReplacement.JSON_PROPERTY_REPLACEMENT_STRING,
23+
SensitiveDataScannerTextReplacement.JSON_PROPERTY_SHOULD_SAVE_MATCH,
2324
SensitiveDataScannerTextReplacement.JSON_PROPERTY_TYPE
2425
})
2526
@jakarta.annotation.Generated(
@@ -32,6 +33,9 @@ public class SensitiveDataScannerTextReplacement {
3233
public static final String JSON_PROPERTY_REPLACEMENT_STRING = "replacement_string";
3334
private String replacementString;
3435

36+
public static final String JSON_PROPERTY_SHOULD_SAVE_MATCH = "should_save_match";
37+
private Boolean shouldSaveMatch;
38+
3539
public static final String JSON_PROPERTY_TYPE = "type";
3640
private SensitiveDataScannerTextReplacementType type =
3741
SensitiveDataScannerTextReplacementType.NONE;
@@ -79,6 +83,29 @@ public void setReplacementString(String replacementString) {
7983
this.replacementString = replacementString;
8084
}
8185

86+
public SensitiveDataScannerTextReplacement shouldSaveMatch(Boolean shouldSaveMatch) {
87+
this.shouldSaveMatch = shouldSaveMatch;
88+
return this;
89+
}
90+
91+
/**
92+
* Only valid when type == <code>replacement_string</code>. When enabled, matches can be unmasked
93+
* in logs by users with ‘Data Scanner Unmask’ permission. As a security best practice, avoid
94+
* masking for highly-sensitive, long-lived data.
95+
*
96+
* @return shouldSaveMatch
97+
*/
98+
@jakarta.annotation.Nullable
99+
@JsonProperty(JSON_PROPERTY_SHOULD_SAVE_MATCH)
100+
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
101+
public Boolean getShouldSaveMatch() {
102+
return shouldSaveMatch;
103+
}
104+
105+
public void setShouldSaveMatch(Boolean shouldSaveMatch) {
106+
this.shouldSaveMatch = shouldSaveMatch;
107+
}
108+
82109
public SensitiveDataScannerTextReplacement type(SensitiveDataScannerTextReplacementType type) {
83110
this.type = type;
84111
this.unparsed |= !type.isValid();
@@ -168,14 +195,16 @@ public boolean equals(Object o) {
168195
return Objects.equals(this.numberOfChars, sensitiveDataScannerTextReplacement.numberOfChars)
169196
&& Objects.equals(
170197
this.replacementString, sensitiveDataScannerTextReplacement.replacementString)
198+
&& Objects.equals(this.shouldSaveMatch, sensitiveDataScannerTextReplacement.shouldSaveMatch)
171199
&& Objects.equals(this.type, sensitiveDataScannerTextReplacement.type)
172200
&& Objects.equals(
173201
this.additionalProperties, sensitiveDataScannerTextReplacement.additionalProperties);
174202
}
175203

176204
@Override
177205
public int hashCode() {
178-
return Objects.hash(numberOfChars, replacementString, type, additionalProperties);
206+
return Objects.hash(
207+
numberOfChars, replacementString, shouldSaveMatch, type, additionalProperties);
179208
}
180209

181210
@Override
@@ -184,6 +213,7 @@ public String toString() {
184213
sb.append("class SensitiveDataScannerTextReplacement {\n");
185214
sb.append(" numberOfChars: ").append(toIndentedString(numberOfChars)).append("\n");
186215
sb.append(" replacementString: ").append(toIndentedString(replacementString)).append("\n");
216+
sb.append(" shouldSaveMatch: ").append(toIndentedString(shouldSaveMatch)).append("\n");
187217
sb.append(" type: ").append(toIndentedString(type)).append("\n");
188218
sb.append(" additionalProperties: ")
189219
.append(toIndentedString(additionalProperties))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2025-08-26T20:31:44.042Z
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
[
2+
{
3+
"httpRequest": {
4+
"headers": {},
5+
"method": "GET",
6+
"path": "/api/v2/sensitive-data-scanner/config",
7+
"keepAlive": false,
8+
"secure": true
9+
},
10+
"httpResponse": {
11+
"body": "{\"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",
12+
"headers": {
13+
"Content-Type": [
14+
"application/json"
15+
]
16+
},
17+
"statusCode": 200,
18+
"reasonPhrase": "OK"
19+
},
20+
"times": {
21+
"remainingTimes": 1
22+
},
23+
"timeToLive": {
24+
"unlimited": true
25+
},
26+
"id": "01611a93-5e74-0630-3c51-f707c3b51e80"
27+
},
28+
{
29+
"httpRequest": {
30+
"body": {
31+
"type": "JSON",
32+
"json": "{\"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\":{}}"
33+
},
34+
"headers": {},
35+
"method": "POST",
36+
"path": "/api/v2/sensitive-data-scanner/config/groups",
37+
"keepAlive": false,
38+
"secure": true
39+
},
40+
"httpResponse": {
41+
"body": "{\"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",
42+
"headers": {
43+
"Content-Type": [
44+
"application/json"
45+
]
46+
},
47+
"statusCode": 200,
48+
"reasonPhrase": "OK"
49+
},
50+
"times": {
51+
"remainingTimes": 1
52+
},
53+
"timeToLive": {
54+
"unlimited": true
55+
},
56+
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa3"
57+
},
58+
{
59+
"httpRequest": {
60+
"body": {
61+
"type": "JSON",
62+
"json": "{\"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\":{}}"
63+
},
64+
"headers": {},
65+
"method": "POST",
66+
"path": "/api/v2/sensitive-data-scanner/config/rules",
67+
"keepAlive": false,
68+
"secure": true
69+
},
70+
"httpResponse": {
71+
"body": "{\"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",
72+
"headers": {
73+
"Content-Type": [
74+
"application/json"
75+
]
76+
},
77+
"statusCode": 200,
78+
"reasonPhrase": "OK"
79+
},
80+
"times": {
81+
"remainingTimes": 1
82+
},
83+
"timeToLive": {
84+
"unlimited": true
85+
},
86+
"id": "d5695745-b55e-b2d2-1a8b-ce6beb63aa60"
87+
},
88+
{
89+
"httpRequest": {
90+
"body": {
91+
"type": "JSON",
92+
"json": "{\"meta\":{}}"
93+
},
94+
"headers": {},
95+
"method": "DELETE",
96+
"path": "/api/v2/sensitive-data-scanner/config/rules/0e517b8a-04c1-4ae0-b57b-22b8e081190c",
97+
"keepAlive": false,
98+
"secure": true
99+
},
100+
"httpResponse": {
101+
"body": "{\"meta\":{\"version\":275280}}\n",
102+
"headers": {
103+
"Content-Type": [
104+
"application/json"
105+
]
106+
},
107+
"statusCode": 200,
108+
"reasonPhrase": "OK"
109+
},
110+
"times": {
111+
"remainingTimes": 1
112+
},
113+
"timeToLive": {
114+
"unlimited": true
115+
},
116+
"id": "9cb4750b-c912-e7e7-baa6-31b157a5f623"
117+
},
118+
{
119+
"httpRequest": {
120+
"body": {
121+
"type": "JSON",
122+
"json": "{\"meta\":{}}"
123+
},
124+
"headers": {},
125+
"method": "DELETE",
126+
"path": "/api/v2/sensitive-data-scanner/config/groups/18cc2267-f3cc-4c15-917d-d3efb15deb03",
127+
"keepAlive": false,
128+
"secure": true
129+
},
130+
"httpResponse": {
131+
"body": "{\"meta\":{\"version\":275281}}\n",
132+
"headers": {
133+
"Content-Type": [
134+
"application/json"
135+
]
136+
},
137+
"statusCode": 200,
138+
"reasonPhrase": "OK"
139+
},
140+
"times": {
141+
"remainingTimes": 1
142+
},
143+
"timeToLive": {
144+
"unlimited": true
145+
},
146+
"id": "e79ae3f1-26ed-be85-15ec-0a35094e9e3f"
147+
}
148+
]

src/test/resources/cassettes/features/v2/Delete_Scanning_Rule_returns_OK_response.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"timeToLive": {
2424
"unlimited": true
2525
},
26-
"id": "01611a93-5e74-0630-3c51-f707c3b51e81"
26+
"id": "01611a93-5e74-0630-3c51-f707c3b51e82"
2727
},
2828
{
2929
"httpRequest": {
@@ -53,7 +53,7 @@
5353
"timeToLive": {
5454
"unlimited": true
5555
},
56-
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa4"
56+
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa5"
5757
},
5858
{
5959
"httpRequest": {

src/test/resources/cassettes/features/v2/Reorder_Groups_returns_Bad_Request_response.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"timeToLive": {
2424
"unlimited": true
2525
},
26-
"id": "01611a93-5e74-0630-3c51-f707c3b51e82"
26+
"id": "01611a93-5e74-0630-3c51-f707c3b51e83"
2727
},
2828
{
2929
"httpRequest": {
@@ -53,7 +53,7 @@
5353
"timeToLive": {
5454
"unlimited": true
5555
},
56-
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa5"
56+
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa6"
5757
},
5858
{
5959
"httpRequest": {

src/test/resources/cassettes/features/v2/Update_Scanning_Group_returns_OK_response.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"timeToLive": {
2424
"unlimited": true
2525
},
26-
"id": "01611a93-5e74-0630-3c51-f707c3b51e83"
26+
"id": "01611a93-5e74-0630-3c51-f707c3b51e84"
2727
},
2828
{
2929
"httpRequest": {
@@ -53,7 +53,7 @@
5353
"timeToLive": {
5454
"unlimited": true
5555
},
56-
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa6"
56+
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa7"
5757
},
5858
{
5959
"httpRequest": {

src/test/resources/cassettes/features/v2/Update_Scanning_Rule_returns_Bad_Request_response.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"timeToLive": {
2424
"unlimited": true
2525
},
26-
"id": "01611a93-5e74-0630-3c51-f707c3b51e80"
26+
"id": "01611a93-5e74-0630-3c51-f707c3b51e81"
2727
},
2828
{
2929
"httpRequest": {
@@ -53,7 +53,7 @@
5353
"timeToLive": {
5454
"unlimited": true
5555
},
56-
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa3"
56+
"id": "e6af4a2f-dfda-8f06-6f3a-f5528b238aa4"
5757
},
5858
{
5959
"httpRequest": {

0 commit comments

Comments
 (0)