-
Notifications
You must be signed in to change notification settings - Fork 91
175 lines (160 loc) · 7.18 KB
/
Copy pathsbom.yml
File metadata and controls
175 lines (160 loc) · 7.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
name: SBOM Test
on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]
workflow_dispatch:
inputs:
wolfssl_ref:
description: 'wolfssl git ref that provides scripts/gen-sbom'
# TODO: switch back to 'master' once wolfSSL/wolfssl#10343 merges.
default: 'refs/pull/10343/head'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# This workflow only reads the repo and uploads artefacts; no API writes.
permissions:
contents: read
jobs:
sbom:
name: wolfTPM SBOM generation (linux)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout wolftpm
uses: actions/checkout@v4
with:
path: wolftpm
# wolfTPM links wolfSSL/wolfCrypt (RNG, parameter encryption, PK
# callbacks), so its SBOM records wolfSSL as a dependency. wolfSSL is
# built + installed here so wolfTPM has a library to link, and the same
# source tree (scripts/gen-sbom + wolfssl/version.h) is passed to
# `make sbom` via WOLFSSL_DIR -- so the recorded wolfSSL dependency
# version matches the linked one. gen-sbom is not yet on wolfssl master,
# so default to the open PR head that carries it (wolfSSL/wolfssl#10343)
# so CI actually exercises `make sbom` instead of silently skipping.
# TODO: switch the fallback back to 'master' once #10343 merges.
- name: Checkout wolfssl (gen-sbom + library source)
uses: actions/checkout@v4
with:
repository: wolfSSL/wolfssl
ref: ${{ github.event.inputs.wolfssl_ref || 'refs/pull/10343/head' }}
path: wolfssl
- name: Install build tooling and SBOM validator (pyspdxtools)
run: |
sudo apt-get update
sudo apt-get install -y build-essential autoconf automake libtool \
pkg-config
python3 -m pip install --user 'spdx-tools==0.8.*'
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Build and install wolfssl
working-directory: wolfssl
run: |
autoreconf -ivf
./configure --enable-wolftpm --enable-pkcallbacks \
--prefix="$GITHUB_WORKSPACE/wolfssl-install"
make -j"$(nproc)"
make install
# gen-sbom lives in wolfssl and may not be on the checked-out ref yet (the
# wolfSSL SBOM change can land separately). Gate on its presence and on
# --dep-wolfssl so this workflow is safe against a gen-sbom that predates
# it.
- name: Detect gen-sbom availability and capabilities
id: gate
run: |
GS="$GITHUB_WORKSPACE/wolfssl/scripts/gen-sbom"
if [ ! -f "$GS" ]; then
echo "have=no" >> "$GITHUB_OUTPUT"
echo "::notice::wolfssl scripts/gen-sbom not present on this ref; skipping SBOM generation."
exit 0
fi
echo "have=yes" >> "$GITHUB_OUTPUT"
if python3 "$GS" --help 2>/dev/null | grep -q -- '--dep-wolfssl'; then
echo "dep_wolfssl=yes" >> "$GITHUB_OUTPUT"
else
echo "dep_wolfssl=no" >> "$GITHUB_OUTPUT"
echo "::notice::gen-sbom on this ref has no --dep-wolfssl; the wolfssl dependency + name-derived identity assertions will be skipped."
fi
- name: Configure and build wolftpm
if: steps.gate.outputs.have == 'yes'
working-directory: wolftpm
run: |
autoreconf -ivf
./configure --enable-swtpm --disable-fwtpm --disable-examples \
--with-wolfcrypt="$GITHUB_WORKSPACE/wolfssl-install"
make -j"$(nproc)"
- name: Generate SBOM
if: steps.gate.outputs.have == 'yes'
working-directory: wolftpm
run: make sbom WOLFSSL_DIR="$GITHUB_WORKSPACE/wolfssl"
- name: Outputs exist and SPDX validates
if: steps.gate.outputs.have == 'yes'
working-directory: wolftpm
run: |
ls wolftpm-*.cdx.json wolftpm-*.spdx.json wolftpm-*.spdx
pyspdxtools --infile wolftpm-*.spdx.json
- name: CycloneDX identity, licence, and captured options
if: steps.gate.outputs.have == 'yes'
working-directory: wolftpm
run: |
python3 - <<'PY'
import glob, json
cdx = json.load(open(glob.glob('wolftpm-*.cdx.json')[0]))
assert cdx['bomFormat'] == 'CycloneDX', cdx.get('bomFormat')
assert cdx['specVersion'] == '1.6', cdx.get('specVersion')
m = cdx['metadata']['component']
assert m['name'] == 'wolftpm', m['name']
assert m['purl'].startswith('pkg:github/wolfSSL/wolftpm@'), m['purl']
# Default override must land as GPL-3.0-or-later (matches source headers).
ids = [l.get('license', {}).get('id') for l in m.get('licenses', [])]
assert 'GPL-3.0-or-later' in ids, ids
# Identity is the hashed library artifact.
assert {h['alg'] for h in m.get('hashes', [])}, 'no component hash'
# SBOM_OPTIONS_H must have been parsed: wolfTPM records its feature
# macros in wolftpm/options.h, so the SBOM's build properties must be
# populated.
props = [p for p in m.get('properties', [])
if p.get('name', '').startswith('wolfssl:build:')]
assert props, 'no wolfssl:build:* properties captured from options.h'
print('CDX ok:', m['name'], m['purl'], ids, f'{len(props)} build props')
PY
- name: Reproducible across two runs (SOURCE_DATE_EPOCH)
if: steps.gate.outputs.have == 'yes'
working-directory: wolftpm
run: |
rm -f wolftpm-*.cdx.json wolftpm-*.spdx.json wolftpm-*.spdx
SOURCE_DATE_EPOCH=1700000000 make sbom \
WOLFSSL_DIR="$GITHUB_WORKSPACE/wolfssl"
sha256sum wolftpm-*.cdx.json wolftpm-*.spdx.json > /tmp/a.sums
rm -f wolftpm-*.cdx.json wolftpm-*.spdx.json wolftpm-*.spdx
SOURCE_DATE_EPOCH=1700000000 make sbom \
WOLFSSL_DIR="$GITHUB_WORKSPACE/wolfssl"
sha256sum wolftpm-*.cdx.json wolftpm-*.spdx.json > /tmp/b.sums
diff /tmp/a.sums /tmp/b.sums
- name: wolfssl recorded as a dependency
if: steps.gate.outputs.have == 'yes' && steps.gate.outputs.dep_wolfssl == 'yes'
working-directory: wolftpm
run: |
python3 - <<'PY'
import glob, json
d = json.load(open(glob.glob('wolftpm-*.spdx.json')[0]))
assert 'wolfssl' in {p['name'] for p in d['packages']}, \
[p['name'] for p in d['packages']]
rels = [(r['spdxElementId'], r['relationshipType'],
r['relatedSpdxElement']) for r in d['relationships']]
assert ('SPDXRef-Package-wolftpm', 'DEPENDS_ON',
'SPDXRef-Package-wolfssl') in rels, rels
print('wolfssl dependency ok')
PY
- name: Upload SBOM artefacts
if: always() && steps.gate.outputs.have == 'yes'
uses: actions/upload-artifact@v4
with:
name: wolftpm-sbom-${{ github.sha }}
path: |
wolftpm/wolftpm-*.cdx.json
wolftpm/wolftpm-*.spdx.json
wolftpm/wolftpm-*.spdx
if-no-files-found: warn
retention-days: 90