From: Simon Falsig <sfalsig@verity.net>
To: ptxdist@pengutronix.de
Cc: Simon Falsig <sfalsig@verity.ch>
Subject: [ptxdist] [PATCH] RFC: sbom_report: Add support
Date: Mon, 18 Sep 2023 16:33:39 +0200 [thread overview]
Message-ID: <20230918143339.4126-1-sfalsig@verity.net> (raw)
In-Reply-To: <20230913160546.71046-3-sfalsig@verity.net>
From: Simon Falsig <sfalsig@verity.ch>
This provides support for building SBOMs in CycloneDX format.
A target is added alongside the other reports, that (based on the
fast-bsp-report) extracts name, version, cpe and license of each target
package, and puts these into a final sbom-report in CycloneDX/JSON
format.
This requires a working Python3 setup with the cyclonedx-bom package
installed.
---
bin/ptxdist | 3 +-
rules/post/ptxd_make_report.make | 15 ++++++--
scripts/lib/ptxd_make_report.sh | 16 +++++++++
scripts/lib/ptxd_make_sbom_report.py | 54 ++++++++++++++++++++++++++++
4 files changed, 85 insertions(+), 3 deletions(-)
create mode 100644 scripts/lib/ptxd_make_sbom_report.py
diff --git a/bin/ptxdist b/bin/ptxdist
index dfb619cbd..15be851f5 100755
--- a/bin/ptxdist
+++ b/bin/ptxdist
@@ -780,6 +780,7 @@ Misc:
full-bsp-report generate a yaml file that describes the BSP and
all packages. More data but will build all
packages if necessary.
+ sbom-report generate a CycloneDX json SBOM
print <var> print the contents of a variable, in the way
it is known by "make"
printnext <var> assumes that the contents of <var> is another
@@ -1807,7 +1808,7 @@ EOF
ptxd_make_log export_src EXPORTDIR="${1}"
exit
;;
- fast-bsp-report|full-bsp-report)
+ fast-bsp-report|full-bsp-report|sbom-report)
check_premake_compiler &&
ptxd_make_log "${cmd}"
exit
diff --git a/rules/post/ptxd_make_report.make b/rules/post/ptxd_make_report.make
index eecd2a577..ffa398c95 100644
--- a/rules/post/ptxd_make_report.make
+++ b/rules/post/ptxd_make_report.make
@@ -10,7 +10,9 @@ ptx/report-env = \
$(image/env) \
ptx_report_target="$(strip $(1))" \
ptx_packages_selected="$(filter-out $(IMAGE_PACKAGES),$(PTX_PACKAGES_SELECTED))" \
- ptx_image_packages="$(IMAGE_PACKAGES)"
+ ptx_image_packages="$(IMAGE_PACKAGES)" \
+ ptx_target_packages="$(PACKAGES)"
+
PHONY += full-bsp-report
full-bsp-report: $(RELEASEDIR)/full-bsp-report.yaml
@@ -26,13 +28,22 @@ $(RELEASEDIR)/full-bsp-report.yaml: \
@$(call ptx/report-env, $@) ptxd_make_full_bsp_report
@$(call finish)
+
PHONY += fast-bsp-report
fast-bsp-report: $(RELEASEDIR)/fast-bsp-report.yaml
-
$(RELEASEDIR)/fast-bsp-report.yaml: $(addprefix $(STATEDIR)/,$(addsuffix .fast-report,$(PTX_PACKAGES_SELECTED)))
@$(call targetinfo)
@$(call ptx/report-env, $@) ptxd_make_fast_bsp_report
@$(call finish)
+
+PHONY += sbom-report
+sbom-report: $(RELEASEDIR)/sbom-report.json
+
+$(RELEASEDIR)/sbom-report.json: $(addprefix $(STATEDIR)/,$(addsuffix .fast-report,$(PACKAGES)))
+ @$(call targetinfo)
+ @$(call ptx/report-env, $@) ptxd_make_sbom_report
+ @$(call finish)
+
# vim: syntax=make
diff --git a/scripts/lib/ptxd_make_report.sh b/scripts/lib/ptxd_make_report.sh
index a363ca5b3..e2da4c05f 100644
--- a/scripts/lib/ptxd_make_report.sh
+++ b/scripts/lib/ptxd_make_report.sh
@@ -144,3 +144,19 @@ ptxd_make_fast_bsp_report() {
}
export -f ptxd_make_fast_bsp_report
+ptxd_make_sbom_report() {
+ local -a ptxd_reply
+ local pkg_lic pkg
+
+ ptxd_make_layer_init || return
+
+ echo "Generating $(ptxd_print_path "${ptx_report_target}") ..."
+ echo
+
+ mkdir -p "$(dirname "${ptx_report_target}")" &&
+ python3 ${PTXDIST_LIB_DIR}/ptxd_make_sbom_report.py "${ptx_report_dir}/fast/" ${ptx_target_packages} > ${PTXDIST_TEMPDIR}/sbom-report &&
+ mv "${PTXDIST_TEMPDIR}/sbom-report" "${ptx_report_target}" ||
+ ptxd_bailout "failed to create SBOM report"
+}
+export -f ptxd_make_sbom_report
+
diff --git a/scripts/lib/ptxd_make_sbom_report.py b/scripts/lib/ptxd_make_sbom_report.py
new file mode 100644
index 000000000..cc6a6f703
--- /dev/null
+++ b/scripts/lib/ptxd_make_sbom_report.py
@@ -0,0 +1,54 @@
+from cyclonedx.factory.license import LicenseFactory
+from cyclonedx.factory.license import LicenseChoiceFactory
+from cyclonedx.model.bom import Bom
+from cyclonedx.model.component import Component
+from cyclonedx.output.json import JsonV1Dot4
+import sys
+import re
+
+lFac = LicenseFactory()
+lcFac = LicenseChoiceFactory(license_factory=lFac)
+bom = Bom()
+
+for i in range(2, len(sys.argv)):
+ pkg_report = sys.argv[1] + sys.argv[i] + ".yaml"
+ with open(pkg_report, 'r') as file:
+ content = file.read()
+ name_ = re.search("name: \'(.+)\'", content).group(1)
+ version_ = re.search("version: \'(.+)\'", content).group(1)
+
+ # First see if we have a full CPE specified, then use that
+ cpe_match = re.search("cpe: \'(.+)\'", content)
+ cpe_ = None
+ if cpe_match is not None:
+ cpe_ = cpe_match.group(1)
+ else:
+ # See if we have the individual components
+ cpe_vendor_match = re.search("cpe_vendor: \'(.+)\'", content)
+ cpe_product_match = re.search("cpe_product: \'(.+)\'", content)
+ cpe_version_match = re.search("cpe_version: \'(.+)\'", content)
+ if cpe_vendor_match is not None and cpe_product_match is not None and cpe_version_match is not None:
+ cpe_ = "cpe:2.3:a:{vendor}:{product}:{version}:*:*:*:*:*:*:*".format(vendor=cpe_vendor_match.group(1),
+ product=cpe_product_match.group(1),
+ version=cpe_version_match.group(1))
+
+ if cpe_ is not None:
+ # We have a CPE, let's validate it. Regex from: https://csrc.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd
+ if not re.fullmatch("cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!\"#$$%&'\(\)\+,/:;"
+ "<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)"
+ "|[\*\-]))(:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!\"#$$%&'\(\)\+,/:;<=>@\[\]\^`\{\|}~]"
+ "))+(\?*|\*?))|[\*\-])){4}", cpe_):
+ raise ValueError("Constructed CPE is not valid: {cpe}".format(cpe=cpe_))
+
+ licenses_ = re.search("licenses: \'(.+)\'", content).group(1)
+ comp = Component(
+ name=name_,
+ version=version_,
+ cpe=cpe_,
+ licenses=[lcFac.make_with_license(licenses_)],
+ bom_ref=name_ + "@" + version_
+ )
+ bom.components.add(comp)
+
+serializedJSON = JsonV1Dot4(bom).output_as_string()
+print(serializedJSON)
--
2.25.1
next prev parent reply other threads:[~2023-09-18 14:34 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-13 16:05 [ptxdist] [PATCH 1/3] RFC: ptxd_make_world: Extract CPE for packages Simon Falsig
2023-09-13 16:05 ` [ptxdist] [PATCH 2/3] RFC: Add CPE for a few packages Simon Falsig
2023-09-15 10:15 ` [ptxdist] [PATCH] " Simon Falsig
2023-09-13 16:05 ` [ptxdist] [PATCH 3/3] RFC: sbom_report: Add support Simon Falsig
2023-09-18 14:33 ` Simon Falsig [this message]
2023-10-21 13:52 ` [ptxdist] [PATCH] " Bruno Thomsen
2023-11-03 7:34 ` Simon Falsig
2023-09-13 21:16 ` [ptxdist] [PATCH 1/3] RFC: ptxd_make_world: Extract CPE for packages Christian Melki
2023-09-14 6:46 ` Simon Falsig
2023-09-15 10:14 ` [ptxdist] [PATCH] " Simon Falsig
2023-09-15 10:39 ` Michael Olbrich
2023-09-18 14:29 ` Simon Falsig
2023-09-18 14:37 ` Simon Falsig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230918143339.4126-1-sfalsig@verity.net \
--to=sfalsig@verity.net \
--cc=ptxdist@pengutronix.de \
--cc=sfalsig@verity.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox