Skip to content

Commit fc6b2f7

Browse files
authored
Merge pull request #64 from TNG/validate-spdx
Validate spdx
2 parents 12b0561 + f25a327 commit fc6b2f7

File tree

7 files changed

+45
-12
lines changed

7 files changed

+45
-12
lines changed

.github/workflows/sbom.yaml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ on:
2323
description: Whether to include modules into the sbom
2424
default: false
2525
type: boolean
26+
validate:
27+
description: Whether to valdiate the generated spdx document using the java spdx tools
28+
default: false
29+
type: boolean
2630
workflow_call:
2731
inputs:
2832
test_archive:
@@ -37,6 +41,9 @@ on:
3741
use_modules:
3842
required: true
3943
type: boolean
44+
validate:
45+
required: true
46+
type: boolean
4047

4148
run-name: ${{ inputs.test_archive }}
4249

@@ -93,7 +100,7 @@ jobs:
93100
test_archive="${{ inputs.test_archive }}"
94101
output_dir="${test_archive%.tar.gz}"
95102
echo "output_dir=$output_dir" >> $GITHUB_OUTPUT
96-
103+
97104
- name: Upload Artifacts
98105
uses: actions/upload-artifact@v4
99106
with:
@@ -102,3 +109,14 @@ jobs:
102109
sbom.spdx.json
103110
sbom.used_files.txt
104111
retention-days: 30
112+
113+
- name: Validate sbom.spdx.json
114+
id: validate_sbom
115+
run: |
116+
export SPDX_TOOLS_VERSION=2.0.2
117+
curl -LO "https://github.com/spdx/tools-java/releases/download/v${SPDX_TOOLS_VERSION}/tools-java-${SPDX_TOOLS_VERSION}.zip"
118+
unzip -j "tools-java-${SPDX_TOOLS_VERSION}.zip" "tools-java-${SPDX_TOOLS_VERSION}-jar-with-dependencies.jar"
119+
java -Xmx15G -Xms12G -jar "tools-java-${SPDX_TOOLS_VERSION}-jar-with-dependencies.jar" Verify "sbom.spdx.json"
120+
if: ${{ inputs.validate }}
121+
122+

.github/workflows/sbom_all_configs.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
output_tree: ${{ matrix.output_tree || 'kernel_build' }}
2222
arch: ${{ matrix.arch || 'x86' }}
2323
use_modules: ${{ matrix.use_modules != 'false' && inputs.use_modules }} # use string 'false' because boolean false and undefined are undistinguishable
24+
validate: ${{ matrix.validate == 'true' }} # memory requirements on github runners are only sufficient for small configs
2425
strategy:
2526
fail-fast: false
2627
matrix:
@@ -39,8 +40,10 @@ jobs:
3940
# v6.17
4041
- test_archive: linux.v6.17.tinyconfig.x86.tar.gz
4142
use_modules: 'false'
43+
validate: 'true'
4244
# - test_archive: linux.v6.17.defconfig.x86.tar.gz
4345
- test_archive: linux.v6.17.defconfig.x86.rust.tar.gz
46+
validate: 'true'
4447
- test_archive: linux.v6.17.allmodconfig.x86.tar.gz
4548
# - test_archive: linux.v6.17.localmodconfig.Ubuntu24.04.x86.tar.gz
4649
- test_archive: linux.v6.17.y.gregkh-linux-stable.x86.tar.gz

sbom/lib/sbom/spdx/core.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,14 @@ class SoftwareAgent(Agent):
9191
@dataclass(kw_only=True)
9292
class CreationInfo(SpdxObject):
9393
type: str = field(init=False, default="CreationInfo")
94-
spdxId: SpdxId = "_:creationinfo"
94+
id: SpdxId = "_:creationinfo"
9595
specVersion: str = SPDX_SPEC_VERSION
9696
createdBy: list[Agent]
9797
created: str = field(default_factory=lambda: datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"))
9898

99+
def to_dict(self) -> dict[str, Any]:
100+
return {("@id" if k == "id" else k): v for k, v in super().to_dict().items()}
101+
99102

100103
@dataclass(kw_only=True)
101104
class Relationship(Element):
@@ -111,10 +114,7 @@ def __post_init__(self):
111114
self.spdxId = generate_spdx_id(f"Relationship_{self.relationshipType}")
112115

113116
def to_dict(self) -> dict[str, Any]:
114-
d = super().to_dict()
115-
d["from"] = d.pop("from_")
116-
d["to"] = d.pop("to")
117-
return d
117+
return {("from" if k == "from_" else k): v for k, v in super().to_dict().items()}
118118

119119

120120
@dataclass(kw_only=True)

sbom/lib/sbom/spdx/software.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ class File(SoftwareArtifact):
4242
type: str = field(init=False, default="software_File")
4343
spdxId: SpdxId = field(default_factory=lambda: generate_spdx_id("software_File"))
4444
name: str # type: ignore
45-
software_FileKind: FileKindType | None = None
45+
software_fileKind: FileKindType | None = None

sbom/lib/sbom/spdx/spdxId.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import uuid
66

77
SpdxId = str
8-
_spdx_uri_prefix = "https://kernel.org/"
8+
_spdx_uri_prefix = "https://spdx.org/spdxdocs/"
99
_uuid = uuid.uuid4()
1010
_counter = count(0)
1111

12+
_generated_ids: dict[str, int] = {}
13+
1214

1315
def set_spdx_uri_prefix(prefix: str) -> None:
1416
global _spdx_uri_prefix
@@ -18,4 +20,14 @@ def set_spdx_uri_prefix(prefix: str) -> None:
1820
def generate_spdx_id(object_type: str, object_suffix: str | None = None) -> SpdxId:
1921
if object_suffix is None:
2022
object_suffix = f"gnrtd{next(_counter)}"
21-
return f"{_spdx_uri_prefix}{_uuid}/{object_type}#{object_suffix}"
23+
spdxId = f"{_spdx_uri_prefix}{_uuid}/{object_type}#{object_suffix}"
24+
25+
# compare spdxIds case-insensitively and deduplicate if needed
26+
spdxId_lower = spdxId.lower()
27+
if spdxId_lower in _generated_ids:
28+
_generated_ids[spdxId_lower] += 1
29+
spdxId += f"-{_generated_ids[spdxId_lower]}"
30+
else:
31+
_generated_ids[spdxId_lower] = 0
32+
33+
return spdxId

sbom/lib/sbom/spdx_graph.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ def build_spdx_graph(
5757
src_tree_element = File(
5858
spdxId=generate_spdx_id("software_File", "$(src_tree)"),
5959
name="$(src_tree)",
60-
software_FileKind="directory",
60+
software_fileKind="directory",
6161
)
6262
output_tree_element = File(
6363
spdxId=generate_spdx_id("software_File", "$(output_tree)"),
6464
name="$(output_tree)",
65-
software_FileKind="directory",
65+
software_fileKind="directory",
6666
)
6767
src_tree_contains_relationship = Relationship(
6868
relationshipType="contains",

sbom/sbom.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def _parse_args() -> Args:
8484
)
8585
parser.add_argument(
8686
"--spdx-uri-prefix",
87-
default="https://kernel.org/",
87+
default="https://spdx.org/spdxdocs/",
8888
help="The uri prefix to be used for all 'spdxId' fields in the spdx document",
8989
)
9090
parser.add_argument(

0 commit comments

Comments
 (0)