Skip to content

Commit 29affcc

Browse files
committed
feat(domain): use semver for package and vulnerability versions
1 parent 679a7bb commit 29affcc

File tree

5 files changed

+38
-27
lines changed

5 files changed

+38
-27
lines changed

src/domain/scanresult/package.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::domain::scanresult::layer::Layer;
33
use crate::domain::scanresult::package_type::PackageType;
44
use crate::domain::scanresult::vulnerability::Vulnerability;
55
use crate::domain::scanresult::weak_hash::WeakHash;
6+
use semver::Version;
67
use std::collections::HashSet;
78
use std::fmt::Debug;
89
use std::hash::{Hash, Hasher};
@@ -11,7 +12,7 @@ use std::sync::{Arc, RwLock};
1112
pub struct Package {
1213
package_type: PackageType,
1314
name: String,
14-
version: String,
15+
version: Version,
1516
path: String,
1617
found_in_layer: Arc<Layer>,
1718
vulnerabilities: RwLock<HashSet<WeakHash<Vulnerability>>>,
@@ -34,7 +35,7 @@ impl Package {
3435
pub(in crate::domain::scanresult) fn new(
3536
package_type: PackageType,
3637
name: String,
37-
version: String,
38+
version: Version,
3839
path: String,
3940
found_in_layer: Arc<Layer>,
4041
) -> Self {
@@ -57,7 +58,7 @@ impl Package {
5758
&self.name
5859
}
5960

60-
pub fn version(&self) -> &str {
61+
pub fn version(&self) -> &Version {
6162
&self.version
6263
}
6364

src/domain/scanresult/scan_result.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::domain::scanresult::severity::Severity;
1414
use crate::domain::scanresult::vulnerability::Vulnerability;
1515
use chrono::{DateTime, NaiveDate, Utc};
1616
use itertools::Itertools;
17+
use semver::Version;
1718
use std::collections::HashMap;
1819
use std::sync::Arc;
1920

@@ -109,14 +110,14 @@ impl ScanResult {
109110
&mut self,
110111
package_type: PackageType,
111112
name: String,
112-
version: String,
113+
version: Version,
113114
path: String,
114115
found_in_layer: Arc<Layer>,
115116
) -> Arc<Package> {
116117
let a_package = Arc::new(Package::new(
117118
package_type,
118119
name.clone(),
119-
version.clone(),
120+
version,
120121
path.clone(),
121122
found_in_layer.clone(),
122123
));
@@ -140,7 +141,7 @@ impl ScanResult {
140141
disclosure_date: NaiveDate,
141142
solution_date: Option<NaiveDate>,
142143
exploitable: bool,
143-
fix_version: Option<String>,
144+
fix_version: Option<Version>,
144145
) -> Arc<Vulnerability> {
145146
self.vulnerabilities
146147
.entry(cve.clone())
@@ -313,7 +314,7 @@ mod tests {
313314
let package = scan_result.add_package(
314315
PackageType::Os,
315316
"musl".to_string(),
316-
"1.2.3".to_string(),
317+
Version::parse("1.2.3").unwrap(),
317318
"/lib/ld-musl-x86_64.so.1".to_string(),
318319
layer.clone(),
319320
);
@@ -336,7 +337,7 @@ mod tests {
336337
Utc::now().naive_utc().date(),
337338
None,
338339
false,
339-
Some("1.2.4".to_string()),
340+
Some(Version::parse("1.2.4").unwrap()),
340341
);
341342

342343
assert_eq!(scan_result.vulnerabilities().len(), 1);
@@ -357,7 +358,7 @@ mod tests {
357358
let package = scan_result.add_package(
358359
PackageType::Os,
359360
"musl".to_string(),
360-
"1.2.3".to_string(),
361+
Version::parse("1.2.3").unwrap(),
361362
"/lib/ld-musl-x86_64.so.1".to_string(),
362363
layer.clone(),
363364
);
@@ -367,7 +368,7 @@ mod tests {
367368
Utc::now().naive_utc().date(),
368369
None,
369370
false,
370-
Some("1.2.4".to_string()),
371+
Some(Version::parse("1.2.4").unwrap()),
371372
);
372373

373374
package.add_vulnerability_found(vuln.clone());
@@ -462,7 +463,7 @@ mod tests {
462463
Utc::now().naive_utc().date(),
463464
None,
464465
false,
465-
Some("1.2.4".to_string()),
466+
Some(Version::parse("1.2.4").unwrap()),
466467
);
467468

468469
vuln.add_accepted_risk(risk.clone());
@@ -488,7 +489,7 @@ mod tests {
488489
let package = scan_result.add_package(
489490
PackageType::Os,
490491
"musl".to_string(),
491-
"1.2.3".to_string(),
492+
Version::parse("1.2.3").unwrap(),
492493
"/lib/ld-musl-x86_64.so.1".to_string(),
493494
layer.clone(),
494495
);
@@ -571,13 +572,13 @@ mod tests {
571572
let package = scan_result.add_package(
572573
PackageType::Os,
573574
"musl".to_string(),
574-
"1.2.3".to_string(),
575+
Version::parse("1.2.3").unwrap(),
575576
"/path".to_string(),
576577
layer.clone(),
577578
);
578579
assert_eq!(package.package_type(), &PackageType::Os);
579580
assert_eq!(package.name(), "musl");
580-
assert_eq!(package.version(), "1.2.3");
581+
assert_eq!(package.version(), &Version::parse("1.2.3").unwrap());
581582
assert_eq!(package.path(), "/path");
582583
assert!(format!("{:?}", package).contains("musl"));
583584
assert_eq!(package.clone(), package);
@@ -589,15 +590,15 @@ mod tests {
589590
now.naive_utc().date(),
590591
Some(now.naive_utc().date()),
591592
true,
592-
Some("1.2.4".to_string()),
593+
Some(Version::parse("1.2.4").unwrap()),
593594
);
594595
assert_eq!(vuln.cve(), "CVE-1");
595596
assert_eq!(vuln.severity(), Severity::High);
596597
assert_eq!(vuln.disclosure_date(), now.naive_utc().date());
597598
assert_eq!(vuln.solution_date(), Some(now.naive_utc().date()));
598599
assert!(vuln.exploitable());
599600
assert!(vuln.fixable());
600-
assert_eq!(vuln.fix_version(), Some("1.2.4"));
601+
assert_eq!(vuln.fix_version(), Some(&Version::parse("1.2.4").unwrap()));
601602
assert!(format!("{:?}", vuln).contains("CVE-1"));
602603

603604
// AcceptedRisk
@@ -672,14 +673,14 @@ mod tests {
672673
let pkg = scan_result.add_package(
673674
PackageType::Os,
674675
"pkg".to_string(),
675-
"1.0".to_string(),
676+
Version::parse("1.0.0").unwrap(),
676677
"/path".to_string(),
677678
layer.clone(),
678679
);
679680
let pkg2 = scan_result.add_package(
680681
PackageType::Os,
681682
"pkg".to_string(),
682-
"1.0".to_string(),
683+
Version::parse("1.0.0").unwrap(),
683684
"/path".to_string(),
684685
layer.clone(),
685686
);

src/domain/scanresult/vulnerability.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::domain::scanresult::package::Package;
44
use crate::domain::scanresult::severity::Severity;
55
use crate::domain::scanresult::weak_hash::WeakHash;
66
use chrono::NaiveDate;
7+
use semver::Version;
78
use std::collections::HashSet;
89
use std::fmt::Debug;
910
use std::hash::{Hash, Hasher};
@@ -15,7 +16,7 @@ pub struct Vulnerability {
1516
disclosure_date: NaiveDate,
1617
solution_date: Option<NaiveDate>,
1718
exploitable: bool,
18-
fix_version: Option<String>,
19+
fix_version: Option<Version>,
1920
found_in_packages: RwLock<HashSet<WeakHash<Package>>>,
2021
accepted_risks: RwLock<HashSet<WeakHash<AcceptedRisk>>>,
2122
}
@@ -40,7 +41,7 @@ impl Vulnerability {
4041
disclosure_date: NaiveDate,
4142
solution_date: Option<NaiveDate>,
4243
exploitable: bool,
43-
fix_version: Option<String>,
44+
fix_version: Option<Version>,
4445
) -> Self {
4546
Self {
4647
cve,
@@ -78,8 +79,8 @@ impl Vulnerability {
7879
self.fix_version.is_some()
7980
}
8081

81-
pub fn fix_version(&self) -> Option<&str> {
82-
self.fix_version.as_deref()
82+
pub fn fix_version(&self) -> Option<&Version> {
83+
self.fix_version.as_ref()
8384
}
8485

8586
pub(in crate::domain::scanresult) fn add_found_in_package(

src/infra/sysdig_image_scanner_json_scan_result_v1.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::domain::scanresult::{
1313
scan_type::ScanType,
1414
severity::Severity,
1515
};
16+
use semver::Version;
1617

1718
impl From<JsonScanResultV1> for ScanResult {
1819
fn from(report: JsonScanResultV1) -> Self {
@@ -55,13 +56,15 @@ fn add_risk_accepts(result: &JsonResult, scan_result: &mut ScanResult) {
5556

5657
fn add_vulnerabilities(result: &JsonResult, scan_result: &mut ScanResult) {
5758
for v in result.vulnerabilities.values() {
59+
let fix_version = v.fix_version.as_ref().and_then(|s| Version::parse(s).ok());
60+
5861
let vuln = scan_result.add_vulnerability(
5962
v.name.clone(),
6063
v.severity.clone().into(),
6164
v.disclosure_date,
6265
v.solution_date,
6366
v.exploitable,
64-
v.fix_version.clone(),
67+
fix_version,
6568
);
6669

6770
v.risk_accept_refs
@@ -86,10 +89,14 @@ fn add_packages(result: &JsonResult, scan_result: &mut ScanResult) {
8689
continue;
8790
};
8891

92+
let Ok(version) = Version::parse(&json_pkg.version) else {
93+
continue;
94+
};
95+
8996
let pkg = scan_result.add_package(
9097
json_pkg.package_type.clone().into(),
9198
json_pkg.name.clone(),
92-
json_pkg.version.clone(),
99+
version,
93100
json_pkg.path.clone(),
94101
layer_where_this_package_is_found,
95102
);

tests/general.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod common;
22

33
use common::TestSetup;
44
use rstest::{fixture, rstest};
5+
use semver::Version;
56
use serde_json::json;
67
use std::collections::HashMap;
78
use sysdig_lsp::domain::scanresult::architecture::Architecture;
@@ -134,15 +135,15 @@ fn scan_result() -> ScanResult {
134135
let package1 = result.add_package(
135136
PackageType::Os,
136137
"package1".to_string(),
137-
"1.0.0".to_string(),
138+
Version::parse("1.0.0").unwrap(),
138139
"/usr/lib/package1".to_string(),
139140
layer.clone(),
140141
);
141142

142143
result.add_package(
143144
PackageType::Os,
144145
"package2".to_string(),
145-
"2.0.0".to_string(),
146+
Version::parse("2.0.0").unwrap(),
146147
"/usr/lib/package2".to_string(),
147148
layer,
148149
);
@@ -153,7 +154,7 @@ fn scan_result() -> ScanResult {
153154
chrono::NaiveDate::from_ymd_opt(2021, 1, 1).unwrap(),
154155
None,
155156
false,
156-
Some("1.0.1".to_string()),
157+
Some(Version::parse("1.0.1").unwrap()),
157158
);
158159

159160
package1.add_vulnerability_found(vulnerability);

0 commit comments

Comments
 (0)