Skip to content

Commit fa04f70

Browse files
committed
sbom: standalone CI validators, ship bomsh_verify, gitignore outputs
- .github/workflows/sbom.yml: standalone (no-autotools) job now runs ntia-conformance-checker and cyclonedx-bom alongside pyspdxtools, matching the integration job. An NTIA or CDX-1.6 schema regression in --user-settings / --srcs handling -- the entry point most embedded customers actually invoke -- now fails CI rather than needing manual review. - Update integration-job assertions for the new pkg:github PURL shape and pin the GitHub Security Advisories externalRef so a regression that drops it fails CI. - scripts/include.am: add bomsh_verify.py to EXTRA_DIST so a release tarball ships the verifier; without this, downstream consumers cannot re-verify a `make bomsh` provenance bundle from a tarball. - .gitignore: /wolfssl-*.{cdx.json,spdx.json,spdx}, /omnibor.wolfssl-*.spdx.json, /omnibor/, /_sbom_staging/, /_bomsh.conf, /bomsh_raw_logfile* -- generated outputs that were untracked but not ignored.
1 parent 3c23492 commit fa04f70

3 files changed

Lines changed: 72 additions & 7 deletions

File tree

.github/workflows/sbom.yml

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,22 @@ jobs:
7272
- uses: actions/checkout@v4
7373

7474
- name: Install standalone-path deps
75-
# pcpp is the in-Python C preprocessor that lets gen-sbom walk
76-
# settings.h + user_settings.h with no compiler invocation.
77-
# spdx-tools is for the post-generation validation step.
75+
# pcpp drives --user-settings; spdx-tools provides pyspdxtools
76+
# for SPDX schema validation; cyclonedx-bom provides the
77+
# CycloneDX 1.6 strict JSON validator; ntia-conformance-checker
78+
# provides the NTIA Minimum Elements (2021) gate. All four
79+
# were previously only run on the autotools integration job,
80+
# which left a regression in the standalone path -- the entry
81+
# point an embedded customer actually invokes -- detectable
82+
# only by hand. Versions match the integration job below so
83+
# tool drift is single-sourced.
7884
run: |
7985
python3 -m pip install --user --upgrade pip
80-
python3 -m pip install --user 'pcpp==1.30.*' 'spdx-tools==0.8.*'
86+
python3 -m pip install --user \
87+
'pcpp==1.30.*' \
88+
'spdx-tools==0.8.*' \
89+
'cyclonedx-bom==7.*' \
90+
'ntia-conformance-checker==5.*'
8191
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
8292
8393
- name: Generate SBOM via standalone Python entry point
@@ -119,6 +129,34 @@ jobs:
119129
# rejects, our portability claim is false.
120130
run: pyspdxtools --infile /tmp/standalone/wolfssl.spdx.json
121131

132+
- name: Standalone SPDX passes NTIA Minimum Elements (2021)
133+
# NTIA Minimum Elements is the conformance gate auditors
134+
# actually rely on: a structurally-valid SPDX that is missing
135+
# supplier / author / version / unique-id is still useless to
136+
# them. Previously only the autotools job ran this; an NTIA
137+
# regression in --user-settings or --srcs handling could only
138+
# be caught by hand. Run it on the standalone path too so
139+
# the embedded entry point holds the same contract.
140+
run: ntia-checker -c ntia /tmp/standalone/wolfssl.spdx.json
141+
142+
- name: Standalone CDX validates per CycloneDX 1.6 strict schema
143+
# Same validator the autotools job runs. Pins both entry
144+
# points against the same CDX 1.6 schema definition; a
145+
# standalone-only CDX regression now fails at PR time.
146+
run: |
147+
python3 - <<'PY'
148+
import sys
149+
from cyclonedx.validation.json import JsonStrictValidator
150+
from cyclonedx.schema import SchemaVersion
151+
v = JsonStrictValidator(SchemaVersion.V1_6)
152+
with open('/tmp/standalone/wolfssl.cdx.json') as f:
153+
errors = v.validate_str(f.read())
154+
if errors:
155+
print(f"INVALID: {errors}", file=sys.stderr)
156+
sys.exit(1)
157+
print("OK: standalone CDX passes CycloneDX 1.6 strict schema")
158+
PY
159+
122160
- name: Standalone SBOM advertises source-merkle hash semantics
123161
# The auditor-facing contract: the standalone SBOM must say
124162
# "this checksum is over a source set, not a library binary",
@@ -472,16 +510,23 @@ jobs:
472510
473511
- name: CPE 2.3 and PURL identifiers well-formed
474512
# A typo in supplier or product name silently breaks every
475-
# downstream OSV / Trivy / Grype scan.
513+
# downstream OSV / Trivy / Grype scan. PURL must be `pkg:github`
514+
# so OSV/GHSA/Snyk/Trivy resolve directly without per-vendor
515+
# CPE-fallback mapping. An advisory externalRef pointing at the
516+
# GitHub Security Advisories index is also pinned so an auditor
517+
# reading the SBOM has a single in-document link to the project's
518+
# disclosures.
476519
run: |
477520
python3 - <<'PY'
478-
import glob, json, re, sys
521+
import glob, json, re
479522
with open(glob.glob('wolfssl-*.spdx.json')[0]) as f:
480523
d = json.load(f)
481524
refs = {r['referenceType']: r['referenceLocator']
482525
for r in d['packages'][0]['externalRefs']}
483526
assert re.match(r'cpe:2\.3:a:wolfssl:wolfssl:[\d.]+:', refs['cpe23Type']), refs
484-
assert re.match(r'pkg:generic/wolfssl@[\d.]+', refs['purl']), refs
527+
assert re.match(r'pkg:github/wolfSSL/wolfssl@v[\d.]+', refs['purl']), refs
528+
assert refs['advisory'] == \
529+
'https://github.com/wolfSSL/wolfssl/security/advisories', refs
485530
print('identifiers ok:', refs)
486531
PY
487532

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ ctaocrypt/src/src/
88
*.libs
99
*.cache
1010
.dirstamp
11+
12+
# SBOM / bomsh output artefacts (produced by `make sbom` / `make bomsh`).
13+
# Built per-release, not source. Listed first so they survive any
14+
# subsequent `!`-style un-ignore patterns added below.
15+
/wolfssl-*.cdx.json
16+
/wolfssl-*.spdx.json
17+
/wolfssl-*.spdx
18+
/omnibor.wolfssl-*.spdx.json
19+
/omnibor/
20+
/_sbom_staging/
21+
/_bomsh.conf
22+
/bomsh_raw_logfile*
1123
*.user
1224
!*-VS2022.vcxproj.user
1325
configure

scripts/include.am

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,11 @@ EXTRA_DIST += scripts/gen-sbom
177177
# SBOM generator unit tests. Shipped so downstream consumers building
178178
# from a release tarball can re-run the regression suite.
179179
EXTRA_DIST += scripts/test_gen_sbom.py
180+
181+
# Bomsh / OmniBOR provenance verifier (invoked from `.github/workflows/
182+
# sbom.yml` and runnable by hand against any local `make bomsh` output;
183+
# see doc/SBOM.md § 3.5). Must ship with the dist tarball so a
184+
# downstream consumer / CRA reviewer who clones a release tarball can
185+
# re-verify the OmniBOR graph against its enriched SPDX without going
186+
# back to the git repo.
187+
EXTRA_DIST += scripts/bomsh_verify.py

0 commit comments

Comments
 (0)