@@ -1,17 +1,34 @@
# SPDX-License-Identifier: MIT
-SBOM_CVE_CHECK_WORKDIR ??= "${WORKDIR}/sbom_cve_check"
-SBOM_CVE_CHECK_DEPLOYDIR = "${SBOM_CVE_CHECK_WORKDIR}/image-deploy"
+require recipes-core/meta/sbom-cve-check-config.inc
-SBOM_CVE_CHECK_EXTRA_ARGS[doc] = "Allow to specify extra arguments to sbom-cve-check. For example to add filtering"
-SBOM_CVE_CHECK_EXTRA_ARGS ?= ""
+SBOM_CVE_CHECK_DEPLOYDIR = "${WORKDIR}/sbom_cve_check/image-deploy"
-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"
-SBOM_CVE_CHECK_EXPORT_VARS ?= "SBOM_CVE_CHECK_EXPORT_FILE"
+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_FILE[doc] = "Default configuration of generated export file"
-SBOM_CVE_CHECK_EXPORT_FILE[type] ?= "spdx3"
-SBOM_CVE_CHECK_EXPORT_FILE[ext] ?= ".cve-check.spdx.json"
+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}.cve-check.spdx.json \
+"
+SBOM_CVE_CHECK_EXPORT_SPDX3[type] ?= "spdx3"
+SBOM_CVE_CHECK_EXPORT_SPDX3[ext] ?= ".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}.cve-check.json \
+"
+SBOM_CVE_CHECK_EXPORT_CVECHECK[type] ?= "yocto-cve-check-manifest"
+SBOM_CVE_CHECK_EXPORT_CVECHECK[ext] ?= ".cve-check.json"
SBOM_CVE_CHECK_ALLOW_NETWORK[doc] = "Set to 1 to enable network usage."
SBOM_CVE_CHECK_ALLOW_NETWORK ?= "0"
@@ -31,7 +48,7 @@ python do_sbom_cve_check() {
sbom_path = d.expand("${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.spdx.json")
vex_manifest_path = d.expand("${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.json")
- dl_db_dir = d.expand("${DL_DIR}/sbom_cve_check/databases")
+ dl_db_dir = d.getVar("SBOM_CVE_CHECK_DATABASES_DIR")
deploy_dir = d.getVar("SBOM_CVE_CHECK_DEPLOYDIR")
img_link_name = d.getVar("IMAGE_LINK_NAME")
img_name = d.getVar("IMAGE_NAME")
@@ -66,9 +83,7 @@ python do_sbom_cve_check() {
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 with exit code {e.exitcode}\n{e.stdout}\n{e.stderr}"
- )
+ bb.error(f"sbom-cve-check failed: {e}")
return
for export_file in export_files:
@@ -79,18 +94,20 @@ python do_sbom_cve_check() {
addtask do_sbom_cve_check after do_create_image_sbom_spdx before do_build
SSTATETASKS += "do_sbom_cve_check"
-SSTATE_SKIP_CREATION:task-sbom-cve-check = "1"
do_sbom_cve_check[cleandirs] = "${SBOM_CVE_CHECK_DEPLOYDIR}"
do_sbom_cve_check[sstate-inputdirs] = "${SBOM_CVE_CHECK_DEPLOYDIR}"
do_sbom_cve_check[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
-do_sbom_cve_check[recrdeptask] += "do_create_image_sbom_spdx"
do_sbom_cve_check[depends] += " \
python3-sbom-cve-check-native:do_populate_sysroot \
${@oe.utils.conditional('SBOM_CVE_CHECK_ALLOW_NETWORK','0',' \
- sbom-cve-check-update-cvelist-native:do_fetch \
- sbom-cve-check-update-nvd-native:do_fetch \
+ sbom-cve-check-update-cvelist-native:do_populate_sysroot \
+ sbom-cve-check-update-nvd-native:do_populate_sysroot \
','',d)} \
"
do_sbom_cve_check[network] = "${SBOM_CVE_CHECK_ALLOW_NETWORK}"
-do_sbom_cve_check[nostamp] = "1"
+
+python do_sbom_cve_check_setscene() {
+ sstate_setscene(d)
+}
+addtask do_sbom_cve_check_setscene
new file mode 100644
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+
+SBOM_CVE_CHECK_DATABASES_DIR ??= "${DL_DIR}/sbom_cve_check/databases"
+SBOM_CVE_CHECK_DATABASES_DIR[doc] = "Download directory path where to store the CVE databases"
@@ -1,7 +1,8 @@
SUMMARY = "Updates the CVE List database"
LICENSE = "MIT"
-SBOM_CVE_CHECK_FETCH_PATH = "${DL_DIR}/sbom_cve_check/databases/cvelist"
+HOMEPAGE = "https://github.com/CVEProject/cvelistV5"
+SBOM_CVE_CHECK_DB_NAME = "cvelist"
SBOM_CVE_CHECK_FETCH_URL = "https://github.com/CVEProject/cvelistV5.git"
-inherit sbom-cve-check-update-db
+require sbom-cve-check-update-db.inc
similarity index 65%
rename from meta/classes-recipe/sbom-cve-check-update-db.bbclass
rename to meta/recipes-core/meta/sbom-cve-check-update-db.inc
@@ -4,19 +4,14 @@ INHIBIT_DEFAULT_DEPS = "1"
EXCLUDE_FROM_WORLD = "1"
inherit native
+require sbom-cve-check-config.inc
-deltask do_patch
-deltask do_configure
-deltask do_compile
-deltask do_install
-deltask do_populate_sysroot
-
-SBOM_CVE_CHECK_FETCH_PATH[doc] = "Path to the Git repository to be downloaded. \
- Should be prefixed by {DL_DIR}/sbom_cve_check/databases/"
+SBOM_CVE_CHECK_DB_NAME[doc] = "Database name, which is the Git repository directory name. \
+ The git repository will be stored in ${SBOM_CVE_CHECK_DATABASES_DIR)/"
SBOM_CVE_CHECK_FETCH_URL[doc] = "Git clone URL of the CVE database"
-SBOM_CVE_CHECK_FETCH_INTERVAL ?= "57600"
+SBOM_CVE_CHECK_FETCH_INTERVAL ??= "57600"
SBOM_CVE_CHECK_FETCH_INTERVAL[doc] = "\
CVE database update interval, in seconds. By default every 16 hours. \
Use 0 to force the update. Use a negative value to skip the update. \
@@ -33,7 +28,8 @@ python do_fetch() {
fetch_interval = int(d.get("SBOM_CVE_CHECK_FETCH_INTERVAL"))
git_url = d.getVar("SBOM_CVE_CHECK_FETCH_URL")
- git_dir = pathlib.Path(d.getVar("SBOM_CVE_CHECK_FETCH_PATH"))
+ git_name = d.getVar("SBOM_CVE_CHECK_DB_NAME")
+ git_dir = pathlib.Path(d.getVar("SBOM_CVE_CHECK_DATABASES_DIR")).joinpath(git_name)
git_dir.mkdir(parents=True, exist_ok=True)
def _exec_git_cmd(args):
@@ -58,7 +54,7 @@ python do_fetch() {
_exec_git_cmd(["clone", "--depth", "1", "--single-branch", git_url, "."])
return
- # Check if an updated is necessary
+ # Check if an update is necessary
if fetch_interval < 0:
return
@@ -79,9 +75,24 @@ python do_fetch() {
}
do_fetch[file-checksums] = ""
-do_fetch[vardeps] = " \
- SBOM_CVE_CHECK_FETCH_PATH \
+do_fetch[vardeps] += " \
+ SBOM_CVE_CHECK_DATABASES_DIR \
+ SBOM_CVE_CHECK_DB_NAME \
SBOM_CVE_CHECK_FETCH_URL \
SBOM_CVE_CHECK_FETCH_INTERVAL \
"
+
do_fetch[nostamp] = "1"
+
+# Leverage BitBake's checksum computation for populated sysroot files to determine
+# whether other recipe tasks dependent on this output need to be re-executed.
+# This serves as a workaround to avoid unnecessary runs of `sbom-cve-check` when
+# the database remains unchanged, given that `do_fetch[nostamp] = "1"` is set.
+do_compile() {
+ git_dir="${SBOM_CVE_CHECK_DATABASES_DIR}/${SBOM_CVE_CHECK_DB_NAME}"
+ git -C "${git_dir}" rev-parse --verify "HEAD^{object}" > "${S}/${SBOM_CVE_CHECK_DB_NAME}.rev"
+}
+
+do_install() {
+ install -m 644 -D -t "${D}${datadir}/sbom_cve_check/databases/" "${S}/${SBOM_CVE_CHECK_DB_NAME}.rev"
+}
@@ -1,7 +1,8 @@
SUMMARY = "Updates the NVD CVE database"
LICENSE = "MIT"
-SBOM_CVE_CHECK_FETCH_PATH = "${DL_DIR}/sbom_cve_check/databases/nvd-fkie"
+HOMEPAGE = "https://github.com/fkie-cad/nvd-json-data-feeds"
+SBOM_CVE_CHECK_DB_NAME = "nvd-fkie"
SBOM_CVE_CHECK_FETCH_URL = "https://github.com/fkie-cad/nvd-json-data-feeds.git"
-inherit sbom-cve-check-update-db
+require sbom-cve-check-update-db.inc
The goal of these changes is to ensure the CVE analysis runs only if either the original SBOM changes or the CVE databases are updated. To achieve this: - Remove the `nostamp` flag from the `do_sbom_cve_check` task. - Remove the unnecessary "recrdeptask" on `do_create_image_sbom_spdx`. The only required dependency is to run after the `do_create_image_sbom_spdx` task of the image recipe. - Add the `do_sbom_cve_check_setscene` task. - Update the dependency for the two CVE database-fetching recipes: the `do_sbom_cve_check` task now runs after their `do_populate_sysroot`. - In the two CVE database-fetching recipes, include a file in the sysroot containing the Git revision of the fetched CVE database. This leverages BitBake's checksum computation for sysroot files to determine if dependent tasks need re-execution. Additional improvements include: - Add missing `HOMEPAGE` links to `sbom-cve-check-update-*-native.bb`. - Move the code in `sbom-cve-check-update-db.bbclass` to a simple include file. Other layers that may want to add a new recipe to download another database can still include it using: `require recipes-core/meta/sbom-cve-check-update-db.inc`. - Rename configuration variables for clarity. - Add `SBOM_CVE_CHECK_DATABASES_DIR` to define the base directory for CVE databases, allowing users to configure an alternate storage location. - Improve documentation for all configuration variables. - By default, the class now generates a JSON file in the `cve-check` format in addition to the exported SPDX 3.0 output. Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com> --- meta/classes-recipe/sbom-cve-check.bbclass | 53 ++++++++++++++-------- meta/recipes-core/meta/sbom-cve-check-config.inc | 4 ++ .../meta/sbom-cve-check-update-cvelist-native.bb | 5 +- .../meta/sbom-cve-check-update-db.inc} | 37 +++++++++------ .../meta/sbom-cve-check-update-nvd-native.bb | 5 +- 5 files changed, 69 insertions(+), 35 deletions(-)