From fc41a76853792528e0f102e0faac3e398d88be6b Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 3 Jun 2025 17:54:22 +0200 Subject: [PATCH] Create ConnectCore Security Services .bbclass This .bbclass allows to generate a .zip file per image, each containing all of the necessary information to run a CVE scan using the Digi ConnectCore Security Services' CVE analysis tool. https://onedigi.atlassian.net/browse/DEL-9632 Signed-off-by: Gabriel Valcazar (cherry picked from commit fabce3a881454c8a7346538127da5f22862654b6) --- meta-digi-dey/classes/ccss.bbclass | 76 ++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 meta-digi-dey/classes/ccss.bbclass diff --git a/meta-digi-dey/classes/ccss.bbclass b/meta-digi-dey/classes/ccss.bbclass new file mode 100644 index 000000000..bebcacf51 --- /dev/null +++ b/meta-digi-dey/classes/ccss.bbclass @@ -0,0 +1,76 @@ +########################################################### +# +# classes/ccss.bbclass - ConnectCore Security Services +# +# Generates an SBOM for the CCSS CVE analysis tool +# +# Copyright (C) 2025 Digi International +# +# +# This source is released under the MIT License. +# +########################################################### + +inherit vigiles + +CCSS_API_VERSION = "0.1" +CCSS_IMAGE_TYPE ?= "dev" +CCSS_ENABLE ?= "0" + +python do_ccss_generate_sbom() { + import json + import os + import shutil + import tempfile + + # Temporary dir to store all files in the SBOM + ccss_tmp_dir = tempfile.mkdtemp(dir=d.getVar('TOPDIR')) + + try: + manifest_file = os.path.join(d.getVar('VIGILES_DIR'), d.getVar('VIGILES_MANIFEST_NAME') + d.getVar('VIGILES_MANIFEST_SUFFIX')) + ccss_kconfig = os.path.join(d.getVar('VIGILES_DIR'),'.'.join([_get_kernel_pf(d), 'config'])) + ccss_uconfig = os.path.join(d.getVar('VIGILES_DIR'),'.'.join([_get_uboot_pf(d), 'config'])) + + # Copy Vigiles manifest and kernel/uboot configs if they're available + if os.path.exists(manifest_file): + shutil.copy(manifest_file, os.path.join(ccss_tmp_dir, 'manifest.json'), follow_symlinks=True) + if os.path.exists(ccss_kconfig): + shutil.copy(ccss_kconfig, os.path.join(ccss_tmp_dir, 'kernel.config'), follow_symlinks=True) + if os.path.exists(ccss_uconfig): + shutil.copy(ccss_uconfig, os.path.join(ccss_tmp_dir, 'uboot.config'), follow_symlinks=True) + + dict_out = dict( + api_version = d.getVar('CCSS_API_VERSION'), + date = d.getVar('DATETIME'), + has_ccss_patches = bb.utils.contains('BBFILE_COLLECTIONS', 'digi-security', 'y', 'n', d), + image_type = d.getVar('CCSS_IMAGE_TYPE'), + som = d.getVar('DIGI_SOM'), + yocto_codename = d.getVar('DISTRO_CODENAME') + ) + + with open(os.path.join(ccss_tmp_dir, 'config.json'), 'w') as f_out: + s = json.dumps(dict_out, indent=2, sort_keys=True) + f_out.write(s) + + # Create .zip file + shutil.make_archive(os.path.join(d.getVar('TOPDIR'), 'CCSS_' + d.getVar('IMAGE_BASENAME') + '-' + d.getVar('DATETIME')), 'zip', ccss_tmp_dir) + finally: + # Remove temporary dir + bb.utils.remove(ccss_tmp_dir, recurse=True) +} + +# Don't execute do_ccss_generate_sbom() unless explicitly enabled for a given +# image +python __anonymous() { + if d.getVar('CCSS_ENABLE') != '1': + d.setVarFlag('do_ccss_generate_sbom', 'noexec', '1') +} + +addtask do_ccss_generate_sbom after do_image before do_image_complete + +# Since do_ccss_generate_sbom() uses the DATETIME variable to create the +# metadata JSON, said variable will expand to different values when the +# function is parsed in different stages of the build (first by the bitbake +# cooker, and then by a worker). This causes metadata/hash mismatch errors due +# to non-deterministic content, so exclude DATETIME from the hash calculation. +do_ccss_generate_sbom[vardepsexclude]="DATETIME"