stix_rs/sdos/
vulnerability.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::common::{CommonProperties, StixObject};
5use crate::sdos::BuilderError;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub struct Vulnerability {
11 #[serde(flatten)]
12 pub common: CommonProperties,
13 pub name: String,
14 pub description: Option<String>,
15}
16
17impl Vulnerability {
18 pub fn builder() -> VulnerabilityBuilder {
19 VulnerabilityBuilder::default()
20 }
21}
22
23#[derive(Debug, Default)]
24pub struct VulnerabilityBuilder {
25 name: Option<String>,
26 description: Option<String>,
27 created_by_ref: Option<String>,
28}
29
30impl VulnerabilityBuilder {
31 pub fn name(mut self, name: impl Into<String>) -> Self {
32 self.name = Some(name.into());
33 self
34 }
35
36 pub fn description(mut self, d: impl Into<String>) -> Self {
37 self.description = Some(d.into());
38 self
39 }
40
41 pub fn created_by_ref(mut self, r: impl Into<String>) -> Self {
42 self.created_by_ref = Some(r.into());
43 self
44 }
45
46 pub fn build(self) -> Result<Vulnerability, BuilderError> {
47 let name = self.name.ok_or(BuilderError::MissingField("name"))?;
48 let common = CommonProperties::new("vulnerability", self.created_by_ref);
49 Ok(Vulnerability {
50 common,
51 name,
52 description: self.description,
53 })
54 }
55}
56
57impl StixObject for Vulnerability {
58 fn id(&self) -> &str {
59 &self.common.id
60 }
61
62 fn type_(&self) -> &str {
63 &self.common.r#type
64 }
65
66 fn created(&self) -> DateTime<Utc> {
67 self.common.created
68 }
69}
70
71impl From<Vulnerability> for crate::StixObjectEnum {
72 fn from(v: Vulnerability) -> Self {
73 crate::StixObjectEnum::Vulnerability(v)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn vulnerability_builder() {
83 let vuln = Vulnerability::builder()
84 .name("CVE-2024-1234")
85 .description("Remote code execution vulnerability")
86 .build()
87 .unwrap();
88
89 assert_eq!(vuln.name, "CVE-2024-1234");
90 assert_eq!(vuln.common.r#type, "vulnerability");
91 }
92
93 #[test]
94 fn vulnerability_serialize() {
95 let vuln = Vulnerability::builder()
96 .name("CVE-2024-5678")
97 .build()
98 .unwrap();
99
100 let json = serde_json::to_string(&vuln).unwrap();
101 assert!(json.contains("\"type\":\"vulnerability\""));
102 assert!(json.contains("\"name\":\"CVE-2024-5678\""));
103 }
104}