diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 901b7a232478..fea9a6d09656 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -70116,11 +70116,20 @@ components: properties: baselineUserLocations: $ref: "#/components/schemas/SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocations" + baselineUserLocationsDuration: + $ref: "#/components/schemas/SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocationsDuration" type: object SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocations: description: "If true, signals are suppressed for the first 24 hours. In that time, Datadog learns the user's regular\naccess locations. This can be helpful to reduce noise and infer VPN usage or credentialed API access." example: true type: boolean + SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocationsDuration: + description: The duration in days during which Datadog learns the user's regular access locations. After this period, signals are generated for accesses from unknown locations. + format: int32 + maximum: 30 + minimum: 1 + nullable: true + type: integer SecurityMonitoringRuleInstantaneousBaseline: description: When set to true, Datadog uses previous values that fall within the defined learning window to construct the baseline, enabling the system to establish an accurate baseline more rapidly rather than relying solely on gradual learning over time. example: false @@ -142415,6 +142424,7 @@ paths: hardcodedEvaluatorType: log4shell impossibleTravelOptions: baselineUserLocations: true + baselineUserLocationsDuration: 7 newValueOptions: instantaneousBaseline: false learningMethod: duration @@ -143171,6 +143181,7 @@ paths: hardcodedEvaluatorType: log4shell impossibleTravelOptions: baselineUserLocations: true + baselineUserLocationsDuration: 7 keepAlive: 3600 maxSignalDuration: 86400 newValueOptions: @@ -143272,6 +143283,7 @@ paths: hardcodedEvaluatorType: log4shell impossibleTravelOptions: baselineUserLocations: true + baselineUserLocationsDuration: 7 keepAlive: 0 maxSignalDuration: 0 newValueOptions: @@ -143385,6 +143397,7 @@ paths: hardcodedEvaluatorType: log4shell impossibleTravelOptions: baselineUserLocations: true + baselineUserLocationsDuration: 7 keepAlive: 1800 maxSignalDuration: 1800 newValueOptions: diff --git a/cassettes/v2/Security-Monitoring_1187227211/Create-a-detection-rule-with-type-impossible_travel-and-baselineUserLocationsDuration-ret_1893385400/frozen.json b/cassettes/v2/Security-Monitoring_1187227211/Create-a-detection-rule-with-type-impossible_travel-and-baselineUserLocationsDuration-ret_1893385400/frozen.json new file mode 100644 index 000000000000..71471cfe816b --- /dev/null +++ b/cassettes/v2/Security-Monitoring_1187227211/Create-a-detection-rule-with-type-impossible_travel-and-baselineUserLocationsDuration-ret_1893385400/frozen.json @@ -0,0 +1 @@ +"2026-05-20T15:12:27.397Z" diff --git a/cassettes/v2/Security-Monitoring_1187227211/Create-a-detection-rule-with-type-impossible_travel-and-baselineUserLocationsDuration-ret_1893385400/recording.har b/cassettes/v2/Security-Monitoring_1187227211/Create-a-detection-rule-with-type-impossible_travel-and-baselineUserLocationsDuration-ret_1893385400/recording.har new file mode 100644 index 000000000000..2cda8ecc8c67 --- /dev/null +++ b/cassettes/v2/Security-Monitoring_1187227211/Create-a-detection-rule-with-type-impossible_travel-and-baselineUserLocationsDuration-ret_1893385400/recording.har @@ -0,0 +1,104 @@ +{ + "log": { + "_recordingName": "Security Monitoring/Create a detection rule with type 'impossible_travel' and baselineUserLocationsDuration returns \"OK\" response", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "da9347584baffca826004d9183d89974", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 627, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + } + ], + "headersSize": 588, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": "{\"cases\":[{\"name\":\"\",\"notifications\":[],\"status\":\"info\"}],\"filters\":[],\"hasExtendedTitle\":true,\"isEnabled\":true,\"message\":\"test\",\"name\":\"Test-Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_res-1779289947\",\"options\":{\"detectionMethod\":\"impossible_travel\",\"evaluationWindow\":900,\"impossibleTravelOptions\":{\"baselineUserLocations\":true,\"baselineUserLocationsDuration\":7},\"keepAlive\":3600,\"maxSignalDuration\":86400},\"queries\":[{\"aggregation\":\"geo_data\",\"distinctFields\":[],\"groupByFields\":[\"@usr.id\"],\"metric\":\"@network.client.geoip\",\"query\":\"*\"}],\"tags\":[],\"type\":\"log_detection\"}" + }, + "queryString": [], + "url": "https://api.datadoghq.com/api/v2/security_monitoring/rules" + }, + "response": { + "bodySize": 1102, + "content": { + "mimeType": "application/json", + "size": 1102, + "text": "{\"name\":\"Test-Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_res-1779289947\",\"createdAt\":1779289949181,\"isDefault\":false,\"isPartner\":false,\"isEnabled\":true,\"isBeta\":false,\"isDeleted\":false,\"isDeprecated\":false,\"queries\":[{\"query\":\"*\",\"groupByFields\":[\"@usr.id\"],\"hasOptionalGroupByFields\":false,\"distinctFields\":[],\"metric\":\"@network.client.geoip\",\"metrics\":[\"@network.client.geoip\"],\"aggregation\":\"geo_data\",\"name\":\"\",\"dataSource\":\"logs\"}],\"options\":{\"evaluationWindow\":900,\"detectionMethod\":\"impossible_travel\",\"maxSignalDuration\":86400,\"keepAlive\":3600,\"impossibleTravelOptions\":{\"baselineUserLocations\":true,\"baselineUserLocationsDuration\":7,\"detectIpTransition\":false}},\"cases\":[{\"name\":\"\",\"status\":\"info\",\"notifications\":[]}],\"message\":\"test\",\"tags\":[],\"hasExtendedTitle\":true,\"type\":\"log_detection\",\"filters\":[],\"version\":1,\"id\":\"v2k-viu-svz\",\"blocking\":false,\"metadata\":{\"entities\":null,\"sources\":null},\"creationAuthorId\":2320499,\"creator\":{\"handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"name\":\"CI Account\"},\"updater\":{\"handle\":\"\",\"name\":\"\"}}" + }, + "cookies": [], + "headers": [ + { + "name": "content-type", + "value": "application/json" + } + ], + "headersSize": 655, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2026-05-20T15:12:28.820Z", + "time": 397 + }, + { + "_id": "4e836004731a194003a96f0169bd0eed", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "accept", + "value": "*/*" + } + ], + "headersSize": 536, + "httpVersion": "HTTP/1.1", + "method": "DELETE", + "queryString": [], + "url": "https://api.datadoghq.com/api/v2/security_monitoring/rules/v2k-viu-svz" + }, + "response": { + "bodySize": 0, + "content": { + "mimeType": "text/plain", + "size": 0 + }, + "cookies": [], + "headers": [], + "headersSize": 601, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 204, + "statusText": "No Content" + }, + "startedDateTime": "2026-05-20T15:12:29.228Z", + "time": 462 + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/features/v2/security_monitoring.feature b/features/v2/security_monitoring.feature index 95306c995407..ff9964a900d9 100644 --- a/features/v2/security_monitoring.feature +++ b/features/v2/security_monitoring.feature @@ -559,6 +559,19 @@ Feature: Security Monitoring And the response "type" is equal to "application_security" And the response "message" is equal to "Test rule" + @skip-validation @team:DataDog/k9-cloud-siem + Scenario: Create a detection rule with type 'impossible_travel' and baselineUserLocationsDuration returns "OK" response + Given new "CreateSecurityMonitoringRule" request + And body with value {"queries":[{"aggregation":"geo_data","groupByFields":["@usr.id"],"distinctFields":[],"metric":"@network.client.geoip","query":"*"}],"cases":[{"name":"","status":"info","notifications":[]}],"hasExtendedTitle":true,"message":"test","isEnabled":true,"options":{"maxSignalDuration":86400,"evaluationWindow":900,"keepAlive":3600,"detectionMethod":"impossible_travel","impossibleTravelOptions":{"baselineUserLocations":true,"baselineUserLocationsDuration":7}},"name":"{{ unique }}","type":"log_detection","tags":[],"filters":[]} + When the request is sent + Then the response status is 200 OK + And the response "name" is equal to "{{ unique }}" + And the response "type" is equal to "log_detection" + And the response "message" is equal to "test" + And the response "options.detectionMethod" is equal to "impossible_travel" + And the response "options.impossibleTravelOptions.baselineUserLocations" is equal to true + And the response "options.impossibleTravelOptions.baselineUserLocationsDuration" is equal to 7 + @skip-validation @team:DataDog/k9-cloud-siem Scenario: Create a detection rule with type 'impossible_travel' returns "OK" response Given new "CreateSecurityMonitoringRule" request diff --git a/services/security_monitoring/src/v2/models/SecurityMonitoringRuleImpossibleTravelOptions.ts b/services/security_monitoring/src/v2/models/SecurityMonitoringRuleImpossibleTravelOptions.ts index 993d9829e949..92973c36c5f7 100644 --- a/services/security_monitoring/src/v2/models/SecurityMonitoringRuleImpossibleTravelOptions.ts +++ b/services/security_monitoring/src/v2/models/SecurityMonitoringRuleImpossibleTravelOptions.ts @@ -9,6 +9,10 @@ export class SecurityMonitoringRuleImpossibleTravelOptions { * access locations. This can be helpful to reduce noise and infer VPN usage or credentialed API access. */ "baselineUserLocations"?: boolean; + /** + * The duration in days during which Datadog learns the user's regular access locations. After this period, signals are generated for accesses from unknown locations. + */ + "baselineUserLocationsDuration"?: number; /** * A container for additional, undeclared properties. * This is a holder for any undeclared properties as specified with @@ -28,6 +32,11 @@ export class SecurityMonitoringRuleImpossibleTravelOptions { baseName: "baselineUserLocations", type: "boolean", }, + baselineUserLocationsDuration: { + baseName: "baselineUserLocationsDuration", + type: "number", + format: "int32", + }, additionalProperties: { baseName: "additionalProperties", type: "{ [key: string]: any; }",