From 39107925f8ebe28653aa6438656c8d70ce91b37f Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Wed, 10 Jun 2026 16:22:34 +0000 Subject: [PATCH] Regenerate client from commit 19949fa of spec repo --- .generator/schemas/v2/openapi.yaml | 158 +++++++++++++++++ ...ndSecurityMonitoringNotificationPreview.rs | 38 ++++ src/datadogV2/api/api_security_monitoring.rs | 166 ++++++++++++++++++ src/datadogV2/model/mod.rs | 16 ++ ...ication_rule_parameters_data_attributes.rs | 17 ++ ...cation_rule_preview_notification_status.rs | 54 ++++++ ...odel_notification_rule_preview_response.rs | 95 ++++++++++ ...cation_rule_preview_response_attributes.rs | 98 +++++++++++ ...notification_rule_preview_response_data.rs | 134 ++++++++++++++ ...notification_rule_preview_response_type.rs | 48 +++++ .../model_notification_rule_preview_result.rs | 132 ++++++++++++++ .../model/model_notification_rule_routing.rs | 102 +++++++++++ .../model_notification_rule_routing_mode.rs | 48 +++++ ...ication_rule_parameters_data_attributes.rs | 17 ++ ...tification-rule-returns-OK-response.frozen | 1 + ...notification-rule-returns-OK-response.json | 39 ++++ .../features/v2/security_monitoring.feature | 22 ++- tests/scenarios/features/v2/undo.json | 6 + tests/scenarios/function_mappings.rs | 33 ++++ 19 files changed, 1220 insertions(+), 4 deletions(-) create mode 100644 examples/v2_security-monitoring_SendSecurityMonitoringNotificationPreview.rs create mode 100644 src/datadogV2/model/model_notification_rule_preview_notification_status.rs create mode 100644 src/datadogV2/model/model_notification_rule_preview_response.rs create mode 100644 src/datadogV2/model/model_notification_rule_preview_response_attributes.rs create mode 100644 src/datadogV2/model/model_notification_rule_preview_response_data.rs create mode 100644 src/datadogV2/model/model_notification_rule_preview_response_type.rs create mode 100644 src/datadogV2/model/model_notification_rule_preview_result.rs create mode 100644 src/datadogV2/model/model_notification_rule_routing.rs create mode 100644 src/datadogV2/model/model_notification_rule_routing_mode.rs create mode 100644 tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.frozen create mode 100644 tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.json diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index e694506b53..3359e9a375 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -23518,6 +23518,8 @@ components: $ref: "#/components/schemas/Enabled" name: $ref: "#/components/schemas/RuleName" + routing: + $ref: "#/components/schemas/NotificationRuleRouting" selectors: $ref: "#/components/schemas/Selectors" targets: @@ -59051,6 +59053,76 @@ components: - targets - version type: object + NotificationRulePreviewNotificationStatus: + description: The notification status for the given rule type. `SUCCESS` means a matching event was found and the notification was sent successfully. `DEFAULT` means no matching event was found and a default placeholder notification was sent instead. `ERROR` means an error occurred while sending the notification. + enum: + - SUCCESS + - DEFAULT + - ERROR + example: SUCCESS + type: string + x-enum-varnames: + - SUCCESS + - DEFAULT + - ERROR + NotificationRulePreviewResponse: + description: Response from the notification preview request. + properties: + data: + $ref: "#/components/schemas/NotificationRulePreviewResponseData" + required: + - data + type: object + NotificationRulePreviewResponseAttributes: + description: Attributes of the notification preview response. + properties: + preview_results: + $ref: "#/components/schemas/NotificationRulePreviewResults" + required: + - preview_results + type: object + NotificationRulePreviewResponseData: + description: The notification preview response data. + properties: + attributes: + $ref: "#/components/schemas/NotificationRulePreviewResponseAttributes" + id: + description: The ID of the notification preview response. + example: rka-loa-zwu + type: string + type: + $ref: "#/components/schemas/NotificationRulePreviewResponseType" + required: + - type + - attributes + type: object + NotificationRulePreviewResponseType: + description: The type of the notification preview response. + enum: + - notification_preview_response + example: notification_preview_response + type: string + x-enum-varnames: + - NOTIFICATION_PREVIEW_RESPONSE + NotificationRulePreviewResult: + description: The preview result for a single rule type. + properties: + notification_status: + $ref: "#/components/schemas/NotificationRulePreviewNotificationStatus" + rule_type: + $ref: "#/components/schemas/RuleTypesItems" + required: + - rule_type + - notification_status + type: object + NotificationRulePreviewResults: + description: List of preview results for each rule type matched by the notification rule. + example: + - notification_status: DEFAULT + rule_type: log_detection + items: + $ref: "#/components/schemas/NotificationRulePreviewResult" + type: array NotificationRuleQuery: description: The query is composed of one or several key:value pairs, which can be used to filter security issues on tags and attributes. example: (source:production_service OR env:prod) @@ -59061,6 +59133,22 @@ components: data: $ref: "#/components/schemas/NotificationRule" type: object + NotificationRuleRouting: + description: Routing configuration for the notification rule. + properties: + mode: + $ref: "#/components/schemas/NotificationRuleRoutingMode" + required: + - mode + type: object + NotificationRuleRoutingMode: + description: The routing mode for the notification rule. `manual` sends notifications to the configured targets. + enum: + - manual + example: manual + type: string + x-enum-varnames: + - MANUAL NotificationRulesListResponse: description: The list of notification rules. properties: @@ -68865,6 +68953,8 @@ components: $ref: "#/components/schemas/Enabled" name: $ref: "#/components/schemas/RuleName" + routing: + $ref: "#/components/schemas/NotificationRuleRouting" selectors: $ref: "#/components/schemas/Selectors" targets: @@ -75175,6 +75265,7 @@ components: - iac_misconfiguration - sast_vulnerability - secret_vulnerability + example: log_detection type: string x-enum-varnames: - APPLICATION_SECURITY @@ -164024,6 +164115,73 @@ paths: x-unstable: |- **Note**: This endpoint is in preview and is subject to change. If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/). + /api/v2/security_monitoring/configuration/notification_rules/send_notification_preview: + post: + description: Send a notification preview to test that a notification rule's targets are properly configured. + operationId: SendSecurityMonitoringNotificationPreview + requestBody: + content: + application/json: + examples: + default: + value: + data: + attributes: + enabled: true + name: Rule 1 + selectors: + query: env:prod + rule_types: + - log_detection + severities: + - critical + trigger_source: security_signals + targets: + - "@john.doe@email.com" + type: notification_rules + schema: + $ref: "#/components/schemas/CreateNotificationRuleParameters" + required: true + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + attributes: + preview_results: + - notification_status: DEFAULT + rule_type: log_detection + id: rka-loa-zwu + type: notification_preview_response + schema: + $ref: "#/components/schemas/NotificationRulePreviewResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Bad Request + "403": + $ref: "#/components/responses/NotAuthorizedResponse" + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - security_monitoring_notification_profiles_write + summary: Test a notification rule + tags: + - Security Monitoring + x-codegen-request-body-name: body + "x-permission": + operator: OR + permissions: + - security_monitoring_notification_profiles_write /api/v2/security_monitoring/configuration/security_filters: get: description: Get the list of configured security filters with their definitions. diff --git a/examples/v2_security-monitoring_SendSecurityMonitoringNotificationPreview.rs b/examples/v2_security-monitoring_SendSecurityMonitoringNotificationPreview.rs new file mode 100644 index 0000000000..606fa5957e --- /dev/null +++ b/examples/v2_security-monitoring_SendSecurityMonitoringNotificationPreview.rs @@ -0,0 +1,38 @@ +// Test a notification rule returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI; +use datadog_api_client::datadogV2::model::CreateNotificationRuleParameters; +use datadog_api_client::datadogV2::model::CreateNotificationRuleParametersData; +use datadog_api_client::datadogV2::model::CreateNotificationRuleParametersDataAttributes; +use datadog_api_client::datadogV2::model::NotificationRulesType; +use datadog_api_client::datadogV2::model::RuleSeverity; +use datadog_api_client::datadogV2::model::RuleTypesItems; +use datadog_api_client::datadogV2::model::Selectors; +use datadog_api_client::datadogV2::model::TriggerSource; + +#[tokio::main] +async fn main() { + let body = + CreateNotificationRuleParameters::new().data(CreateNotificationRuleParametersData::new( + CreateNotificationRuleParametersDataAttributes::new( + "Rule 1".to_string(), + Selectors::new(TriggerSource::SECURITY_SIGNALS) + .query("env:prod".to_string()) + .rule_types(vec![RuleTypesItems::LOG_DETECTION]) + .severities(vec![RuleSeverity::CRITICAL]), + vec!["@john.doe@email.com".to_string()], + ) + .enabled(true), + NotificationRulesType::NOTIFICATION_RULES, + )); + let configuration = datadog::Configuration::new(); + let api = SecurityMonitoringAPI::with_config(configuration); + let resp = api + .send_security_monitoring_notification_preview(body) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadogV2/api/api_security_monitoring.rs b/src/datadogV2/api/api_security_monitoring.rs index 872f771c86..abfc4c7cce 100644 --- a/src/datadogV2/api/api_security_monitoring.rs +++ b/src/datadogV2/api/api_security_monitoring.rs @@ -2365,6 +2365,15 @@ pub enum SearchSecurityMonitoringSignalsError { UnknownValue(serde_json::Value), } +/// SendSecurityMonitoringNotificationPreviewError is a struct for typed errors of method [`SecurityMonitoringAPI::send_security_monitoring_notification_preview`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum SendSecurityMonitoringNotificationPreviewError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// TestExistingSecurityMonitoringRuleError is a struct for typed errors of method [`SecurityMonitoringAPI::test_existing_security_monitoring_rule`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -19338,6 +19347,163 @@ impl SecurityMonitoringAPI { } } + /// Send a notification preview to test that a notification rule's targets are properly configured. + pub async fn send_security_monitoring_notification_preview( + &self, + body: crate::datadogV2::model::CreateNotificationRuleParameters, + ) -> Result< + crate::datadogV2::model::NotificationRulePreviewResponse, + datadog::Error, + > { + match self + .send_security_monitoring_notification_preview_with_http_info(body) + .await + { + Ok(response_content) => { + if let Some(e) = response_content.entity { + Ok(e) + } else { + Err(datadog::Error::Serde(serde::de::Error::custom( + "response content was None", + ))) + } + } + Err(err) => Err(err), + } + } + + /// Send a notification preview to test that a notification rule's targets are properly configured. + pub async fn send_security_monitoring_notification_preview_with_http_info( + &self, + body: crate::datadogV2::model::CreateNotificationRuleParameters, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.send_security_monitoring_notification_preview"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/security_monitoring/configuration/notification_rules/send_notification_preview", + local_configuration.get_operation_host(operation_id)); + let mut local_req_builder = + local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + // build body parameters + let output = Vec::new(); + let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter); + if body.serialize(&mut ser).is_ok() { + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + #[cfg(feature = "zstd")] + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::( + &local_content, + ) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = + serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } + /// Test an existing rule. pub async fn test_existing_security_monitoring_rule( &self, diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index 8b52d870fe..63762e9947 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -9682,6 +9682,10 @@ pub mod model_create_notification_rule_parameters_data; pub use self::model_create_notification_rule_parameters_data::CreateNotificationRuleParametersData; pub mod model_create_notification_rule_parameters_data_attributes; pub use self::model_create_notification_rule_parameters_data_attributes::CreateNotificationRuleParametersDataAttributes; +pub mod model_notification_rule_routing; +pub use self::model_notification_rule_routing::NotificationRuleRouting; +pub mod model_notification_rule_routing_mode; +pub use self::model_notification_rule_routing_mode::NotificationRuleRoutingMode; pub mod model_notification_rule_response; pub use self::model_notification_rule_response::NotificationRuleResponse; pub mod model_patch_notification_rule_parameters; @@ -9808,6 +9812,18 @@ pub mod model_security_monitoring_integration_config_update_data; pub use self::model_security_monitoring_integration_config_update_data::SecurityMonitoringIntegrationConfigUpdateData; pub mod model_security_monitoring_integration_config_update_attributes; pub use self::model_security_monitoring_integration_config_update_attributes::SecurityMonitoringIntegrationConfigUpdateAttributes; +pub mod model_notification_rule_preview_response; +pub use self::model_notification_rule_preview_response::NotificationRulePreviewResponse; +pub mod model_notification_rule_preview_response_data; +pub use self::model_notification_rule_preview_response_data::NotificationRulePreviewResponseData; +pub mod model_notification_rule_preview_response_attributes; +pub use self::model_notification_rule_preview_response_attributes::NotificationRulePreviewResponseAttributes; +pub mod model_notification_rule_preview_result; +pub use self::model_notification_rule_preview_result::NotificationRulePreviewResult; +pub mod model_notification_rule_preview_notification_status; +pub use self::model_notification_rule_preview_notification_status::NotificationRulePreviewNotificationStatus; +pub mod model_notification_rule_preview_response_type; +pub use self::model_notification_rule_preview_response_type::NotificationRulePreviewResponseType; pub mod model_security_filters_response; pub use self::model_security_filters_response::SecurityFiltersResponse; pub mod model_security_filter; diff --git a/src/datadogV2/model/model_create_notification_rule_parameters_data_attributes.rs b/src/datadogV2/model/model_create_notification_rule_parameters_data_attributes.rs index a39c4873bc..7bf6f94eb7 100644 --- a/src/datadogV2/model/model_create_notification_rule_parameters_data_attributes.rs +++ b/src/datadogV2/model/model_create_notification_rule_parameters_data_attributes.rs @@ -17,6 +17,9 @@ pub struct CreateNotificationRuleParametersDataAttributes { /// Name of the notification rule. #[serde(rename = "name")] pub name: String, + /// Routing configuration for the notification rule. + #[serde(rename = "routing")] + pub routing: Option, /// Selectors are used to filter security issues for which notifications should be generated. /// Users can specify rule severities, rule types, a query to filter security issues on tags and attributes, and the trigger source. /// Only the trigger_source field is required. @@ -50,6 +53,7 @@ impl CreateNotificationRuleParametersDataAttributes { CreateNotificationRuleParametersDataAttributes { enabled: None, name, + routing: None, selectors, targets, time_aggregation: None, @@ -63,6 +67,11 @@ impl CreateNotificationRuleParametersDataAttributes { self } + pub fn routing(mut self, value: crate::datadogV2::model::NotificationRuleRouting) -> Self { + self.routing = Some(value); + self + } + pub fn time_aggregation(mut self, value: i64) -> Self { self.time_aggregation = Some(value); self @@ -96,6 +105,7 @@ impl<'de> Deserialize<'de> for CreateNotificationRuleParametersDataAttributes { { let mut enabled: Option = None; let mut name: Option = None; + let mut routing: Option = None; let mut selectors: Option = None; let mut targets: Option> = None; let mut time_aggregation: Option = None; @@ -116,6 +126,12 @@ impl<'de> Deserialize<'de> for CreateNotificationRuleParametersDataAttributes { "name" => { name = Some(serde_json::from_value(v).map_err(M::Error::custom)?); } + "routing" => { + if v.is_null() { + continue; + } + routing = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } "selectors" => { selectors = Some(serde_json::from_value(v).map_err(M::Error::custom)?); } @@ -143,6 +159,7 @@ impl<'de> Deserialize<'de> for CreateNotificationRuleParametersDataAttributes { let content = CreateNotificationRuleParametersDataAttributes { enabled, name, + routing, selectors, targets, time_aggregation, diff --git a/src/datadogV2/model/model_notification_rule_preview_notification_status.rs b/src/datadogV2/model/model_notification_rule_preview_notification_status.rs new file mode 100644 index 0000000000..463dd1fdb0 --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_preview_notification_status.rs @@ -0,0 +1,54 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum NotificationRulePreviewNotificationStatus { + SUCCESS, + DEFAULT, + ERROR, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for NotificationRulePreviewNotificationStatus { + fn to_string(&self) -> String { + match self { + Self::SUCCESS => String::from("SUCCESS"), + Self::DEFAULT => String::from("DEFAULT"), + Self::ERROR => String::from("ERROR"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for NotificationRulePreviewNotificationStatus { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for NotificationRulePreviewNotificationStatus { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "SUCCESS" => Self::SUCCESS, + "DEFAULT" => Self::DEFAULT, + "ERROR" => Self::ERROR, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_notification_rule_preview_response.rs b/src/datadogV2/model/model_notification_rule_preview_response.rs new file mode 100644 index 0000000000..c51bf8cc72 --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_preview_response.rs @@ -0,0 +1,95 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Response from the notification preview request. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct NotificationRulePreviewResponse { + /// The notification preview response data. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::NotificationRulePreviewResponseData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl NotificationRulePreviewResponse { + pub fn new( + data: crate::datadogV2::model::NotificationRulePreviewResponseData, + ) -> NotificationRulePreviewResponse { + NotificationRulePreviewResponse { + data, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for NotificationRulePreviewResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct NotificationRulePreviewResponseVisitor; + impl<'a> Visitor<'a> for NotificationRulePreviewResponseVisitor { + type Value = NotificationRulePreviewResponse; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut data: Option = + None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "data" => { + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let data = data.ok_or_else(|| M::Error::missing_field("data"))?; + + let content = NotificationRulePreviewResponse { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(NotificationRulePreviewResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_notification_rule_preview_response_attributes.rs b/src/datadogV2/model/model_notification_rule_preview_response_attributes.rs new file mode 100644 index 0000000000..224b89e9e9 --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_preview_response_attributes.rs @@ -0,0 +1,98 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes of the notification preview response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct NotificationRulePreviewResponseAttributes { + /// List of preview results for each rule type matched by the notification rule. + #[serde(rename = "preview_results")] + pub preview_results: Vec, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl NotificationRulePreviewResponseAttributes { + pub fn new( + preview_results: Vec, + ) -> NotificationRulePreviewResponseAttributes { + NotificationRulePreviewResponseAttributes { + preview_results, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for NotificationRulePreviewResponseAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct NotificationRulePreviewResponseAttributesVisitor; + impl<'a> Visitor<'a> for NotificationRulePreviewResponseAttributesVisitor { + type Value = NotificationRulePreviewResponseAttributes; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut preview_results: Option< + Vec, + > = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "preview_results" => { + preview_results = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let preview_results = + preview_results.ok_or_else(|| M::Error::missing_field("preview_results"))?; + + let content = NotificationRulePreviewResponseAttributes { + preview_results, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(NotificationRulePreviewResponseAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_notification_rule_preview_response_data.rs b/src/datadogV2/model/model_notification_rule_preview_response_data.rs new file mode 100644 index 0000000000..fadbdf1be4 --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_preview_response_data.rs @@ -0,0 +1,134 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// The notification preview response data. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct NotificationRulePreviewResponseData { + /// Attributes of the notification preview response. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::NotificationRulePreviewResponseAttributes, + /// The ID of the notification preview response. + #[serde(rename = "id")] + pub id: Option, + /// The type of the notification preview response. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::NotificationRulePreviewResponseType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl NotificationRulePreviewResponseData { + pub fn new( + attributes: crate::datadogV2::model::NotificationRulePreviewResponseAttributes, + type_: crate::datadogV2::model::NotificationRulePreviewResponseType, + ) -> NotificationRulePreviewResponseData { + NotificationRulePreviewResponseData { + attributes, + id: None, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn id(mut self, value: String) -> Self { + self.id = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for NotificationRulePreviewResponseData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct NotificationRulePreviewResponseDataVisitor; + impl<'a> Visitor<'a> for NotificationRulePreviewResponseDataVisitor { + type Value = NotificationRulePreviewResponseData; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut attributes: Option< + crate::datadogV2::model::NotificationRulePreviewResponseAttributes, + > = None; + let mut id: Option = None; + let mut type_: Option< + crate::datadogV2::model::NotificationRulePreviewResponseType, + > = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "attributes" => { + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "id" => { + if v.is_null() { + continue; + } + id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::NotificationRulePreviewResponseType::UnparsedObject(_type_) => { + _unparsed = true; + }, + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let attributes = attributes.ok_or_else(|| M::Error::missing_field("attributes"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = NotificationRulePreviewResponseData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(NotificationRulePreviewResponseDataVisitor) + } +} diff --git a/src/datadogV2/model/model_notification_rule_preview_response_type.rs b/src/datadogV2/model/model_notification_rule_preview_response_type.rs new file mode 100644 index 0000000000..f378f42cf9 --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_preview_response_type.rs @@ -0,0 +1,48 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum NotificationRulePreviewResponseType { + NOTIFICATION_PREVIEW_RESPONSE, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for NotificationRulePreviewResponseType { + fn to_string(&self) -> String { + match self { + Self::NOTIFICATION_PREVIEW_RESPONSE => String::from("notification_preview_response"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for NotificationRulePreviewResponseType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for NotificationRulePreviewResponseType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "notification_preview_response" => Self::NOTIFICATION_PREVIEW_RESPONSE, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_notification_rule_preview_result.rs b/src/datadogV2/model/model_notification_rule_preview_result.rs new file mode 100644 index 0000000000..b61a102aac --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_preview_result.rs @@ -0,0 +1,132 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// The preview result for a single rule type. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct NotificationRulePreviewResult { + /// The notification status for the given rule type. `SUCCESS` means a matching event was found and the notification was sent successfully. `DEFAULT` means no matching event was found and a default placeholder notification was sent instead. `ERROR` means an error occurred while sending the notification. + #[serde(rename = "notification_status")] + pub notification_status: crate::datadogV2::model::NotificationRulePreviewNotificationStatus, + /// Security rule type which can be used in security rules. + /// Signal-based notification rules can filter signals based on rule types application_security, log_detection, + /// workload_security, signal_correlation, cloud_configuration and infrastructure_configuration. + /// Vulnerability-based notification rules can filter vulnerabilities based on rule types application_code_vulnerability, + /// application_library_vulnerability, attack_path, container_image_vulnerability, identity_risk, misconfiguration, + /// api_security, host_vulnerability, iac_misconfiguration, sast_vulnerability and secret_vulnerability. + #[serde(rename = "rule_type")] + pub rule_type: crate::datadogV2::model::RuleTypesItems, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl NotificationRulePreviewResult { + pub fn new( + notification_status: crate::datadogV2::model::NotificationRulePreviewNotificationStatus, + rule_type: crate::datadogV2::model::RuleTypesItems, + ) -> NotificationRulePreviewResult { + NotificationRulePreviewResult { + notification_status, + rule_type, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for NotificationRulePreviewResult { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct NotificationRulePreviewResultVisitor; + impl<'a> Visitor<'a> for NotificationRulePreviewResultVisitor { + type Value = NotificationRulePreviewResult; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut notification_status: Option< + crate::datadogV2::model::NotificationRulePreviewNotificationStatus, + > = None; + let mut rule_type: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "notification_status" => { + notification_status = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _notification_status) = notification_status { + match _notification_status { + crate::datadogV2::model::NotificationRulePreviewNotificationStatus::UnparsedObject(_notification_status) => { + _unparsed = true; + }, + _ => {} + } + } + } + "rule_type" => { + rule_type = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _rule_type) = rule_type { + match _rule_type { + crate::datadogV2::model::RuleTypesItems::UnparsedObject( + _rule_type, + ) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let notification_status = notification_status + .ok_or_else(|| M::Error::missing_field("notification_status"))?; + let rule_type = rule_type.ok_or_else(|| M::Error::missing_field("rule_type"))?; + + let content = NotificationRulePreviewResult { + notification_status, + rule_type, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(NotificationRulePreviewResultVisitor) + } +} diff --git a/src/datadogV2/model/model_notification_rule_routing.rs b/src/datadogV2/model/model_notification_rule_routing.rs new file mode 100644 index 0000000000..70b3897dd5 --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_routing.rs @@ -0,0 +1,102 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Routing configuration for the notification rule. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct NotificationRuleRouting { + /// The routing mode for the notification rule. `manual` sends notifications to the configured targets. + #[serde(rename = "mode")] + pub mode: crate::datadogV2::model::NotificationRuleRoutingMode, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl NotificationRuleRouting { + pub fn new( + mode: crate::datadogV2::model::NotificationRuleRoutingMode, + ) -> NotificationRuleRouting { + NotificationRuleRouting { + mode, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for NotificationRuleRouting { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct NotificationRuleRoutingVisitor; + impl<'a> Visitor<'a> for NotificationRuleRoutingVisitor { + type Value = NotificationRuleRouting; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut mode: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "mode" => { + mode = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _mode) = mode { + match _mode { + crate::datadogV2::model::NotificationRuleRoutingMode::UnparsedObject(_mode) => { + _unparsed = true; + }, + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let mode = mode.ok_or_else(|| M::Error::missing_field("mode"))?; + + let content = NotificationRuleRouting { + mode, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(NotificationRuleRoutingVisitor) + } +} diff --git a/src/datadogV2/model/model_notification_rule_routing_mode.rs b/src/datadogV2/model/model_notification_rule_routing_mode.rs new file mode 100644 index 0000000000..d75abc893f --- /dev/null +++ b/src/datadogV2/model/model_notification_rule_routing_mode.rs @@ -0,0 +1,48 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum NotificationRuleRoutingMode { + MANUAL, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for NotificationRuleRoutingMode { + fn to_string(&self) -> String { + match self { + Self::MANUAL => String::from("manual"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for NotificationRuleRoutingMode { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for NotificationRuleRoutingMode { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "manual" => Self::MANUAL, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_patch_notification_rule_parameters_data_attributes.rs b/src/datadogV2/model/model_patch_notification_rule_parameters_data_attributes.rs index d31b3ee90d..5a311a7278 100644 --- a/src/datadogV2/model/model_patch_notification_rule_parameters_data_attributes.rs +++ b/src/datadogV2/model/model_patch_notification_rule_parameters_data_attributes.rs @@ -17,6 +17,9 @@ pub struct PatchNotificationRuleParametersDataAttributes { /// Name of the notification rule. #[serde(rename = "name")] pub name: Option, + /// Routing configuration for the notification rule. + #[serde(rename = "routing")] + pub routing: Option, /// Selectors are used to filter security issues for which notifications should be generated. /// Users can specify rule severities, rule types, a query to filter security issues on tags and attributes, and the trigger source. /// Only the trigger_source field is required. @@ -49,6 +52,7 @@ impl PatchNotificationRuleParametersDataAttributes { PatchNotificationRuleParametersDataAttributes { enabled: None, name: None, + routing: None, selectors: None, targets: None, time_aggregation: None, @@ -68,6 +72,11 @@ impl PatchNotificationRuleParametersDataAttributes { self } + pub fn routing(mut self, value: crate::datadogV2::model::NotificationRuleRouting) -> Self { + self.routing = Some(value); + self + } + pub fn selectors(mut self, value: crate::datadogV2::model::Selectors) -> Self { self.selectors = Some(value); self @@ -122,6 +131,7 @@ impl<'de> Deserialize<'de> for PatchNotificationRuleParametersDataAttributes { { let mut enabled: Option = None; let mut name: Option = None; + let mut routing: Option = None; let mut selectors: Option = None; let mut targets: Option> = None; let mut time_aggregation: Option = None; @@ -146,6 +156,12 @@ impl<'de> Deserialize<'de> for PatchNotificationRuleParametersDataAttributes { } name = Some(serde_json::from_value(v).map_err(M::Error::custom)?); } + "routing" => { + if v.is_null() { + continue; + } + routing = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } "selectors" => { if v.is_null() { continue; @@ -182,6 +198,7 @@ impl<'de> Deserialize<'de> for PatchNotificationRuleParametersDataAttributes { let content = PatchNotificationRuleParametersDataAttributes { enabled, name, + routing, selectors, targets, time_aggregation, diff --git a/tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.frozen b/tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.frozen new file mode 100644 index 0000000000..dbdcb687da --- /dev/null +++ b/tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.frozen @@ -0,0 +1 @@ +2026-06-10T09:27:59.116Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.json b/tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.json new file mode 100644 index 0000000000..53265ba45d --- /dev/null +++ b/tests/scenarios/cassettes/v2/security_monitoring/Test-a-notification-rule-returns-OK-response.json @@ -0,0 +1,39 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"enabled\":true,\"name\":\"Rule 1\",\"selectors\":{\"query\":\"env:prod\",\"rule_types\":[\"log_detection\"],\"severities\":[\"critical\"],\"trigger_source\":\"security_signals\"},\"targets\":[\"@john.doe@email.com\"]},\"type\":\"notification_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/security_monitoring/configuration/notification_rules/send_notification_preview" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"rka-loa-zwu\",\"attributes\":{\"preview_results\":[{\"rule_type\":\"log_detection\",\"notification_status\":\"DEFAULT\"}]},\"type\":\"notification_preview_response\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Wed, 10 Jun 2026 09:27:59 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/features/v2/security_monitoring.feature b/tests/scenarios/features/v2/security_monitoring.feature index bae8918780..7e93f0077a 100644 --- a/tests/scenarios/features/v2/security_monitoring.feature +++ b/tests/scenarios/features/v2/security_monitoring.feature @@ -759,7 +759,7 @@ Feature: Security Monitoring @generated @skip @team:DataDog/cloud-security-posture-management Scenario: Create a new signal-based notification rule returns "Bad Request" response Given new "CreateSignalNotificationRule" request - And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400}, "type": "notification_rules"}} + And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "routing": {"mode": "manual"}, "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400}, "type": "notification_rules"}} When the request is sent Then the response status is 400 Bad Request @@ -773,7 +773,7 @@ Feature: Security Monitoring @generated @skip @team:DataDog/cloud-security-posture-management Scenario: Create a new vulnerability-based notification rule returns "Bad Request" response Given new "CreateVulnerabilityNotificationRule" request - And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400}, "type": "notification_rules"}} + And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "routing": {"mode": "manual"}, "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400}, "type": "notification_rules"}} When the request is sent Then the response status is 400 Bad Request @@ -2470,7 +2470,7 @@ Feature: Security Monitoring Scenario: Patch a signal-based notification rule returns "The server cannot process the request because it contains invalid data." response Given new "PatchSignalNotificationRule" request And request contains "id" parameter from "REPLACE.ME" - And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400, "version": 1}, "id": "aaa-bbb-ccc", "type": "notification_rules"}} + And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "routing": {"mode": "manual"}, "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400, "version": 1}, "id": "aaa-bbb-ccc", "type": "notification_rules"}} When the request is sent Then the response status is 422 The server cannot process the request because it contains invalid data. @@ -2504,7 +2504,7 @@ Feature: Security Monitoring Scenario: Patch a vulnerability-based notification rule returns "The server cannot process the request because it contains invalid data." response Given new "PatchVulnerabilityNotificationRule" request And request contains "id" parameter from "REPLACE.ME" - And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400, "version": 1}, "id": "aaa-bbb-ccc", "type": "notification_rules"}} + And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "routing": {"mode": "manual"}, "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400, "version": 1}, "id": "aaa-bbb-ccc", "type": "notification_rules"}} When the request is sent Then the response status is 422 The server cannot process the request because it contains invalid data. @@ -2611,6 +2611,20 @@ Feature: Security Monitoring When the request is sent Then the response status is 200 OK + @generated @skip @team:DataDog/k9-cloud-siem + Scenario: Test a notification rule returns "Bad Request" response + Given new "SendSecurityMonitoringNotificationPreview" request + And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "routing": {"mode": "manual"}, "selectors": {"query": "(source:production_service OR env:prod)", "rule_types": ["misconfiguration", "attack_path"], "severities": ["critical"], "trigger_source": "security_findings"}, "targets": ["@john.doe@email.com"], "time_aggregation": 86400}, "type": "notification_rules"}} + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/k9-cloud-siem + Scenario: Test a notification rule returns "OK" response + Given new "SendSecurityMonitoringNotificationPreview" request + And body with value {"data": {"attributes": {"enabled": true, "name": "Rule 1", "selectors": {"query": "env:prod", "rule_types": ["log_detection"], "severities": ["critical"], "trigger_source": "security_signals"}, "targets": ["@john.doe@email.com"]}, "type": "notification_rules"}} + When the request is sent + Then the response status is 200 OK + @skip @team:DataDog/k9-cloud-siem Scenario: Test a rule returns "Bad Request" response Given new "TestSecurityMonitoringRule" request diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 811e650c25..72c8a80e0e 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -7025,6 +7025,12 @@ "type": "safe" } }, + "SendSecurityMonitoringNotificationPreview": { + "tag": "Security Monitoring", + "undo": { + "type": "safe" + } + }, "ListSecurityFilters": { "tag": "Security Monitoring", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index b9fc0b089e..50f0e72833 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -3528,6 +3528,10 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.ValidateSecurityMonitoringIntegrationConfig".into(), test_v2_validate_security_monitoring_integration_config, ); + world.function_mappings.insert( + "v2.SendSecurityMonitoringNotificationPreview".into(), + test_v2_send_security_monitoring_notification_preview, + ); world.function_mappings.insert( "v2.ListSecurityFilters".into(), test_v2_list_security_filters, @@ -26191,6 +26195,35 @@ fn test_v2_validate_security_monitoring_integration_config( world.response.code = response.status.as_u16(); } +fn test_v2_send_security_monitoring_notification_preview( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_security_monitoring + .as_ref() + .expect("api instance not found"); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let response = + match block_on(api.send_security_monitoring_notification_preview_with_http_info(body)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + fn test_v2_list_security_filters(world: &mut DatadogWorld, _parameters: &HashMap) { let api = world .api_instances