diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 901b7a23247..fea9a6d0965 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/examples/v2/security-monitoring/CreateSecurityMonitoringRule_3243059428.java b/examples/v2/security-monitoring/CreateSecurityMonitoringRule_3243059428.java new file mode 100644 index 00000000000..8efe152ee31 --- /dev/null +++ b/examples/v2/security-monitoring/CreateSecurityMonitoringRule_3243059428.java @@ -0,0 +1,71 @@ +// Create a detection rule with type 'impossible_travel' and baselineUserLocationsDuration returns +// "OK" response + +import com.datadog.api.client.ApiClient; +import com.datadog.api.client.ApiException; +import com.datadog.api.client.v2.api.SecurityMonitoringApi; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleCaseCreate; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleCreatePayload; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleDetectionMethod; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleEvaluationWindow; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleImpossibleTravelOptions; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleKeepAlive; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleMaxSignalDuration; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleOptions; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleQueryAggregation; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleResponse; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleSeverity; +import com.datadog.api.client.v2.model.SecurityMonitoringRuleTypeCreate; +import com.datadog.api.client.v2.model.SecurityMonitoringStandardRuleCreatePayload; +import com.datadog.api.client.v2.model.SecurityMonitoringStandardRuleQuery; +import java.util.Collections; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = ApiClient.getDefaultApiClient(); + SecurityMonitoringApi apiInstance = new SecurityMonitoringApi(defaultClient); + + SecurityMonitoringRuleCreatePayload body = + new SecurityMonitoringRuleCreatePayload( + new SecurityMonitoringStandardRuleCreatePayload() + .queries( + Collections.singletonList( + new SecurityMonitoringStandardRuleQuery() + .aggregation(SecurityMonitoringRuleQueryAggregation.GEO_DATA) + .groupByFields(Collections.singletonList("@usr.id")) + .metric("@network.client.geoip") + .query("*"))) + .cases( + Collections.singletonList( + new SecurityMonitoringRuleCaseCreate() + .name("") + .status(SecurityMonitoringRuleSeverity.INFO))) + .hasExtendedTitle(true) + .message("test") + .isEnabled(true) + .options( + new SecurityMonitoringRuleOptions() + .maxSignalDuration(SecurityMonitoringRuleMaxSignalDuration.ONE_DAY) + .evaluationWindow(SecurityMonitoringRuleEvaluationWindow.FIFTEEN_MINUTES) + .keepAlive(SecurityMonitoringRuleKeepAlive.ONE_HOUR) + .detectionMethod(SecurityMonitoringRuleDetectionMethod.IMPOSSIBLE_TRAVEL) + .impossibleTravelOptions( + new SecurityMonitoringRuleImpossibleTravelOptions() + .baselineUserLocations(true) + .baselineUserLocationsDuration(7))) + .name("Example-Security-Monitoring") + .type(SecurityMonitoringRuleTypeCreate.LOG_DETECTION)); + + try { + SecurityMonitoringRuleResponse result = apiInstance.createSecurityMonitoringRule(body); + System.out.println(result); + } catch (ApiException e) { + System.err.println( + "Exception when calling SecurityMonitoringApi#createSecurityMonitoringRule"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/datadog/api/client/v2/model/SecurityMonitoringRuleImpossibleTravelOptions.java b/src/main/java/com/datadog/api/client/v2/model/SecurityMonitoringRuleImpossibleTravelOptions.java index 754348831be..0e39ed7958b 100644 --- a/src/main/java/com/datadog/api/client/v2/model/SecurityMonitoringRuleImpossibleTravelOptions.java +++ b/src/main/java/com/datadog/api/client/v2/model/SecurityMonitoringRuleImpossibleTravelOptions.java @@ -15,10 +15,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +import org.openapitools.jackson.nullable.JsonNullable; /** Options on impossible travel detection method. */ @JsonPropertyOrder({ - SecurityMonitoringRuleImpossibleTravelOptions.JSON_PROPERTY_BASELINE_USER_LOCATIONS + SecurityMonitoringRuleImpossibleTravelOptions.JSON_PROPERTY_BASELINE_USER_LOCATIONS, + SecurityMonitoringRuleImpossibleTravelOptions.JSON_PROPERTY_BASELINE_USER_LOCATIONS_DURATION }) @jakarta.annotation.Generated( value = "https://github.com/DataDog/datadog-api-client-java/blob/master/.generator") @@ -27,6 +29,10 @@ public class SecurityMonitoringRuleImpossibleTravelOptions { public static final String JSON_PROPERTY_BASELINE_USER_LOCATIONS = "baselineUserLocations"; private Boolean baselineUserLocations; + public static final String JSON_PROPERTY_BASELINE_USER_LOCATIONS_DURATION = + "baselineUserLocationsDuration"; + private JsonNullable baselineUserLocationsDuration = JsonNullable.undefined(); + public SecurityMonitoringRuleImpossibleTravelOptions baselineUserLocations( Boolean baselineUserLocations) { this.baselineUserLocations = baselineUserLocations; @@ -51,6 +57,40 @@ public void setBaselineUserLocations(Boolean baselineUserLocations) { this.baselineUserLocations = baselineUserLocations; } + public SecurityMonitoringRuleImpossibleTravelOptions baselineUserLocationsDuration( + Integer baselineUserLocationsDuration) { + this.baselineUserLocationsDuration = JsonNullable.of(baselineUserLocationsDuration); + return this; + } + + /** + * 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. minimum: 1 maximum: 30 + * + * @return baselineUserLocationsDuration + */ + @jakarta.annotation.Nullable + @JsonIgnore + public Integer getBaselineUserLocationsDuration() { + return baselineUserLocationsDuration.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_BASELINE_USER_LOCATIONS_DURATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public JsonNullable getBaselineUserLocationsDuration_JsonNullable() { + return baselineUserLocationsDuration; + } + + @JsonProperty(JSON_PROPERTY_BASELINE_USER_LOCATIONS_DURATION) + public void setBaselineUserLocationsDuration_JsonNullable( + JsonNullable baselineUserLocationsDuration) { + this.baselineUserLocationsDuration = baselineUserLocationsDuration; + } + + public void setBaselineUserLocationsDuration(Integer baselineUserLocationsDuration) { + this.baselineUserLocationsDuration = JsonNullable.of(baselineUserLocationsDuration); + } + /** * A container for additional, undeclared properties. This is a holder for any undeclared * properties as specified with the 'additionalProperties' keyword in the OAS document. @@ -112,6 +152,9 @@ public boolean equals(Object o) { return Objects.equals( this.baselineUserLocations, securityMonitoringRuleImpossibleTravelOptions.baselineUserLocations) + && Objects.equals( + this.baselineUserLocationsDuration, + securityMonitoringRuleImpossibleTravelOptions.baselineUserLocationsDuration) && Objects.equals( this.additionalProperties, securityMonitoringRuleImpossibleTravelOptions.additionalProperties); @@ -119,7 +162,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(baselineUserLocations, additionalProperties); + return Objects.hash(baselineUserLocations, baselineUserLocationsDuration, additionalProperties); } @Override @@ -129,6 +172,9 @@ public String toString() { sb.append(" baselineUserLocations: ") .append(toIndentedString(baselineUserLocations)) .append("\n"); + sb.append(" baselineUserLocationsDuration: ") + .append(toIndentedString(baselineUserLocationsDuration)) + .append("\n"); sb.append(" additionalProperties: ") .append(toIndentedString(additionalProperties)) .append("\n"); diff --git a/src/test/resources/cassettes/features/v2/Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_response.freeze b/src/test/resources/cassettes/features/v2/Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_response.freeze new file mode 100644 index 00000000000..55a8fd17a92 --- /dev/null +++ b/src/test/resources/cassettes/features/v2/Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_response.freeze @@ -0,0 +1 @@ +2026-05-20T15:12:27.397Z \ No newline at end of file diff --git a/src/test/resources/cassettes/features/v2/Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_response.json b/src/test/resources/cassettes/features/v2/Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_response.json new file mode 100644 index 00000000000..279e284ac82 --- /dev/null +++ b/src/test/resources/cassettes/features/v2/Create_a_detection_rule_with_type_impossible_travel_and_baselineUserLocationsDuration_returns_OK_response.json @@ -0,0 +1,53 @@ +[ + { + "httpRequest": { + "body": { + "type": "JSON", + "json": "{\"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\"}" + }, + "headers": {}, + "method": "POST", + "path": "/api/v2/security_monitoring/rules", + "keepAlive": false, + "secure": true + }, + "httpResponse": { + "body": "{\"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\":\"\"}}", + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "statusCode": 200, + "reasonPhrase": "OK" + }, + "times": { + "remainingTimes": 1 + }, + "timeToLive": { + "unlimited": true + }, + "id": "da934758-4baf-fca8-2600-4d9183d89974" + }, + { + "httpRequest": { + "headers": {}, + "method": "DELETE", + "path": "/api/v2/security_monitoring/rules/v2k-viu-svz", + "keepAlive": false, + "secure": true + }, + "httpResponse": { + "headers": {}, + "statusCode": 204, + "reasonPhrase": "No Content" + }, + "times": { + "remainingTimes": 1 + }, + "timeToLive": { + "unlimited": true + }, + "id": "4e836004-731a-1940-03a9-6f0169bd0eed" + } +] \ No newline at end of file diff --git a/src/test/resources/com/datadog/api/client/v2/api/security_monitoring.feature b/src/test/resources/com/datadog/api/client/v2/api/security_monitoring.feature index 95306c99540..ff9964a900d 100644 --- a/src/test/resources/com/datadog/api/client/v2/api/security_monitoring.feature +++ b/src/test/resources/com/datadog/api/client/v2/api/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