osbuild-depsolve-dnf: add SBOM support for DNF5

Enable generating SBOM documents for depsolved transactions when using
DNF5. Enable SBOM testing with DNF5 in unit tests.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This commit is contained in:
Tomáš Hozza 2024-11-11 14:39:41 +01:00 committed by Simon de Vlieger
parent def6a9fabd
commit 562a30ce93
3 changed files with 18 additions and 17 deletions

View file

@ -2,7 +2,7 @@ import os
import os.path
import tempfile
from datetime import datetime
from typing import List
from typing import Dict, List
import libdnf5 as dnf5
from libdnf5.base import GoalProblem_NO_PROBLEM as NO_PROBLEM
@ -19,6 +19,8 @@ from osbuild.solver import (
modify_rootdir_path,
read_keys,
)
from osbuild.util.sbom.dnf5 import dnf_pkgset_to_sbom_pkgset
from osbuild.util.sbom.spdx import bom_pkgset_to_spdx2_doc
def remote_location(package, schemes=("http", "ftp", "file", "https")):
@ -276,6 +278,17 @@ class DNF5(SolverBase):
def _timestamp_to_rfc3339(timestamp):
return datetime.utcfromtimestamp(timestamp).strftime('%Y-%m-%dT%H:%M:%SZ')
@staticmethod
def _sbom_for_pkgset(pkgset: List[dnf5.rpm.Package]) -> Dict:
"""
Create an SBOM document for the given package set.
For now, only SPDX v2 is supported.
"""
pkgset = dnf_pkgset_to_sbom_pkgset(pkgset)
spdx_doc = bom_pkgset_to_spdx2_doc(pkgset)
return spdx_doc.to_dict()
def dump(self):
"""dump returns a list of all available packages"""
packages = []
@ -445,4 +458,8 @@ class DNF5(SolverBase):
"packages": packages,
"repos": repositories,
}
if "sbom" in arguments:
response["sbom"] = self._sbom_for_pkgset(last_transaction)
return response

View file

@ -161,15 +161,6 @@ def validate_request(request):
sbom = request["arguments"].get("sbom")
if sbom is not None:
# NB: check the DNF5 flag here, instead of in the dnf5 module,
# to consistently return this error message, even if there are other
# potential errors in the request, such as broken repository.
if config.get("use_dnf5", False):
return {
"kind": "InvalidRequest",
"reason": "SBOM support for DNF5 is not implemented"
}
if command != "depsolve":
return {
"kind": "InvalidRequest",

View file

@ -1280,13 +1280,6 @@ def test_depsolve(tmp_path, repo_servers, dnf_config, detect_fn, with_sbom, test
res, exit_code = depsolve(transactions, repo_configs, root_dir,
cache_dir, dnf_config, opt_metadata, with_sbom)
# NB: dnf5 implementation does not support SBOM yet
if dnf_config.get("use_dnf5", False) and with_sbom:
assert exit_code != 0
assert res["kind"] == "InvalidRequest"
assert res["reason"] == "SBOM support for DNF5 is not implemented"
continue
if test_case.get("error", False):
assert exit_code != 0
assert res["kind"] == test_case["error_kind"]