Skip to content

Commit df1607e

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add user behavior case actions in API spec (#596)
Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 381b731 commit df1607e

8 files changed

+58
-22
lines changed

.apigentools-info

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
"spec_versions": {
55
"v1": {
66
"apigentools_version": "1.6.6",
7-
"regenerated": "2025-04-10 11:41:51.981428",
8-
"spec_repo_commit": "7f98e0a9"
7+
"regenerated": "2025-04-10 18:01:28.069893",
8+
"spec_repo_commit": "c0a45137"
99
},
1010
"v2": {
1111
"apigentools_version": "1.6.6",
12-
"regenerated": "2025-04-10 11:41:52.001570",
13-
"spec_repo_commit": "7f98e0a9"
12+
"regenerated": "2025-04-10 18:01:28.087415",
13+
"spec_repo_commit": "c0a45137"
1414
}
1515
}
1616
}

.generator/schemas/v2/openapi.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27215,6 +27215,7 @@ components:
2721527215
$ref: '#/components/schemas/SecurityMonitoringRuleCaseActionType'
2721627216
type: object
2721727217
SecurityMonitoringRuleCaseActionOptions:
27218+
additionalProperties: {}
2721827219
description: Options for the rule action
2721927220
properties:
2722027221
duration:
@@ -27223,16 +27224,24 @@ components:
2722327224
format: int64
2722427225
minimum: 0
2722527226
type: integer
27227+
userBehaviorName:
27228+
$ref: '#/components/schemas/SecurityMonitoringRuleCaseActionOptionsUserBehaviorName'
2722627229
type: object
27230+
SecurityMonitoringRuleCaseActionOptionsUserBehaviorName:
27231+
description: Used with the case action of type 'user_behavior'. The value specified
27232+
in this field is applied as a risk tag to all users affected by the rule.
27233+
type: string
2722727234
SecurityMonitoringRuleCaseActionType:
2722827235
description: The action type.
2722927236
enum:
2723027237
- block_ip
2723127238
- block_user
27239+
- user_behavior
2723227240
type: string
2723327241
x-enum-varnames:
2723427242
- BLOCK_IP
2723527243
- BLOCK_USER
27244+
- USER_BEHAVIOR
2723627245
SecurityMonitoringRuleCaseCreate:
2723727246
description: Case when signal is generated.
2723827247
properties:

examples/v2_security-monitoring_CreateSecurityMonitoringRule_1965169892.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,19 @@ async fn main() {
2424
SecurityMonitoringStandardRuleCreatePayload::new(
2525
vec![
2626
SecurityMonitoringRuleCaseCreate::new(SecurityMonitoringRuleSeverity::INFO)
27-
.actions(vec![SecurityMonitoringRuleCaseAction::new()
28-
.options(SecurityMonitoringRuleCaseActionOptions::new().duration(900))
29-
.type_(SecurityMonitoringRuleCaseActionType::BLOCK_IP)])
27+
.actions(vec![
28+
SecurityMonitoringRuleCaseAction::new()
29+
.options(
30+
SecurityMonitoringRuleCaseActionOptions::new().duration(900),
31+
)
32+
.type_(SecurityMonitoringRuleCaseActionType::BLOCK_IP),
33+
SecurityMonitoringRuleCaseAction::new()
34+
.options(
35+
SecurityMonitoringRuleCaseActionOptions::new()
36+
.user_behavior_name("behavior".to_string()),
37+
)
38+
.type_(SecurityMonitoringRuleCaseActionType::USER_BEHAVIOR),
39+
])
3040
.condition("a > 100000".to_string())
3141
.name("".to_string())
3242
.notifications(vec![]),

src/datadogV2/model/model_security_monitoring_rule_case_action_options.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ pub struct SecurityMonitoringRuleCaseActionOptions {
1414
/// Duration of the action in seconds. 0 indicates no expiration.
1515
#[serde(rename = "duration")]
1616
pub duration: Option<i64>,
17+
/// Used with the case action of type 'user_behavior'. The value specified in this field is applied as a risk tag to all users affected by the rule.
18+
#[serde(rename = "userBehaviorName")]
19+
pub user_behavior_name: Option<String>,
1720
#[serde(flatten)]
1821
pub additional_properties: std::collections::BTreeMap<String, serde_json::Value>,
1922
#[serde(skip)]
@@ -25,6 +28,7 @@ impl SecurityMonitoringRuleCaseActionOptions {
2528
pub fn new() -> SecurityMonitoringRuleCaseActionOptions {
2629
SecurityMonitoringRuleCaseActionOptions {
2730
duration: None,
31+
user_behavior_name: None,
2832
additional_properties: std::collections::BTreeMap::new(),
2933
_unparsed: false,
3034
}
@@ -35,6 +39,11 @@ impl SecurityMonitoringRuleCaseActionOptions {
3539
self
3640
}
3741

42+
pub fn user_behavior_name(mut self, value: String) -> Self {
43+
self.user_behavior_name = Some(value);
44+
self
45+
}
46+
3847
pub fn additional_properties(
3948
mut self,
4049
value: std::collections::BTreeMap<String, serde_json::Value>,
@@ -68,6 +77,7 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleCaseActionOptions {
6877
M: MapAccess<'a>,
6978
{
7079
let mut duration: Option<i64> = None;
80+
let mut user_behavior_name: Option<String> = None;
7181
let mut additional_properties: std::collections::BTreeMap<
7282
String,
7383
serde_json::Value,
@@ -82,6 +92,13 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleCaseActionOptions {
8292
}
8393
duration = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
8494
}
95+
"userBehaviorName" => {
96+
if v.is_null() {
97+
continue;
98+
}
99+
user_behavior_name =
100+
Some(serde_json::from_value(v).map_err(M::Error::custom)?);
101+
}
85102
&_ => {
86103
if let Ok(value) = serde_json::from_value(v.clone()) {
87104
additional_properties.insert(k, value);
@@ -92,6 +109,7 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleCaseActionOptions {
92109

93110
let content = SecurityMonitoringRuleCaseActionOptions {
94111
duration,
112+
user_behavior_name,
95113
additional_properties,
96114
_unparsed,
97115
};

src/datadogV2/model/model_security_monitoring_rule_case_action_type.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
99
pub enum SecurityMonitoringRuleCaseActionType {
1010
BLOCK_IP,
1111
BLOCK_USER,
12+
USER_BEHAVIOR,
1213
UnparsedObject(crate::datadog::UnparsedObject),
1314
}
1415

@@ -17,6 +18,7 @@ impl ToString for SecurityMonitoringRuleCaseActionType {
1718
match self {
1819
Self::BLOCK_IP => String::from("block_ip"),
1920
Self::BLOCK_USER => String::from("block_user"),
21+
Self::USER_BEHAVIOR => String::from("user_behavior"),
2022
Self::UnparsedObject(v) => v.value.to_string(),
2123
}
2224
}
@@ -43,6 +45,7 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleCaseActionType {
4345
Ok(match s.as_str() {
4446
"block_ip" => Self::BLOCK_IP,
4547
"block_user" => Self::BLOCK_USER,
48+
"user_behavior" => Self::USER_BEHAVIOR,
4649
_ => Self::UnparsedObject(crate::datadog::UnparsedObject {
4750
value: serde_json::Value::String(s.into()),
4851
}),
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2025-02-06T16:50:39.787Z
1+
2025-04-09T15:02:05.047Z

tests/scenarios/cassettes/v2/security_monitoring/Create-a-detection-rule-with-type-application-security-returns-OK-response.json

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{
44
"request": {
55
"body": {
6-
"string": "{\"cases\":[{\"actions\":[{\"options\":{\"duration\":900},\"type\":\"block_ip\"}],\"condition\":\"a > 100000\",\"name\":\"\",\"notifications\":[],\"status\":\"info\"}],\"filters\":[],\"groupSignalsBy\":[\"service\"],\"isEnabled\":true,\"message\":\"Test rule\",\"name\":\"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1738860639_appsec_rule\",\"options\":{\"detectionMethod\":\"threshold\",\"evaluationWindow\":900,\"keepAlive\":3600,\"maxSignalDuration\":86400},\"queries\":[{\"aggregation\":\"count\",\"distinctFields\":[],\"groupByFields\":[\"service\",\"@http.client_ip\"],\"query\":\"@appsec.security_activity:business_logic.users.login.failure\"}],\"tags\":[],\"type\":\"application_security\"}",
6+
"string": "{\"cases\":[{\"actions\":[{\"options\":{\"duration\":900},\"type\":\"block_ip\"},{\"options\":{\"userBehaviorName\":\"behavior\"},\"type\":\"user_behavior\"}],\"condition\":\"a > 100000\",\"name\":\"\",\"notifications\":[],\"status\":\"info\"}],\"filters\":[],\"groupSignalsBy\":[\"service\"],\"isEnabled\":true,\"message\":\"Test rule\",\"name\":\"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1744210925_appsec_rule\",\"options\":{\"detectionMethod\":\"threshold\",\"evaluationWindow\":900,\"keepAlive\":3600,\"maxSignalDuration\":86400},\"queries\":[{\"aggregation\":\"count\",\"distinctFields\":[],\"groupByFields\":[\"service\",\"@http.client_ip\"],\"query\":\"@appsec.security_activity:business_logic.users.login.failure\"}],\"tags\":[],\"type\":\"application_security\"}",
77
"encoding": null
88
},
99
"headers": {
@@ -19,7 +19,7 @@
1919
},
2020
"response": {
2121
"body": {
22-
"string": "{\"name\":\"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1738860639_appsec_rule\",\"createdAt\":1738860640426,\"isDefault\":false,\"isPartner\":false,\"isEnabled\":true,\"isBeta\":false,\"isDeleted\":false,\"isDeprecated\":false,\"queries\":[{\"query\":\"@appsec.security_activity:business_logic.users.login.failure\",\"groupByFields\":[\"service\",\"@http.client_ip\"],\"hasOptionalGroupByFields\":false,\"distinctFields\":[],\"aggregation\":\"count\",\"name\":\"\",\"dataSource\":\"app_sec_spans\"}],\"options\":{\"evaluationWindow\":900,\"detectionMethod\":\"threshold\",\"maxSignalDuration\":86400,\"keepAlive\":3600},\"cases\":[{\"name\":\"\",\"status\":\"info\",\"notifications\":[],\"condition\":\"a \\u003e 100000\",\"actions\":[{\"type\":\"block_ip\",\"options\":{\"duration\":900}}]}],\"message\":\"Test rule\",\"tags\":[],\"hasExtendedTitle\":false,\"type\":\"application_security\",\"filters\":[],\"version\":1,\"id\":\"rfn-h2v-udr\",\"blocking\":true,\"groupSignalsBy\":[\"service\"],\"casesActions\":[[{\"type\":\"block_ip\",\"options\":{\"duration\":900}}]],\"dependencies\":[\"business_logic.users.login.failure\"],\"metadata\":{\"entities\":null,\"sources\":null},\"creator\":{\"handle\":\"\",\"name\":\"\"},\"updater\":{\"handle\":\"\",\"name\":\"\"}}",
22+
"string": "{\"name\":\"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1744210925_appsec_rule\",\"createdAt\":1744210925675,\"isDefault\":false,\"isPartner\":false,\"isEnabled\":true,\"isBeta\":false,\"isDeleted\":false,\"isDeprecated\":false,\"queries\":[{\"query\":\"@appsec.security_activity:business_logic.users.login.failure\",\"groupByFields\":[\"service\",\"@http.client_ip\"],\"hasOptionalGroupByFields\":false,\"distinctFields\":[],\"aggregation\":\"count\",\"name\":\"\",\"dataSource\":\"app_sec_spans\"}],\"options\":{\"evaluationWindow\":900,\"detectionMethod\":\"threshold\",\"maxSignalDuration\":86400,\"keepAlive\":3600},\"cases\":[{\"name\":\"\",\"status\":\"info\",\"notifications\":[],\"condition\":\"a \\u003e 100000\",\"actions\":[{\"type\":\"block_ip\",\"options\":{\"duration\":900}},{\"type\":\"user_behavior\",\"options\":{\"userBehaviorName\":\"behavior\"}}]}],\"message\":\"Test rule\",\"tags\":[],\"hasExtendedTitle\":false,\"type\":\"application_security\",\"filters\":[],\"version\":1,\"id\":\"lfr-zxg-fyc\",\"blocking\":true,\"groupSignalsBy\":[\"service\"],\"dependencies\":[\"business_logic.users.login.failure\"],\"metadata\":{\"entities\":null,\"sources\":null},\"creationAuthorId\":2320499,\"creator\":{\"handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"name\":\"CI Account\"},\"updater\":{\"handle\":\"\",\"name\":\"\"}}",
2323
"encoding": null
2424
},
2525
"headers": {
@@ -32,7 +32,7 @@
3232
"message": "OK"
3333
}
3434
},
35-
"recorded_at": "Thu, 06 Feb 2025 16:50:39 GMT"
35+
"recorded_at": "Wed, 09 Apr 2025 15:02:05 GMT"
3636
},
3737
{
3838
"request": {
@@ -43,24 +43,20 @@
4343
]
4444
},
4545
"method": "delete",
46-
"uri": "https://api.datadoghq.com/api/v2/security_monitoring/rules/rfn-h2v-udr"
46+
"uri": "https://api.datadoghq.com/api/v2/security_monitoring/rules/lfr-zxg-fyc"
4747
},
4848
"response": {
4949
"body": {
50-
"string": "{\"status\":\"404\",\"title\":\"Not Found\"}",
50+
"string": "",
5151
"encoding": null
5252
},
53-
"headers": {
54-
"Content-Type": [
55-
"application/json"
56-
]
57-
},
53+
"headers": {},
5854
"status": {
59-
"code": 404,
60-
"message": "Not Found"
55+
"code": 204,
56+
"message": "No Content"
6157
}
6258
},
63-
"recorded_at": "Thu, 06 Feb 2025 16:50:39 GMT"
59+
"recorded_at": "Wed, 09 Apr 2025 15:02:05 GMT"
6460
}
6561
],
6662
"recorded_with": "VCR 6.0.0"

tests/scenarios/features/v2/security_monitoring.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ Feature: Security Monitoring
203203
@skip-validation @team:DataDog/k9-cloud-security-platform
204204
Scenario: Create a detection rule with type 'application_security 'returns "OK" response
205205
Given new "CreateSecurityMonitoringRule" request
206-
And body with value {"type":"application_security","name":"{{unique}}_appsec_rule","queries":[{"query":"@appsec.security_activity:business_logic.users.login.failure","aggregation":"count","groupByFields":["service","@http.client_ip"],"distinctFields":[]}],"filters":[],"cases":[{"name":"","status":"info","notifications":[],"condition":"a > 100000","actions":[{"type":"block_ip","options":{"duration":900}}]}],"options":{"keepAlive":3600,"maxSignalDuration":86400,"evaluationWindow":900,"detectionMethod":"threshold"},"isEnabled":true,"message":"Test rule","tags":[],"groupSignalsBy":["service"]}
206+
And body with value {"type":"application_security","name":"{{unique}}_appsec_rule","queries":[{"query":"@appsec.security_activity:business_logic.users.login.failure","aggregation":"count","groupByFields":["service","@http.client_ip"],"distinctFields":[]}],"filters":[],"cases":[{"name":"","status":"info","notifications":[],"condition":"a > 100000","actions":[{"type":"block_ip","options":{"duration":900}}, {"type":"user_behavior","options":{"userBehaviorName":"behavior"}}]}],"options":{"keepAlive":3600,"maxSignalDuration":86400,"evaluationWindow":900,"detectionMethod":"threshold"},"isEnabled":true,"message":"Test rule","tags":[],"groupSignalsBy":["service"]}
207207
When the request is sent
208208
Then the response status is 200 OK
209209
And the response "name" is equal to "{{ unique }}_appsec_rule"

0 commit comments

Comments
 (0)