Skip to content

Commit cf7bdfe

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add sequence detection to security monitoring rules (#914)
Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 3c4c3b3 commit cf7bdfe

15 files changed

+849
-0
lines changed

.generator/schemas/v2/openapi.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20470,6 +20470,8 @@ components:
2047020470
$ref: '#/components/schemas/SecurityMonitoringRuleMaxSignalDuration'
2047120471
newValueOptions:
2047220472
$ref: '#/components/schemas/SecurityMonitoringRuleNewValueOptions'
20473+
sequenceDetectionOptions:
20474+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionOptions'
2047320475
thirdPartyRuleOptions:
2047420476
$ref: '#/components/schemas/SecurityMonitoringRuleThirdPartyOptions'
2047520477
type: object
@@ -40786,6 +40788,7 @@ components:
4078640788
- hardcoded
4078740789
- third_party
4078840790
- anomaly_threshold
40791+
- sequence_detection
4078940792
type: string
4079040793
x-enum-varnames:
4079140794
- THRESHOLD
@@ -40795,6 +40798,7 @@ components:
4079540798
- HARDCODED
4079640799
- THIRD_PARTY
4079740800
- ANOMALY_THRESHOLD
40801+
- SEQUENCE_DETECTION
4079840802
SecurityMonitoringRuleEvaluationWindow:
4079940803
description: 'A time window is specified to match when at least one of the cases
4080040804
matches true. This is a sliding window
@@ -41008,6 +41012,8 @@ components:
4100841012
$ref: '#/components/schemas/SecurityMonitoringRuleMaxSignalDuration'
4100941013
newValueOptions:
4101041014
$ref: '#/components/schemas/SecurityMonitoringRuleNewValueOptions'
41015+
sequenceDetectionOptions:
41016+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionOptions'
4101141017
thirdPartyRuleOptions:
4101241018
$ref: '#/components/schemas/SecurityMonitoringRuleThirdPartyOptions'
4101341019
type: object
@@ -41083,6 +41089,47 @@ components:
4108341089
oneOf:
4108441090
- $ref: '#/components/schemas/SecurityMonitoringStandardRuleResponse'
4108541091
- $ref: '#/components/schemas/SecurityMonitoringSignalRuleResponse'
41092+
SecurityMonitoringRuleSequenceDetectionOptions:
41093+
description: Options on sequence detection method.
41094+
properties:
41095+
stepTransitions:
41096+
description: Transitions defining the allowed order of steps and their evaluation
41097+
windows.
41098+
items:
41099+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionStepTransition'
41100+
type: array
41101+
steps:
41102+
description: Steps that define the conditions to be matched in sequence.
41103+
items:
41104+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionStep'
41105+
type: array
41106+
type: object
41107+
SecurityMonitoringRuleSequenceDetectionStep:
41108+
description: Step definition for sequence detection containing the step name,
41109+
condition, and evaluation window.
41110+
properties:
41111+
condition:
41112+
description: Condition referencing rule queries (e.g., `a > 0`).
41113+
type: string
41114+
evaluationWindow:
41115+
$ref: '#/components/schemas/SecurityMonitoringRuleEvaluationWindow'
41116+
name:
41117+
description: Unique name identifying the step.
41118+
type: string
41119+
type: object
41120+
SecurityMonitoringRuleSequenceDetectionStepTransition:
41121+
description: Transition from a parent step to a child step within a sequence
41122+
detection rule.
41123+
properties:
41124+
child:
41125+
description: Name of the child step.
41126+
type: string
41127+
evaluationWindow:
41128+
$ref: '#/components/schemas/SecurityMonitoringRuleEvaluationWindow'
41129+
parent:
41130+
description: Name of the parent step.
41131+
type: string
41132+
type: object
4108641133
SecurityMonitoringRuleSeverity:
4108741134
description: Severity of the Security Signal.
4108841135
enum:
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Create a detection rule with detection method 'sequence_detection' returns "OK"
2+
// response
3+
use datadog_api_client::datadog;
4+
use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI;
5+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleCaseCreate;
6+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleCreatePayload;
7+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleDetectionMethod;
8+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleEvaluationWindow;
9+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleKeepAlive;
10+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleMaxSignalDuration;
11+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleOptions;
12+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleQueryAggregation;
13+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSequenceDetectionOptions;
14+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSequenceDetectionStep;
15+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSequenceDetectionStepTransition;
16+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSeverity;
17+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleTypeCreate;
18+
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardDataSource;
19+
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardRuleCreatePayload;
20+
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardRuleQuery;
21+
22+
#[tokio::main]
23+
async fn main() {
24+
let body =
25+
SecurityMonitoringRuleCreatePayload::SecurityMonitoringStandardRuleCreatePayload(Box::new(
26+
SecurityMonitoringStandardRuleCreatePayload::new(
27+
vec![
28+
SecurityMonitoringRuleCaseCreate::new(SecurityMonitoringRuleSeverity::INFO)
29+
.condition("step_b > 0".to_string())
30+
.name("".to_string())
31+
.notifications(vec![]),
32+
],
33+
true,
34+
"Logs and signals asdf".to_string(),
35+
"Example-Security-Monitoring".to_string(),
36+
SecurityMonitoringRuleOptions::new()
37+
.detection_method(SecurityMonitoringRuleDetectionMethod::SEQUENCE_DETECTION)
38+
.evaluation_window(SecurityMonitoringRuleEvaluationWindow::ZERO_MINUTES)
39+
.keep_alive(SecurityMonitoringRuleKeepAlive::FIVE_MINUTES)
40+
.max_signal_duration(SecurityMonitoringRuleMaxSignalDuration::TEN_MINUTES)
41+
.sequence_detection_options(
42+
SecurityMonitoringRuleSequenceDetectionOptions::new()
43+
.step_transitions(vec![
44+
SecurityMonitoringRuleSequenceDetectionStepTransition::new()
45+
.child("step_b".to_string())
46+
.evaluation_window(
47+
SecurityMonitoringRuleEvaluationWindow::FIFTEEN_MINUTES,
48+
)
49+
.parent("step_a".to_string()),
50+
])
51+
.steps(vec![
52+
SecurityMonitoringRuleSequenceDetectionStep::new()
53+
.condition("a > 0".to_string())
54+
.evaluation_window(
55+
SecurityMonitoringRuleEvaluationWindow::ONE_MINUTE,
56+
)
57+
.name("step_a".to_string()),
58+
SecurityMonitoringRuleSequenceDetectionStep::new()
59+
.condition("b > 0".to_string())
60+
.evaluation_window(
61+
SecurityMonitoringRuleEvaluationWindow::ONE_MINUTE,
62+
)
63+
.name("step_b".to_string()),
64+
]),
65+
),
66+
vec![
67+
SecurityMonitoringStandardRuleQuery::new()
68+
.aggregation(SecurityMonitoringRuleQueryAggregation::COUNT)
69+
.data_source(SecurityMonitoringStandardDataSource::LOGS)
70+
.distinct_fields(vec![])
71+
.group_by_fields(vec![])
72+
.has_optional_group_by_fields(false)
73+
.name("".to_string())
74+
.query("service:logs-rule-reducer source:paul test2".to_string()),
75+
SecurityMonitoringStandardRuleQuery::new()
76+
.aggregation(SecurityMonitoringRuleQueryAggregation::COUNT)
77+
.data_source(SecurityMonitoringStandardDataSource::LOGS)
78+
.distinct_fields(vec![])
79+
.group_by_fields(vec![])
80+
.has_optional_group_by_fields(false)
81+
.name("".to_string())
82+
.query("service:logs-rule-reducer source:paul test1".to_string()),
83+
],
84+
)
85+
.tags(vec![])
86+
.type_(SecurityMonitoringRuleTypeCreate::LOG_DETECTION),
87+
));
88+
let configuration = datadog::Configuration::new();
89+
let api = SecurityMonitoringAPI::with_config(configuration);
90+
let resp = api.create_security_monitoring_rule(body).await;
91+
if let Ok(value) = resp {
92+
println!("{:#?}", value);
93+
} else {
94+
println!("{:#?}", resp.unwrap_err());
95+
}
96+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Validate a detection rule with detection method 'sequence_detection' returns
2+
// "OK" response
3+
use datadog_api_client::datadog;
4+
use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI;
5+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleCaseCreate;
6+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleDetectionMethod;
7+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleEvaluationWindow;
8+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleKeepAlive;
9+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleMaxSignalDuration;
10+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleOptions;
11+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleQueryAggregation;
12+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSequenceDetectionOptions;
13+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSequenceDetectionStep;
14+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSequenceDetectionStepTransition;
15+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSeverity;
16+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleTypeCreate;
17+
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleValidatePayload;
18+
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardRulePayload;
19+
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardRuleQuery;
20+
21+
#[tokio::main]
22+
async fn main() {
23+
let body =
24+
SecurityMonitoringRuleValidatePayload::SecurityMonitoringStandardRulePayload(Box::new(
25+
SecurityMonitoringStandardRulePayload::new(
26+
vec![
27+
SecurityMonitoringRuleCaseCreate::new(SecurityMonitoringRuleSeverity::INFO)
28+
.condition("step_b > 0".to_string())
29+
.name("".to_string())
30+
.notifications(vec![]),
31+
],
32+
true,
33+
"My security monitoring rule".to_string(),
34+
"My security monitoring rule".to_string(),
35+
SecurityMonitoringRuleOptions::new()
36+
.detection_method(SecurityMonitoringRuleDetectionMethod::SEQUENCE_DETECTION)
37+
.evaluation_window(SecurityMonitoringRuleEvaluationWindow::ZERO_MINUTES)
38+
.keep_alive(SecurityMonitoringRuleKeepAlive::FIVE_MINUTES)
39+
.max_signal_duration(SecurityMonitoringRuleMaxSignalDuration::TEN_MINUTES)
40+
.sequence_detection_options(
41+
SecurityMonitoringRuleSequenceDetectionOptions::new()
42+
.step_transitions(vec![
43+
SecurityMonitoringRuleSequenceDetectionStepTransition::new()
44+
.child("step_b".to_string())
45+
.evaluation_window(
46+
SecurityMonitoringRuleEvaluationWindow::FIFTEEN_MINUTES,
47+
)
48+
.parent("step_a".to_string()),
49+
])
50+
.steps(vec![
51+
SecurityMonitoringRuleSequenceDetectionStep::new()
52+
.condition("a > 0".to_string())
53+
.evaluation_window(
54+
SecurityMonitoringRuleEvaluationWindow::ONE_MINUTE,
55+
)
56+
.name("step_a".to_string()),
57+
SecurityMonitoringRuleSequenceDetectionStep::new()
58+
.condition("b > 0".to_string())
59+
.evaluation_window(
60+
SecurityMonitoringRuleEvaluationWindow::ONE_MINUTE,
61+
)
62+
.name("step_b".to_string()),
63+
]),
64+
),
65+
vec![
66+
SecurityMonitoringStandardRuleQuery::new()
67+
.aggregation(SecurityMonitoringRuleQueryAggregation::COUNT)
68+
.distinct_fields(vec![])
69+
.group_by_fields(vec!["@userIdentity.assumed_role".to_string()])
70+
.name("".to_string())
71+
.query("source:source_here".to_string()),
72+
SecurityMonitoringStandardRuleQuery::new()
73+
.aggregation(SecurityMonitoringRuleQueryAggregation::COUNT)
74+
.distinct_fields(vec![])
75+
.group_by_fields(vec![])
76+
.name("".to_string())
77+
.query("source:source_here2".to_string()),
78+
],
79+
)
80+
.has_extended_title(true)
81+
.tags(vec!["env:prod".to_string(), "team:security".to_string()])
82+
.type_(SecurityMonitoringRuleTypeCreate::LOG_DETECTION),
83+
));
84+
let configuration = datadog::Configuration::new();
85+
let api = SecurityMonitoringAPI::with_config(configuration);
86+
let resp = api.validate_security_monitoring_rule(body).await;
87+
if let Ok(value) = resp {
88+
println!("{:#?}", value);
89+
} else {
90+
println!("{:#?}", resp.unwrap_err());
91+
}
92+
}

src/datadogV2/model/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5222,6 +5222,12 @@ pub mod model_security_monitoring_rule_new_value_options_learning_method;
52225222
pub use self::model_security_monitoring_rule_new_value_options_learning_method::SecurityMonitoringRuleNewValueOptionsLearningMethod;
52235223
pub mod model_security_monitoring_rule_new_value_options_learning_threshold;
52245224
pub use self::model_security_monitoring_rule_new_value_options_learning_threshold::SecurityMonitoringRuleNewValueOptionsLearningThreshold;
5225+
pub mod model_security_monitoring_rule_sequence_detection_options;
5226+
pub use self::model_security_monitoring_rule_sequence_detection_options::SecurityMonitoringRuleSequenceDetectionOptions;
5227+
pub mod model_security_monitoring_rule_sequence_detection_step_transition;
5228+
pub use self::model_security_monitoring_rule_sequence_detection_step_transition::SecurityMonitoringRuleSequenceDetectionStepTransition;
5229+
pub mod model_security_monitoring_rule_sequence_detection_step;
5230+
pub use self::model_security_monitoring_rule_sequence_detection_step::SecurityMonitoringRuleSequenceDetectionStep;
52255231
pub mod model_security_monitoring_rule_third_party_options;
52265232
pub use self::model_security_monitoring_rule_third_party_options::SecurityMonitoringRuleThirdPartyOptions;
52275233
pub mod model_security_monitoring_third_party_root_query;

src/datadogV2/model/model_historical_job_options.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ pub struct HistoricalJobOptions {
3434
/// Options on new value detection method.
3535
#[serde(rename = "newValueOptions")]
3636
pub new_value_options: Option<crate::datadogV2::model::SecurityMonitoringRuleNewValueOptions>,
37+
/// Options on sequence detection method.
38+
#[serde(rename = "sequenceDetectionOptions")]
39+
pub sequence_detection_options:
40+
Option<crate::datadogV2::model::SecurityMonitoringRuleSequenceDetectionOptions>,
3741
/// Options on third party detection method.
3842
#[serde(rename = "thirdPartyRuleOptions")]
3943
pub third_party_rule_options:
@@ -54,6 +58,7 @@ impl HistoricalJobOptions {
5458
keep_alive: None,
5559
max_signal_duration: None,
5660
new_value_options: None,
61+
sequence_detection_options: None,
5762
third_party_rule_options: None,
5863
additional_properties: std::collections::BTreeMap::new(),
5964
_unparsed: false,
@@ -108,6 +113,14 @@ impl HistoricalJobOptions {
108113
self
109114
}
110115

116+
pub fn sequence_detection_options(
117+
mut self,
118+
value: crate::datadogV2::model::SecurityMonitoringRuleSequenceDetectionOptions,
119+
) -> Self {
120+
self.sequence_detection_options = Some(value);
121+
self
122+
}
123+
111124
pub fn third_party_rule_options(
112125
mut self,
113126
value: crate::datadogV2::model::SecurityMonitoringRuleThirdPartyOptions,
@@ -166,6 +179,9 @@ impl<'de> Deserialize<'de> for HistoricalJobOptions {
166179
let mut new_value_options: Option<
167180
crate::datadogV2::model::SecurityMonitoringRuleNewValueOptions,
168181
> = None;
182+
let mut sequence_detection_options: Option<
183+
crate::datadogV2::model::SecurityMonitoringRuleSequenceDetectionOptions,
184+
> = None;
169185
let mut third_party_rule_options: Option<
170186
crate::datadogV2::model::SecurityMonitoringRuleThirdPartyOptions,
171187
> = None;
@@ -250,6 +266,13 @@ impl<'de> Deserialize<'de> for HistoricalJobOptions {
250266
new_value_options =
251267
Some(serde_json::from_value(v).map_err(M::Error::custom)?);
252268
}
269+
"sequenceDetectionOptions" => {
270+
if v.is_null() {
271+
continue;
272+
}
273+
sequence_detection_options =
274+
Some(serde_json::from_value(v).map_err(M::Error::custom)?);
275+
}
253276
"thirdPartyRuleOptions" => {
254277
if v.is_null() {
255278
continue;
@@ -272,6 +295,7 @@ impl<'de> Deserialize<'de> for HistoricalJobOptions {
272295
keep_alive,
273296
max_signal_duration,
274297
new_value_options,
298+
sequence_detection_options,
275299
third_party_rule_options,
276300
additional_properties,
277301
_unparsed,

src/datadogV2/model/model_security_monitoring_rule_detection_method.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub enum SecurityMonitoringRuleDetectionMethod {
1414
HARDCODED,
1515
THIRD_PARTY,
1616
ANOMALY_THRESHOLD,
17+
SEQUENCE_DETECTION,
1718
UnparsedObject(crate::datadog::UnparsedObject),
1819
}
1920

@@ -27,6 +28,7 @@ impl ToString for SecurityMonitoringRuleDetectionMethod {
2728
Self::HARDCODED => String::from("hardcoded"),
2829
Self::THIRD_PARTY => String::from("third_party"),
2930
Self::ANOMALY_THRESHOLD => String::from("anomaly_threshold"),
31+
Self::SEQUENCE_DETECTION => String::from("sequence_detection"),
3032
Self::UnparsedObject(v) => v.value.to_string(),
3133
}
3234
}
@@ -58,6 +60,7 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleDetectionMethod {
5860
"hardcoded" => Self::HARDCODED,
5961
"third_party" => Self::THIRD_PARTY,
6062
"anomaly_threshold" => Self::ANOMALY_THRESHOLD,
63+
"sequence_detection" => Self::SEQUENCE_DETECTION,
6164
_ => Self::UnparsedObject(crate::datadog::UnparsedObject {
6265
value: serde_json::Value::String(s.into()),
6366
}),

0 commit comments

Comments
 (0)