Skip to content

Commit

Permalink
feat: add RH processing for SPDX as well
Browse files Browse the repository at this point in the history
  • Loading branch information
ctron committed Feb 19, 2025
1 parent 82c8013 commit 2b09639
Show file tree
Hide file tree
Showing 10 changed files with 2,053 additions and 47 deletions.
1,749 changes: 1,749 additions & 0 deletions etc/test-data/spdx/rh/product_component/openssl-3.0.7-18.el9_2.spdx.json

Large diffs are not rendered by default.

141 changes: 141 additions & 0 deletions etc/test-data/spdx/rh/product_component/rhel-9.2-eus.spdx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"creationInfo": {
"created": "2006-08-14T02:34:56Z",
"creators": [
"Tool: example SPDX document only",
"Organization: Red Hat"
]
},
"name": "Red Hat Enterprise Linux 9.2 EUS",
"documentNamespace": "https://www.redhat.com/rhel-9.2-eus.spdx.json",
"packages": [
{
"SPDXID": "SPDXRef-RHEL-9.2-EUS",
"name": "Red Hat Enterprise Linux",
"versionInfo": "9.2 EUS",
"supplier": "Organization: Red Hat",
"downloadLocation": "NOASSERTION",
"licenseConcluded": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceLocator": "cpe:/a:redhat:rhel_eus:9.2::appstream",
"referenceType": "cpe22Type"
},
{
"referenceCategory": "SECURITY",
"referenceLocator": "cpe:/a:redhat:rhel_eus:9.2::baseos",
"referenceType": "cpe22Type"
}
]
},
{
"SPDXID": "SPDXRef-openssl-3.0.7-18.el9-2",
"name": "openssl",
"versionInfo": "3.0.7-18.el9_2",
"supplier": "Organization: Red Hat",
"downloadLocation": "NOASSERTION",
"packageFileName": "openssl-3.0.7-18.el9_2.src.rpm",
"licenseConcluded": "Apache-2.0",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-aarch64-baseos-eus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-s390x-baseos-eus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-ppc64le-baseos-eus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-i686-baseos-eus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-x86_64-baseos-eus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-aarch64-baseos-aus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-s390x-baseos-aus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-ppc64le-baseos-aus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-i686-baseos-aus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-x86_64-baseos-aus-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-aarch64-baseos-e4s-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-s390x-baseos-e4s-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-ppc64le-baseos-e4s-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-i686-baseos-e4s-source-rpms"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/redhat/[email protected]_2?arch=src&repository_id=rhel-9-for-x86_64-baseos-e4s-source-rpms"
}
],
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "31b5079268339cff7ba65a0aee77930560c5adef4b1b3f8f5927a43ee468dag0"
}
]
}
],
"files": [],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": "SPDXRef-RHEL-9.2-EUS"
},
{
"spdxElementId": "SPDXRef-openssl-3.0.7-18.el9-2",
"relationshipType": "PACKAGE_OF",
"relatedSpdxElement": "SPDXRef-RHEL-9.2-EUS"
}
]
}
2 changes: 2 additions & 0 deletions modules/fundamental/tests/sbom/cyclonedx/external/rh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ async fn prod_comp(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {

let _service = SbomService::new(ctx.db.clone());

// TODO: implement when we have the tools

Ok(())
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![allow(clippy::expect_used)]

mod rh;

use test_context::test_context;
use test_log::test;
use trustify_test_context::TrustifyContext;
Expand Down
37 changes: 37 additions & 0 deletions modules/fundamental/tests/sbom/spdx/external/rh.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#![allow(clippy::expect_used)]
#![allow(clippy::unwrap_used)]

use test_context::test_context;
use test_log::test;
use trustify_module_fundamental::sbom::service::SbomService;
use trustify_test_context::TrustifyContext;

#[test_context(TrustifyContext)]
#[test(tokio::test)]
async fn prod_comp(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
let mut result = ctx
.ingest_documents([
"spdx/rh/product_component/rhel-9.2-eus.spdx.json",
"spdx/rh/product_component/openssl-3.0.7-18.el9_2.spdx.json",
])
.await?;

let _prod = result
.pop()
.unwrap()
.id
.try_as_uid()
.expect("must have a uid");
let _comp = result
.pop()
.unwrap()
.id
.try_as_uid()
.expect("must have a uid");

let _service = SbomService::new(ctx.db.clone());

// TODO: implement when we have the tools

Ok(())
}
2 changes: 1 addition & 1 deletion modules/ingestor/src/graph/sbom/common/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl FileCreator {
});
}

#[instrument(skip_all, fields(num=self.nodes.len()), ret)]
#[instrument(skip_all, fields(num=self.nodes.len()), err(level=tracing::Level::INFO))]
pub async fn create(self, db: &impl ConnectionTrait) -> Result<(), DbErr> {
for batch in &self.nodes.into_iter().chunked() {
sbom_node::Entity::insert_many(batch)
Expand Down
47 changes: 21 additions & 26 deletions modules/ingestor/src/graph/sbom/cyclonedx.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::graph::sbom::processor::InitContext;
use crate::graph::{
cpe::CpeCreator,
product::ProductInformation,
purl::creator::PurlCreator,
sbom::{
processor::{PostContext, Processor, RedHatProductComponentRelationships},
processor::{
InitContext, PostContext, Processor, RedHatProductComponentRelationships, RunProcessors,
},
CycloneDx as CycloneDxProcessor, LicenseCreator, LicenseInfo, PackageCreator,
PackageReference, RelationshipCreator, SbomContext, SbomInformation,
},
Expand Down Expand Up @@ -107,13 +108,17 @@ impl SbomContext {

// init processors

let supplier = sbom
let suppliers = sbom
.metadata
.as_ref()
.and_then(|m| m.supplier.as_ref().and_then(|org| org.name.as_deref()));
for processor in &mut processors {
processor.init(InitContext { supplier })
.and_then(|m| m.supplier.as_ref().and_then(|org| org.name.as_deref()))
.into_iter()
.collect::<Vec<_>>();
InitContext {
document_node_id: CYCLONEDX_DOC_REF,
suppliers: &suppliers,
}
.run(&mut processors);

// extract "describes"

Expand Down Expand Up @@ -141,15 +146,6 @@ impl SbomContext {
)
.await?;

for processor in &mut processors {
processor.init(InitContext {
supplier: component
.supplier
.as_ref()
.and_then(|org| org.name.as_deref()),
})
}

if let Some(ver) = component.version.clone() {
pr.ingest_product_version(ver.to_string(), Some(self.sbom.sbom_id), connection)
.await?;
Expand Down Expand Up @@ -192,7 +188,7 @@ impl SbomContext {

// create

creator.create(connection, &processors).await?;
creator.create(connection, &mut processors).await?;

// done

Expand Down Expand Up @@ -239,11 +235,11 @@ impl<'a> Creator<'a> {
self.relations.push((left, rel, right));
}

#[instrument(skip(self, db, post), err(level=tracing::Level::INFO))]
#[instrument(skip(self, db, processors), err(level=tracing::Level::INFO))]
pub async fn create(
self,
db: &impl ConnectionTrait,
post: &[Box<dyn Processor>],
processors: &mut [Box<dyn Processor>],
) -> anyhow::Result<()> {
let mut purls = PurlCreator::new();
let mut cpes = CpeCreator::new();
Expand Down Expand Up @@ -272,15 +268,14 @@ impl<'a> Creator<'a> {

// post process

for post in post {
post.post(PostContext {
cpes: &cpes,
purls: &purls,
packages: &mut packages,
relationships: &mut relationships.rels,
externals: &mut relationships.externals,
});
PostContext {
cpes: &cpes,
purls: &purls,
packages: &mut packages,
relationships: &mut relationships.rels,
externals: &mut relationships.externals,
}
.run(processors);

// create

Expand Down
32 changes: 28 additions & 4 deletions modules/ingestor/src/graph/sbom/processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ pub use rh_prod_comp::RedHatProductComponentRelationships;

/// A processor for the ingestion process. Allowing to intervene with the ingestion.
pub trait Processor: Debug {
/// Called exactly once before all others
/// Called exactly once, before all others
fn init(&mut self, _ctx: InitContext) {}
/// Called once all components have been processed, but before storing into the database.
fn post(&self, _ctx: PostContext) {}

/// Called once, after all components have been processed, but before storing into the database.
fn post(&self, _ctx: &mut PostContext) {}
}

#[derive(Copy, Clone)]
pub struct InitContext<'a> {
pub supplier: Option<&'a str>,
pub suppliers: &'a [&'a str],
pub document_node_id: &'a str,
}

pub struct PostContext<'a> {
Expand All @@ -28,3 +31,24 @@ pub struct PostContext<'a> {
pub relationships: &'a mut Vec<package_relates_to_package::ActiveModel>,
pub externals: &'a mut ExternalNodeCreator,
}

/// Helper running processors
pub trait RunProcessors {
fn run(&mut self, processors: &mut [Box<dyn Processor>]);
}

impl RunProcessors for InitContext<'_> {
fn run(&mut self, processors: &mut [Box<dyn Processor>]) {
for processor in processors {
processor.init(*self);
}
}
}

impl RunProcessors for PostContext<'_> {
fn run(&mut self, processors: &mut [Box<dyn Processor>]) {
for processor in processors {
processor.post(self);
}
}
}
Loading

0 comments on commit 2b09639

Please sign in to comment.