Skip to content

Commit 24035b3

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add baselineUserLocationsDuration to Impossible Travel rule options (#4119)
Co-authored-by: ci.datadog-api-spec <packages@datadoghq.com>
1 parent 15d3503 commit 24035b3

6 files changed

Lines changed: 180 additions & 2 deletions

.generator/schemas/v2/openapi.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70685,11 +70685,20 @@ components:
7068570685
properties:
7068670686
baselineUserLocations:
7068770687
$ref: "#/components/schemas/SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocations"
70688+
baselineUserLocationsDuration:
70689+
$ref: "#/components/schemas/SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocationsDuration"
7068870690
type: object
7068970691
SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocations:
7069070692
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."
7069170693
example: true
7069270694
type: boolean
70695+
SecurityMonitoringRuleImpossibleTravelOptionsBaselineUserLocationsDuration:
70696+
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.
70697+
format: int32
70698+
maximum: 30
70699+
minimum: 1
70700+
nullable: true
70701+
type: integer
7069370702
SecurityMonitoringRuleInstantaneousBaseline:
7069470703
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.
7069570704
example: false
@@ -143305,6 +143314,7 @@ paths:
143305143314
hardcodedEvaluatorType: log4shell
143306143315
impossibleTravelOptions:
143307143316
baselineUserLocations: true
143317+
baselineUserLocationsDuration: 7
143308143318
newValueOptions:
143309143319
instantaneousBaseline: false
143310143320
learningMethod: duration
@@ -144061,6 +144071,7 @@ paths:
144061144071
hardcodedEvaluatorType: log4shell
144062144072
impossibleTravelOptions:
144063144073
baselineUserLocations: true
144074+
baselineUserLocationsDuration: 7
144064144075
keepAlive: 3600
144065144076
maxSignalDuration: 86400
144066144077
newValueOptions:
@@ -144162,6 +144173,7 @@ paths:
144162144173
hardcodedEvaluatorType: log4shell
144163144174
impossibleTravelOptions:
144164144175
baselineUserLocations: true
144176+
baselineUserLocationsDuration: 7
144165144177
keepAlive: 0
144166144178
maxSignalDuration: 0
144167144179
newValueOptions:
@@ -144275,6 +144287,7 @@ paths:
144275144287
hardcodedEvaluatorType: log4shell
144276144288
impossibleTravelOptions:
144277144289
baselineUserLocations: true
144290+
baselineUserLocationsDuration: 7
144278144291
keepAlive: 1800
144279144292
maxSignalDuration: 1800
144280144293
newValueOptions:

api/datadogV2/model_security_monitoring_rule_impossible_travel_options.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ type SecurityMonitoringRuleImpossibleTravelOptions struct {
1313
// If true, signals are suppressed for the first 24 hours. In that time, Datadog learns the user's regular
1414
// access locations. This can be helpful to reduce noise and infer VPN usage or credentialed API access.
1515
BaselineUserLocations *bool `json:"baselineUserLocations,omitempty"`
16+
// 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.
17+
BaselineUserLocationsDuration datadog.NullableInt32 `json:"baselineUserLocationsDuration,omitempty"`
1618
// UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct
1719
UnparsedObject map[string]interface{} `json:"-"`
1820
AdditionalProperties map[string]interface{} `json:"-"`
@@ -63,6 +65,45 @@ func (o *SecurityMonitoringRuleImpossibleTravelOptions) SetBaselineUserLocations
6365
o.BaselineUserLocations = &v
6466
}
6567

68+
// GetBaselineUserLocationsDuration returns the BaselineUserLocationsDuration field value if set, zero value otherwise (both if not set or set to explicit null).
69+
func (o *SecurityMonitoringRuleImpossibleTravelOptions) GetBaselineUserLocationsDuration() int32 {
70+
if o == nil || o.BaselineUserLocationsDuration.Get() == nil {
71+
var ret int32
72+
return ret
73+
}
74+
return *o.BaselineUserLocationsDuration.Get()
75+
}
76+
77+
// GetBaselineUserLocationsDurationOk returns a tuple with the BaselineUserLocationsDuration field value if set, nil otherwise
78+
// and a boolean to check if the value has been set.
79+
// NOTE: If the value is an explicit nil, `nil, true` will be returned.
80+
func (o *SecurityMonitoringRuleImpossibleTravelOptions) GetBaselineUserLocationsDurationOk() (*int32, bool) {
81+
if o == nil {
82+
return nil, false
83+
}
84+
return o.BaselineUserLocationsDuration.Get(), o.BaselineUserLocationsDuration.IsSet()
85+
}
86+
87+
// HasBaselineUserLocationsDuration returns a boolean if a field has been set.
88+
func (o *SecurityMonitoringRuleImpossibleTravelOptions) HasBaselineUserLocationsDuration() bool {
89+
return o != nil && o.BaselineUserLocationsDuration.IsSet()
90+
}
91+
92+
// SetBaselineUserLocationsDuration gets a reference to the given datadog.NullableInt32 and assigns it to the BaselineUserLocationsDuration field.
93+
func (o *SecurityMonitoringRuleImpossibleTravelOptions) SetBaselineUserLocationsDuration(v int32) {
94+
o.BaselineUserLocationsDuration.Set(&v)
95+
}
96+
97+
// SetBaselineUserLocationsDurationNil sets the value for BaselineUserLocationsDuration to be an explicit nil.
98+
func (o *SecurityMonitoringRuleImpossibleTravelOptions) SetBaselineUserLocationsDurationNil() {
99+
o.BaselineUserLocationsDuration.Set(nil)
100+
}
101+
102+
// UnsetBaselineUserLocationsDuration ensures that no value is present for BaselineUserLocationsDuration, not even an explicit nil.
103+
func (o *SecurityMonitoringRuleImpossibleTravelOptions) UnsetBaselineUserLocationsDuration() {
104+
o.BaselineUserLocationsDuration.Unset()
105+
}
106+
66107
// MarshalJSON serializes the struct using spec logic.
67108
func (o SecurityMonitoringRuleImpossibleTravelOptions) MarshalJSON() ([]byte, error) {
68109
toSerialize := map[string]interface{}{}
@@ -72,6 +113,9 @@ func (o SecurityMonitoringRuleImpossibleTravelOptions) MarshalJSON() ([]byte, er
72113
if o.BaselineUserLocations != nil {
73114
toSerialize["baselineUserLocations"] = o.BaselineUserLocations
74115
}
116+
if o.BaselineUserLocationsDuration.IsSet() {
117+
toSerialize["baselineUserLocationsDuration"] = o.BaselineUserLocationsDuration.Get()
118+
}
75119

76120
for key, value := range o.AdditionalProperties {
77121
toSerialize[key] = value
@@ -82,18 +126,20 @@ func (o SecurityMonitoringRuleImpossibleTravelOptions) MarshalJSON() ([]byte, er
82126
// UnmarshalJSON deserializes the given payload.
83127
func (o *SecurityMonitoringRuleImpossibleTravelOptions) UnmarshalJSON(bytes []byte) (err error) {
84128
all := struct {
85-
BaselineUserLocations *bool `json:"baselineUserLocations,omitempty"`
129+
BaselineUserLocations *bool `json:"baselineUserLocations,omitempty"`
130+
BaselineUserLocationsDuration datadog.NullableInt32 `json:"baselineUserLocationsDuration,omitempty"`
86131
}{}
87132
if err = datadog.Unmarshal(bytes, &all); err != nil {
88133
return datadog.Unmarshal(bytes, &o.UnparsedObject)
89134
}
90135
additionalProperties := make(map[string]interface{})
91136
if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil {
92-
datadog.DeleteKeys(additionalProperties, &[]string{"baselineUserLocations"})
137+
datadog.DeleteKeys(additionalProperties, &[]string{"baselineUserLocations", "baselineUserLocationsDuration"})
93138
} else {
94139
return err
95140
}
96141
o.BaselineUserLocations = all.BaselineUserLocations
142+
o.BaselineUserLocationsDuration = all.BaselineUserLocationsDuration
97143

98144
if len(additionalProperties) > 0 {
99145
o.AdditionalProperties = additionalProperties
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Create a detection rule with type 'impossible_travel' and baselineUserLocationsDuration returns "OK" response
2+
3+
package main
4+
5+
import (
6+
"context"
7+
"encoding/json"
8+
"fmt"
9+
"os"
10+
11+
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
12+
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
13+
)
14+
15+
func main() {
16+
body := datadogV2.SecurityMonitoringRuleCreatePayload{
17+
SecurityMonitoringStandardRuleCreatePayload: &datadogV2.SecurityMonitoringStandardRuleCreatePayload{
18+
Queries: []datadogV2.SecurityMonitoringStandardRuleQuery{
19+
{
20+
Aggregation: datadogV2.SECURITYMONITORINGRULEQUERYAGGREGATION_GEO_DATA.Ptr(),
21+
GroupByFields: []string{
22+
"@usr.id",
23+
},
24+
DistinctFields: []string{},
25+
Metric: datadog.PtrString("@network.client.geoip"),
26+
Query: datadog.PtrString("*"),
27+
},
28+
},
29+
Cases: []datadogV2.SecurityMonitoringRuleCaseCreate{
30+
{
31+
Name: datadog.PtrString(""),
32+
Status: datadogV2.SECURITYMONITORINGRULESEVERITY_INFO,
33+
Notifications: []string{},
34+
},
35+
},
36+
HasExtendedTitle: datadog.PtrBool(true),
37+
Message: "test",
38+
IsEnabled: true,
39+
Options: datadogV2.SecurityMonitoringRuleOptions{
40+
MaxSignalDuration: datadogV2.SECURITYMONITORINGRULEMAXSIGNALDURATION_ONE_DAY.Ptr(),
41+
EvaluationWindow: datadogV2.SECURITYMONITORINGRULEEVALUATIONWINDOW_FIFTEEN_MINUTES.Ptr(),
42+
KeepAlive: datadogV2.SECURITYMONITORINGRULEKEEPALIVE_ONE_HOUR.Ptr(),
43+
DetectionMethod: datadogV2.SECURITYMONITORINGRULEDETECTIONMETHOD_IMPOSSIBLE_TRAVEL.Ptr(),
44+
ImpossibleTravelOptions: &datadogV2.SecurityMonitoringRuleImpossibleTravelOptions{
45+
BaselineUserLocations: datadog.PtrBool(true),
46+
BaselineUserLocationsDuration: *datadog.NewNullableInt32(datadog.PtrInt32(7)),
47+
},
48+
},
49+
Name: "Example-Security-Monitoring",
50+
Type: datadogV2.SECURITYMONITORINGRULETYPECREATE_LOG_DETECTION.Ptr(),
51+
Tags: []string{},
52+
Filters: []datadogV2.SecurityMonitoringFilter{},
53+
}}
54+
ctx := datadog.NewDefaultContext(context.Background())
55+
configuration := datadog.NewConfiguration()
56+
apiClient := datadog.NewAPIClient(configuration)
57+
api := datadogV2.NewSecurityMonitoringApi(apiClient)
58+
resp, r, err := api.CreateSecurityMonitoringRule(ctx, body)
59+
60+
if err != nil {
61+
fmt.Fprintf(os.Stderr, "Error when calling `SecurityMonitoringApi.CreateSecurityMonitoringRule`: %v\n", err)
62+
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
63+
}
64+
65+
responseContent, _ := json.MarshalIndent(resp, "", " ")
66+
fmt.Fprintf(os.Stdout, "Response from `SecurityMonitoringApi.CreateSecurityMonitoringRule`:\n%s\n", responseContent)
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2026-05-20T15:12:27.397Z
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
interactions:
2+
- request:
3+
body: |
4+
{"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"}
5+
form: {}
6+
headers:
7+
Accept:
8+
- application/json
9+
Content-Type:
10+
- application/json
11+
id: 0
12+
method: POST
13+
url: https://api.datadoghq.com/api/v2/security_monitoring/rules
14+
response:
15+
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
16+
Account"},"updater":{"handle":"","name":""}}'
17+
code: 200
18+
duration: 0ms
19+
headers:
20+
Content-Type:
21+
- application/json
22+
status: 200 OK
23+
- request:
24+
body: ''
25+
form: {}
26+
headers:
27+
Accept:
28+
- '*/*'
29+
id: 1
30+
method: DELETE
31+
url: https://api.datadoghq.com/api/v2/security_monitoring/rules/v2k-viu-svz
32+
response:
33+
body: ''
34+
code: 204
35+
duration: 0ms
36+
headers: {}
37+
status: 204 No Content
38+
version: 2

tests/scenarios/features/v2/security_monitoring.feature

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,19 @@ Feature: Security Monitoring
559559
And the response "type" is equal to "application_security"
560560
And the response "message" is equal to "Test rule"
561561

562+
@skip-validation @team:DataDog/k9-cloud-siem
563+
Scenario: Create a detection rule with type 'impossible_travel' and baselineUserLocationsDuration returns "OK" response
564+
Given new "CreateSecurityMonitoringRule" request
565+
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":[]}
566+
When the request is sent
567+
Then the response status is 200 OK
568+
And the response "name" is equal to "{{ unique }}"
569+
And the response "type" is equal to "log_detection"
570+
And the response "message" is equal to "test"
571+
And the response "options.detectionMethod" is equal to "impossible_travel"
572+
And the response "options.impossibleTravelOptions.baselineUserLocations" is equal to true
573+
And the response "options.impossibleTravelOptions.baselineUserLocationsDuration" is equal to 7
574+
562575
@skip-validation @team:DataDog/k9-cloud-siem
563576
Scenario: Create a detection rule with type 'impossible_travel' returns "OK" response
564577
Given new "CreateSecurityMonitoringRule" request

0 commit comments

Comments
 (0)