diff --git a/.generated-info b/.generated-info index 54f289296114..3bdd0a805300 100644 --- a/.generated-info +++ b/.generated-info @@ -1,4 +1,4 @@ { - "spec_repo_commit": "98e3371", - "generated": "2025-08-27 08:45:02.412" + "spec_repo_commit": "62a19e4", + "generated": "2025-08-27 15:01:20.504" } diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 7d9ee66a1278..e09c94804791 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -39445,6 +39445,12 @@ components: replacement_string: description: Required if type == 'replacement_string'. type: string + should_save_match: + description: "Only valid when type == `replacement_string`. When enabled, + matches can be unmasked in logs by users with \u2018Data Scanner Unmask\u2019 + permission. As a security best practice, avoid masking for highly-sensitive, + long-lived data." + type: boolean type: $ref: '#/components/schemas/SensitiveDataScannerTextReplacementType' type: object diff --git a/cassettes/features/v2/sensitive_data_scanner/Create-Scanning-Rule-with-should-save-match-returns-OK-response.frozen b/cassettes/features/v2/sensitive_data_scanner/Create-Scanning-Rule-with-should-save-match-returns-OK-response.frozen new file mode 100644 index 000000000000..5834759fc6e9 --- /dev/null +++ b/cassettes/features/v2/sensitive_data_scanner/Create-Scanning-Rule-with-should-save-match-returns-OK-response.frozen @@ -0,0 +1 @@ +2025-08-26T20:31:44.042Z \ No newline at end of file diff --git a/cassettes/features/v2/sensitive_data_scanner/Create-Scanning-Rule-with-should-save-match-returns-OK-response.yml b/cassettes/features/v2/sensitive_data_scanner/Create-Scanning-Rule-with-should-save-match-returns-OK-response.yml new file mode 100644 index 000000000000..2edabc78acf1 --- /dev/null +++ b/cassettes/features/v2/sensitive_data_scanner/Create-Scanning-Rule-with-should-save-match-returns-OK-response.yml @@ -0,0 +1,118 @@ +http_interactions: +- recorded_at: Tue, 26 Aug 2025 20:31:44 GMT + request: + body: null + headers: + Accept: + - application/json + method: GET + uri: https://api.datadoghq.com/api/v2/sensitive-data-scanner/config + response: + body: + encoding: UTF-8 + string: '{"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}} + + ' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +- recorded_at: Tue, 26 Aug 2025 20:31:44 GMT + request: + body: + encoding: UTF-8 + string: '{"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":{}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/groups + response: + body: + encoding: UTF-8 + string: '{"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}} + + ' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +- recorded_at: Tue, 26 Aug 2025 20:31:44 GMT + request: + body: + encoding: UTF-8 + string: '{"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":{}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/rules + response: + body: + encoding: UTF-8 + string: '{"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}} + + ' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +- recorded_at: Tue, 26 Aug 2025 20:31:44 GMT + request: + body: + encoding: UTF-8 + string: '{"meta":{}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/rules/0e517b8a-04c1-4ae0-b57b-22b8e081190c + response: + body: + encoding: UTF-8 + string: '{"meta":{"version":275280}} + + ' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +- recorded_at: Tue, 26 Aug 2025 20:31:44 GMT + request: + body: + encoding: UTF-8 + string: '{"meta":{}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v2/sensitive-data-scanner/config/groups/18cc2267-f3cc-4c15-917d-d3efb15deb03 + response: + body: + encoding: UTF-8 + string: '{"meta":{"version":275281}} + + ' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +recorded_with: VCR 6.0.0 diff --git a/examples/v2/sensitive-data-scanner/CreateScanningRule_502667299.rb b/examples/v2/sensitive-data-scanner/CreateScanningRule_502667299.rb new file mode 100644 index 000000000000..35280315670a --- /dev/null +++ b/examples/v2/sensitive-data-scanner/CreateScanningRule_502667299.rb @@ -0,0 +1,37 @@ +# Create Scanning Rule with should_save_match returns "OK" response + +require "datadog_api_client" +api_instance = DatadogAPIClient::V2::SensitiveDataScannerAPI.new + +# there is a valid "scanning_group" in the system +GROUP_DATA_ID = ENV["GROUP_DATA_ID"] + +body = DatadogAPIClient::V2::SensitiveDataScannerRuleCreateRequest.new({ + meta: DatadogAPIClient::V2::SensitiveDataScannerMetaVersionOnly.new({}), + data: DatadogAPIClient::V2::SensitiveDataScannerRuleCreate.new({ + type: DatadogAPIClient::V2::SensitiveDataScannerRuleType::SENSITIVE_DATA_SCANNER_RULE, + attributes: DatadogAPIClient::V2::SensitiveDataScannerRuleAttributes.new({ + name: "Example-Sensitive-Data-Scanner", + pattern: "pattern", + text_replacement: DatadogAPIClient::V2::SensitiveDataScannerTextReplacement.new({ + type: DatadogAPIClient::V2::SensitiveDataScannerTextReplacementType::REPLACEMENT_STRING, + replacement_string: "REDACTED", + should_save_match: true, + }), + tags: [ + "sensitive_data:true", + ], + is_enabled: true, + priority: 1, + }), + relationships: DatadogAPIClient::V2::SensitiveDataScannerRuleRelationships.new({ + group: DatadogAPIClient::V2::SensitiveDataScannerGroupData.new({ + data: DatadogAPIClient::V2::SensitiveDataScannerGroup.new({ + type: DatadogAPIClient::V2::SensitiveDataScannerGroupType::SENSITIVE_DATA_SCANNER_GROUP, + id: GROUP_DATA_ID, + }), + }), + }), + }), +}) +p api_instance.create_scanning_rule(body) diff --git a/features/v2/sensitive_data_scanner.feature b/features/v2/sensitive_data_scanner.feature index 75cc05b79786..4516e161032d 100644 --- a/features/v2/sensitive_data_scanner.feature +++ b/features/v2/sensitive_data_scanner.feature @@ -50,6 +50,17 @@ Feature: Sensitive Data Scanner And the response "data.attributes.included_keyword_configuration.character_count" is equal to 35 And the response "data.attributes.included_keyword_configuration.keywords[0]" is equal to "credit card" + @team:DataDog/sensitive-data-scanner + Scenario: Create Scanning Rule with should_save_match returns "OK" response + Given a valid "configuration" in the system + And there is a valid "scanning_group" in the system + And new "CreateScanningRule" request + 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 }}"}}}}} + When the request is sent + Then the response status is 200 OK + And the response "data.type" is equal to "sensitive_data_scanner_rule" + And the response "data.attributes.name" is equal to "{{ unique }}" + @generated @skip @team:DataDog/sensitive-data-scanner Scenario: Delete Scanning Group returns "Bad Request" response Given new "DeleteScanningGroup" request diff --git a/lib/datadog_api_client/v2/models/sensitive_data_scanner_text_replacement.rb b/lib/datadog_api_client/v2/models/sensitive_data_scanner_text_replacement.rb index dfe73d1b7605..61e6e6335ca3 100644 --- a/lib/datadog_api_client/v2/models/sensitive_data_scanner_text_replacement.rb +++ b/lib/datadog_api_client/v2/models/sensitive_data_scanner_text_replacement.rb @@ -28,6 +28,9 @@ class SensitiveDataScannerTextReplacement # Required if type == 'replacement_string'. attr_accessor :replacement_string + # 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. + attr_accessor :should_save_match + # Type of the replacement text. None means no replacement. # hash means the data will be stubbed. replacement_string means that # one can chose a text to replace the data. partial_replacement_from_beginning @@ -44,6 +47,7 @@ def self.attribute_map { :'number_of_chars' => :'number_of_chars', :'replacement_string' => :'replacement_string', + :'should_save_match' => :'should_save_match', :'type' => :'type' } end @@ -54,6 +58,7 @@ def self.openapi_types { :'number_of_chars' => :'Integer', :'replacement_string' => :'String', + :'should_save_match' => :'Boolean', :'type' => :'SensitiveDataScannerTextReplacementType' } end @@ -84,6 +89,10 @@ def initialize(attributes = {}) self.replacement_string = attributes[:'replacement_string'] end + if attributes.key?(:'should_save_match') + self.should_save_match = attributes[:'should_save_match'] + end + if attributes.key?(:'type') self.type = attributes[:'type'] end @@ -135,6 +144,7 @@ def ==(o) self.class == o.class && number_of_chars == o.number_of_chars && replacement_string == o.replacement_string && + should_save_match == o.should_save_match && type == o.type && additional_properties == o.additional_properties end @@ -143,7 +153,7 @@ def ==(o) # @return [Integer] Hash code # @!visibility private def hash - [number_of_chars, replacement_string, type, additional_properties].hash + [number_of_chars, replacement_string, should_save_match, type, additional_properties].hash end end end