From: Joshua Watt <jpewhacker@gmail.com>
To: openembedded-core@lists.openembedded.org
Cc: Joshua Watt <JPEWhacker@gmail.com>
Subject: [OE-core][PATCH] scripts/contrib: Add oe-image-files-spdx script
Date: Tue, 11 Feb 2025 08:03:25 -0700 [thread overview]
Message-ID: <20250211150325.256258-1-JPEWhacker@gmail.com> (raw)
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.
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
.../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 00000000000..285851c9848
--- /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 00000000000..44f76eacd8e
--- /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 00000000000..3fab5dd605d
--- /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 00000000000..c28a133f2dd
--- /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 00000000000..8476bf63696
--- /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 00000000000..901e5110b2e
--- /dev/null
+++ b/scripts/contrib/oe-image-files-spdx/src/oe_image_files/version.py
@@ -0,0 +1 @@
+VERSION = "0.0.1"
--
2.48.1
reply other threads:[~2025-02-11 15:03 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20250211150325.256258-1-JPEWhacker@gmail.com \
--to=jpewhacker@gmail.com \
--cc=openembedded-core@lists.openembedded.org \
/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