diff options
Diffstat (limited to 'scripts/contrib/oe-image-files-spdx/src/oe_image_files/main.py')
-rw-r--r-- | scripts/contrib/oe-image-files-spdx/src/oe_image_files/main.py | 86 |
1 files changed, 86 insertions, 0 deletions
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 @@ | |||
1 | # SPDX-License-Identifier: MIT | ||
2 | |||
3 | import argparse | ||
4 | from pathlib import Path | ||
5 | |||
6 | |||
7 | from spdx_python_model import v3_0_1 as spdx_3_0_1 | ||
8 | from .version import VERSION | ||
9 | |||
10 | |||
11 | def main(): | ||
12 | parser = argparse.ArgumentParser( | ||
13 | description="Show the packaged files and checksums in an OE image from the SPDX SBoM" | ||
14 | ) | ||
15 | parser.add_argument("file", help="SPDX 3 input file", type=Path) | ||
16 | parser.add_argument("--version", "-V", action="version", version=VERSION) | ||
17 | |||
18 | args = parser.parse_args() | ||
19 | |||
20 | # Load SPDX data from file into a new object set | ||
21 | objset = spdx_3_0_1.SHACLObjectSet() | ||
22 | with args.file.open("r") as f: | ||
23 | d = spdx_3_0_1.JSONLDDeserializer() | ||
24 | d.read(f, objset) | ||
25 | |||
26 | # Find the top level SPDX Document object | ||
27 | for o in objset.foreach_type(spdx_3_0_1.SpdxDocument): | ||
28 | doc = o | ||
29 | break | ||
30 | else: | ||
31 | print("ERROR: No SPDX Document found!") | ||
32 | return 1 | ||
33 | |||
34 | # Find the root SBoM in the document | ||
35 | for o in doc.rootElement: | ||
36 | if isinstance(o, spdx_3_0_1.software_Sbom): | ||
37 | sbom = o | ||
38 | break | ||
39 | else: | ||
40 | print("ERROR: SBoM not found in document") | ||
41 | return 1 | ||
42 | |||
43 | # Find the root file system package in the SBoM | ||
44 | for o in sbom.rootElement: | ||
45 | if ( | ||
46 | isinstance(o, spdx_3_0_1.software_Package) | ||
47 | and o.software_primaryPurpose == spdx_3_0_1.software_SoftwarePurpose.archive | ||
48 | ): | ||
49 | root_package = o | ||
50 | break | ||
51 | else: | ||
52 | print("ERROR: Package not found in document") | ||
53 | return 1 | ||
54 | |||
55 | # Find all relationships of type "contains" that go FROM the root file | ||
56 | # system | ||
57 | files = [] | ||
58 | for rel in objset.foreach_type(spdx_3_0_1.Relationship): | ||
59 | if not rel.relationshipType == spdx_3_0_1.RelationshipType.contains: | ||
60 | continue | ||
61 | |||
62 | if not rel.from_ is root_package: | ||
63 | continue | ||
64 | |||
65 | # Iterate over all files in the TO of the relationship | ||
66 | for o in rel.to: | ||
67 | if not isinstance(o, spdx_3_0_1.software_File): | ||
68 | continue | ||
69 | |||
70 | # Find the SHA 256 hash of the file (if any) | ||
71 | for h in o.verifiedUsing: | ||
72 | if ( | ||
73 | isinstance(h, spdx_3_0_1.Hash) | ||
74 | and h.algorithm == spdx_3_0_1.HashAlgorithm.sha256 | ||
75 | ): | ||
76 | files.append((o.name, h.hashValue)) | ||
77 | break | ||
78 | else: | ||
79 | files.append((o.name, "")) | ||
80 | |||
81 | # Print files | ||
82 | files.sort(key=lambda x: x[0]) | ||
83 | for name, hash_val in files: | ||
84 | print(f"{name} - {hash_val}") | ||
85 | |||
86 | return 0 | ||