From b85442caa1738fcb2dddb179e745d8c806b5b568 Mon Sep 17 00:00:00 2001 From: "vasile.baluta" Date: Thu, 2 Jun 2022 18:55:59 +0200 Subject: [PATCH 1/2] Add varible to control bom upload. --- .project | 11 +++++++++++ classes/dependency-track.bbclass | 11 +++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 .project diff --git a/.project b/.project new file mode 100644 index 0000000..f85e9e0 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + meta-dependencytrack + + + + + + + + diff --git a/classes/dependency-track.bbclass b/classes/dependency-track.bbclass index 387ceba..b47b894 100644 --- a/classes/dependency-track.bbclass +++ b/classes/dependency-track.bbclass @@ -11,6 +11,9 @@ DEPENDENCYTRACK_SBOM ??= "${DEPENDENCYTRACK_DIR}/bom.json" DEPENDENCYTRACK_TMP ??= "${TMPDIR}/dependency-track" DEPENDENCYTRACK_LOCK ??= "${DEPENDENCYTRACK_TMP}/bom.lock" +# Set DEPENDENCYTRACK_UPLOAD to False if you want to control the upload in other +# steps. +DEPENDENCYTRACK_UPLOAD ??= "True" DEPENDENCYTRACK_PROJECT ??= "" DEPENDENCYTRACK_API_URL ??= "http://localhost:8081/api" DEPENDENCYTRACK_API_KEY ??= "" @@ -74,6 +77,10 @@ python do_dependencytrack_upload () { import urllib from pathlib import Path + dt_upload = bb.utils.to_boolean(d.getVar('DEPENDENCYTRACK_UPLOAD')) + if not dt_upload: + return + sbom_path = d.getVar("DEPENDENCYTRACK_SBOM") dt_project = d.getVar("DEPENDENCYTRACK_PROJECT") dt_url = f"{d.getVar('DEPENDENCYTRACK_API_URL')}/v1/bom" @@ -86,7 +93,7 @@ python do_dependencytrack_upload () { "bom": base64.b64encode(sbom.encode()).decode('ascii') }).encode() bb.debug(2, f"Uploading SBOM to project {dt_project} at {dt_url}") - + headers = { "Content-Type": "application/json", "X-API-Key": d.getVar("DEPENDENCYTRACK_API_KEY") @@ -96,7 +103,7 @@ python do_dependencytrack_upload () { data=payload, headers=headers, method="PUT") - + try: urllib.request.urlopen(req) except urllib.error.HTTPError as e: From b8568a0caa7029d56d809b67ddfb7acca6df70c9 Mon Sep 17 00:00:00 2001 From: "vasile.baluta" Date: Tue, 7 Jun 2022 09:37:46 +0200 Subject: [PATCH 2/2] add license information --- classes/dependency-track.bbclass | 51 ++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/classes/dependency-track.bbclass b/classes/dependency-track.bbclass index b47b894..58975e8 100644 --- a/classes/dependency-track.bbclass +++ b/classes/dependency-track.bbclass @@ -18,6 +18,8 @@ DEPENDENCYTRACK_PROJECT ??= "" DEPENDENCYTRACK_API_URL ??= "http://localhost:8081/api" DEPENDENCYTRACK_API_KEY ??= "" +DT_LICENSE_CONVERSION_MAP ??= '{ "GPLv2+" : "GPL-2.0-or-later", "GPLv2" : "GPL-2.0", "LGPLv2" : "LGPL-2.0", "LGPLv2+" : "LGPL-2.0-or-later", "LGPLv2.1+" : "LGPL-2.1-or-later", "LGPLv2.1" : "LGPL-2.1"}' + python do_dependencytrack_init() { import uuid from datetime import datetime @@ -56,11 +58,15 @@ python do_dependencytrack_collect() { for index, cpe in enumerate(oe.cve_check.get_cpe_ids(name, version)): bb.debug(2, f"Collecting pagkage {name}@{version} ({cpe})") if not next((c for c in sbom["components"] if c["cpe"] == cpe), None): - sbom["components"].append({ + component_json = { "name": names[index], "version": version, - "cpe": cpe - }) + "cpe": cpe, + } + license_json = get_licenses(d) + if license_json: + component_json["licenses"] = license_json + sbom["components"].append(component_json) # write it back to the deploy directory write_sbom(d, sbom) @@ -127,3 +133,42 @@ def write_sbom(d, sbom): Path(d.getVar("DEPENDENCYTRACK_SBOM")).write_text( json.dumps(sbom, indent=2) ) + +def get_licenses(d) : + from pathlib import Path + import json + license_expression = d.getVar("LICENSE") + if license_expression: + license_json = [] + licenses = license_expression.replace("|", "").replace("&", "").split() + for license in licenses: + license_conversion_map = json.loads(d.getVar('DT_LICENSE_CONVERSION_MAP')) + converted_license = None + try: + converted_license = license_conversion_map[license] + except Exception as e: + pass + if not converted_license: + converted_license = license + # Search for the license in COMMON_LICENSE_DIR and LICENSE_PATH + for directory in [d.getVar('COMMON_LICENSE_DIR')] + (d.getVar('LICENSE_PATH') or '').split(): + try: + with (Path(directory) / converted_license).open(errors="replace") as f: + extractedText = f.read() + license_data = { + "license": { + "name" : converted_license, + "text": { + "contentType": "text/plain", + "content": extractedText + } + } + } + license_json.append(license_data) + break + except FileNotFoundError: + pass + license_json.append({"expression" : license_expression}) + return license_json + return None +