diff --git a/Cargo.lock b/Cargo.lock index 620832f92..adb3af49c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8509,6 +8509,7 @@ dependencies = [ "trustify-common", "trustify-cvss", "trustify-entity", + "trustify-module-analysis", "trustify-module-ingestor", "trustify-module-storage", "trustify-test-context", diff --git a/modules/fundamental/Cargo.toml b/modules/fundamental/Cargo.toml index b5a7deb73..ba42588a4 100644 --- a/modules/fundamental/Cargo.toml +++ b/modules/fundamental/Cargo.toml @@ -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 } diff --git a/modules/fundamental/src/sbom/model/details.rs b/modules/fundamental/src/sbom/model/details.rs index 909fb701c..fe9d76cde 100644 --- a/modules/fundamental/src/sbom/model/details.rs +++ b/modules/fundamental/src/sbom/model/details.rs @@ -21,6 +21,7 @@ use trustify_common::{ cpe::CpeCompare, db::{ multi_model::{FromQueryResultMultiModel, SelectIntoMultiModel}, + query::Query, ConnectionOrTransaction, VersionMatches, }, memo::Memo, @@ -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), - service: &SbomService, + sbom_service: &SbomService, tx: &ConnectionOrTransaction<'_>, ) -> Result, Error> { let relevant_advisory_info = sbom @@ -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?, @@ -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, Error> { + let described_by = summary.described_by; let mut advisories = HashMap::new(); let sbom_cpes = described_by @@ -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::>(); + 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( diff --git a/modules/fundamental/src/vulnerability/service/test.rs b/modules/fundamental/src/vulnerability/service/test.rs index 90f35eeb3..1b25c3198 100644 --- a/modules/fundamental/src/vulnerability/service/test.rs +++ b/modules/fundamental/src/vulnerability/service/test.rs @@ -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; @@ -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/quarkus-vertx-http@2.13.8.Final-redhat-00004?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?;