diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 92c1c1fc7..842f6f5c4 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -215,6 +215,16 @@ components: required: true schema: type: string + ApplicationSecurityServiceNameParam: + description: |- + The name of the service to retrieve Application Security details for. + Returns all matching services across environments. + example: web-store + in: path + name: service_filter + required: true + schema: + type: string ApplicationSecurityWafCustomRuleIDParam: description: The ID of the custom rule. example: 3b5-v82-ns6 @@ -8309,6 +8319,303 @@ components: required: - data type: object + ApplicationSecurityServiceAttributes: + description: Application Security details describing a service in a given environment. + properties: + agent_versions: + description: The Datadog Agent versions reporting for the service. + example: + - 7.50.0 + items: + description: A Datadog Agent version reporting for the service. + example: 7.50.0 + type: string + type: array + app_type: + description: The application type of the service, such as `web` or `serverless`. + example: web + type: string + asm_threat_compatible: + description: Whether the service is compatible with Application Security Management (Threats). + example: true + type: boolean + backend_waf_event_count: + description: The number of backend WAF events detected for the service. + example: 10 + format: int64 + type: integer + business_logic: + description: The enabled business logic detection rules for the service. + example: + - users.login.success + items: + description: A business logic detection rule enabled for the service. + example: users.login.success + type: string + type: array + color: + deprecated: true + description: "Deprecated: a display color associated with the service in the UI." + example: "" + type: string + env: + description: The environment the service runs in. + example: prod + type: string + event_count: + description: The number of Application Security events detected for the service. + example: 42 + format: int64 + type: integer + event_trend: + deprecated: true + description: "Deprecated: the trend of Application Security events over time." + example: + - 0 + items: + description: A point in the Application Security events trend. + example: 0 + format: int64 + type: integer + type: array + has_appsec_enabled: + description: Whether Application Security Management (Threats) is enabled for the service. + example: true + type: boolean + hits: + deprecated: true + description: "Deprecated: the number of hits for the service." + example: 0 + format: int64 + type: integer + iast_product_activation: + description: Whether Interactive Application Security Testing (IAST) is enabled for the service. + example: false + type: boolean + iast_product_compatibility: + description: The Interactive Application Security Testing (IAST) compatibility status of the service. + example: compatible + type: string + iast_product_compatibility_reasons: + description: The reasons explaining the Interactive Application Security Testing (IAST) compatibility status. + example: + - service_not_compatible + items: + description: A reason explaining the Interactive Application Security Testing (IAST) compatibility status. + example: service_not_compatible + type: string + type: array + languages: + description: The programming languages detected for the service. + example: + - go + items: + description: A programming language detected for the service. + example: go + type: string + type: array + last_ingested_spans: + description: The Unix timestamp, in seconds, of the last ingested span for the service. + example: 1610000000 + format: int64 + type: integer + rc_capabilities: + description: The Remote Configuration capabilities reported by the service. + example: + - ASM_DD_RULES + items: + description: A Remote Configuration capability reported by the service. + example: ASM_DD_RULES + type: string + type: array + recommended_business_logic: + description: The recommended business logic detection rules for the service. + example: + - users.login.success + items: + description: A recommended business logic detection rule for the service. + example: users.login.success + type: string + type: array + risk_product_activation: + description: Whether Software Composition Analysis (SCA) is enabled for the service. + example: false + type: boolean + risk_product_compatibility: + description: The Software Composition Analysis (SCA) compatibility status of the service. + example: compatible + type: string + risk_product_compatibility_reasons: + description: The reasons explaining the Software Composition Analysis (SCA) compatibility status. + example: + - service_not_compatible + items: + description: A reason explaining the Software Composition Analysis (SCA) compatibility status. + example: service_not_compatible + type: string + type: array + rules_version: + description: The WAF rules versions applied to the service. + example: + - 1.13.0 + items: + description: A WAF rules version applied to the service. + example: 1.13.0 + type: string + type: array + service: + description: The name of the service. + example: web-store + type: string + signal_count: + deprecated: true + description: "Deprecated: the number of security signals for the service." + example: 0 + format: int64 + type: integer + signal_trend: + deprecated: true + description: "Deprecated: the trend of security signals over time." + example: + - 0 + items: + description: A point in the security signals trend. + example: 0 + format: int64 + type: integer + type: array + source: + description: The data sources that contributed information about the service. + example: + - services-activity + items: + description: A data source that contributed information about the service. + example: services-activity + type: string + type: array + teams: + description: The teams that own the service. + example: + - security-team + items: + description: A team that owns the service. + example: security-team + type: string + type: array + tracer_versions: + description: The Datadog tracing library versions reporting for the service. + example: + - 1.60.0 + items: + description: A Datadog tracing library version reporting for the service. + example: 1.60.0 + type: string + type: array + vm-activation: + description: The Vulnerability Management activation status of the service. + example: enabled + type: string + vuln_critical_count: + deprecated: true + description: "Deprecated: the number of critical-severity vulnerabilities for the service." + example: 0 + format: int64 + type: integer + vuln_high_count: + deprecated: true + description: "Deprecated: the number of high-severity vulnerabilities for the service." + example: 0 + format: int64 + type: integer + without_filter_services: + description: The total number of services available without applying the service filter. + example: 0 + format: int64 + type: integer + required: + - service + - env + - app_type + - has_appsec_enabled + - asm_threat_compatible + - languages + - teams + - event_count + - backend_waf_event_count + - risk_product_activation + - risk_product_compatibility + - risk_product_compatibility_reasons + - iast_product_activation + - iast_product_compatibility + - iast_product_compatibility_reasons + - vm-activation + - agent_versions + - tracer_versions + - rules_version + - rc_capabilities + - source + - last_ingested_spans + - business_logic + - recommended_business_logic + - without_filter_services + - color + - event_trend + - signal_trend + - signal_count + - hits + - vuln_high_count + - vuln_critical_count + type: object + ApplicationSecurityServiceResource: + description: A JSON:API resource describing a service and its Application Security details. + properties: + attributes: + $ref: "#/components/schemas/ApplicationSecurityServiceAttributes" + id: + description: The unique identifier of the service, formatted as `_`. + example: web-store_prod + type: string + type: + $ref: "#/components/schemas/ApplicationSecurityServiceType" + required: + - id + - type + - attributes + type: object + ApplicationSecurityServiceType: + default: service_env + description: The type of the resource. The value should always be `service_env`. + enum: + - service_env + example: service_env + type: string + x-enum-varnames: + - SERVICE_ENV + ApplicationSecurityServicesMetadata: + description: Metadata returned alongside the list of services. + properties: + num_services_with_appsec: + description: The number of services with Application Security Management (Threats) enabled. + example: 1 + format: int64 + type: integer + required: + - num_services_with_appsec + type: object + ApplicationSecurityServicesResponse: + description: Response object containing the list of services matching the requested name. + properties: + data: + description: The list of services matching the requested name. + items: + $ref: "#/components/schemas/ApplicationSecurityServiceResource" + type: array + meta: + $ref: "#/components/schemas/ApplicationSecurityServicesMetadata" + required: + - data + - meta + type: object ApplicationSecurityWafCustomRuleAction: description: The definition of `ApplicationSecurityWafCustomRuleAction` object. properties: @@ -165752,6 +166059,87 @@ paths: x-unstable: |- **Note**: This endpoint is in public beta and it's subject to change. If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/). + /api/v2/security/asm/services/{service_filter}: + get: + description: |- + Retrieve Application Security details for services matching the given name. + Returns Application Security activation, compatibility, and product enablement + information for each matching `(service, environment)` pair, along with a count + of services that have Application Security Management (Threats) enabled. + operationId: GetAsmServiceByName + parameters: + - $ref: "#/components/parameters/ApplicationSecurityServiceNameParam" + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + - attributes: + agent_versions: + - 7.50.0 + app_type: web + asm_threat_compatible: true + backend_waf_event_count: 10 + business_logic: [] + color: "" + env: prod + event_count: 42 + event_trend: [] + has_appsec_enabled: true + hits: 0 + iast_product_activation: false + iast_product_compatibility: compatible + iast_product_compatibility_reasons: [] + languages: + - go + last_ingested_spans: 1610000000 + rc_capabilities: + - ASM_DD_RULES + recommended_business_logic: [] + risk_product_activation: false + risk_product_compatibility: compatible + risk_product_compatibility_reasons: [] + rules_version: + - 1.13.0 + service: web-store + signal_count: 0 + signal_trend: [] + source: + - services-activity + teams: + - security-team + tracer_versions: + - 1.60.0 + vm-activation: enabled + vuln_critical_count: 0 + vuln_high_count: 0 + without_filter_services: 0 + id: web-store_prod + type: service_env + meta: + num_services_with_appsec: 1 + schema: + $ref: "#/components/schemas/ApplicationSecurityServicesResponse" + description: OK + "403": + $ref: "#/components/responses/NotAuthorizedResponse" + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + summary: Get Application Security details for a service + tags: + - "Application Security" + "x-permission": + operator: OR + permissions: + - apm_service_catalog_read + - appsec_protect_read + - apm_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/cloud_workload/policy/download: get: description: |- diff --git a/examples/v2_application-security_GetAsmServiceByName.rs b/examples/v2_application-security_GetAsmServiceByName.rs new file mode 100644 index 000000000..7614cb167 --- /dev/null +++ b/examples/v2_application-security_GetAsmServiceByName.rs @@ -0,0 +1,18 @@ +// Get Application Security details for a service returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_application_security::ApplicationSecurityAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.GetAsmServiceByName", true); + let api = ApplicationSecurityAPI::with_config(configuration); + let resp = api + .get_asm_service_by_name("service_filter".to_string()) + .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 24bb229c1..0f994441f 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -643,6 +643,7 @@ impl Default for Configuration { ("v2.update_connection".to_owned(), false), ("v2.get_pruned_trace_by_id".to_owned(), false), ("v2.get_trace_by_id".to_owned(), false), + ("v2.get_asm_service_by_name".to_owned(), false), ("v2.create_report_schedule".to_owned(), false), ("v2.patch_report_schedule".to_owned(), false), ("v2.delete_sourcemaps".to_owned(), false), diff --git a/src/datadogV2/api/api_application_security.rs b/src/datadogV2/api/api_application_security.rs index a1f8b33f6..11585c0a2 100644 --- a/src/datadogV2/api/api_application_security.rs +++ b/src/datadogV2/api/api_application_security.rs @@ -6,6 +6,7 @@ use flate2::{ write::{GzEncoder, ZlibEncoder}, Compression, }; +use log::warn; use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; use std::io::Write; @@ -82,6 +83,14 @@ pub enum GetApplicationSecurityWafPolicyError { UnknownValue(serde_json::Value), } +/// GetAsmServiceByNameError is a struct for typed errors of method [`ApplicationSecurityAPI::get_asm_service_by_name`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetAsmServiceByNameError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// ListApplicationSecurityWAFCustomRulesError is a struct for typed errors of method [`ApplicationSecurityAPI::list_application_security_waf_custom_rules`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1313,6 +1322,132 @@ impl ApplicationSecurityAPI { } } + /// Retrieve Application Security details for services matching the given name. + /// Returns Application Security activation, compatibility, and product enablement + /// information for each matching `(service, environment)` pair, along with a count + /// of services that have Application Security Management (Threats) enabled. + pub async fn get_asm_service_by_name( + &self, + service_filter: String, + ) -> Result< + crate::datadogV2::model::ApplicationSecurityServicesResponse, + datadog::Error, + > { + match self + .get_asm_service_by_name_with_http_info(service_filter) + .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 Application Security details for services matching the given name. + /// Returns Application Security activation, compatibility, and product enablement + /// information for each matching `(service, environment)` pair, along with a count + /// of services that have Application Security Management (Threats) enabled. + pub async fn get_asm_service_by_name_with_http_info( + &self, + service_filter: String, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.get_asm_service_by_name"; + 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_asm_service_by_name' 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/asm/services/{service_filter}", + local_configuration.get_operation_host(operation_id), + service_filter = datadog::urlencode(service_filter) + ); + 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::( + &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)) + } + } + /// Retrieve a list of WAF custom rule. pub async fn list_application_security_waf_custom_rules( &self, diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index e4f8accf4..388195ef8 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -9734,6 +9734,16 @@ pub mod model_security_entity_risk_scores_meta; pub use self::model_security_entity_risk_scores_meta::SecurityEntityRiskScoresMeta; pub mod model_security_entity_risk_score_response; pub use self::model_security_entity_risk_score_response::SecurityEntityRiskScoreResponse; +pub mod model_application_security_services_response; +pub use self::model_application_security_services_response::ApplicationSecurityServicesResponse; +pub mod model_application_security_service_resource; +pub use self::model_application_security_service_resource::ApplicationSecurityServiceResource; +pub mod model_application_security_service_attributes; +pub use self::model_application_security_service_attributes::ApplicationSecurityServiceAttributes; +pub mod model_application_security_service_type; +pub use self::model_application_security_service_type::ApplicationSecurityServiceType; +pub mod model_application_security_services_metadata; +pub use self::model_application_security_services_metadata::ApplicationSecurityServicesMetadata; pub mod model_security_findings_sort; pub use self::model_security_findings_sort::SecurityFindingsSort; pub mod model_list_security_findings_response; diff --git a/src/datadogV2/model/model_application_security_service_attributes.rs b/src/datadogV2/model/model_application_security_service_attributes.rs new file mode 100644 index 000000000..e38732e9b --- /dev/null +++ b/src/datadogV2/model/model_application_security_service_attributes.rs @@ -0,0 +1,492 @@ +// 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}; + +/// Application Security details describing a service in a given environment. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ApplicationSecurityServiceAttributes { + /// The Datadog Agent versions reporting for the service. + #[serde(rename = "agent_versions")] + pub agent_versions: Vec, + /// The application type of the service, such as `web` or `serverless`. + #[serde(rename = "app_type")] + pub app_type: String, + /// Whether the service is compatible with Application Security Management (Threats). + #[serde(rename = "asm_threat_compatible")] + pub asm_threat_compatible: bool, + /// The number of backend WAF events detected for the service. + #[serde(rename = "backend_waf_event_count")] + pub backend_waf_event_count: i64, + /// The enabled business logic detection rules for the service. + #[serde(rename = "business_logic")] + pub business_logic: Vec, + /// Deprecated: a display color associated with the service in the UI. + #[deprecated] + #[serde(rename = "color")] + pub color: String, + /// The environment the service runs in. + #[serde(rename = "env")] + pub env: String, + /// The number of Application Security events detected for the service. + #[serde(rename = "event_count")] + pub event_count: i64, + /// Deprecated: the trend of Application Security events over time. + #[deprecated] + #[serde(rename = "event_trend")] + pub event_trend: Vec, + /// Whether Application Security Management (Threats) is enabled for the service. + #[serde(rename = "has_appsec_enabled")] + pub has_appsec_enabled: bool, + /// Deprecated: the number of hits for the service. + #[deprecated] + #[serde(rename = "hits")] + pub hits: i64, + /// Whether Interactive Application Security Testing (IAST) is enabled for the service. + #[serde(rename = "iast_product_activation")] + pub iast_product_activation: bool, + /// The Interactive Application Security Testing (IAST) compatibility status of the service. + #[serde(rename = "iast_product_compatibility")] + pub iast_product_compatibility: String, + /// The reasons explaining the Interactive Application Security Testing (IAST) compatibility status. + #[serde(rename = "iast_product_compatibility_reasons")] + pub iast_product_compatibility_reasons: Vec, + /// The programming languages detected for the service. + #[serde(rename = "languages")] + pub languages: Vec, + /// The Unix timestamp, in seconds, of the last ingested span for the service. + #[serde(rename = "last_ingested_spans")] + pub last_ingested_spans: i64, + /// The Remote Configuration capabilities reported by the service. + #[serde(rename = "rc_capabilities")] + pub rc_capabilities: Vec, + /// The recommended business logic detection rules for the service. + #[serde(rename = "recommended_business_logic")] + pub recommended_business_logic: Vec, + /// Whether Software Composition Analysis (SCA) is enabled for the service. + #[serde(rename = "risk_product_activation")] + pub risk_product_activation: bool, + /// The Software Composition Analysis (SCA) compatibility status of the service. + #[serde(rename = "risk_product_compatibility")] + pub risk_product_compatibility: String, + /// The reasons explaining the Software Composition Analysis (SCA) compatibility status. + #[serde(rename = "risk_product_compatibility_reasons")] + pub risk_product_compatibility_reasons: Vec, + /// The WAF rules versions applied to the service. + #[serde(rename = "rules_version")] + pub rules_version: Vec, + /// The name of the service. + #[serde(rename = "service")] + pub service: String, + /// Deprecated: the number of security signals for the service. + #[deprecated] + #[serde(rename = "signal_count")] + pub signal_count: i64, + /// Deprecated: the trend of security signals over time. + #[deprecated] + #[serde(rename = "signal_trend")] + pub signal_trend: Vec, + /// The data sources that contributed information about the service. + #[serde(rename = "source")] + pub source: Vec, + /// The teams that own the service. + #[serde(rename = "teams")] + pub teams: Vec, + /// The Datadog tracing library versions reporting for the service. + #[serde(rename = "tracer_versions")] + pub tracer_versions: Vec, + /// The Vulnerability Management activation status of the service. + #[serde(rename = "vm-activation")] + pub vm_activation: String, + /// Deprecated: the number of critical-severity vulnerabilities for the service. + #[deprecated] + #[serde(rename = "vuln_critical_count")] + pub vuln_critical_count: i64, + /// Deprecated: the number of high-severity vulnerabilities for the service. + #[deprecated] + #[serde(rename = "vuln_high_count")] + pub vuln_high_count: i64, + /// The total number of services available without applying the service filter. + #[serde(rename = "without_filter_services")] + pub without_filter_services: i64, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ApplicationSecurityServiceAttributes { + pub fn new( + agent_versions: Vec, + app_type: String, + asm_threat_compatible: bool, + backend_waf_event_count: i64, + business_logic: Vec, + color: String, + env: String, + event_count: i64, + event_trend: Vec, + has_appsec_enabled: bool, + hits: i64, + iast_product_activation: bool, + iast_product_compatibility: String, + iast_product_compatibility_reasons: Vec, + languages: Vec, + last_ingested_spans: i64, + rc_capabilities: Vec, + recommended_business_logic: Vec, + risk_product_activation: bool, + risk_product_compatibility: String, + risk_product_compatibility_reasons: Vec, + rules_version: Vec, + service: String, + signal_count: i64, + signal_trend: Vec, + source: Vec, + teams: Vec, + tracer_versions: Vec, + vm_activation: String, + vuln_critical_count: i64, + vuln_high_count: i64, + without_filter_services: i64, + ) -> ApplicationSecurityServiceAttributes { + #[allow(deprecated)] + ApplicationSecurityServiceAttributes { + agent_versions, + app_type, + asm_threat_compatible, + backend_waf_event_count, + business_logic, + color, + env, + event_count, + event_trend, + has_appsec_enabled, + hits, + iast_product_activation, + iast_product_compatibility, + iast_product_compatibility_reasons, + languages, + last_ingested_spans, + rc_capabilities, + recommended_business_logic, + risk_product_activation, + risk_product_compatibility, + risk_product_compatibility_reasons, + rules_version, + service, + signal_count, + signal_trend, + source, + teams, + tracer_versions, + vm_activation, + vuln_critical_count, + vuln_high_count, + without_filter_services, + 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 ApplicationSecurityServiceAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ApplicationSecurityServiceAttributesVisitor; + impl<'a> Visitor<'a> for ApplicationSecurityServiceAttributesVisitor { + type Value = ApplicationSecurityServiceAttributes; + + 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 agent_versions: Option> = None; + let mut app_type: Option = None; + let mut asm_threat_compatible: Option = None; + let mut backend_waf_event_count: Option = None; + let mut business_logic: Option> = None; + let mut color: Option = None; + let mut env: Option = None; + let mut event_count: Option = None; + let mut event_trend: Option> = None; + let mut has_appsec_enabled: Option = None; + let mut hits: Option = None; + let mut iast_product_activation: Option = None; + let mut iast_product_compatibility: Option = None; + let mut iast_product_compatibility_reasons: Option> = None; + let mut languages: Option> = None; + let mut last_ingested_spans: Option = None; + let mut rc_capabilities: Option> = None; + let mut recommended_business_logic: Option> = None; + let mut risk_product_activation: Option = None; + let mut risk_product_compatibility: Option = None; + let mut risk_product_compatibility_reasons: Option> = None; + let mut rules_version: Option> = None; + let mut service: Option = None; + let mut signal_count: Option = None; + let mut signal_trend: Option> = None; + let mut source: Option> = None; + let mut teams: Option> = None; + let mut tracer_versions: Option> = None; + let mut vm_activation: Option = None; + let mut vuln_critical_count: Option = None; + let mut vuln_high_count: Option = None; + let mut without_filter_services: 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() { + "agent_versions" => { + agent_versions = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "app_type" => { + app_type = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "asm_threat_compatible" => { + asm_threat_compatible = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "backend_waf_event_count" => { + backend_waf_event_count = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "business_logic" => { + business_logic = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "color" => { + color = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "env" => { + env = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "event_count" => { + event_count = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "event_trend" => { + event_trend = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "has_appsec_enabled" => { + has_appsec_enabled = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "hits" => { + hits = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "iast_product_activation" => { + iast_product_activation = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "iast_product_compatibility" => { + iast_product_compatibility = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "iast_product_compatibility_reasons" => { + iast_product_compatibility_reasons = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "languages" => { + languages = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "last_ingested_spans" => { + last_ingested_spans = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "rc_capabilities" => { + rc_capabilities = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "recommended_business_logic" => { + recommended_business_logic = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "risk_product_activation" => { + risk_product_activation = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "risk_product_compatibility" => { + risk_product_compatibility = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "risk_product_compatibility_reasons" => { + risk_product_compatibility_reasons = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "rules_version" => { + rules_version = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "service" => { + service = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "signal_count" => { + signal_count = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "signal_trend" => { + signal_trend = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "source" => { + source = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "teams" => { + teams = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "tracer_versions" => { + tracer_versions = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "vm-activation" => { + vm_activation = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "vuln_critical_count" => { + vuln_critical_count = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "vuln_high_count" => { + vuln_high_count = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "without_filter_services" => { + without_filter_services = + 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 agent_versions = + agent_versions.ok_or_else(|| M::Error::missing_field("agent_versions"))?; + let app_type = app_type.ok_or_else(|| M::Error::missing_field("app_type"))?; + let asm_threat_compatible = asm_threat_compatible + .ok_or_else(|| M::Error::missing_field("asm_threat_compatible"))?; + let backend_waf_event_count = backend_waf_event_count + .ok_or_else(|| M::Error::missing_field("backend_waf_event_count"))?; + let business_logic = + business_logic.ok_or_else(|| M::Error::missing_field("business_logic"))?; + let color = color.ok_or_else(|| M::Error::missing_field("color"))?; + let env = env.ok_or_else(|| M::Error::missing_field("env"))?; + let event_count = + event_count.ok_or_else(|| M::Error::missing_field("event_count"))?; + let event_trend = + event_trend.ok_or_else(|| M::Error::missing_field("event_trend"))?; + let has_appsec_enabled = has_appsec_enabled + .ok_or_else(|| M::Error::missing_field("has_appsec_enabled"))?; + let hits = hits.ok_or_else(|| M::Error::missing_field("hits"))?; + let iast_product_activation = iast_product_activation + .ok_or_else(|| M::Error::missing_field("iast_product_activation"))?; + let iast_product_compatibility = iast_product_compatibility + .ok_or_else(|| M::Error::missing_field("iast_product_compatibility"))?; + let iast_product_compatibility_reasons = iast_product_compatibility_reasons + .ok_or_else(|| M::Error::missing_field("iast_product_compatibility_reasons"))?; + let languages = languages.ok_or_else(|| M::Error::missing_field("languages"))?; + let last_ingested_spans = last_ingested_spans + .ok_or_else(|| M::Error::missing_field("last_ingested_spans"))?; + let rc_capabilities = + rc_capabilities.ok_or_else(|| M::Error::missing_field("rc_capabilities"))?; + let recommended_business_logic = recommended_business_logic + .ok_or_else(|| M::Error::missing_field("recommended_business_logic"))?; + let risk_product_activation = risk_product_activation + .ok_or_else(|| M::Error::missing_field("risk_product_activation"))?; + let risk_product_compatibility = risk_product_compatibility + .ok_or_else(|| M::Error::missing_field("risk_product_compatibility"))?; + let risk_product_compatibility_reasons = risk_product_compatibility_reasons + .ok_or_else(|| M::Error::missing_field("risk_product_compatibility_reasons"))?; + let rules_version = + rules_version.ok_or_else(|| M::Error::missing_field("rules_version"))?; + let service = service.ok_or_else(|| M::Error::missing_field("service"))?; + let signal_count = + signal_count.ok_or_else(|| M::Error::missing_field("signal_count"))?; + let signal_trend = + signal_trend.ok_or_else(|| M::Error::missing_field("signal_trend"))?; + let source = source.ok_or_else(|| M::Error::missing_field("source"))?; + let teams = teams.ok_or_else(|| M::Error::missing_field("teams"))?; + let tracer_versions = + tracer_versions.ok_or_else(|| M::Error::missing_field("tracer_versions"))?; + let vm_activation = + vm_activation.ok_or_else(|| M::Error::missing_field("vm_activation"))?; + let vuln_critical_count = vuln_critical_count + .ok_or_else(|| M::Error::missing_field("vuln_critical_count"))?; + let vuln_high_count = + vuln_high_count.ok_or_else(|| M::Error::missing_field("vuln_high_count"))?; + let without_filter_services = without_filter_services + .ok_or_else(|| M::Error::missing_field("without_filter_services"))?; + + #[allow(deprecated)] + let content = ApplicationSecurityServiceAttributes { + agent_versions, + app_type, + asm_threat_compatible, + backend_waf_event_count, + business_logic, + color, + env, + event_count, + event_trend, + has_appsec_enabled, + hits, + iast_product_activation, + iast_product_compatibility, + iast_product_compatibility_reasons, + languages, + last_ingested_spans, + rc_capabilities, + recommended_business_logic, + risk_product_activation, + risk_product_compatibility, + risk_product_compatibility_reasons, + rules_version, + service, + signal_count, + signal_trend, + source, + teams, + tracer_versions, + vm_activation, + vuln_critical_count, + vuln_high_count, + without_filter_services, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ApplicationSecurityServiceAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_application_security_service_resource.rs b/src/datadogV2/model/model_application_security_service_resource.rs new file mode 100644 index 000000000..241cecaa2 --- /dev/null +++ b/src/datadogV2/model/model_application_security_service_resource.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}; + +/// A JSON:API resource describing a service and its Application Security details. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ApplicationSecurityServiceResource { + /// Application Security details describing a service in a given environment. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::ApplicationSecurityServiceAttributes, + /// The unique identifier of the service, formatted as `_`. + #[serde(rename = "id")] + pub id: String, + /// The type of the resource. The value should always be `service_env`. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::ApplicationSecurityServiceType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ApplicationSecurityServiceResource { + pub fn new( + attributes: crate::datadogV2::model::ApplicationSecurityServiceAttributes, + id: String, + type_: crate::datadogV2::model::ApplicationSecurityServiceType, + ) -> ApplicationSecurityServiceResource { + ApplicationSecurityServiceResource { + 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 ApplicationSecurityServiceResource { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ApplicationSecurityServiceResourceVisitor; + impl<'a> Visitor<'a> for ApplicationSecurityServiceResourceVisitor { + type Value = ApplicationSecurityServiceResource; + + 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::ApplicationSecurityServiceAttributes, + > = None; + let mut 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() { + "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::ApplicationSecurityServiceType::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 = ApplicationSecurityServiceResource { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ApplicationSecurityServiceResourceVisitor) + } +} diff --git a/src/datadogV2/model/model_application_security_service_type.rs b/src/datadogV2/model/model_application_security_service_type.rs new file mode 100644 index 000000000..4e8a96af5 --- /dev/null +++ b/src/datadogV2/model/model_application_security_service_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 ApplicationSecurityServiceType { + SERVICE_ENV, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for ApplicationSecurityServiceType { + fn to_string(&self) -> String { + match self { + Self::SERVICE_ENV => String::from("service_env"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for ApplicationSecurityServiceType { + 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 ApplicationSecurityServiceType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "service_env" => Self::SERVICE_ENV, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_application_security_services_metadata.rs b/src/datadogV2/model/model_application_security_services_metadata.rs new file mode 100644 index 000000000..9ce01e0aa --- /dev/null +++ b/src/datadogV2/model/model_application_security_services_metadata.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}; + +/// Metadata returned alongside the list of services. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ApplicationSecurityServicesMetadata { + /// The number of services with Application Security Management (Threats) enabled. + #[serde(rename = "num_services_with_appsec")] + pub num_services_with_appsec: i64, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ApplicationSecurityServicesMetadata { + pub fn new(num_services_with_appsec: i64) -> ApplicationSecurityServicesMetadata { + ApplicationSecurityServicesMetadata { + num_services_with_appsec, + 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 ApplicationSecurityServicesMetadata { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ApplicationSecurityServicesMetadataVisitor; + impl<'a> Visitor<'a> for ApplicationSecurityServicesMetadataVisitor { + type Value = ApplicationSecurityServicesMetadata; + + 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 num_services_with_appsec: 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() { + "num_services_with_appsec" => { + num_services_with_appsec = + 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 num_services_with_appsec = num_services_with_appsec + .ok_or_else(|| M::Error::missing_field("num_services_with_appsec"))?; + + let content = ApplicationSecurityServicesMetadata { + num_services_with_appsec, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ApplicationSecurityServicesMetadataVisitor) + } +} diff --git a/src/datadogV2/model/model_application_security_services_response.rs b/src/datadogV2/model/model_application_security_services_response.rs new file mode 100644 index 000000000..dd7f9ea86 --- /dev/null +++ b/src/datadogV2/model/model_application_security_services_response.rs @@ -0,0 +1,108 @@ +// 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 object containing the list of services matching the requested name. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ApplicationSecurityServicesResponse { + /// The list of services matching the requested name. + #[serde(rename = "data")] + pub data: Vec, + /// Metadata returned alongside the list of services. + #[serde(rename = "meta")] + pub meta: crate::datadogV2::model::ApplicationSecurityServicesMetadata, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ApplicationSecurityServicesResponse { + pub fn new( + data: Vec, + meta: crate::datadogV2::model::ApplicationSecurityServicesMetadata, + ) -> ApplicationSecurityServicesResponse { + ApplicationSecurityServicesResponse { + data, + meta, + 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 ApplicationSecurityServicesResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ApplicationSecurityServicesResponseVisitor; + impl<'a> Visitor<'a> for ApplicationSecurityServicesResponseVisitor { + type Value = ApplicationSecurityServicesResponse; + + 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< + Vec, + > = None; + let mut meta: 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)?); + } + "meta" => { + meta = 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 meta = meta.ok_or_else(|| M::Error::missing_field("meta"))?; + + let content = ApplicationSecurityServicesResponse { + data, + meta, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ApplicationSecurityServicesResponseVisitor) + } +} diff --git a/tests/scenarios/features/v2/application_security.feature b/tests/scenarios/features/v2/application_security.feature index 4dbda1c46..710a60641 100644 --- a/tests/scenarios/features/v2/application_security.feature +++ b/tests/scenarios/features/v2/application_security.feature @@ -148,6 +148,14 @@ Feature: Application Security When the request is sent Then the response status is 204 OK + @generated @skip @team:DataDog/asm-backend + Scenario: Get Application Security details for a service returns "OK" response + Given operation "GetAsmServiceByName" enabled + And new "GetAsmServiceByName" request + And request contains "service_filter" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + @team:DataDog/asm-backend Scenario: Get a WAF Policy returns "OK" response Given there is a valid "policy" in the system diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index b7bddb161..3f66e97af 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -6883,6 +6883,12 @@ "type": "safe" } }, + "GetAsmServiceByName": { + "tag": "Application Security", + "undo": { + "type": "safe" + } + }, "DownloadCloudWorkloadPolicyFile": { "tag": "CSM Threats", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 2d0b4b83a..2e625ff37 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -6318,6 +6318,10 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.UpdateApplicationSecurityWafPolicy".into(), test_v2_update_application_security_waf_policy, ); + world.function_mappings.insert( + "v2.GetAsmServiceByName".into(), + test_v2_get_asm_service_by_name, + ); world.function_mappings.insert( "v2.ListCSMThreatsAgentRules".into(), test_v2_list_csm_threats_agent_rules, @@ -49267,6 +49271,32 @@ fn test_v2_update_application_security_waf_policy( world.response.code = response.status.as_u16(); } +fn test_v2_get_asm_service_by_name(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_application_security + .as_ref() + .expect("api instance not found"); + let service_filter = + serde_json::from_value(_parameters.get("service_filter").unwrap().clone()).unwrap(); + let response = match block_on(api.get_asm_service_by_name_with_http_info(service_filter)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + fn test_v2_list_csm_threats_agent_rules( world: &mut DatadogWorld, _parameters: &HashMap,