Skip to content

Commit

Permalink
feat: find purls for affected packages
Browse files Browse the repository at this point in the history
  • Loading branch information
dejanb committed Nov 25, 2024
1 parent 7d6b71e commit 3c7b66e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions modules/fundamental/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ trustify-auth = { workspace = true }
trustify-common = { workspace = true }
trustify-cvss = { workspace = true }
trustify-entity = { workspace = true }
trustify-module-analysis = { workspace = true }
trustify-module-ingestor = { workspace = true }
trustify-module-storage = { workspace = true }

Expand Down
40 changes: 32 additions & 8 deletions modules/fundamental/src/sbom/model/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use trustify_common::{
cpe::CpeCompare,
db::{
multi_model::{FromQueryResultMultiModel, SelectIntoMultiModel},
query::Query,
ConnectionOrTransaction, VersionMatches,
},
memo::Memo,
Expand All @@ -45,7 +46,7 @@ impl SbomDetails {
/// turn an (sbom, sbom_node) row into an [`SbomDetails`], if possible
pub async fn from_entity(
(sbom, node): (sbom::Model, Option<sbom_node::Model>),
service: &SbomService,
sbom_service: &SbomService,
tx: &ConnectionOrTransaction<'_>,
) -> Result<Option<SbomDetails>, Error> {
let relevant_advisory_info = sbom
Expand Down Expand Up @@ -116,15 +117,16 @@ impl SbomDetails {
.all(tx)
.await?;

let summary = SbomSummary::from_entity((sbom, node), service, tx).await?;
let summary = SbomSummary::from_entity((sbom, node), sbom_service, tx).await?;

Ok(match summary {
Some(summary) => Some(SbomDetails {
summary: summary.clone(),
advisories: SbomAdvisory::from_models(
&summary.clone().described_by,
summary.clone(),
&relevant_advisory_info,
&product_advisory_statuses,
sbom_service,
tx,
)
.await?,
Expand All @@ -143,11 +145,13 @@ pub struct SbomAdvisory {

impl SbomAdvisory {
pub async fn from_models(
described_by: &[SbomPackage],
summary: SbomSummary,
statuses: &[QueryCatcher],
product_statuses: &[ProductStatusCatcher],
sbom_service: &SbomService,
tx: &ConnectionOrTransaction<'_>,
) -> Result<Vec<Self>, Error> {
let described_by = summary.described_by;
let mut advisories = HashMap::new();

let sbom_cpes = described_by
Expand Down Expand Up @@ -255,11 +259,31 @@ impl SbomAdvisory {

let mut packages = vec![];
if let Some(package) = &product.product_status.package {
let package = SbomPackage {
name: package.to_string(),
..Default::default()
// We need to enable search on namespace/name pattern as well
// Also, from the brief look at it, the search is case sensitive
// which doesn't cover all use cases
let parts = package.split('/').collect::<Vec<_>>();
let name = if parts.len() == 1 { parts[0] } else { parts[1] };

let query = Query {
q: format!("name={}", name),
sort: Default::default(),
};
packages.push(package);

let mut sbom_packages = sbom_service
.fetch_sbom_packages(summary.head.id, query, Default::default(), ())
.await?;
if !sbom_packages.items.is_empty() {
packages.append(&mut sbom_packages.items);
} else {
// We couldn't find full package by name
// So let's return at least basic info
let package = SbomPackage {
name: package.to_string(),
..Default::default()
};
packages.push(package);
}
}

let status = SbomStatus::new(
Expand Down
7 changes: 7 additions & 0 deletions modules/fundamental/src/vulnerability/service/test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::str::FromStr;

use crate::purl::model::details::purl::StatusContext;
use crate::purl::service::PurlService;
use crate::sbom::service::SbomService;
Expand Down Expand Up @@ -238,6 +240,11 @@ async fn product_statuses(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
assert_eq!(quarkus_adv.status, "fixed");
assert_eq!(quarkus_adv.vulnerability.identifier, "CVE-2023-0044");

let quarkus_adv = &quarkus_sbom.advisories[0].status[2];
assert_eq!(quarkus_adv.packages.len(), 1);
assert_eq!(quarkus_adv.packages[0].purl.len(), 1);
assert_eq!(quarkus_adv.packages[0].purl[0].head.purl, Purl::from_str("pkg:maven/io.quarkus/[email protected]?repository_url=https://maven.repository.redhat.com/ga/&type=jar").unwrap());

let vuln = vuln_service
.fetch_vulnerability("CVE-2023-0044", Default::default(), Transactional::None)
.await?;
Expand Down

0 comments on commit 3c7b66e

Please sign in to comment.