diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 840ac4eef..92bd2709b 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -53721,6 +53721,310 @@ components: required: - data type: object + SecurityMonitoringSignalInvestigationFeedbackMetric: + description: A feedback metric containing user response. + properties: + placeholder: + description: Placeholder text for the metric. + example: Enter your feedback here + type: string + prompt: + description: The question or prompt. + example: How helpful was this investigation? + type: string + response: + description: The user's response. + example: Very helpful + type: string + type: + description: The type of metric. + example: sentiment + type: string + required: + - type + - prompt + - response + type: object + SecurityMonitoringSignalInvestigationFeedbackRequest: + description: Request body for submitting investigation feedback. + properties: + data: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackRequestData' + required: + - data + type: object + SecurityMonitoringSignalInvestigationFeedbackRequestAttributes: + description: Attributes for investigation feedback. + properties: + feedback: + description: The feedback text. + example: positive + type: string + feedback_content: + description: Structured feedback content. + items: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackSection' + type: array + incomplete: + description: Whether the feedback is incomplete. + example: false + type: boolean + rating: + description: The rating value. + example: positive + type: string + signal_id: + description: The unique ID of the security signal. + example: AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA + type: string + type: + description: The type of feedback. + example: metrics + type: string + required: + - signal_id + - feedback + type: object + SecurityMonitoringSignalInvestigationFeedbackRequestData: + description: Data for submitting investigation feedback. + properties: + attributes: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackRequestAttributes' + type: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackType' + required: + - type + - attributes + type: object + SecurityMonitoringSignalInvestigationFeedbackResponse: + description: Response containing investigation feedback. + properties: + data: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackResponseData' + required: + - data + type: object + SecurityMonitoringSignalInvestigationFeedbackResponseAttributes: + description: Attributes of investigation feedback. + properties: + feedback: + description: The feedback text. + example: positive + type: string + feedback_content: + description: Structured feedback content. + items: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackSection' + type: array + investigation_id: + description: The unique ID of the investigation. + example: 550e8400-e29b-41d4-a716-446655440001 + type: string + rating: + description: The rating value. + example: positive + type: string + signal_id: + description: The unique ID of the security signal. + example: AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA + type: string + required: + - feedback + - signal_id + - investigation_id + type: object + SecurityMonitoringSignalInvestigationFeedbackResponseData: + description: Data containing investigation feedback. + properties: + attributes: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackResponseAttributes' + id: + description: The unique ID of the investigation. + example: 550e8400-e29b-41d4-a716-446655440001 + type: string + type: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackType' + required: + - id + - type + - attributes + type: object + SecurityMonitoringSignalInvestigationFeedbackSection: + description: A feedback section containing metrics. + properties: + id: + description: The section identifier. + example: section-1 + type: string + metrics: + description: Array of feedback metrics. + items: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackMetric' + type: array + title: + description: The section title. + example: Investigation Quality + type: string + required: + - id + - title + - metrics + type: object + SecurityMonitoringSignalInvestigationFeedbackType: + description: The type of feedback. + enum: + - investigation_feedback + example: investigation_feedback + type: string + x-enum-varnames: + - INVESTIGATION_FEEDBACK + SecurityMonitoringSignalInvestigationRequest: + description: Request body for creating a security signal investigation. + properties: + data: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationRequestData' + required: + - data + type: object + SecurityMonitoringSignalInvestigationRequestAttributes: + description: Attributes for creating a signal investigation. + properties: + deployment: + description: Optional deployment override for the investigation. + example: live + type: string + signal_id: + description: The unique ID of the security signal. + example: AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA + type: string + required: + - signal_id + type: object + SecurityMonitoringSignalInvestigationRequestData: + description: Data for creating a signal investigation. + properties: + attributes: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationRequestAttributes' + type: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationType' + required: + - type + - attributes + type: object + SecurityMonitoringSignalInvestigationResponse: + description: Response containing investigation details for a security signal. + properties: + data: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationResponseData' + required: + - data + type: object + SecurityMonitoringSignalInvestigationResponseAttributes: + description: Attributes of a signal investigation response. + properties: + investigation_id: + description: The unique ID of the investigation. + example: 550e8400-e29b-41d4-a716-446655440001 + type: string + rule_id: + description: The ID of the rule that triggered the signal. + example: def-000-an8 + type: string + signal_id: + description: The unique ID of the security signal. + example: AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA + type: string + state: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationState' + step: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationStep' + required: + - signal_id + - rule_id + - investigation_id + type: object + SecurityMonitoringSignalInvestigationResponseData: + description: Data containing the investigation details. + properties: + attributes: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationResponseAttributes' + id: + description: The unique ID of the investigation. + example: 550e8400-e29b-41d4-a716-446655440001 + type: string + type: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationType' + required: + - id + - type + - attributes + type: object + SecurityMonitoringSignalInvestigationState: + description: The state of the investigation. + enum: + - investigating + - completed + example: completed + type: string + x-enum-varnames: + - INVESTIGATING + - COMPLETED + SecurityMonitoringSignalInvestigationStep: + description: Information about an investigation step. + properties: + stepOutputs: + description: Array of step outputs. + items: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationStepOutput' + type: array + required: + - stepOutputs + type: object + SecurityMonitoringSignalInvestigationStepOutput: + description: Output from an investigation step. + properties: + currentStepAnalysisOneliner: + description: A one-line summary of the step analysis. + example: This appears to be a potential security threat. + type: string + currentStepAnalysisSummary: + description: A detailed summary of the step analysis. + example: The analysis indicates unusual access patterns that warrant further + investigation. + type: string + name: + description: The name of the investigation step. + example: startStep + type: string + verdict: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationStepOutputVerdict' + required: + - name + - currentStepAnalysisSummary + - verdict + type: object + SecurityMonitoringSignalInvestigationStepOutputVerdict: + description: The verdict from the investigation step. + enum: + - unspecified + - benign + - suspicious + - inconclusive + example: benign + type: string + x-enum-varnames: + - UNSPECIFIED + - BENIGN + - SUSPICIOUS + - INCONCLUSIVE + SecurityMonitoringSignalInvestigationType: + description: The type of investigation signal. + enum: + - investigation_signal + example: investigation_signal + type: string + x-enum-varnames: + - INVESTIGATION_SIGNAL SecurityMonitoringSignalListRequest: description: The request for a security signal list. properties: @@ -93882,6 +94186,157 @@ paths: operator: OR permissions: - security_monitoring_signals_read + /api/v2/security_monitoring/signals/investigation: + post: + description: Create an investigation for a security signal using AI-powered + analysis. + operationId: CreateSignalInvestigation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationRequest' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationResponse' + description: OK + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Bad Request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Not Found + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - security_monitoring_signals_read + summary: Create a security signal investigation + tags: + - Security Monitoring + x-codegen-request-body-name: body + x-permission: + operator: OR + permissions: + - security_monitoring_signals_read + 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/signals/investigation/feedback: + put: + description: Provide feedback on a security signal investigation. + operationId: UpdateInvestigationFeedback + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackRequest' + required: true + responses: + '200': + description: OK + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Bad Request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Not Found + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - security_monitoring_signals_read + summary: Update investigation feedback + tags: + - Security Monitoring + x-codegen-request-body-name: body + x-permission: + operator: OR + permissions: + - security_monitoring_signals_read + 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/signals/investigation/feedback/{signal_id}: + get: + description: Retrieve feedback for a security signal investigation. + operationId: GetInvestigationFeedback + parameters: + - $ref: '#/components/parameters/SignalID' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SecurityMonitoringSignalInvestigationFeedbackResponse' + description: OK + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Bad Request + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Not Found + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - security_monitoring_signals_read + summary: Get investigation feedback + tags: + - Security Monitoring + x-permission: + operator: OR + permissions: + - security_monitoring_signals_read + 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/signals/search: post: description: 'Returns security signals that match a search query. diff --git a/examples/v2_security-monitoring_CreateSignalInvestigation.rs b/examples/v2_security-monitoring_CreateSignalInvestigation.rs new file mode 100644 index 000000000..31561ecef --- /dev/null +++ b/examples/v2_security-monitoring_CreateSignalInvestigation.rs @@ -0,0 +1,29 @@ +// Create a security signal investigation returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationRequest; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationRequestAttributes; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationRequestData; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationType; + +#[tokio::main] +async fn main() { + let body = SecurityMonitoringSignalInvestigationRequest::new( + SecurityMonitoringSignalInvestigationRequestData::new( + SecurityMonitoringSignalInvestigationRequestAttributes::new( + "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA".to_string(), + ) + .deployment("live".to_string()), + SecurityMonitoringSignalInvestigationType::INVESTIGATION_SIGNAL, + ), + ); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.CreateSignalInvestigation", true); + let api = SecurityMonitoringAPI::with_config(configuration); + let resp = api.create_signal_investigation(body).await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_security-monitoring_GetInvestigationFeedback.rs b/examples/v2_security-monitoring_GetInvestigationFeedback.rs new file mode 100644 index 000000000..8b6ba5b26 --- /dev/null +++ b/examples/v2_security-monitoring_GetInvestigationFeedback.rs @@ -0,0 +1,18 @@ +// Get investigation feedback returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.GetInvestigationFeedback", true); + let api = SecurityMonitoringAPI::with_config(configuration); + let resp = api + .get_investigation_feedback("signal_id".to_string()) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_security-monitoring_UpdateInvestigationFeedback.rs b/examples/v2_security-monitoring_UpdateInvestigationFeedback.rs new file mode 100644 index 000000000..2335e9bdd --- /dev/null +++ b/examples/v2_security-monitoring_UpdateInvestigationFeedback.rs @@ -0,0 +1,46 @@ +// Update investigation feedback returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_security_monitoring::SecurityMonitoringAPI; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackMetric; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequest; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequestAttributes; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequestData; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackSection; +use datadog_api_client::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType; + +#[tokio::main] +async fn main() { + let body = SecurityMonitoringSignalInvestigationFeedbackRequest::new( + SecurityMonitoringSignalInvestigationFeedbackRequestData::new( + SecurityMonitoringSignalInvestigationFeedbackRequestAttributes::new( + "positive".to_string(), + "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA".to_string(), + ) + .feedback_content(vec![ + SecurityMonitoringSignalInvestigationFeedbackSection::new( + "section-1".to_string(), + vec![SecurityMonitoringSignalInvestigationFeedbackMetric::new( + "How helpful was this investigation?".to_string(), + "Very helpful".to_string(), + "sentiment".to_string(), + ) + .placeholder("Enter your feedback here".to_string())], + "Investigation Quality".to_string(), + ), + ]) + .incomplete(false) + .rating("positive".to_string()) + .type_("metrics".to_string()), + SecurityMonitoringSignalInvestigationFeedbackType::INVESTIGATION_FEEDBACK, + ), + ); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.UpdateInvestigationFeedback", true); + let api = SecurityMonitoringAPI::with_config(configuration); + let resp = api.update_investigation_feedback(body).await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadog/configuration.rs b/src/datadog/configuration.rs index 3beeee96c..f20d2f2d2 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -143,8 +143,10 @@ impl Default for Configuration { ("v2.update_open_api".to_owned(), false), ("v2.cancel_threat_hunting_job".to_owned(), false), ("v2.convert_job_result_to_signal".to_owned(), false), + ("v2.create_signal_investigation".to_owned(), false), ("v2.delete_threat_hunting_job".to_owned(), false), ("v2.get_finding".to_owned(), false), + ("v2.get_investigation_feedback".to_owned(), false), ("v2.get_rule_version_history".to_owned(), false), ("v2.get_secrets_rules".to_owned(), false), ("v2.get_security_monitoring_histsignal".to_owned(), false), @@ -166,6 +168,7 @@ impl Default for Configuration { "v2.search_security_monitoring_histsignals".to_owned(), false, ), + ("v2.update_investigation_feedback".to_owned(), false), ("v2.create_dataset".to_owned(), false), ("v2.delete_dataset".to_owned(), false), ("v2.get_all_datasets".to_owned(), false), diff --git a/src/datadogV2/api/api_security_monitoring.rs b/src/datadogV2/api/api_security_monitoring.rs index 339dcd548..35837adbc 100644 --- a/src/datadogV2/api/api_security_monitoring.rs +++ b/src/datadogV2/api/api_security_monitoring.rs @@ -1273,6 +1273,15 @@ pub enum CreateSecurityMonitoringSuppressionError { UnknownValue(serde_json::Value), } +/// CreateSignalInvestigationError is a struct for typed errors of method [`SecurityMonitoringAPI::create_signal_investigation`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CreateSignalInvestigationError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// CreateSignalNotificationRuleError is a struct for typed errors of method [`SecurityMonitoringAPI::create_signal_notification_rule`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1409,6 +1418,15 @@ pub enum GetFindingError { UnknownValue(serde_json::Value), } +/// GetInvestigationFeedbackError is a struct for typed errors of method [`SecurityMonitoringAPI::get_investigation_feedback`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetInvestigationFeedbackError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// GetResourceEvaluationFiltersError is a struct for typed errors of method [`SecurityMonitoringAPI::get_resource_evaluation_filters`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1760,6 +1778,15 @@ pub enum UpdateCustomFrameworkError { UnknownValue(serde_json::Value), } +/// UpdateInvestigationFeedbackError is a struct for typed errors of method [`SecurityMonitoringAPI::update_investigation_feedback`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UpdateInvestigationFeedbackError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// UpdateResourceEvaluationFiltersError is a struct for typed errors of method [`SecurityMonitoringAPI::update_resource_evaluation_filters`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -3969,6 +3996,171 @@ impl SecurityMonitoringAPI { } } + /// Create an investigation for a security signal using AI-powered analysis. + pub async fn create_signal_investigation( + &self, + body: crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequest, + ) -> Result< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponse, + datadog::Error, + > { + match self.create_signal_investigation_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), + } + } + + /// Create an investigation for a security signal using AI-powered analysis. + pub async fn create_signal_investigation_with_http_info( + &self, + body: crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequest, + ) -> Result< + datadog::ResponseContent< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponse, + >, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.create_signal_investigation"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.create_signal_investigation' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/security_monitoring/signals/investigation", + 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)), + } + } + "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::< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponse, + >(&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)) + } + } + /// Create a new notification rule for security signals and return the created rule. pub async fn create_signal_notification_rule( &self, @@ -6025,6 +6217,129 @@ impl SecurityMonitoringAPI { } } + /// Retrieve feedback for a security signal investigation. + pub async fn get_investigation_feedback( + &self, + signal_id: String, + ) -> Result< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponse, + datadog::Error, + > { + match self + .get_investigation_feedback_with_http_info(signal_id) + .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), + } + } + + /// Retrieve feedback for a security signal investigation. + pub async fn get_investigation_feedback_with_http_info( + &self, + signal_id: String, + ) -> Result< + datadog::ResponseContent< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponse, + >, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.get_investigation_feedback"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.get_investigation_feedback' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/security_monitoring/signals/investigation/feedback/{signal_id}", + local_configuration.get_operation_host(operation_id), + signal_id = datadog::urlencode(signal_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + 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"), + ); + }; + + 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::< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponse, + >(&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)) + } + } + /// List resource filters. pub async fn get_resource_evaluation_filters( &self, @@ -12886,6 +13201,151 @@ impl SecurityMonitoringAPI { } } + /// Provide feedback on a security signal investigation. + pub async fn update_investigation_feedback( + &self, + body: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequest, + ) -> Result<(), datadog::Error> { + match self + .update_investigation_feedback_with_http_info(body) + .await + { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + + /// Provide feedback on a security signal investigation. + pub async fn update_investigation_feedback_with_http_info( + &self, + body: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequest, + ) -> Result, datadog::Error> + { + let local_configuration = &self.config; + let operation_id = "v2.update_investigation_feedback"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.update_investigation_feedback' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/security_monitoring/signals/investigation/feedback", + local_configuration.get_operation_host(operation_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::PUT, 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("*/*")); + + // 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)), + } + } + "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() { + Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: None, + }) + } 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)) + } + } + /// Update resource filters. pub async fn update_resource_evaluation_filters( &self, diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index 52f721cb3..0c0ce9687 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -6760,6 +6760,46 @@ pub mod model_security_monitoring_signals_list_response_meta; pub use self::model_security_monitoring_signals_list_response_meta::SecurityMonitoringSignalsListResponseMeta; pub mod model_security_monitoring_signals_list_response_meta_page; pub use self::model_security_monitoring_signals_list_response_meta_page::SecurityMonitoringSignalsListResponseMetaPage; +pub mod model_security_monitoring_signal_investigation_request; +pub use self::model_security_monitoring_signal_investigation_request::SecurityMonitoringSignalInvestigationRequest; +pub mod model_security_monitoring_signal_investigation_request_data; +pub use self::model_security_monitoring_signal_investigation_request_data::SecurityMonitoringSignalInvestigationRequestData; +pub mod model_security_monitoring_signal_investigation_request_attributes; +pub use self::model_security_monitoring_signal_investigation_request_attributes::SecurityMonitoringSignalInvestigationRequestAttributes; +pub mod model_security_monitoring_signal_investigation_type; +pub use self::model_security_monitoring_signal_investigation_type::SecurityMonitoringSignalInvestigationType; +pub mod model_security_monitoring_signal_investigation_response; +pub use self::model_security_monitoring_signal_investigation_response::SecurityMonitoringSignalInvestigationResponse; +pub mod model_security_monitoring_signal_investigation_response_data; +pub use self::model_security_monitoring_signal_investigation_response_data::SecurityMonitoringSignalInvestigationResponseData; +pub mod model_security_monitoring_signal_investigation_response_attributes; +pub use self::model_security_monitoring_signal_investigation_response_attributes::SecurityMonitoringSignalInvestigationResponseAttributes; +pub mod model_security_monitoring_signal_investigation_state; +pub use self::model_security_monitoring_signal_investigation_state::SecurityMonitoringSignalInvestigationState; +pub mod model_security_monitoring_signal_investigation_step; +pub use self::model_security_monitoring_signal_investigation_step::SecurityMonitoringSignalInvestigationStep; +pub mod model_security_monitoring_signal_investigation_step_output; +pub use self::model_security_monitoring_signal_investigation_step_output::SecurityMonitoringSignalInvestigationStepOutput; +pub mod model_security_monitoring_signal_investigation_step_output_verdict; +pub use self::model_security_monitoring_signal_investigation_step_output_verdict::SecurityMonitoringSignalInvestigationStepOutputVerdict; +pub mod model_security_monitoring_signal_investigation_feedback_request; +pub use self::model_security_monitoring_signal_investigation_feedback_request::SecurityMonitoringSignalInvestigationFeedbackRequest; +pub mod model_security_monitoring_signal_investigation_feedback_request_data; +pub use self::model_security_monitoring_signal_investigation_feedback_request_data::SecurityMonitoringSignalInvestigationFeedbackRequestData; +pub mod model_security_monitoring_signal_investigation_feedback_request_attributes; +pub use self::model_security_monitoring_signal_investigation_feedback_request_attributes::SecurityMonitoringSignalInvestigationFeedbackRequestAttributes; +pub mod model_security_monitoring_signal_investigation_feedback_section; +pub use self::model_security_monitoring_signal_investigation_feedback_section::SecurityMonitoringSignalInvestigationFeedbackSection; +pub mod model_security_monitoring_signal_investigation_feedback_metric; +pub use self::model_security_monitoring_signal_investigation_feedback_metric::SecurityMonitoringSignalInvestigationFeedbackMetric; +pub mod model_security_monitoring_signal_investigation_feedback_type; +pub use self::model_security_monitoring_signal_investigation_feedback_type::SecurityMonitoringSignalInvestigationFeedbackType; +pub mod model_security_monitoring_signal_investigation_feedback_response; +pub use self::model_security_monitoring_signal_investigation_feedback_response::SecurityMonitoringSignalInvestigationFeedbackResponse; +pub mod model_security_monitoring_signal_investigation_feedback_response_data; +pub use self::model_security_monitoring_signal_investigation_feedback_response_data::SecurityMonitoringSignalInvestigationFeedbackResponseData; +pub mod model_security_monitoring_signal_investigation_feedback_response_attributes; +pub use self::model_security_monitoring_signal_investigation_feedback_response_attributes::SecurityMonitoringSignalInvestigationFeedbackResponseAttributes; pub mod model_security_monitoring_signal_list_request; pub use self::model_security_monitoring_signal_list_request::SecurityMonitoringSignalListRequest; pub mod model_security_monitoring_signal_list_request_filter; diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_metric.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_metric.rs new file mode 100644 index 000000000..a85c0f635 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_metric.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}; + +/// A feedback metric containing user response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackMetric { + /// Placeholder text for the metric. + #[serde(rename = "placeholder")] + pub placeholder: Option, + /// The question or prompt. + #[serde(rename = "prompt")] + pub prompt: String, + /// The user's response. + #[serde(rename = "response")] + pub response: String, + /// The type of metric. + #[serde(rename = "type")] + pub type_: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackMetric { + pub fn new( + prompt: String, + response: String, + type_: String, + ) -> SecurityMonitoringSignalInvestigationFeedbackMetric { + SecurityMonitoringSignalInvestigationFeedbackMetric { + placeholder: None, + prompt, + response, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn placeholder(mut self, value: String) -> Self { + self.placeholder = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for SecurityMonitoringSignalInvestigationFeedbackMetric { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackMetricVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackMetricVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackMetric; + + 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 placeholder: Option = None; + let mut prompt: Option = None; + let mut response: Option = None; + let mut 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() { + "placeholder" => { + if v.is_null() { + continue; + } + placeholder = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "prompt" => { + prompt = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "response" => { + response = 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 Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let prompt = prompt.ok_or_else(|| M::Error::missing_field("prompt"))?; + let response = response.ok_or_else(|| M::Error::missing_field("response"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = SecurityMonitoringSignalInvestigationFeedbackMetric { + placeholder, + prompt, + response, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationFeedbackMetricVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request.rs new file mode 100644 index 000000000..8e4e112c3 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request.rs @@ -0,0 +1,94 @@ +// 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}; + +/// Request body for submitting investigation feedback. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackRequest { + /// Data for submitting investigation feedback. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequestData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackRequest { + pub fn new( + data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequestData, + ) -> SecurityMonitoringSignalInvestigationFeedbackRequest { + SecurityMonitoringSignalInvestigationFeedbackRequest { + 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 SecurityMonitoringSignalInvestigationFeedbackRequest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackRequestVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackRequestVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackRequest; + + 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 = SecurityMonitoringSignalInvestigationFeedbackRequest { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationFeedbackRequestVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request_attributes.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request_attributes.rs new file mode 100644 index 000000000..c76959b99 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request_attributes.rs @@ -0,0 +1,179 @@ +// 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 for investigation feedback. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackRequestAttributes { + /// The feedback text. + #[serde(rename = "feedback")] + pub feedback: String, + /// Structured feedback content. + #[serde(rename = "feedback_content")] + pub feedback_content: + Option>, + /// Whether the feedback is incomplete. + #[serde(rename = "incomplete")] + pub incomplete: Option, + /// The rating value. + #[serde(rename = "rating")] + pub rating: Option, + /// The unique ID of the security signal. + #[serde(rename = "signal_id")] + pub signal_id: String, + /// The type of feedback. + #[serde(rename = "type")] + pub type_: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackRequestAttributes { + pub fn new( + feedback: String, + signal_id: String, + ) -> SecurityMonitoringSignalInvestigationFeedbackRequestAttributes { + SecurityMonitoringSignalInvestigationFeedbackRequestAttributes { + feedback, + feedback_content: None, + incomplete: None, + rating: None, + signal_id, + type_: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn feedback_content( + mut self, + value: Vec, + ) -> Self { + self.feedback_content = Some(value); + self + } + + pub fn incomplete(mut self, value: bool) -> Self { + self.incomplete = Some(value); + self + } + + pub fn rating(mut self, value: String) -> Self { + self.rating = Some(value); + self + } + + pub fn type_(mut self, value: String) -> Self { + self.type_ = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for SecurityMonitoringSignalInvestigationFeedbackRequestAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackRequestAttributesVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackRequestAttributesVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackRequestAttributes; + + 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 feedback: Option = None; + let mut feedback_content: Option> = None; + let mut incomplete: Option = None; + let mut rating: Option = None; + let mut signal_id: Option = None; + let mut 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() { + "feedback" => { + feedback = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "feedback_content" => { + if v.is_null() { + continue; + } + feedback_content = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "incomplete" => { + if v.is_null() { + continue; + } + incomplete = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "rating" => { + if v.is_null() { + continue; + } + rating = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "signal_id" => { + signal_id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + if v.is_null() { + continue; + } + type_ = 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 feedback = feedback.ok_or_else(|| M::Error::missing_field("feedback"))?; + let signal_id = signal_id.ok_or_else(|| M::Error::missing_field("signal_id"))?; + + let content = SecurityMonitoringSignalInvestigationFeedbackRequestAttributes { + feedback, + feedback_content, + incomplete, + rating, + signal_id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer + .deserialize_any(SecurityMonitoringSignalInvestigationFeedbackRequestAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request_data.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request_data.rs new file mode 100644 index 000000000..67f11e825 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_request_data.rs @@ -0,0 +1,117 @@ +// 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}; + +/// Data for submitting investigation feedback. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackRequestData { + /// Attributes for investigation feedback. + #[serde(rename = "attributes")] + pub attributes: + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequestAttributes, + /// The type of feedback. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackRequestData { + pub fn new( + attributes: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackRequestAttributes, + type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType, + ) -> SecurityMonitoringSignalInvestigationFeedbackRequestData { + SecurityMonitoringSignalInvestigationFeedbackRequestData { + attributes, + 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 SecurityMonitoringSignalInvestigationFeedbackRequestData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackRequestDataVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackRequestDataVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackRequestData; + + 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 = None; + let mut type_: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType, + > = 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)?); + } + "type" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType::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 = SecurityMonitoringSignalInvestigationFeedbackRequestData { + attributes, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer + .deserialize_any(SecurityMonitoringSignalInvestigationFeedbackRequestDataVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response.rs new file mode 100644 index 000000000..38ed5be85 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response.rs @@ -0,0 +1,94 @@ +// 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 containing investigation feedback. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackResponse { + /// Data containing investigation feedback. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponseData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackResponse { + pub fn new( + data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponseData, + ) -> SecurityMonitoringSignalInvestigationFeedbackResponse { + SecurityMonitoringSignalInvestigationFeedbackResponse { + 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 SecurityMonitoringSignalInvestigationFeedbackResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackResponseVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackResponseVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackResponse; + + 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 = SecurityMonitoringSignalInvestigationFeedbackResponse { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationFeedbackResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response_attributes.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response_attributes.rs new file mode 100644 index 000000000..b31a6296a --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response_attributes.rs @@ -0,0 +1,158 @@ +// 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 investigation feedback. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackResponseAttributes { + /// The feedback text. + #[serde(rename = "feedback")] + pub feedback: String, + /// Structured feedback content. + #[serde(rename = "feedback_content")] + pub feedback_content: + Option>, + /// The unique ID of the investigation. + #[serde(rename = "investigation_id")] + pub investigation_id: String, + /// The rating value. + #[serde(rename = "rating")] + pub rating: Option, + /// The unique ID of the security signal. + #[serde(rename = "signal_id")] + pub signal_id: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackResponseAttributes { + pub fn new( + feedback: String, + investigation_id: String, + signal_id: String, + ) -> SecurityMonitoringSignalInvestigationFeedbackResponseAttributes { + SecurityMonitoringSignalInvestigationFeedbackResponseAttributes { + feedback, + feedback_content: None, + investigation_id, + rating: None, + signal_id, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn feedback_content( + mut self, + value: Vec, + ) -> Self { + self.feedback_content = Some(value); + self + } + + pub fn rating(mut self, value: String) -> Self { + self.rating = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for SecurityMonitoringSignalInvestigationFeedbackResponseAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackResponseAttributesVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackResponseAttributesVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackResponseAttributes; + + 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 feedback: Option = None; + let mut feedback_content: Option> = None; + let mut investigation_id: Option = None; + let mut rating: Option = None; + let mut signal_id: 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() { + "feedback" => { + feedback = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "feedback_content" => { + if v.is_null() { + continue; + } + feedback_content = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "investigation_id" => { + investigation_id = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "rating" => { + if v.is_null() { + continue; + } + rating = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "signal_id" => { + signal_id = 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 feedback = feedback.ok_or_else(|| M::Error::missing_field("feedback"))?; + let investigation_id = + investigation_id.ok_or_else(|| M::Error::missing_field("investigation_id"))?; + let signal_id = signal_id.ok_or_else(|| M::Error::missing_field("signal_id"))?; + + let content = SecurityMonitoringSignalInvestigationFeedbackResponseAttributes { + feedback, + feedback_content, + investigation_id, + rating, + signal_id, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer + .deserialize_any(SecurityMonitoringSignalInvestigationFeedbackResponseAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response_data.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response_data.rs new file mode 100644 index 000000000..663d2efd8 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_response_data.rs @@ -0,0 +1,128 @@ +// 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}; + +/// Data containing investigation feedback. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackResponseData { + /// Attributes of investigation feedback. + #[serde(rename = "attributes")] + pub attributes: + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponseAttributes, + /// The unique ID of the investigation. + #[serde(rename = "id")] + pub id: String, + /// The type of feedback. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackResponseData { + pub fn new( + attributes: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackResponseAttributes, + id: String, + type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType, + ) -> SecurityMonitoringSignalInvestigationFeedbackResponseData { + SecurityMonitoringSignalInvestigationFeedbackResponseData { + attributes, + id, + 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 SecurityMonitoringSignalInvestigationFeedbackResponseData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackResponseDataVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackResponseDataVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackResponseData; + + 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 = None; + let mut id: Option = None; + let mut type_: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationFeedbackType, + > = 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" => { + 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::SecurityMonitoringSignalInvestigationFeedbackType::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 id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = SecurityMonitoringSignalInvestigationFeedbackResponseData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer + .deserialize_any(SecurityMonitoringSignalInvestigationFeedbackResponseDataVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_section.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_section.rs new file mode 100644 index 000000000..ed3f497e8 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_section.rs @@ -0,0 +1,116 @@ +// 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}; + +/// A feedback section containing metrics. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationFeedbackSection { + /// The section identifier. + #[serde(rename = "id")] + pub id: String, + /// Array of feedback metrics. + #[serde(rename = "metrics")] + pub metrics: Vec, + /// The section title. + #[serde(rename = "title")] + pub title: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationFeedbackSection { + pub fn new( + id: String, + metrics: Vec, + title: String, + ) -> SecurityMonitoringSignalInvestigationFeedbackSection { + SecurityMonitoringSignalInvestigationFeedbackSection { + id, + metrics, + title, + 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 SecurityMonitoringSignalInvestigationFeedbackSection { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationFeedbackSectionVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationFeedbackSectionVisitor { + type Value = SecurityMonitoringSignalInvestigationFeedbackSection; + + 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 id: Option = None; + let mut metrics: Option> = None; + let mut title: 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() { + "id" => { + id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "metrics" => { + metrics = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "title" => { + title = 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 id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let metrics = metrics.ok_or_else(|| M::Error::missing_field("metrics"))?; + let title = title.ok_or_else(|| M::Error::missing_field("title"))?; + + let content = SecurityMonitoringSignalInvestigationFeedbackSection { + id, + metrics, + title, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationFeedbackSectionVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_type.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_type.rs new file mode 100644 index 000000000..fa830823e --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_feedback_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 SecurityMonitoringSignalInvestigationFeedbackType { + INVESTIGATION_FEEDBACK, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for SecurityMonitoringSignalInvestigationFeedbackType { + fn to_string(&self) -> String { + match self { + Self::INVESTIGATION_FEEDBACK => String::from("investigation_feedback"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for SecurityMonitoringSignalInvestigationFeedbackType { + 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 SecurityMonitoringSignalInvestigationFeedbackType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "investigation_feedback" => Self::INVESTIGATION_FEEDBACK, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_request.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_request.rs new file mode 100644 index 000000000..2bd6bca07 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_request.rs @@ -0,0 +1,96 @@ +// 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}; + +/// Request body for creating a security signal investigation. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationRequest { + /// Data for creating a signal investigation. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequestData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationRequest { + pub fn new( + data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequestData, + ) -> SecurityMonitoringSignalInvestigationRequest { + SecurityMonitoringSignalInvestigationRequest { + 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 SecurityMonitoringSignalInvestigationRequest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationRequestVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationRequestVisitor { + type Value = SecurityMonitoringSignalInvestigationRequest; + + 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< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequestData, + > = 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 = SecurityMonitoringSignalInvestigationRequest { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationRequestVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_request_attributes.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_request_attributes.rs new file mode 100644 index 000000000..8b6fd4aa5 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_request_attributes.rs @@ -0,0 +1,109 @@ +// 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 for creating a signal investigation. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationRequestAttributes { + /// Optional deployment override for the investigation. + #[serde(rename = "deployment")] + pub deployment: Option, + /// The unique ID of the security signal. + #[serde(rename = "signal_id")] + pub signal_id: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationRequestAttributes { + pub fn new(signal_id: String) -> SecurityMonitoringSignalInvestigationRequestAttributes { + SecurityMonitoringSignalInvestigationRequestAttributes { + deployment: None, + signal_id, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn deployment(mut self, value: String) -> Self { + self.deployment = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for SecurityMonitoringSignalInvestigationRequestAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationRequestAttributesVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationRequestAttributesVisitor { + type Value = SecurityMonitoringSignalInvestigationRequestAttributes; + + 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 deployment: Option = None; + let mut signal_id: 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() { + "deployment" => { + if v.is_null() { + continue; + } + deployment = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "signal_id" => { + signal_id = 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 signal_id = signal_id.ok_or_else(|| M::Error::missing_field("signal_id"))?; + + let content = SecurityMonitoringSignalInvestigationRequestAttributes { + deployment, + signal_id, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationRequestAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_request_data.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_request_data.rs new file mode 100644 index 000000000..9be029af7 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_request_data.rs @@ -0,0 +1,117 @@ +// 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}; + +/// Data for creating a signal investigation. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationRequestData { + /// Attributes for creating a signal investigation. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequestAttributes, + /// The type of investigation signal. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationRequestData { + pub fn new( + attributes: crate::datadogV2::model::SecurityMonitoringSignalInvestigationRequestAttributes, + type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationType, + ) -> SecurityMonitoringSignalInvestigationRequestData { + SecurityMonitoringSignalInvestigationRequestData { + attributes, + 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 SecurityMonitoringSignalInvestigationRequestData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationRequestDataVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationRequestDataVisitor { + type Value = SecurityMonitoringSignalInvestigationRequestData; + + 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::SecurityMonitoringSignalInvestigationRequestAttributes, + > = None; + let mut type_: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationType, + > = 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)?); + } + "type" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::SecurityMonitoringSignalInvestigationType::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 = SecurityMonitoringSignalInvestigationRequestData { + attributes, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationRequestDataVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_response.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_response.rs new file mode 100644 index 000000000..a8f6401fd --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_response.rs @@ -0,0 +1,96 @@ +// 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 containing investigation details for a security signal. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationResponse { + /// Data containing the investigation details. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponseData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationResponse { + pub fn new( + data: crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponseData, + ) -> SecurityMonitoringSignalInvestigationResponse { + SecurityMonitoringSignalInvestigationResponse { + 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 SecurityMonitoringSignalInvestigationResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationResponseVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationResponseVisitor { + type Value = SecurityMonitoringSignalInvestigationResponse; + + 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< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponseData, + > = 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 = SecurityMonitoringSignalInvestigationResponse { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_response_attributes.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_response_attributes.rs new file mode 100644 index 000000000..7da09cdc7 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_response_attributes.rs @@ -0,0 +1,170 @@ +// 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 a signal investigation response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationResponseAttributes { + /// The unique ID of the investigation. + #[serde(rename = "investigation_id")] + pub investigation_id: String, + /// The ID of the rule that triggered the signal. + #[serde(rename = "rule_id")] + pub rule_id: String, + /// The unique ID of the security signal. + #[serde(rename = "signal_id")] + pub signal_id: String, + /// The state of the investigation. + #[serde(rename = "state")] + pub state: Option, + /// Information about an investigation step. + #[serde(rename = "step")] + pub step: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationResponseAttributes { + pub fn new( + investigation_id: String, + rule_id: String, + signal_id: String, + ) -> SecurityMonitoringSignalInvestigationResponseAttributes { + SecurityMonitoringSignalInvestigationResponseAttributes { + investigation_id, + rule_id, + signal_id, + state: None, + step: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn state( + mut self, + value: crate::datadogV2::model::SecurityMonitoringSignalInvestigationState, + ) -> Self { + self.state = Some(value); + self + } + + pub fn step( + mut self, + value: crate::datadogV2::model::SecurityMonitoringSignalInvestigationStep, + ) -> Self { + self.step = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for SecurityMonitoringSignalInvestigationResponseAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationResponseAttributesVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationResponseAttributesVisitor { + type Value = SecurityMonitoringSignalInvestigationResponseAttributes; + + 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 investigation_id: Option = None; + let mut rule_id: Option = None; + let mut signal_id: Option = None; + let mut state: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationState, + > = None; + let mut step: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationStep, + > = 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() { + "investigation_id" => { + investigation_id = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "rule_id" => { + rule_id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "signal_id" => { + signal_id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "state" => { + if v.is_null() { + continue; + } + state = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _state) = state { + match _state { + crate::datadogV2::model::SecurityMonitoringSignalInvestigationState::UnparsedObject(_state) => { + _unparsed = true; + }, + _ => {} + } + } + } + "step" => { + if v.is_null() { + continue; + } + step = 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 investigation_id = + investigation_id.ok_or_else(|| M::Error::missing_field("investigation_id"))?; + let rule_id = rule_id.ok_or_else(|| M::Error::missing_field("rule_id"))?; + let signal_id = signal_id.ok_or_else(|| M::Error::missing_field("signal_id"))?; + + let content = SecurityMonitoringSignalInvestigationResponseAttributes { + investigation_id, + rule_id, + signal_id, + state, + step, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationResponseAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_response_data.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_response_data.rs new file mode 100644 index 000000000..b6147c93b --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_response_data.rs @@ -0,0 +1,127 @@ +// 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}; + +/// Data containing the investigation details. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationResponseData { + /// Attributes of a signal investigation response. + #[serde(rename = "attributes")] + pub attributes: + crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponseAttributes, + /// The unique ID of the investigation. + #[serde(rename = "id")] + pub id: String, + /// The type of investigation signal. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationResponseData { + pub fn new( + attributes: crate::datadogV2::model::SecurityMonitoringSignalInvestigationResponseAttributes, + id: String, + type_: crate::datadogV2::model::SecurityMonitoringSignalInvestigationType, + ) -> SecurityMonitoringSignalInvestigationResponseData { + SecurityMonitoringSignalInvestigationResponseData { + attributes, + id, + 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 SecurityMonitoringSignalInvestigationResponseData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationResponseDataVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationResponseDataVisitor { + type Value = SecurityMonitoringSignalInvestigationResponseData; + + 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 = None; + let mut id: Option = None; + let mut type_: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationType, + > = 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" => { + 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::SecurityMonitoringSignalInvestigationType::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 id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = SecurityMonitoringSignalInvestigationResponseData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationResponseDataVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_state.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_state.rs new file mode 100644 index 000000000..4d3c9d898 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_state.rs @@ -0,0 +1,51 @@ +// 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 SecurityMonitoringSignalInvestigationState { + INVESTIGATING, + COMPLETED, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for SecurityMonitoringSignalInvestigationState { + fn to_string(&self) -> String { + match self { + Self::INVESTIGATING => String::from("investigating"), + Self::COMPLETED => String::from("completed"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for SecurityMonitoringSignalInvestigationState { + 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 SecurityMonitoringSignalInvestigationState { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "investigating" => Self::INVESTIGATING, + "completed" => Self::COMPLETED, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_step.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_step.rs new file mode 100644 index 000000000..a8a970af0 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_step.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}; + +/// Information about an investigation step. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationStep { + /// Array of step outputs. + #[serde(rename = "stepOutputs")] + pub step_outputs: Vec, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationStep { + pub fn new( + step_outputs: Vec, + ) -> SecurityMonitoringSignalInvestigationStep { + SecurityMonitoringSignalInvestigationStep { + step_outputs, + 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 SecurityMonitoringSignalInvestigationStep { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationStepVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationStepVisitor { + type Value = SecurityMonitoringSignalInvestigationStep; + + 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 step_outputs: 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() { + "stepOutputs" => { + step_outputs = + 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 step_outputs = + step_outputs.ok_or_else(|| M::Error::missing_field("step_outputs"))?; + + let content = SecurityMonitoringSignalInvestigationStep { + step_outputs, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationStepVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_step_output.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_step_output.rs new file mode 100644 index 000000000..6f8f2faa1 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_step_output.rs @@ -0,0 +1,146 @@ +// 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}; + +/// Output from an investigation step. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SecurityMonitoringSignalInvestigationStepOutput { + /// A one-line summary of the step analysis. + #[serde(rename = "currentStepAnalysisOneliner")] + pub current_step_analysis_oneliner: Option, + /// A detailed summary of the step analysis. + #[serde(rename = "currentStepAnalysisSummary")] + pub current_step_analysis_summary: String, + /// The name of the investigation step. + #[serde(rename = "name")] + pub name: String, + /// The verdict from the investigation step. + #[serde(rename = "verdict")] + pub verdict: crate::datadogV2::model::SecurityMonitoringSignalInvestigationStepOutputVerdict, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SecurityMonitoringSignalInvestigationStepOutput { + pub fn new( + current_step_analysis_summary: String, + name: String, + verdict: crate::datadogV2::model::SecurityMonitoringSignalInvestigationStepOutputVerdict, + ) -> SecurityMonitoringSignalInvestigationStepOutput { + SecurityMonitoringSignalInvestigationStepOutput { + current_step_analysis_oneliner: None, + current_step_analysis_summary, + name, + verdict, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn current_step_analysis_oneliner(mut self, value: String) -> Self { + self.current_step_analysis_oneliner = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for SecurityMonitoringSignalInvestigationStepOutput { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SecurityMonitoringSignalInvestigationStepOutputVisitor; + impl<'a> Visitor<'a> for SecurityMonitoringSignalInvestigationStepOutputVisitor { + type Value = SecurityMonitoringSignalInvestigationStepOutput; + + 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 current_step_analysis_oneliner: Option = None; + let mut current_step_analysis_summary: Option = None; + let mut name: Option = None; + let mut verdict: Option< + crate::datadogV2::model::SecurityMonitoringSignalInvestigationStepOutputVerdict, + > = 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() { + "currentStepAnalysisOneliner" => { + if v.is_null() { + continue; + } + current_step_analysis_oneliner = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "currentStepAnalysisSummary" => { + current_step_analysis_summary = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "name" => { + name = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "verdict" => { + verdict = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _verdict) = verdict { + match _verdict { + crate::datadogV2::model::SecurityMonitoringSignalInvestigationStepOutputVerdict::UnparsedObject(_verdict) => { + _unparsed = true; + }, + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let current_step_analysis_summary = current_step_analysis_summary + .ok_or_else(|| M::Error::missing_field("current_step_analysis_summary"))?; + let name = name.ok_or_else(|| M::Error::missing_field("name"))?; + let verdict = verdict.ok_or_else(|| M::Error::missing_field("verdict"))?; + + let content = SecurityMonitoringSignalInvestigationStepOutput { + current_step_analysis_oneliner, + current_step_analysis_summary, + name, + verdict, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SecurityMonitoringSignalInvestigationStepOutputVisitor) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_step_output_verdict.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_step_output_verdict.rs new file mode 100644 index 000000000..65d092e03 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_step_output_verdict.rs @@ -0,0 +1,57 @@ +// 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 SecurityMonitoringSignalInvestigationStepOutputVerdict { + UNSPECIFIED, + BENIGN, + SUSPICIOUS, + INCONCLUSIVE, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for SecurityMonitoringSignalInvestigationStepOutputVerdict { + fn to_string(&self) -> String { + match self { + Self::UNSPECIFIED => String::from("unspecified"), + Self::BENIGN => String::from("benign"), + Self::SUSPICIOUS => String::from("suspicious"), + Self::INCONCLUSIVE => String::from("inconclusive"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for SecurityMonitoringSignalInvestigationStepOutputVerdict { + 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 SecurityMonitoringSignalInvestigationStepOutputVerdict { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "unspecified" => Self::UNSPECIFIED, + "benign" => Self::BENIGN, + "suspicious" => Self::SUSPICIOUS, + "inconclusive" => Self::INCONCLUSIVE, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_security_monitoring_signal_investigation_type.rs b/src/datadogV2/model/model_security_monitoring_signal_investigation_type.rs new file mode 100644 index 000000000..d55414285 --- /dev/null +++ b/src/datadogV2/model/model_security_monitoring_signal_investigation_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 SecurityMonitoringSignalInvestigationType { + INVESTIGATION_SIGNAL, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for SecurityMonitoringSignalInvestigationType { + fn to_string(&self) -> String { + match self { + Self::INVESTIGATION_SIGNAL => String::from("investigation_signal"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for SecurityMonitoringSignalInvestigationType { + 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 SecurityMonitoringSignalInvestigationType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "investigation_signal" => Self::INVESTIGATION_SIGNAL, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/tests/scenarios/features/v2/security_monitoring.feature b/tests/scenarios/features/v2/security_monitoring.feature index ccc027734..f5c5e55c0 100644 --- a/tests/scenarios/features/v2/security_monitoring.feature +++ b/tests/scenarios/features/v2/security_monitoring.feature @@ -578,6 +578,30 @@ Feature: Security Monitoring And the response "data.attributes.exclusion_filters[0].name" is equal to "Exclude staging" And the response "data.attributes.exclusion_filters[0].query" is equal to "source:staging" + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Create a security signal investigation returns "Bad Request" response + Given operation "CreateSignalInvestigation" enabled + And new "CreateSignalInvestigation" request + And body with value {"data": {"attributes": {"deployment": "live", "signal_id": "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA"}, "type": "investigation_signal"}} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Create a security signal investigation returns "Not Found" response + Given operation "CreateSignalInvestigation" enabled + And new "CreateSignalInvestigation" request + And body with value {"data": {"attributes": {"deployment": "live", "signal_id": "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA"}, "type": "investigation_signal"}} + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Create a security signal investigation returns "OK" response + Given operation "CreateSignalInvestigation" enabled + And new "CreateSignalInvestigation" request + And body with value {"data": {"attributes": {"deployment": "live", "signal_id": "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA"}, "type": "investigation_signal"}} + When the request is sent + Then the response status is 200 OK + @generated @skip @team:DataDog/k9-cloud-security-platform Scenario: Create a suppression rule returns "Bad Request" response Given new "CreateSecurityMonitoringSuppression" request @@ -1284,6 +1308,30 @@ Feature: Security Monitoring When the request is sent Then the response status is 200 Notification rule details. + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Get investigation feedback returns "Bad Request" response + Given operation "GetInvestigationFeedback" enabled + And new "GetInvestigationFeedback" request + And request contains "signal_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Get investigation feedback returns "Not Found" response + Given operation "GetInvestigationFeedback" enabled + And new "GetInvestigationFeedback" request + And request contains "signal_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Get investigation feedback returns "OK" response + Given operation "GetInvestigationFeedback" enabled + And new "GetInvestigationFeedback" request + And request contains "signal_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + @skip-go @skip-java @skip-ruby @team:DataDog/k9-cloud-security-platform Scenario: Get rule version history returns "OK" response Given operation "GetRuleVersionHistory" enabled @@ -2007,6 +2055,30 @@ Feature: Security Monitoring And the response "name" is equal to "{{ unique }}-Updated" And the response "id" has the same value as "security_rule.id" + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Update investigation feedback returns "Bad Request" response + Given operation "UpdateInvestigationFeedback" enabled + And new "UpdateInvestigationFeedback" request + And body with value {"data": {"attributes": {"feedback": "positive", "feedback_content": [{"id": "section-1", "metrics": [{"placeholder": "Enter your feedback here", "prompt": "How helpful was this investigation?", "response": "Very helpful", "type": "sentiment"}], "title": "Investigation Quality"}], "incomplete": false, "rating": "positive", "signal_id": "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA", "type": "metrics"}, "type": "investigation_feedback"}} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Update investigation feedback returns "Not Found" response + Given operation "UpdateInvestigationFeedback" enabled + And new "UpdateInvestigationFeedback" request + And body with value {"data": {"attributes": {"feedback": "positive", "feedback_content": [{"id": "section-1", "metrics": [{"placeholder": "Enter your feedback here", "prompt": "How helpful was this investigation?", "response": "Very helpful", "type": "sentiment"}], "title": "Investigation Quality"}], "incomplete": false, "rating": "positive", "signal_id": "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA", "type": "metrics"}, "type": "investigation_feedback"}} + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/k9-cloud-security-platform + Scenario: Update investigation feedback returns "OK" response + Given operation "UpdateInvestigationFeedback" enabled + And new "UpdateInvestigationFeedback" request + And body with value {"data": {"attributes": {"feedback": "positive", "feedback_content": [{"id": "section-1", "metrics": [{"placeholder": "Enter your feedback here", "prompt": "How helpful was this investigation?", "response": "Very helpful", "type": "sentiment"}], "title": "Investigation Quality"}], "incomplete": false, "rating": "positive", "signal_id": "AAAAAWgN8Xwgr1vKDQAAAABBV2dOOFh3ZzZobm1mWXJFYTR0OA", "type": "metrics"}, "type": "investigation_feedback"}} + When the request is sent + Then the response status is 200 OK + @team:DataDog/k9-cloud-security-platform Scenario: Update resource filters returns "Bad Request" response Given new "UpdateResourceEvaluationFilters" request diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 41fa31182..4fbc7c857 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -4579,6 +4579,24 @@ "type": "safe" } }, + "CreateSignalInvestigation": { + "tag": "Security Monitoring", + "undo": { + "type": "safe" + } + }, + "UpdateInvestigationFeedback": { + "tag": "Security Monitoring", + "undo": { + "type": "idempotent" + } + }, + "GetInvestigationFeedback": { + "tag": "Security Monitoring", + "undo": { + "type": "safe" + } + }, "SearchSecurityMonitoringSignals": { "tag": "Security Monitoring", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 3fb5c92c2..276ae0354 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -2731,6 +2731,18 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.ListSecurityMonitoringSignalsWithPagination".into(), test_v2_list_security_monitoring_signals_with_pagination, ); + world.function_mappings.insert( + "v2.CreateSignalInvestigation".into(), + test_v2_create_signal_investigation, + ); + world.function_mappings.insert( + "v2.UpdateInvestigationFeedback".into(), + test_v2_update_investigation_feedback, + ); + world.function_mappings.insert( + "v2.GetInvestigationFeedback".into(), + test_v2_get_investigation_feedback, + ); world.function_mappings.insert( "v2.SearchSecurityMonitoringSignals".into(), test_v2_search_security_monitoring_signals, @@ -19674,6 +19686,90 @@ fn test_v2_list_security_monitoring_signals_with_pagination( world.response.code = 200; } +fn test_v2_create_signal_investigation( + 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.create_signal_investigation_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_update_investigation_feedback( + 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.update_investigation_feedback_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_get_investigation_feedback( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_security_monitoring + .as_ref() + .expect("api instance not found"); + let signal_id = serde_json::from_value(_parameters.get("signal_id").unwrap().clone()).unwrap(); + let response = match block_on(api.get_investigation_feedback_with_http_info(signal_id)) { + 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_search_security_monitoring_signals( world: &mut DatadogWorld, _parameters: &HashMap,