From 36be59464ca56c209a4a67bd99f9a5cb6f29558d Mon Sep 17 00:00:00 2001 From: Joshua Watt Date: Tue, 11 Feb 2025 08:03:25 -0700 Subject: [PATCH] scripts/contrib: Add oe-image-files-spdx script Adds a template for a python project that processes the SPDX 3.0.1 output from a build and lists all the files on the root file system with their checksums This is intended to be an example to show how to deal with the SPDX data to do common tasks. (From OE-Core rev: 3d9c5588ce6181b519810e3378b55826ffcaee49) Signed-off-by: Joshua Watt Signed-off-by: Mathieu Dubois-Briand Signed-off-by: Richard Purdie --- .../contrib/oe-image-files-spdx/.gitignore | 8 ++ scripts/contrib/oe-image-files-spdx/README.md | 24 ++++++ .../oe-image-files-spdx/pyproject.toml | 23 +++++ .../src/oe_image_files/__init__.py | 1 + .../src/oe_image_files/main.py | 86 +++++++++++++++++++ .../src/oe_image_files/version.py | 1 + 6 files changed, 143 insertions(+) create mode 100644 scripts/contrib/oe-image-files-spdx/.gitignore create mode 100644 scripts/contrib/oe-image-files-spdx/README.md create mode 100644 scripts/contrib/oe-image-files-spdx/pyproject.toml create mode 100644 scripts/contrib/oe-image-files-spdx/src/oe_image_files/__init__.py create mode 100644 scripts/contrib/oe-image-files-spdx/src/oe_image_files/main.py create mode 100644 scripts/contrib/oe-image-files-spdx/src/oe_image_files/version.py diff --git a/scripts/contrib/oe-image-files-spdx/.gitignore b/scripts/contrib/oe-image-files-spdx/.gitignore new file mode 100644 index 0000000000..285851c984 --- /dev/null +++ b/scripts/contrib/oe-image-files-spdx/.gitignore @@ -0,0 +1,8 @@ +*.spdx.json +*.pyc +*.bak +*.swp +*.swo +*.swn +venv/* +.venv/* diff --git a/scripts/contrib/oe-image-files-spdx/README.md b/scripts/contrib/oe-image-files-spdx/README.md new file mode 100644 index 0000000000..44f76eacd8 --- /dev/null +++ b/scripts/contrib/oe-image-files-spdx/README.md @@ -0,0 +1,24 @@ +# OE Image Files from SBoM + +This is an example python script that will list the packaged files with their +checksums based on the SPDX 3.0.1 SBoM. + +It can be used as a template for other programs to investigate output based on +OE SPDX SBoMs + +## Installation + +This project can be installed using an virtual environment: +``` +python3 -m venv .venv +.venv/bin/activate +python3 -m pip install -e '.[dev]' +``` + +## Usage + +After installing, the `oe-image-files` program can be used to show the files, e.g.: + +``` +oe-image-files core-image-minimal-qemux86-64.rootfs.spdx.json +``` diff --git a/scripts/contrib/oe-image-files-spdx/pyproject.toml b/scripts/contrib/oe-image-files-spdx/pyproject.toml new file mode 100644 index 0000000000..3fab5dd605 --- /dev/null +++ b/scripts/contrib/oe-image-files-spdx/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "oe-image-files" +description = "Displays all packaged files on the root file system" +dynamic = ["version"] +requires-python = ">= 3.8" +readme = "README.md" + +dependencies = [ + "spdx_python_model @ git+https://github.com/spdx/spdx-python-model.git@aa40861f11d1b5d20edba7101835341a70d91179", +] + +[project.scripts] +oe-image-files = "oe_image_files:main" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.version] +path = "src/oe_image_files/version.py" + +[tool.hatch.metadata] +allow-direct-references = true diff --git a/scripts/contrib/oe-image-files-spdx/src/oe_image_files/__init__.py b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/__init__.py new file mode 100644 index 0000000000..c28a133f2d --- /dev/null +++ b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/__init__.py @@ -0,0 +1 @@ +from .main import main diff --git a/scripts/contrib/oe-image-files-spdx/src/oe_image_files/main.py b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/main.py new file mode 100644 index 0000000000..8476bf6369 --- /dev/null +++ b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/main.py @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: MIT + +import argparse +from pathlib import Path + + +from spdx_python_model import v3_0_1 as spdx_3_0_1 +from .version import VERSION + + +def main(): + parser = argparse.ArgumentParser( + description="Show the packaged files and checksums in an OE image from the SPDX SBoM" + ) + parser.add_argument("file", help="SPDX 3 input file", type=Path) + parser.add_argument("--version", "-V", action="version", version=VERSION) + + args = parser.parse_args() + + # Load SPDX data from file into a new object set + objset = spdx_3_0_1.SHACLObjectSet() + with args.file.open("r") as f: + d = spdx_3_0_1.JSONLDDeserializer() + d.read(f, objset) + + # Find the top level SPDX Document object + for o in objset.foreach_type(spdx_3_0_1.SpdxDocument): + doc = o + break + else: + print("ERROR: No SPDX Document found!") + return 1 + + # Find the root SBoM in the document + for o in doc.rootElement: + if isinstance(o, spdx_3_0_1.software_Sbom): + sbom = o + break + else: + print("ERROR: SBoM not found in document") + return 1 + + # Find the root file system package in the SBoM + for o in sbom.rootElement: + if ( + isinstance(o, spdx_3_0_1.software_Package) + and o.software_primaryPurpose == spdx_3_0_1.software_SoftwarePurpose.archive + ): + root_package = o + break + else: + print("ERROR: Package not found in document") + return 1 + + # Find all relationships of type "contains" that go FROM the root file + # system + files = [] + for rel in objset.foreach_type(spdx_3_0_1.Relationship): + if not rel.relationshipType == spdx_3_0_1.RelationshipType.contains: + continue + + if not rel.from_ is root_package: + continue + + # Iterate over all files in the TO of the relationship + for o in rel.to: + if not isinstance(o, spdx_3_0_1.software_File): + continue + + # Find the SHA 256 hash of the file (if any) + for h in o.verifiedUsing: + if ( + isinstance(h, spdx_3_0_1.Hash) + and h.algorithm == spdx_3_0_1.HashAlgorithm.sha256 + ): + files.append((o.name, h.hashValue)) + break + else: + files.append((o.name, "")) + + # Print files + files.sort(key=lambda x: x[0]) + for name, hash_val in files: + print(f"{name} - {hash_val}") + + return 0 diff --git a/scripts/contrib/oe-image-files-spdx/src/oe_image_files/version.py b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/version.py new file mode 100644 index 0000000000..901e5110b2 --- /dev/null +++ b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/version.py @@ -0,0 +1 @@ +VERSION = "0.0.1"