Skip to content

Commit 015cb9e

Browse files
committed
feat: include all scores in PurlStatus
1 parent a93901a commit 015cb9e

File tree

11 files changed

+176
-92
lines changed

11 files changed

+176
-92
lines changed

modules/fundamental/src/purl/model/details/purl.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
Error,
33
advisory::model::AdvisoryHead,
4-
common::{LicenseInfo, LicenseRefMapping, license_filtering},
4+
common::{LicenseInfo, LicenseRefMapping, license_filtering, model::Score},
55
purl::model::{
66
BasePurlHead, PurlHead, VersionedPurlHead, details::version_range::VersionRange,
77
},
@@ -22,7 +22,7 @@ use trustify_common::{
2222
memo::Memo,
2323
purl::Purl,
2424
};
25-
use trustify_cvss::cvss3::{Cvss3Base, score::Score, severity::Severity};
25+
use trustify_cvss::cvss3::{Cvss3Base, score::Score as Cvss3Score, severity::Severity};
2626
use trustify_entity::{
2727
advisory, base_purl, cpe, cvss3, license, organization, product, product_status,
2828
product_version, product_version_range, purl_status, qualified_purl, sbom, sbom_package,
@@ -312,7 +312,11 @@ impl PurlAdvisory {
312312
pub struct PurlStatus {
313313
pub vulnerability: VulnerabilityHead,
314314
pub advisory: AdvisoryHead,
315+
/// All CVSS scores associated with the vulnerability
316+
pub scores: Vec<Score>,
317+
#[deprecated(since = "0.5.0", note = "Please use `scores` instead")]
315318
pub average_severity: Severity,
319+
#[deprecated(since = "0.5.0", note = "Please use `scores` instead")]
316320
pub average_score: f64,
317321
pub status: String,
318322
#[schema(required)]
@@ -336,9 +340,14 @@ impl PurlStatus {
336340
cpe: Option<String>,
337341
tx: &C,
338342
) -> Result<Self, Error> {
339-
let cvss3 = vuln.find_related(cvss3::Entity).all(tx).await?;
340-
let average_score = Score::from_iter(cvss3.iter().map(Cvss3Base::from));
341343
let issuer = Memo::Provided(advisory.find_related(organization::Entity).one(tx).await?);
344+
let cvss3 = vuln.find_related(cvss3::Entity).all(tx).await?;
345+
let average_score = Cvss3Score::from_iter(cvss3.iter().map(Cvss3Base::from));
346+
let all_scores = cvss3
347+
.iter()
348+
.cloned()
349+
.filter_map(|cvss3| Score::try_from(cvss3).ok())
350+
.collect();
342351

343352
Ok(Self {
344353
vulnerability: VulnerabilityHead::from_vulnerability_entity(
@@ -348,8 +357,11 @@ impl PurlStatus {
348357
)
349358
.await?,
350359
advisory: AdvisoryHead::from_advisory(advisory, issuer, tx).await?,
360+
#[allow(deprecated)]
351361
average_severity: average_score.severity(),
362+
#[allow(deprecated)]
352363
average_score: average_score.value(),
364+
scores: all_scores,
353365
status,
354366
context: cpe.map(StatusContext::Cpe),
355367
version_range,
@@ -362,13 +374,23 @@ impl PurlStatus {
362374
status: String,
363375
version_range: Option<VersionRange>,
364376
cpe: Option<String>,
365-
score: Score,
377+
scores: &[cvss3::Model],
366378
) -> Result<Self, Error> {
379+
let average_score = Cvss3Score::from_iter(scores.iter().map(Cvss3Base::from));
380+
let all_scores = scores
381+
.iter()
382+
.cloned()
383+
.filter_map(|cvss3| Score::try_from(cvss3).ok())
384+
.collect();
385+
367386
Ok(Self {
368387
vulnerability: vuln_head,
369388
advisory: advisory_head,
370-
average_severity: score.severity(),
371-
average_score: score.value(),
389+
#[allow(deprecated)]
390+
average_severity: average_score.severity(),
391+
#[allow(deprecated)]
392+
average_score: average_score.value(),
393+
scores: all_scores,
372394
status,
373395
context: cpe.map(StatusContext::Cpe),
374396
version_range,

modules/fundamental/src/vulnerability/endpoints/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
endpoints::Deprecation,
77
vulnerability::{
88
model::{
9-
AnalysisRequest, AnalysisResponse, VulnerabilityDetails, VulnerabilitySummary,
10-
v2::AnalysisResponseV2,
9+
AnalysisRequest, AnalysisResponseV3, VulnerabilityDetails, VulnerabilitySummary,
10+
v2::AnalysisResponse,
1111
},
1212
service::VulnerabilityService,
1313
},
@@ -111,7 +111,7 @@ pub async fn get(
111111
tag = "vulnerability",
112112
request_body = AnalysisRequest,
113113
responses(
114-
(status = 200, description = "Analyze the provided purls to search for known vulnerabilities", body = AnalysisResponseV2),
114+
(status = 200, description = "Analyze the provided purls to search for known vulnerabilities", body = AnalysisResponse),
115115
),
116116
)]
117117
#[post("/v2/vulnerability/analyze")]
@@ -133,7 +133,7 @@ pub async fn analyze(
133133
tag = "vulnerability",
134134
request_body = AnalysisRequest,
135135
responses(
136-
(status = 200, description = "Analyze the provided purls to search for known vulnerabilities", body = AnalysisResponse),
136+
(status = 200, description = "Analyze the provided purls to search for known vulnerabilities", body = AnalysisResponseV3),
137137
),
138138
)]
139139
#[post("/v3/vulnerability/analyze")]
@@ -144,7 +144,7 @@ pub async fn analyze_v3(
144144
_: Require<ReadAdvisory>,
145145
) -> actix_web::Result<impl Responder> {
146146
let tx = db.begin_read().await?;
147-
let details = service.analyze_purls(purls, &tx).await?;
147+
let details = service.analyze_purls_v3(purls, &tx).await?;
148148

149149
Ok(HttpResponse::Ok().json(details))
150150
}

modules/fundamental/src/vulnerability/model/analyze.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{purl::model::details::purl::PurlStatus, vulnerability::model::VulnerabilityHead};
1+
use crate::purl::model::details::purl::PurlStatus;
22
use serde::{Deserialize, Serialize};
33
use std::{collections::BTreeMap, ops::Deref};
44
use utoipa::ToSchema;
@@ -9,25 +9,22 @@ pub struct AnalysisRequest {
99
}
1010

1111
#[derive(Serialize, Deserialize, Debug, ToSchema, Default)]
12-
pub struct AnalysisResult {
13-
pub details: Vec<AnalysisDetails>,
12+
pub struct AnalysisResultV3 {
13+
pub details: Vec<AnalysisDetailsV3>,
1414
pub warnings: Vec<String>,
1515
}
1616

1717
#[derive(Serialize, Deserialize, Debug, ToSchema)]
18-
pub struct AnalysisDetails {
19-
#[serde(flatten)]
20-
pub head: VulnerabilityHead,
21-
18+
pub struct AnalysisDetailsV3 {
2219
/// List of purl statuses
2320
pub purl_statuses: Vec<PurlStatus>,
2421
}
2522

2623
#[derive(Serialize, Deserialize, Debug, ToSchema)]
27-
pub struct AnalysisResponse(pub BTreeMap<String, AnalysisResult>);
24+
pub struct AnalysisResponseV3(pub BTreeMap<String, AnalysisResultV3>);
2825

29-
impl Deref for AnalysisResponse {
30-
type Target = BTreeMap<String, AnalysisResult>;
26+
impl Deref for AnalysisResponseV3 {
27+
type Target = BTreeMap<String, AnalysisResultV3>;
3128

3229
fn deref(&self) -> &Self::Target {
3330
&self.0

modules/fundamental/src/vulnerability/model/v2.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use std::{collections::BTreeMap, ops::Deref};
66
use utoipa::ToSchema;
77

88
#[derive(Serialize, Deserialize, Debug, ToSchema, Default)]
9-
pub struct AnalysisResultV2 {
10-
pub details: Vec<AnalysisDetailsV2>,
9+
pub struct AnalysisResult {
10+
pub details: Vec<AnalysisDetails>,
1111
pub warnings: Vec<String>,
1212
}
1313

1414
#[derive(Serialize, Deserialize, Debug, ToSchema)]
15-
pub struct AnalysisDetailsV2 {
15+
pub struct AnalysisDetails {
1616
#[serde(flatten)]
1717
pub head: VulnerabilityHead,
1818

@@ -30,10 +30,10 @@ pub struct AnalysisAdvisory {
3030
}
3131

3232
#[derive(Serialize, Deserialize, Debug, ToSchema)]
33-
pub struct AnalysisResponseV2(pub BTreeMap<String, AnalysisResultV2>);
33+
pub struct AnalysisResponse(pub BTreeMap<String, AnalysisResult>);
3434

35-
impl Deref for AnalysisResponseV2 {
36-
type Target = BTreeMap<String, AnalysisResultV2>;
35+
impl Deref for AnalysisResponse {
36+
type Target = BTreeMap<String, AnalysisResult>;
3737

3838
fn deref(&self) -> &Self::Target {
3939
&self.0

0 commit comments

Comments
 (0)