Skip to content

Support Cloud SIEM scheduled rules in API client #809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .generated-info
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"spec_repo_commit": "c5cca50",
"generated": "2025-08-07 18:08:43.875"
"spec_repo_commit": "d02c8a3",
"generated": "2025-08-08 12:12:16.900"
}
69 changes: 69 additions & 0 deletions .generator/schemas/v2/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36336,6 +36336,12 @@ components:
SecurityMonitoringRuleUpdatePayload:
description: Update an existing rule.
properties:
calculatedFields:
description: Calculated fields. Only allowed for scheduled rules - in other
words, when schedulingOptions is also defined.
items:
$ref: '#/components/schemas/CalculatedField'
type: array
cases:
description: Cases for generating signals.
items:
Expand Down Expand Up @@ -36392,6 +36398,8 @@ components:
items:
$ref: '#/components/schemas/SecurityMonitoringReferenceTable'
type: array
schedulingOptions:
$ref: '#/components/schemas/SecurityMonitoringSchedulingOptions'
tags:
description: Tags for generated signals.
items:
Expand All @@ -36418,6 +36426,27 @@ components:
- $ref: '#/components/schemas/SecurityMonitoringStandardRulePayload'
- $ref: '#/components/schemas/SecurityMonitoringSignalRulePayload'
- $ref: '#/components/schemas/CloudConfigurationRulePayload'
SecurityMonitoringSchedulingOptions:
description: Options for scheduled rules. When this field is present, the rule
runs based on the schedule. When absent, it runs real-time on ingested logs.
nullable: true
properties:
rrule:
description: Schedule for the rule queries, written in RRULE syntax. See
[RFC](https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html)
for syntax reference.
example: FREQ=HOURLY;INTERVAL=1;
type: string
start:
description: Start date for the schedule, in ISO 8601 format without timezone.
example: '2025-07-14T12:00:00'
type: string
timezone:
description: Time zone of the start date, in the [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
format.
example: America/New_York
type: string
type: object
SecurityMonitoringSignal:
description: Object description of a security signal.
properties:
Expand Down Expand Up @@ -37096,6 +37125,12 @@ components:
SecurityMonitoringStandardRuleCreatePayload:
description: Create a new rule.
properties:
calculatedFields:
description: Calculated fields. Only allowed for scheduled rules - in other
words, when schedulingOptions is also defined.
items:
$ref: '#/components/schemas/CalculatedField'
type: array
cases:
description: Cases for generating signals.
example: []
Expand Down Expand Up @@ -37148,6 +37183,8 @@ components:
items:
$ref: '#/components/schemas/SecurityMonitoringReferenceTable'
type: array
schedulingOptions:
$ref: '#/components/schemas/SecurityMonitoringSchedulingOptions'
tags:
description: Tags for generated signals.
example:
Expand Down Expand Up @@ -37177,6 +37214,12 @@ components:
SecurityMonitoringStandardRulePayload:
description: The payload of a rule.
properties:
calculatedFields:
description: Calculated fields. Only allowed for scheduled rules - in other
words, when schedulingOptions is also defined.
items:
$ref: '#/components/schemas/CalculatedField'
type: array
cases:
description: Cases for generating signals.
example: []
Expand Down Expand Up @@ -37237,6 +37280,8 @@ components:
items:
$ref: '#/components/schemas/SecurityMonitoringReferenceTable'
type: array
schedulingOptions:
$ref: '#/components/schemas/SecurityMonitoringSchedulingOptions'
tags:
description: Tags for generated signals.
example:
Expand Down Expand Up @@ -37293,6 +37338,14 @@ components:
example: false
readOnly: true
type: boolean
index:
description: '**This field is currently unstable and might be removed in
a minor version upgrade.**

The index to run the query on, if the `dataSource` is `logs`. Only used
for scheduled rules - in other words, when the `schedulingOptions` field
is present in the rule payload.'
type: string
metric:
deprecated: true
description: '(Deprecated) The target field to aggregate over when using
Expand Down Expand Up @@ -37320,6 +37373,12 @@ components:
SecurityMonitoringStandardRuleResponse:
description: Rule.
properties:
calculatedFields:
description: Calculated fields. Only allowed for scheduled rules - in other
words, when schedulingOptions is also defined.
items:
$ref: '#/components/schemas/CalculatedField'
type: array
cases:
description: Cases for generating signals.
items:
Expand Down Expand Up @@ -37405,6 +37464,8 @@ components:
items:
$ref: '#/components/schemas/SecurityMonitoringReferenceTable'
type: array
schedulingOptions:
$ref: '#/components/schemas/SecurityMonitoringSchedulingOptions'
tags:
description: Tags for generated signals.
items:
Expand Down Expand Up @@ -37436,6 +37497,12 @@ components:
SecurityMonitoringStandardRuleTestPayload:
description: The payload of a rule to test
properties:
calculatedFields:
description: Calculated fields. Only allowed for scheduled rules - in other
words, when schedulingOptions is also defined.
items:
$ref: '#/components/schemas/CalculatedField'
type: array
cases:
description: Cases for generating signals.
example: []
Expand Down Expand Up @@ -37488,6 +37555,8 @@ components:
items:
$ref: '#/components/schemas/SecurityMonitoringReferenceTable'
type: array
schedulingOptions:
$ref: '#/components/schemas/SecurityMonitoringSchedulingOptions'
tags:
description: Tags for generated signals.
example:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Create a scheduled detection rule returns "OK" response
use datadog_api_client::datadog;
use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleCaseCreate;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleCreatePayload;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleEvaluationWindow;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleKeepAlive;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleMaxSignalDuration;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleOptions;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleQueryAggregation;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleSeverity;
use datadog_api_client::datadogV2::model::SecurityMonitoringRuleTypeCreate;
use datadog_api_client::datadogV2::model::SecurityMonitoringSchedulingOptions;
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardRuleCreatePayload;
use datadog_api_client::datadogV2::model::SecurityMonitoringStandardRuleQuery;

#[tokio::main]
async fn main() {
let body =
SecurityMonitoringRuleCreatePayload::SecurityMonitoringStandardRuleCreatePayload(Box::new(
SecurityMonitoringStandardRuleCreatePayload::new(
vec![
SecurityMonitoringRuleCaseCreate::new(SecurityMonitoringRuleSeverity::INFO)
.condition("a > 0".to_string())
.name("".to_string())
.notifications(vec![]),
],
true,
"Test rule".to_string(),
"Example-Security-Monitoring".to_string(),
SecurityMonitoringRuleOptions::new()
.evaluation_window(SecurityMonitoringRuleEvaluationWindow::FIFTEEN_MINUTES)
.keep_alive(SecurityMonitoringRuleKeepAlive::ONE_HOUR)
.max_signal_duration(SecurityMonitoringRuleMaxSignalDuration::ONE_DAY),
vec![SecurityMonitoringStandardRuleQuery::new()
.aggregation(SecurityMonitoringRuleQueryAggregation::COUNT)
.distinct_fields(vec![])
.group_by_fields(vec![])
.index("main".to_string())
.query("@test:true".to_string())],
)
.filters(vec![])
.scheduling_options(Some(
SecurityMonitoringSchedulingOptions::new()
.rrule("FREQ=HOURLY;INTERVAL=2;".to_string())
.start("2025-06-18T12:00:00".to_string())
.timezone("Europe/Paris".to_string()),
))
.tags(vec![])
.type_(SecurityMonitoringRuleTypeCreate::LOG_DETECTION),
));
let configuration = datadog::Configuration::new();
let api = SecurityMonitoringAPI::with_config(configuration);
let resp = api.create_security_monitoring_rule(body).await;
if let Ok(value) = resp {
println!("{:#?}", value);
} else {
println!("{:#?}", resp.unwrap_err());
}
}
6 changes: 4 additions & 2 deletions src/datadogV2/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4656,6 +4656,8 @@ pub mod model_security_monitoring_list_rules_response;
pub use self::model_security_monitoring_list_rules_response::SecurityMonitoringListRulesResponse;
pub mod model_security_monitoring_standard_rule_response;
pub use self::model_security_monitoring_standard_rule_response::SecurityMonitoringStandardRuleResponse;
pub mod model_calculated_field;
pub use self::model_calculated_field::CalculatedField;
pub mod model_security_monitoring_rule_case;
pub use self::model_security_monitoring_rule_case::SecurityMonitoringRuleCase;
pub mod model_security_monitoring_rule_case_action;
Expand Down Expand Up @@ -4714,6 +4716,8 @@ pub mod model_security_monitoring_standard_data_source;
pub use self::model_security_monitoring_standard_data_source::SecurityMonitoringStandardDataSource;
pub mod model_security_monitoring_reference_table;
pub use self::model_security_monitoring_reference_table::SecurityMonitoringReferenceTable;
pub mod model_security_monitoring_scheduling_options;
pub use self::model_security_monitoring_scheduling_options::SecurityMonitoringSchedulingOptions;
pub mod model_security_monitoring_third_party_rule_case;
pub use self::model_security_monitoring_third_party_rule_case::SecurityMonitoringThirdPartyRuleCase;
pub mod model_security_monitoring_rule_type_read;
Expand Down Expand Up @@ -5138,8 +5142,6 @@ pub mod model_historical_job_response_attributes;
pub use self::model_historical_job_response_attributes::HistoricalJobResponseAttributes;
pub mod model_job_definition;
pub use self::model_job_definition::JobDefinition;
pub mod model_calculated_field;
pub use self::model_calculated_field::CalculatedField;
pub mod model_historical_job_options;
pub use self::model_historical_job_options::HistoricalJobOptions;
pub mod model_historical_job_query;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ use std::fmt::{self, Formatter};
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct SecurityMonitoringRuleUpdatePayload {
/// Calculated fields. Only allowed for scheduled rules - in other words, when schedulingOptions is also defined.
#[serde(rename = "calculatedFields")]
pub calculated_fields: Option<Vec<crate::datadogV2::model::CalculatedField>>,
/// Cases for generating signals.
#[serde(rename = "cases")]
pub cases: Option<Vec<crate::datadogV2::model::SecurityMonitoringRuleCase>>,
Expand Down Expand Up @@ -51,6 +54,14 @@ pub struct SecurityMonitoringRuleUpdatePayload {
/// Reference tables for the rule.
#[serde(rename = "referenceTables")]
pub reference_tables: Option<Vec<crate::datadogV2::model::SecurityMonitoringReferenceTable>>,
/// Options for scheduled rules. When this field is present, the rule runs based on the schedule. When absent, it runs real-time on ingested logs.
#[serde(
rename = "schedulingOptions",
default,
with = "::serde_with::rust::double_option"
)]
pub scheduling_options:
Option<Option<crate::datadogV2::model::SecurityMonitoringSchedulingOptions>>,
/// Tags for generated signals.
#[serde(rename = "tags")]
pub tags: Option<Vec<String>>,
Expand All @@ -71,6 +82,7 @@ pub struct SecurityMonitoringRuleUpdatePayload {
impl SecurityMonitoringRuleUpdatePayload {
pub fn new() -> SecurityMonitoringRuleUpdatePayload {
SecurityMonitoringRuleUpdatePayload {
calculated_fields: None,
cases: None,
compliance_signal_options: None,
custom_message: None,
Expand All @@ -84,6 +96,7 @@ impl SecurityMonitoringRuleUpdatePayload {
options: None,
queries: None,
reference_tables: None,
scheduling_options: None,
tags: None,
third_party_cases: None,
version: None,
Expand All @@ -92,6 +105,14 @@ impl SecurityMonitoringRuleUpdatePayload {
}
}

pub fn calculated_fields(
mut self,
value: Vec<crate::datadogV2::model::CalculatedField>,
) -> Self {
self.calculated_fields = Some(value);
self
}

pub fn cases(
mut self,
value: Vec<crate::datadogV2::model::SecurityMonitoringRuleCase>,
Expand Down Expand Up @@ -175,6 +196,14 @@ impl SecurityMonitoringRuleUpdatePayload {
self
}

pub fn scheduling_options(
mut self,
value: Option<crate::datadogV2::model::SecurityMonitoringSchedulingOptions>,
) -> Self {
self.scheduling_options = Some(value);
self
}

pub fn tags(mut self, value: Vec<String>) -> Self {
self.tags = Some(value);
self
Expand Down Expand Up @@ -225,6 +254,8 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleUpdatePayload {
where
M: MapAccess<'a>,
{
let mut calculated_fields: Option<Vec<crate::datadogV2::model::CalculatedField>> =
None;
let mut cases: Option<Vec<crate::datadogV2::model::SecurityMonitoringRuleCase>> =
None;
let mut compliance_signal_options: Option<
Expand All @@ -246,6 +277,9 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleUpdatePayload {
let mut reference_tables: Option<
Vec<crate::datadogV2::model::SecurityMonitoringReferenceTable>,
> = None;
let mut scheduling_options: Option<
Option<crate::datadogV2::model::SecurityMonitoringSchedulingOptions>,
> = None;
let mut tags: Option<Vec<String>> = None;
let mut third_party_cases: Option<
Vec<crate::datadogV2::model::SecurityMonitoringThirdPartyRuleCase>,
Expand All @@ -259,6 +293,13 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleUpdatePayload {

while let Some((k, v)) = map.next_entry::<String, serde_json::Value>()? {
match k.as_str() {
"calculatedFields" => {
if v.is_null() {
continue;
}
calculated_fields =
Some(serde_json::from_value(v).map_err(M::Error::custom)?);
}
"cases" => {
if v.is_null() {
continue;
Expand Down Expand Up @@ -343,6 +384,10 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleUpdatePayload {
reference_tables =
Some(serde_json::from_value(v).map_err(M::Error::custom)?);
}
"schedulingOptions" => {
scheduling_options =
Some(serde_json::from_value(v).map_err(M::Error::custom)?);
}
"tags" => {
if v.is_null() {
continue;
Expand Down Expand Up @@ -371,6 +416,7 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleUpdatePayload {
}

let content = SecurityMonitoringRuleUpdatePayload {
calculated_fields,
cases,
compliance_signal_options,
custom_message,
Expand All @@ -384,6 +430,7 @@ impl<'de> Deserialize<'de> for SecurityMonitoringRuleUpdatePayload {
options,
queries,
reference_tables,
scheduling_options,
tags,
third_party_cases,
version,
Expand Down
Loading
Loading