datadog_api_client/datadogV2/model/
model_vulnerability_attributes.rs

1// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
2// This product includes software developed at Datadog (https://www.datadoghq.com/).
3// Copyright 2019-Present Datadog, Inc.
4use serde::de::{Error, MapAccess, Visitor};
5use serde::{Deserialize, Deserializer, Serialize};
6use serde_with::skip_serializing_none;
7use std::fmt::{self, Formatter};
8
9/// The JSON:API attributes of the vulnerability.
10#[non_exhaustive]
11#[skip_serializing_none]
12#[derive(Clone, Debug, PartialEq, Serialize)]
13pub struct VulnerabilityAttributes {
14    /// Vulnerability advisory ID.
15    #[serde(rename = "advisory_id")]
16    pub advisory_id: Option<String>,
17    /// Code vulnerability location.
18    #[serde(rename = "code_location")]
19    pub code_location: Option<crate::datadogV2::model::CodeLocation>,
20    /// Vulnerability CVE list.
21    #[serde(rename = "cve_list")]
22    pub cve_list: Vec<String>,
23    /// Vulnerability severities.
24    #[serde(rename = "cvss")]
25    pub cvss: crate::datadogV2::model::VulnerabilityCvss,
26    /// Static library vulnerability location.
27    #[serde(rename = "dependency_locations")]
28    pub dependency_locations: Option<crate::datadogV2::model::VulnerabilityDependencyLocations>,
29    /// Vulnerability description.
30    #[serde(rename = "description")]
31    pub description: String,
32    /// The related vulnerability asset ecosystem.
33    #[serde(rename = "ecosystem")]
34    pub ecosystem: Option<crate::datadogV2::model::VulnerabilityEcosystem>,
35    /// Vulnerability exposure time in seconds.
36    #[serde(rename = "exposure_time")]
37    pub exposure_time: i64,
38    /// First detection of the vulnerability in [RFC 3339](<https://datatracker.ietf.org/doc/html/rfc3339>) format
39    #[serde(rename = "first_detection")]
40    pub first_detection: String,
41    /// Whether the vulnerability has a remediation or not.
42    #[serde(rename = "fix_available")]
43    pub fix_available: bool,
44    /// Vulnerability language.
45    #[serde(rename = "language")]
46    pub language: String,
47    /// Last detection of the vulnerability in [RFC 3339](<https://datatracker.ietf.org/doc/html/rfc3339>) format
48    #[serde(rename = "last_detection")]
49    pub last_detection: String,
50    /// Vulnerability library.
51    #[serde(rename = "library")]
52    pub library: Option<crate::datadogV2::model::Library>,
53    /// Vulnerability origin.
54    #[serde(rename = "origin")]
55    pub origin: Vec<String>,
56    /// List of remediations.
57    #[serde(rename = "remediations")]
58    pub remediations: Vec<crate::datadogV2::model::Remediation>,
59    /// Vulnerability `repo_digest` list (when the vulnerability is related to `Image` asset).
60    #[serde(rename = "repo_digests")]
61    pub repo_digests: Option<Vec<String>>,
62    /// Vulnerability risks.
63    #[serde(rename = "risks")]
64    pub risks: crate::datadogV2::model::VulnerabilityRisks,
65    /// The vulnerability status.
66    #[serde(rename = "status")]
67    pub status: crate::datadogV2::model::VulnerabilityStatus,
68    /// Vulnerability title.
69    #[serde(rename = "title")]
70    pub title: String,
71    /// The vulnerability tool.
72    #[serde(rename = "tool")]
73    pub tool: crate::datadogV2::model::VulnerabilityTool,
74    /// The vulnerability type.
75    #[serde(rename = "type")]
76    pub type_: crate::datadogV2::model::VulnerabilityType,
77    #[serde(flatten)]
78    pub additional_properties: std::collections::BTreeMap<String, serde_json::Value>,
79    #[serde(skip)]
80    #[serde(default)]
81    pub(crate) _unparsed: bool,
82}
83
84impl VulnerabilityAttributes {
85    pub fn new(
86        cve_list: Vec<String>,
87        cvss: crate::datadogV2::model::VulnerabilityCvss,
88        description: String,
89        exposure_time: i64,
90        first_detection: String,
91        fix_available: bool,
92        language: String,
93        last_detection: String,
94        origin: Vec<String>,
95        remediations: Vec<crate::datadogV2::model::Remediation>,
96        risks: crate::datadogV2::model::VulnerabilityRisks,
97        status: crate::datadogV2::model::VulnerabilityStatus,
98        title: String,
99        tool: crate::datadogV2::model::VulnerabilityTool,
100        type_: crate::datadogV2::model::VulnerabilityType,
101    ) -> VulnerabilityAttributes {
102        VulnerabilityAttributes {
103            advisory_id: None,
104            code_location: None,
105            cve_list,
106            cvss,
107            dependency_locations: None,
108            description,
109            ecosystem: None,
110            exposure_time,
111            first_detection,
112            fix_available,
113            language,
114            last_detection,
115            library: None,
116            origin,
117            remediations,
118            repo_digests: None,
119            risks,
120            status,
121            title,
122            tool,
123            type_,
124            additional_properties: std::collections::BTreeMap::new(),
125            _unparsed: false,
126        }
127    }
128
129    pub fn advisory_id(mut self, value: String) -> Self {
130        self.advisory_id = Some(value);
131        self
132    }
133
134    pub fn code_location(mut self, value: crate::datadogV2::model::CodeLocation) -> Self {
135        self.code_location = Some(value);
136        self
137    }
138
139    pub fn dependency_locations(
140        mut self,
141        value: crate::datadogV2::model::VulnerabilityDependencyLocations,
142    ) -> Self {
143        self.dependency_locations = Some(value);
144        self
145    }
146
147    pub fn ecosystem(mut self, value: crate::datadogV2::model::VulnerabilityEcosystem) -> Self {
148        self.ecosystem = Some(value);
149        self
150    }
151
152    pub fn library(mut self, value: crate::datadogV2::model::Library) -> Self {
153        self.library = Some(value);
154        self
155    }
156
157    pub fn repo_digests(mut self, value: Vec<String>) -> Self {
158        self.repo_digests = Some(value);
159        self
160    }
161
162    pub fn additional_properties(
163        mut self,
164        value: std::collections::BTreeMap<String, serde_json::Value>,
165    ) -> Self {
166        self.additional_properties = value;
167        self
168    }
169}
170
171impl<'de> Deserialize<'de> for VulnerabilityAttributes {
172    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173    where
174        D: Deserializer<'de>,
175    {
176        struct VulnerabilityAttributesVisitor;
177        impl<'a> Visitor<'a> for VulnerabilityAttributesVisitor {
178            type Value = VulnerabilityAttributes;
179
180            fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
181                f.write_str("a mapping")
182            }
183
184            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
185            where
186                M: MapAccess<'a>,
187            {
188                let mut advisory_id: Option<String> = None;
189                let mut code_location: Option<crate::datadogV2::model::CodeLocation> = None;
190                let mut cve_list: Option<Vec<String>> = None;
191                let mut cvss: Option<crate::datadogV2::model::VulnerabilityCvss> = None;
192                let mut dependency_locations: Option<
193                    crate::datadogV2::model::VulnerabilityDependencyLocations,
194                > = None;
195                let mut description: Option<String> = None;
196                let mut ecosystem: Option<crate::datadogV2::model::VulnerabilityEcosystem> = None;
197                let mut exposure_time: Option<i64> = None;
198                let mut first_detection: Option<String> = None;
199                let mut fix_available: Option<bool> = None;
200                let mut language: Option<String> = None;
201                let mut last_detection: Option<String> = None;
202                let mut library: Option<crate::datadogV2::model::Library> = None;
203                let mut origin: Option<Vec<String>> = None;
204                let mut remediations: Option<Vec<crate::datadogV2::model::Remediation>> = None;
205                let mut repo_digests: Option<Vec<String>> = None;
206                let mut risks: Option<crate::datadogV2::model::VulnerabilityRisks> = None;
207                let mut status: Option<crate::datadogV2::model::VulnerabilityStatus> = None;
208                let mut title: Option<String> = None;
209                let mut tool: Option<crate::datadogV2::model::VulnerabilityTool> = None;
210                let mut type_: Option<crate::datadogV2::model::VulnerabilityType> = None;
211                let mut additional_properties: std::collections::BTreeMap<
212                    String,
213                    serde_json::Value,
214                > = std::collections::BTreeMap::new();
215                let mut _unparsed = false;
216
217                while let Some((k, v)) = map.next_entry::<String, serde_json::Value>()? {
218                    match k.as_str() {
219                        "advisory_id" => {
220                            if v.is_null() {
221                                continue;
222                            }
223                            advisory_id =
224                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
225                        }
226                        "code_location" => {
227                            if v.is_null() {
228                                continue;
229                            }
230                            code_location =
231                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
232                        }
233                        "cve_list" => {
234                            cve_list = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
235                        }
236                        "cvss" => {
237                            cvss = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
238                        }
239                        "dependency_locations" => {
240                            if v.is_null() {
241                                continue;
242                            }
243                            dependency_locations =
244                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
245                        }
246                        "description" => {
247                            description =
248                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
249                        }
250                        "ecosystem" => {
251                            if v.is_null() {
252                                continue;
253                            }
254                            ecosystem = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
255                            if let Some(ref _ecosystem) = ecosystem {
256                                match _ecosystem {
257                                    crate::datadogV2::model::VulnerabilityEcosystem::UnparsedObject(_ecosystem) => {
258                                        _unparsed = true;
259                                    },
260                                    _ => {}
261                                }
262                            }
263                        }
264                        "exposure_time" => {
265                            exposure_time =
266                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
267                        }
268                        "first_detection" => {
269                            first_detection =
270                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
271                        }
272                        "fix_available" => {
273                            fix_available =
274                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
275                        }
276                        "language" => {
277                            language = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
278                        }
279                        "last_detection" => {
280                            last_detection =
281                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
282                        }
283                        "library" => {
284                            if v.is_null() {
285                                continue;
286                            }
287                            library = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
288                        }
289                        "origin" => {
290                            origin = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
291                        }
292                        "remediations" => {
293                            remediations =
294                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
295                        }
296                        "repo_digests" => {
297                            if v.is_null() {
298                                continue;
299                            }
300                            repo_digests =
301                                Some(serde_json::from_value(v).map_err(M::Error::custom)?);
302                        }
303                        "risks" => {
304                            risks = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
305                        }
306                        "status" => {
307                            status = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
308                            if let Some(ref _status) = status {
309                                match _status {
310                                    crate::datadogV2::model::VulnerabilityStatus::UnparsedObject(_status) => {
311                                        _unparsed = true;
312                                    },
313                                    _ => {}
314                                }
315                            }
316                        }
317                        "title" => {
318                            title = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
319                        }
320                        "tool" => {
321                            tool = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
322                            if let Some(ref _tool) = tool {
323                                match _tool {
324                                    crate::datadogV2::model::VulnerabilityTool::UnparsedObject(
325                                        _tool,
326                                    ) => {
327                                        _unparsed = true;
328                                    }
329                                    _ => {}
330                                }
331                            }
332                        }
333                        "type" => {
334                            type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
335                            if let Some(ref _type_) = type_ {
336                                match _type_ {
337                                    crate::datadogV2::model::VulnerabilityType::UnparsedObject(
338                                        _type_,
339                                    ) => {
340                                        _unparsed = true;
341                                    }
342                                    _ => {}
343                                }
344                            }
345                        }
346                        &_ => {
347                            if let Ok(value) = serde_json::from_value(v.clone()) {
348                                additional_properties.insert(k, value);
349                            }
350                        }
351                    }
352                }
353                let cve_list = cve_list.ok_or_else(|| M::Error::missing_field("cve_list"))?;
354                let cvss = cvss.ok_or_else(|| M::Error::missing_field("cvss"))?;
355                let description =
356                    description.ok_or_else(|| M::Error::missing_field("description"))?;
357                let exposure_time =
358                    exposure_time.ok_or_else(|| M::Error::missing_field("exposure_time"))?;
359                let first_detection =
360                    first_detection.ok_or_else(|| M::Error::missing_field("first_detection"))?;
361                let fix_available =
362                    fix_available.ok_or_else(|| M::Error::missing_field("fix_available"))?;
363                let language = language.ok_or_else(|| M::Error::missing_field("language"))?;
364                let last_detection =
365                    last_detection.ok_or_else(|| M::Error::missing_field("last_detection"))?;
366                let origin = origin.ok_or_else(|| M::Error::missing_field("origin"))?;
367                let remediations =
368                    remediations.ok_or_else(|| M::Error::missing_field("remediations"))?;
369                let risks = risks.ok_or_else(|| M::Error::missing_field("risks"))?;
370                let status = status.ok_or_else(|| M::Error::missing_field("status"))?;
371                let title = title.ok_or_else(|| M::Error::missing_field("title"))?;
372                let tool = tool.ok_or_else(|| M::Error::missing_field("tool"))?;
373                let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?;
374
375                let content = VulnerabilityAttributes {
376                    advisory_id,
377                    code_location,
378                    cve_list,
379                    cvss,
380                    dependency_locations,
381                    description,
382                    ecosystem,
383                    exposure_time,
384                    first_detection,
385                    fix_available,
386                    language,
387                    last_detection,
388                    library,
389                    origin,
390                    remediations,
391                    repo_digests,
392                    risks,
393                    status,
394                    title,
395                    tool,
396                    type_,
397                    additional_properties,
398                    _unparsed,
399                };
400
401                Ok(content)
402            }
403        }
404
405        deserializer.deserialize_any(VulnerabilityAttributesVisitor)
406    }
407}