diff options
-rw-r--r-- | meta/classes/create-spdx-2.2.bbclass | 58 | ||||
-rw-r--r-- | meta/lib/oe/sbom.py | 4 | ||||
-rw-r--r-- | meta/lib/oe/spdx.py | 13 |
3 files changed, 67 insertions, 8 deletions
diff --git a/meta/classes/create-spdx-2.2.bbclass b/meta/classes/create-spdx-2.2.bbclass index 28a42e009f..454dd7a7a0 100644 --- a/meta/classes/create-spdx-2.2.bbclass +++ b/meta/classes/create-spdx-2.2.bbclass | |||
@@ -406,6 +406,54 @@ def collect_dep_sources(d, dep_recipes): | |||
406 | 406 | ||
407 | return sources | 407 | return sources |
408 | 408 | ||
409 | def add_download_packages(d, doc, recipe): | ||
410 | import os.path | ||
411 | from bb.fetch2 import decodeurl, CHECKSUM_LIST | ||
412 | import bb.process | ||
413 | import oe.spdx | ||
414 | import oe.sbom | ||
415 | |||
416 | for download_idx, src_uri in enumerate(d.getVar('SRC_URI').split()): | ||
417 | f = bb.fetch2.FetchData(src_uri, d) | ||
418 | |||
419 | for name in f.names: | ||
420 | package = oe.spdx.SPDXPackage() | ||
421 | package.name = "%s-source-%d" % (d.getVar("PN"), download_idx + 1) | ||
422 | package.SPDXID = oe.sbom.get_download_spdxid(d, download_idx + 1) | ||
423 | |||
424 | if f.type == "file": | ||
425 | continue | ||
426 | |||
427 | uri = f.type | ||
428 | proto = getattr(f, "proto", None) | ||
429 | if proto is not None: | ||
430 | uri = uri + "+" + proto | ||
431 | uri = uri + "://" + f.host + f.path | ||
432 | |||
433 | if f.method.supports_srcrev(): | ||
434 | uri = uri + "@" + f.revisions[name] | ||
435 | |||
436 | if f.method.supports_checksum(f): | ||
437 | for checksum_id in CHECKSUM_LIST: | ||
438 | if checksum_id.upper() not in oe.spdx.SPDXPackage.ALLOWED_CHECKSUMS: | ||
439 | continue | ||
440 | |||
441 | expected_checksum = getattr(f, "%s_expected" % checksum_id) | ||
442 | if expected_checksum is None: | ||
443 | continue | ||
444 | |||
445 | c = oe.spdx.SPDXChecksum() | ||
446 | c.algorithm = checksum_id.upper() | ||
447 | c.checksumValue = expected_checksum | ||
448 | package.checksums.append(c) | ||
449 | |||
450 | package.downloadLocation = uri | ||
451 | doc.packages.append(package) | ||
452 | doc.add_relationship(doc, "DESCRIBES", package) | ||
453 | # In the future, we might be able to do more fancy dependencies, | ||
454 | # but this should be sufficient for now | ||
455 | doc.add_relationship(package, "BUILD_DEPENDENCY_OF", recipe) | ||
456 | |||
409 | python do_create_spdx() { | 457 | python do_create_spdx() { |
410 | from datetime import datetime, timezone | 458 | from datetime import datetime, timezone |
411 | import oe.sbom | 459 | import oe.sbom |
@@ -458,14 +506,6 @@ python do_create_spdx() { | |||
458 | if bb.data.inherits_class("native", d) or bb.data.inherits_class("cross", d): | 506 | if bb.data.inherits_class("native", d) or bb.data.inherits_class("cross", d): |
459 | recipe.annotations.append(create_annotation(d, "isNative")) | 507 | recipe.annotations.append(create_annotation(d, "isNative")) |
460 | 508 | ||
461 | for s in d.getVar('SRC_URI').split(): | ||
462 | if not s.startswith("file://"): | ||
463 | s = s.split(';')[0] | ||
464 | recipe.downloadLocation = s | ||
465 | break | ||
466 | else: | ||
467 | recipe.downloadLocation = "NOASSERTION" | ||
468 | |||
469 | homepage = d.getVar("HOMEPAGE") | 509 | homepage = d.getVar("HOMEPAGE") |
470 | if homepage: | 510 | if homepage: |
471 | recipe.homepage = homepage | 511 | recipe.homepage = homepage |
@@ -507,6 +547,8 @@ python do_create_spdx() { | |||
507 | doc.packages.append(recipe) | 547 | doc.packages.append(recipe) |
508 | doc.add_relationship(doc, "DESCRIBES", recipe) | 548 | doc.add_relationship(doc, "DESCRIBES", recipe) |
509 | 549 | ||
550 | add_download_packages(d, doc, recipe) | ||
551 | |||
510 | if process_sources(d) and include_sources: | 552 | if process_sources(d) and include_sources: |
511 | recipe_archive = deploy_dir_spdx / "recipes" / (doc.name + ".tar.zst") | 553 | recipe_archive = deploy_dir_spdx / "recipes" / (doc.name + ".tar.zst") |
512 | with optional_tarfile(recipe_archive, archive_sources) as archive: | 554 | with optional_tarfile(recipe_archive, archive_sources) as archive: |
diff --git a/meta/lib/oe/sbom.py b/meta/lib/oe/sbom.py index bbf466bbad..22ed5070ea 100644 --- a/meta/lib/oe/sbom.py +++ b/meta/lib/oe/sbom.py | |||
@@ -14,6 +14,10 @@ def get_recipe_spdxid(d): | |||
14 | return "SPDXRef-%s-%s" % ("Recipe", d.getVar("PN")) | 14 | return "SPDXRef-%s-%s" % ("Recipe", d.getVar("PN")) |
15 | 15 | ||
16 | 16 | ||
17 | def get_download_spdxid(d, idx): | ||
18 | return "SPDXRef-Download-%s-%d" % (d.getVar("PN"), idx) | ||
19 | |||
20 | |||
17 | def get_package_spdxid(pkg): | 21 | def get_package_spdxid(pkg): |
18 | return "SPDXRef-Package-%s" % pkg | 22 | return "SPDXRef-Package-%s" % pkg |
19 | 23 | ||
diff --git a/meta/lib/oe/spdx.py b/meta/lib/oe/spdx.py index c74ea68878..7aaf2af5ed 100644 --- a/meta/lib/oe/spdx.py +++ b/meta/lib/oe/spdx.py | |||
@@ -216,6 +216,18 @@ class SPDXPackageVerificationCode(SPDXObject): | |||
216 | 216 | ||
217 | 217 | ||
218 | class SPDXPackage(SPDXObject): | 218 | class SPDXPackage(SPDXObject): |
219 | ALLOWED_CHECKSUMS = [ | ||
220 | "SHA1", | ||
221 | "SHA224", | ||
222 | "SHA256", | ||
223 | "SHA384", | ||
224 | "SHA512", | ||
225 | "MD2", | ||
226 | "MD4", | ||
227 | "MD5", | ||
228 | "MD6", | ||
229 | ] | ||
230 | |||
219 | name = _String() | 231 | name = _String() |
220 | SPDXID = _String() | 232 | SPDXID = _String() |
221 | versionInfo = _String() | 233 | versionInfo = _String() |
@@ -234,6 +246,7 @@ class SPDXPackage(SPDXObject): | |||
234 | hasFiles = _StringList() | 246 | hasFiles = _StringList() |
235 | packageFileName = _String() | 247 | packageFileName = _String() |
236 | annotations = _ObjectList(SPDXAnnotation) | 248 | annotations = _ObjectList(SPDXAnnotation) |
249 | checksums = _ObjectList(SPDXChecksum) | ||
237 | 250 | ||
238 | 251 | ||
239 | class SPDXFile(SPDXObject): | 252 | class SPDXFile(SPDXObject): |