blob: 1bd1af22b6cbe55f993ffedf9b8a7694863b7778 [file]
# SPDX-License-Identifier: MIT
# Common functionality for the sbom-cve-check classes.
require conf/sbom-cve-check-config.inc
SBOM_CVE_CHECK_DEPLOYDIR = "${WORKDIR}/sbom-cve-check/image-deploy"
SBOM_CVE_CHECK_SCAN_SCOPE ?= "target"
SBOM_CVE_CHECK_SCAN_SCOPE[doc] = "Whether to scan target and native, just target, or just native. \
Valid values are both, target, native."
SBOM_CVE_CHECK_EXTRA_ARGS[doc] = "Allow to specify extra arguments to sbom-cve-check. \
For example to add export flags for filtering (e.g., only export vulnerable CVEs). \
"
SBOM_CVE_CHECK_EXTRA_ARGS ??= ""
SBOM_CVE_CHECK_EXPORT_VARS[doc] = "List of variables that declare export files to generate. \
Each variable must have a 'type' and an 'ext' flag set. \
The 'type' flag contains the value that is passed to the --export-type command flags. \
The 'ext' flag contains the filename extension (suffix). The output filename is going \
to be ${IMAGE_NAME}${ext} \
"
SBOM_CVE_CHECK_EXPORT_VARS ?= "SBOM_CVE_CHECK_EXPORT_SPDX3 SBOM_CVE_CHECK_EXPORT_CVECHECK"
SBOM_CVE_CHECK_EXPORT_SPDX3[doc] = "Export configuration to generate an SPDX3 SBOM file, \
with the following name: ${IMAGE_NAME}.sbom-cve-check.spdx.json \
"
SBOM_CVE_CHECK_EXPORT_SPDX3[type] ?= "spdx3"
SBOM_CVE_CHECK_EXPORT_SPDX3[ext] ?= ".sbom-cve-check.spdx.json"
SBOM_CVE_CHECK_EXPORT_CVECHECK[doc] = "Export configuration to generate a JSON manifest \
in the same format as the cve-check class, with the following name: \
${IMAGE_NAME}.sbom-cve-check.json \
"
SBOM_CVE_CHECK_EXPORT_CVECHECK[type] ?= "yocto-cve-check-manifest"
SBOM_CVE_CHECK_EXPORT_CVECHECK[ext] ?= ".sbom-cve-check.yocto.json"
SBOM_CVE_CHECK_EXPORT_SUMMARY[doc] = "Export configuration to generate a human-readable \
summary report, with the following name: \
${IMAGE_NAME}.cve.txt \
"
SBOM_CVE_CHECK_EXPORT_SUMMARY[type] ?= "summary"
SBOM_CVE_CHECK_EXPORT_SUMMARY[ext] ?= ".cve.txt"
SBOM_CVE_CHECK_UPDATE_DB_DEPENDENCIES ?= " \
sbom-cve-check-update-cvelist-native:do_patch \
sbom-cve-check-update-nvd-native:do_patch \
"
SBOM_CVE_CHECK_SHOW_WARNINGS ?= "1"
SBOM_CVE_CHECK_SHOW_WARNINGS[doc] = "Show warning messages when unpatched CVEs are found. \
Requires the SBOM_CVE_CHECK_EXPORT_CVECHECK report type to be enabled"
def show_warnings_from_file(cvecheck_export_file):
import json
try:
with open(cvecheck_export_file, "r") as f:
report = json.load(f)
except (json.JSONDecodeError, UnicodeDecodeError) as e:
bb.error(f"Failed to open JSON report file {f}: {e}")
return
packages = report.get("package", [])
for package in packages:
unpatched = []
cves = package.get("issue", [])
for cve in cves:
if cve["status"] == "Unpatched":
unpatched.append(cve["id"])
if unpatched:
pname = package["name"]
version = package["version"]
bb.warn(f"{pname}-{version}: Found unpatched CVEs: {', '.join(unpatched)}")
def run_sbom_cve_check(d, sbom_path, export_base_name, export_link_name=None):
import os
import bb
from oe.cve_check import update_symlinks
if not bb.data.inherits_class("create-spdx-3.0", d):
bb.fatal("Cannot execute sbom-cve-check: missing create-spdx-3.0 inherit.")
dl_db_dir = d.getVar("SBOM_CVE_CHECK_DEPLOY_DB_DIR")
out_deploy_dir = d.getVar("SBOM_CVE_CHECK_DEPLOYDIR")
scan_scope = d.getVar("SBOM_CVE_CHECK_SCAN_SCOPE")
export_files = []
for export_var in d.getVar("SBOM_CVE_CHECK_EXPORT_VARS").split():
export_ext = d.getVarFlag(export_var, "ext")
export_path = f"{out_deploy_dir}/{export_base_name}{export_ext}"
export_link = f"{out_deploy_dir}/{export_link_name}{export_ext}" if export_link_name else None
export_type = d.getVarFlag(export_var, "type")
export_files.append((export_type, export_path, export_link))
cmd_env = os.environ.copy()
cmd_env["SBOM_CVE_CHECK_DATABASES_DIR"] = dl_db_dir
cmd_args = [
d.expand("${STAGING_BINDIR_NATIVE}/sbom-cve-check"),
"--sbom-path",
sbom_path,
"--disable-auto-updates",
"--export-process-native",
scan_scope,
]
for export_type, export_file, export_link in export_files:
cmd_args.extend(
["--export-type", export_type, "--export-path", export_file]
)
cmd_args.extend(d.getVar("SBOM_CVE_CHECK_EXTRA_ARGS").split())
try:
bb.note("Running: {}".format(" ".join(cmd_args)))
bb.process.run(cmd_args, env=cmd_env)
except bb.process.ExecutionError as e:
bb.fatal(f"sbom-cve-check failed: {e}")
show_warnings = bb.utils.to_boolean(d.getVar("SBOM_CVE_CHECK_SHOW_WARNINGS"))
for export_type, export_file, export_link in export_files:
bb.note(f"sbom-cve-check exported: {export_file}")
if export_link:
update_symlinks(export_file, export_link)
if show_warnings and export_type == d.getVarFlag("SBOM_CVE_CHECK_EXPORT_CVECHECK", "type"):
show_warnings_from_file(export_file)