From b197f41454cb25a3f76988b086bb498453ceac8c Mon Sep 17 00:00:00 2001 From: Matthew Brady Date: Fri, 15 Nov 2024 14:26:02 +0100 Subject: [PATCH] v1.0.15 - Added support for Yocto-5, will run Detect on startup if detect_opts specified. --- README.md | 4 ++-- pyproject.toml | 2 +- yocto_import_sbom/BBClass.py | 21 ++++++++++++--------- yocto_import_sbom/BOMClass.py | 4 +++- yocto_import_sbom/ConfigClass.py | 16 ++++++++++------ yocto_import_sbom/SBOMClass.py | 4 ++-- yocto_import_sbom/main.py | 13 ++++++++++++- 7 files changed, 42 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 6cc5cd4..a4bdc29 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Black Duck SCA Scan Yocto Script - bd_scan_yocto_via_sbom.py v1.0.14 +# Black Duck SCA Scan Yocto Script - bd_scan_yocto_via_sbom.py v1.0.15 # PROVISION OF THIS SCRIPT This script is provided under the MIT license (see LICENSE file). @@ -158,7 +158,7 @@ There are several additional options to modify the behaviour of this utility inc --detect_jar_path DETECT_JAR_PATH Detect jar path --detect_opts DETECT_OPTS - Additional Detect options + Additional Detect options (remove leading '--' from options) --api_timeout Specify API timeout in seconds (default 60) - will be used in Detect as --detect.timeout --sbom_create_custom_components diff --git a/pyproject.toml b/pyproject.toml index 07e68fc..ba04657 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "bd_scan_yocto_via_sbom" -version = "1.0.14" +version = "1.0.15" authors = [ { name="Matthew Brady", email="mbrad@blackduck.com" }, ] diff --git a/yocto_import_sbom/BBClass.py b/yocto_import_sbom/BBClass.py index 42693a8..63e6008 100644 --- a/yocto_import_sbom/BBClass.py +++ b/yocto_import_sbom/BBClass.py @@ -245,21 +245,24 @@ def check_files(conf): licman_dir = os.path.dirname(manpath) if not conf.license_manifest: - if not conf.target or not conf.machine: - logging.error("Manifest file not specified and it could not be determined as Target not specified or " - "machine not identified from environment") - return False - else: - manpath = os.path.join(conf.deploy_dir, "licenses", - f"{conf.target}-{machine}-*", "license.manifest") + # if not conf.target or not conf.machine: + # logging.error("Manifest file not specified and it could not be determined as Target not specified or " + # "machine not identified from environment") + # return False + # else: + # Pre Yocto-v5 path + # manpath = os.path.join(conf.deploy_dir, "licenses", + # f"{conf.target}-{machine}-*", "license.manifest") + manpath = os.path.join(conf.deploy_dir, "licenses", "**", "license.manifest") + logging.debug(f"License.manifest glob path is {manpath}") manifest = "" - manlist = glob.glob(manpath) + manlist = glob.glob(manpath, recursive=True) if len(manlist) > 0: # Get most recent file manifest = manlist[-1] if not os.path.isfile(manifest): - logging.error(f"Manifest file '{manifest}' could not be located") + logging.error(f"Manifest file 'license.manifest' could not be located (Search path is '{manpath})") return False else: logging.info(f"Located license.manifest file {manifest}") diff --git a/yocto_import_sbom/BOMClass.py b/yocto_import_sbom/BOMClass.py index c321c14..79560f9 100644 --- a/yocto_import_sbom/BOMClass.py +++ b/yocto_import_sbom/BOMClass.py @@ -228,7 +228,7 @@ def process_cve_file(self, cve_file, reclist): self.CVEPatchedVulnList = patched_vulns return - def run_detect_sigscan(self, conf, tdir): + def run_detect_sigscan(self, conf, tdir, extra_opt=''): import shutil cmd = self.get_detect(conf) @@ -243,6 +243,8 @@ def run_detect_sigscan(self, conf, tdir): detect_cmd += "--detect.wait.for.results=true " if 'detect.timeout' not in conf.detect_opts: detect_cmd += f"--detect.timeout={conf.api_timeout} " + if extra_opt != '': + detect_cmd += f"{extra_opt} " if conf.detect_opts: detect_cmd += conf.detect_opts diff --git a/yocto_import_sbom/ConfigClass.py b/yocto_import_sbom/ConfigClass.py index 19727e6..1573b9d 100644 --- a/yocto_import_sbom/ConfigClass.py +++ b/yocto_import_sbom/ConfigClass.py @@ -4,6 +4,7 @@ import sys from .OEClass import OE +script_version = "v1.0.15" class Config: def __init__(self): @@ -80,7 +81,7 @@ def __init__(self): "from OE data are scanned by default)", action='store_true') parser.add_argument("--detect_jar_path", help="OPTIONAL Synopsys Detect jar path", default="") - parser.add_argument("--detect_opts", help="OPTIONAL Additional Synopsys Detect options", default="") + parser.add_argument("--detect_opts", help="OPTIONAL Additional Synopsys Detect options (remove leading '--')", default="") parser.add_argument("--api_timeout", help="OPTIONAL API and Detect timeout in seconds (default 60)", default="60") parser.add_argument("--sbom_create_custom_components", @@ -122,7 +123,7 @@ def __init__(self): self.skip_sig_scan = False self.scan_all_packages = False self.detect_jar = '' - self.detect_opts = args.detect_opts + self.detect_opts = '' self.api_timeout = args.api_timeout self.sbom_custom_components = args.sbom_create_custom_components self.cve_check_dir = '' @@ -144,7 +145,7 @@ def __init__(self): else: logging.basicConfig(level=loglevel) - logging.info("Black Duck Yocto scan via SBOM utility - v1.0.14") + logging.info(f"Black Duck Yocto scan via SBOM utility - {script_version}") logging.info("SUPPLIED ARGUMENTS:") for arg in vars(args): logging.info(f"--{arg}={getattr(args, arg)}") @@ -213,9 +214,9 @@ def __init__(self): if args.target: self.target = args.target - elif not self.license_manifest: - logging.error(f"Target --target required if --license_manifest not specified") - terminate = True + # elif not self.license_manifest: + # logging.error(f"Target --target required if --license_manifest not specified") + # terminate = True if args.bitbake_layers_file: if not os.path.exists(args.bitbake_layers_file): @@ -286,6 +287,9 @@ def __init__(self): else: self.recipe_report = args.recipe_report + if args.detect_opts != '': + self.detect_opts = args.detect_opts.replace('detect', '--detect') + if terminate: sys.exit(2) return diff --git a/yocto_import_sbom/SBOMClass.py b/yocto_import_sbom/SBOMClass.py index 7b2c221..bf70ae7 100644 --- a/yocto_import_sbom/SBOMClass.py +++ b/yocto_import_sbom/SBOMClass.py @@ -81,9 +81,9 @@ def add_package(self, recipe): recipe_layer = recipe.layer recipe_name = recipe.name if recipe.epoch: - recipe_version = f"{recipe.epoch}:{recipe.orig_version}" + recipe_version = f"{recipe.epoch}:{recipe.version}" else: - recipe_version = recipe.orig_version + recipe_version = recipe.version recipe_pr = 'r0' else: recipe_layer = recipe.oe_layer['name'] diff --git a/yocto_import_sbom/main.py b/yocto_import_sbom/main.py index 751ebb0..d7a32c5 100644 --- a/yocto_import_sbom/main.py +++ b/yocto_import_sbom/main.py @@ -7,12 +7,23 @@ import logging import sys +import tempfile +import os + +empty_dir = tempfile.TemporaryDirectory() + def main(): conf = Config() logging.info("") logging.info("--- PHASE 1 - PROCESS PROJECT --------------------------------------------") + bom = BOM(conf) + if conf.detect_opts != '': + if not bom.run_detect_sigscan(conf, empty_dir.name, extra_opt='--detect.tools=DETECTOR'): + logging.error("Unable to run Detect to initialise project") + sys.exit(2) + reclist = RecipeList() bb = BB() if not bb.process(conf, reclist): @@ -46,7 +57,7 @@ def main(): logging.info("Done creating SBOM file") logging.info("") logging.info("--- PHASE 4 - UPLOAD SBOM ------------------------------------------------") - bom = BOM(conf) + # bom = BOM(conf) if bom.upload_sbom(conf, bom, sbom): logging.info(f"Uploaded SBOM file '{sbom.file}' to create project "