summaryrefslogtreecommitdiffstats
path: root/meta/classes/create-spdx.bbclass
diff options
context:
space:
mode:
authorJoshua Watt <JPEWhacker@gmail.com>2021-09-01 13:44:45 (GMT)
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-09-03 08:53:28 (GMT)
commit0b871c57b8c3e45fd64d10037a32033d4a347d67 (patch)
tree9860f64e2453bc409bcf83f0e01c14f87d0e2817 /meta/classes/create-spdx.bbclass
parent69faca3df61409927c312e6f060faee945de0373 (diff)
downloadpoky-0b871c57b8c3e45fd64d10037a32033d4a347d67.tar.gz
classes/create-spdx: Add runtime dependency mapping
(From OE-Core rev: 82f3229bce41dc101c79865033432161dac269d8) Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes/create-spdx.bbclass')
-rw-r--r--meta/classes/create-spdx.bbclass179
1 files changed, 178 insertions, 1 deletions
diff --git a/meta/classes/create-spdx.bbclass b/meta/classes/create-spdx.bbclass
index 14caae8..28a2e64 100644
--- a/meta/classes/create-spdx.bbclass
+++ b/meta/classes/create-spdx.bbclass
@@ -13,6 +13,8 @@ SPDXDIR ??= "${WORKDIR}/spdx"
13SPDXDEPLOY = "${SPDXDIR}/deploy" 13SPDXDEPLOY = "${SPDXDIR}/deploy"
14SPDXWORK = "${SPDXDIR}/work" 14SPDXWORK = "${SPDXDIR}/work"
15 15
16SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy"
17
16SPDX_INCLUDE_SOURCES ??= "0" 18SPDX_INCLUDE_SOURCES ??= "0"
17SPDX_INCLUDE_PACKAGED ??= "0" 19SPDX_INCLUDE_PACKAGED ??= "0"
18SPDX_ARCHIVE_SOURCES ??= "0" 20SPDX_ARCHIVE_SOURCES ??= "0"
@@ -486,6 +488,163 @@ do_create_spdx[cleandirs] = "${SPDXDEPLOY} ${SPDXWORK}"
486do_create_spdx[depends] += "${PATCHDEPENDENCY}" 488do_create_spdx[depends] += "${PATCHDEPENDENCY}"
487do_create_spdx[deptask] = "do_create_spdx" 489do_create_spdx[deptask] = "do_create_spdx"
488 490
491def collect_package_providers(d):
492 from pathlib import Path
493 import oe.sbom
494 import oe.spdx
495 import json
496
497 deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX"))
498
499 providers = {}
500
501 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
502 deps = sorted(set(
503 dep[0] for dep in taskdepdata.values() if
504 dep[1] == "do_create_spdx" and dep[0] != d.getVar("PN")
505 ))
506 deps.append(d.getVar("PN"))
507
508 for dep_pn in deps:
509 recipe_data = oe.packagedata.read_pkgdata(dep_pn, d)
510
511 for pkg in recipe_data.get("PACKAGES", "").split():
512
513 pkg_data = oe.packagedata.read_subpkgdata_dict(pkg, d)
514 rprovides = set(n for n, _ in bb.utils.explode_dep_versions2(pkg_data.get("RPROVIDES", "")).items())
515 rprovides.add(pkg)
516
517 for r in rprovides:
518 providers[r] = pkg
519
520 return providers
521
522collect_package_providers[vardepsexclude] += "BB_TASKDEPDATA"
523
524python do_create_runtime_spdx() {
525 from datetime import datetime, timezone
526 import oe.sbom
527 import oe.spdx
528 import oe.packagedata
529 from pathlib import Path
530
531 deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX"))
532 spdx_deploy = Path(d.getVar("SPDXRUNTIMEDEPLOY"))
533
534 creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
535
536 providers = collect_package_providers(d)
537
538 bb.build.exec_func("read_subpackage_metadata", d)
539
540 dep_package_cache = {}
541
542 pkgdest = Path(d.getVar("PKGDEST"))
543 for package in d.getVar("PACKAGES").split():
544 localdata = bb.data.createCopy(d)
545 pkg_name = d.getVar("PKG:%s" % package) or package
546 localdata.setVar("PKG", pkg_name)
547 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + package)
548
549 if not oe.packagedata.packaged(package, localdata):
550 continue
551
552 pkg_spdx_path = deploy_dir_spdx / "packages" / (pkg_name + ".spdx.json")
553
554 package_doc, package_doc_sha1 = oe.sbom.read_doc(pkg_spdx_path)
555
556 for p in package_doc.packages:
557 if p.name == pkg_name:
558 spdx_package = p
559 break
560 else:
561 bb.fatal("Package '%s' not found in %s" % (pkg_name, pkg_spdx_path))
562
563 runtime_doc = oe.spdx.SPDXDocument()
564 runtime_doc.name = "runtime-" + pkg_name
565 runtime_doc.documentNamespace = get_doc_namespace(localdata, runtime_doc)
566 runtime_doc.creationInfo.created = creation_time
567 runtime_doc.creationInfo.comment = "This document was created by analyzing package runtime dependencies."
568 runtime_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass")
569 runtime_doc.creationInfo.creators.append("Organization: OpenEmbedded ()")
570 runtime_doc.creationInfo.creators.append("Person: N/A ()")
571
572 package_ref = oe.spdx.SPDXExternalDocumentRef()
573 package_ref.externalDocumentId = "DocumentRef-package"
574 package_ref.spdxDocument = package_doc.documentNamespace
575 package_ref.checksum.algorithm = "SHA1"
576 package_ref.checksum.checksumValue = package_doc_sha1
577
578 runtime_doc.externalDocumentRefs.append(package_ref)
579
580 runtime_doc.add_relationship(
581 runtime_doc.SPDXID,
582 "AMENDS",
583 "%s:%s" % (package_ref.externalDocumentId, package_doc.SPDXID)
584 )
585
586 deps = bb.utils.explode_dep_versions2(localdata.getVar("RDEPENDS") or "")
587 seen_deps = set()
588 for dep, _ in deps.items():
589 if dep in seen_deps:
590 continue
591
592 dep = providers[dep]
593
594 if not oe.packagedata.packaged(dep, localdata):
595 continue
596
597 dep_pkg_data = oe.packagedata.read_subpkgdata_dict(dep, d)
598 dep_pkg = dep_pkg_data["PKG"]
599
600 if dep in dep_package_cache:
601 (dep_spdx_package, dep_package_ref) = dep_package_cache[dep]
602 else:
603 dep_path = deploy_dir_spdx / "packages" / ("%s.spdx.json" % dep_pkg)
604
605 spdx_dep_doc, spdx_dep_sha1 = oe.sbom.read_doc(dep_path)
606
607 for pkg in spdx_dep_doc.packages:
608 if pkg.name == dep_pkg:
609 dep_spdx_package = pkg
610 break
611 else:
612 bb.fatal("Package '%s' not found in %s" % (dep_pkg, dep_path))
613
614 dep_package_ref = oe.spdx.SPDXExternalDocumentRef()
615 dep_package_ref.externalDocumentId = "DocumentRef-runtime-dependency-" + spdx_dep_doc.name
616 dep_package_ref.spdxDocument = spdx_dep_doc.documentNamespace
617 dep_package_ref.checksum.algorithm = "SHA1"
618 dep_package_ref.checksum.checksumValue = spdx_dep_sha1
619
620 dep_package_cache[dep] = (dep_spdx_package, dep_package_ref)
621
622 runtime_doc.externalDocumentRefs.append(dep_package_ref)
623
624 runtime_doc.add_relationship(
625 "%s:%s" % (dep_package_ref.externalDocumentId, dep_spdx_package.SPDXID),
626 "RUNTIME_DEPENDENCY_OF",
627 "%s:%s" % (package_ref.externalDocumentId, spdx_package.SPDXID)
628 )
629 seen_deps.add(dep)
630
631 oe.sbom.write_doc(d, runtime_doc, "runtime", spdx_deploy)
632}
633
634addtask do_create_runtime_spdx after do_create_spdx before do_build do_rm_work
635SSTATETASKS += "do_create_runtime_spdx"
636do_create_runtime_spdx[sstate-inputdirs] = "${SPDXRUNTIMEDEPLOY}"
637do_create_runtime_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}"
638
639python do_create_runtime_spdx_setscene () {
640 sstate_setscene(d)
641}
642addtask do_create_runtime_spdx_setscene
643
644do_create_runtime_spdx[dirs] = "${SPDXRUNTIMEDEPLOY}"
645do_create_runtime_spdx[cleandirs] = "${SPDXRUNTIMEDEPLOY}"
646do_create_runtime_spdx[rdeptask] = "do_create_spdx"
647
489def spdx_get_src(d): 648def spdx_get_src(d):
490 """ 649 """
491 save patched source of the recipe in SPDX_WORKDIR. 650 save patched source of the recipe in SPDX_WORKDIR.
@@ -537,7 +696,7 @@ def spdx_get_src(d):
537 finally: 696 finally:
538 d.setVar("WORKDIR", workdir) 697 d.setVar("WORKDIR", workdir)
539 698
540do_rootfs[recrdeptask] += "do_create_spdx" 699do_rootfs[recrdeptask] += "do_create_spdx do_create_runtime_spdx"
541 700
542ROOTFS_POSTUNINSTALL_COMMAND =+ "image_combine_spdx ; " 701ROOTFS_POSTUNINSTALL_COMMAND =+ "image_combine_spdx ; "
543python image_combine_spdx() { 702python image_combine_spdx() {
@@ -598,6 +757,24 @@ python image_combine_spdx() {
598 else: 757 else:
599 bb.fatal("Unable to find package with name '%s' in SPDX file %s" % (name, pkg_spdx_path)) 758 bb.fatal("Unable to find package with name '%s' in SPDX file %s" % (name, pkg_spdx_path))
600 759
760 runtime_spdx_path = deploy_dir_spdx / "runtime" / ("runtime-" + name + ".spdx.json")
761 runtime_doc, runtime_doc_sha1 = oe.sbom.read_doc(runtime_spdx_path)
762
763 runtime_ref = oe.spdx.SPDXExternalDocumentRef()
764 runtime_ref.externalDocumentId = "DocumentRef-%s" % runtime_doc.name
765 runtime_ref.spdxDocument = runtime_doc.documentNamespace
766 runtime_ref.checksum.algorithm = "SHA1"
767 runtime_ref.checksum.checksumValue = runtime_doc_sha1
768
769 # "OTHER" isn't ideal here, but I can't find a relationship that makes sense
770 doc.externalDocumentRefs.append(runtime_ref)
771 doc.add_relationship(
772 image,
773 "OTHER",
774 "%s:%s" % (runtime_ref.externalDocumentId, runtime_doc.SPDXID),
775 comment="Runtime dependencies for %s" % name
776 )
777
601 image_spdx_path = imgdeploydir / (image_name + ".spdx.json") 778 image_spdx_path = imgdeploydir / (image_name + ".spdx.json")
602 779
603 with image_spdx_path.open("wb") as f: 780 with image_spdx_path.open("wb") as f: