| # 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", | |
| "--offline-mode", | |
| "--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) | |