1pub use cyclonedx_bom as model;
24
25pub mod pdf {
26 pub mod generator;
27}
28
29#[cfg(test)]
30mod tests {
31 use cyclonedx_bom::models::bom::Bom;
32 use cyclonedx_bom::models::metadata::Metadata;
33 use cyclonedx_bom::models::tool::{Tool, Tools};
34 use cyclonedx_bom::models::vulnerability::{Vulnerabilities, Vulnerability};
35
36 use cyclonedx_bom::models::vulnerability_rating::{
37 Score, ScoreMethod, Severity, VulnerabilityRating, VulnerabilityRatings,
38 };
39 use cyclonedx_bom::prelude::{DateTime, NormalizedString, SpecVersion, UrnUuid};
40 use std::fs;
41 use std::io::BufReader;
42
43 fn create_sample_vex() -> Bom {
44 Bom {
47 spec_version: SpecVersion::V1_5,
48 version: 1,
49 serial_number: Some(
50 UrnUuid::new("urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79".to_string())
51 .expect("Unable to create urn:uuid"),
52 ),
53 metadata: Some(Metadata {
54 timestamp: Some(DateTime::now().expect("failed to convert date")),
55 tools: Some(Tools::List(vec![Tool {
56 name: Some(NormalizedString::new("my_tool")),
57 ..Tool::default()
58 }])),
59 ..Metadata::default()
60 }),
61 vulnerabilities: Some(Vulnerabilities(vec![
62 Vulnerability {
63 bom_ref: None,
64 id: None,
65 vulnerability_source: None,
66 description: Some(
67 "Known vulnerability in library that allows unauthorized access"
68 .to_string(),
69 ),
70 detail: Some(
71 "Detailed explanation of the vulnerability and its potential impact."
72 .to_string(),
73 ),
74 recommendation: Some("Upgrade to version 1.2.4 or later".to_string()),
75 workaround: None,
76 proof_of_concept: None,
77 advisories: None,
78 created: None,
79 published: None,
80 updated: None,
81 rejected: None,
82 vulnerability_credits: None,
83 tools: None,
84 vulnerability_analysis: None,
85 vulnerability_targets: None,
86 vulnerability_ratings: Some(VulnerabilityRatings(vec![VulnerabilityRating {
87 score: Some(Score::from(8.1)),
88 severity: Some(Severity::High),
89 score_method: Some(ScoreMethod::CVSSv31),
90 vector: Some(NormalizedString::new(
91 "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
92 )),
93 vulnerability_source: None,
94 justification: None,
95 }])),
96
97 vulnerability_references: None,
98 cwes: None,
99 properties: None,
100 },
101 Vulnerability {
102 bom_ref: None,
103 id: None,
104 vulnerability_source: None,
105 description: Some("Component does not use the affected library".to_string()),
106 detail: Some(
107 "Detailed explanation of the vulnerability and its potential impact."
108 .to_string(),
109 ),
110 recommendation: Some("Upgrade to version 1.2.3 or later".to_string()),
111 workaround: None,
112 proof_of_concept: None,
113 advisories: None,
114 created: None,
115 published: None,
116 updated: None,
117 rejected: None,
118 vulnerability_credits: None,
119 tools: None,
120 vulnerability_analysis: None,
121 vulnerability_targets: None,
122 vulnerability_ratings: Some(VulnerabilityRatings(vec![VulnerabilityRating {
123 score: Some(Score::from(6.5)),
124 severity: Some(Severity::High),
125 score_method: Some(ScoreMethod::CVSSv31),
126 vector: Some(NormalizedString::new(
127 "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L",
128 )),
129 vulnerability_source: None,
130 justification: None,
131 }])),
132
133 vulnerability_references: None,
134 cwes: None,
135 properties: None,
136 },
137 ])),
138 ..Bom::default()
139 }
140 }
141
142 #[test]
143 fn test_vex_serialization() {
144 let vex = create_sample_vex();
145
146 let mut output = Vec::<u8>::new();
148 vex.clone()
149 .output_as_json_v1_5(&mut output)
150 .expect("failed to read vex object");
151
152 let json_str = String::from_utf8(output).expect("failed to serialize json object");
153
154 println!("Serialized VEX: {}", json_str);
155
156 let parsed_json =
157 serde_json::from_str(&json_str).expect("serde failed to read json from string object");
158 let deserialization_result = Bom::parse_json_value(parsed_json);
159
160 match deserialization_result {
162 Ok(deserialized) => {
163 println!("Deserialized CycloneDX: {:?}", deserialized);
164 assert_eq!(vex.serial_number, deserialized.serial_number);
166 assert_eq!(vex.spec_version, deserialized.spec_version);
167 }
168 Err(err) => {
169 panic!("Deserialization failed: {:?}", err);
170 }
171 }
172 }
173
174 #[test]
175 fn test_vex_file_io() {
176 use std::io::Write;
177
178 let vex = create_sample_vex();
179 let mut output = Vec::<u8>::new();
180 vex.clone()
181 .output_as_json_v1_5(&mut output)
182 .expect("failed to read vex object");
183 let json_str = String::from_utf8(output).expect("failed to serialize json object");
184
185 let mut temp_file = std::env::temp_dir();
187 temp_file.push("test_vex.json");
188
189 let mut file = fs::File::create(&temp_file).expect("Failed to create temp file");
191 file.write_all(json_str.as_bytes())
192 .expect("Failed to write to temp file");
193
194 let content_reader =
196 BufReader::new(fs::File::open(&temp_file).expect("failed to open file"));
197 let loaded_vex: Bom = Bom::parse_from_json(content_reader).expect("Failed to parse JSON");
198
199 fs::remove_file(&temp_file).expect("Failed to remove temp file");
201
202 assert_eq!(vex.serial_number, loaded_vex.serial_number);
204 }
205
206 #[test]
207 fn test_generate_sample_file() {
208 let vex = create_sample_vex();
209 let mut output = Vec::<u8>::new();
210 vex.clone()
211 .output_as_json_v1_5(&mut output)
212 .expect("failed to read vex object");
213 let json_str = String::from_utf8(output).expect("failed to serialize json object");
214
215 fs::write("sample_vex.json", json_str).expect("Failed to write sample file");
217
218 println!("Sample VEX file created at sample_vex.json");
219 }
220}