Skip to content

Commit 62839aa

Browse files
committed
sbom user guide
Adds a software bill of materials to the Erlang/OTP user guide (not internal documentation). add also information about how users can verify the software bill of material artefact using `cosign` and/or `gh`
1 parent 79dacb7 commit 62839aa

File tree

3 files changed

+229
-0
lines changed

3 files changed

+229
-0
lines changed

system/doc/docs.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"system_principles/upgrade.md": [],
3232
"system_principles/versions.md": [],
3333
"system_principles/misc.md": [],
34+
"sbom/sbom.md": [],
3435
"embedded/embedded.md": [],
3536
"getting_started/getting_started.md": [],
3637
"getting_started/seq_prog.md": [],

system/doc/guides

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ reference_manual:Erlang Reference Manual
77
efficiency_guide:Efficiency Guide
88
tutorial:Interoperability Tutorial
99
embedded:Embedded Systems User's Guide
10+
sbom:Software Bill Of Materials

system/doc/sbom/sbom.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
<!--
2+
%CopyrightBegin%
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
6+
Copyright Ericsson AB 2025. All Rights Reserved.
7+
8+
Licensed under the Apache License, Version 2.0 (the "License");
9+
you may not use this file except in compliance with the License.
10+
You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing, software
15+
distributed under the License is distributed on an "AS IS" BASIS,
16+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
See the License for the specific language governing permissions and
18+
limitations under the License.
19+
20+
%CopyrightEnd%
21+
-->
22+
23+
# Software Bill Of Materials
24+
25+
[](){: #sbom }
26+
27+
# Software Bill-of-Materials (SBOM)
28+
29+
A Software Bill-of-Materials (SBOM) is a document to share information about the
30+
software used, dependencies and, essentially, what the software is made of. SBOMs have many
31+
different use cases, and some examples include verification of licenses, or
32+
vulnerability scanning using databases such as [CVE](https://www.cve.org/) and [OSV](https://osv.dev/), among others.
33+
34+
Erlang/OTP has multiple third-party dependencies. Some are vendored into the source code of Erlang/OTP:
35+
- pcre2 (`erts/emulator/pcre`)
36+
- zlib (`erts/emulator/zlib`)
37+
- asmjit (`erts/emulator/asmjit`)
38+
- openssl (`erts/emulator/openssl`)
39+
- zstd (`erts/emulator/zstd`)
40+
- others
41+
42+
The Erlang/OTP project provides source SBOMs starting with OTP 28. Below we detail structure of the source SBOM
43+
44+
## Source SBOM Structure And General Understanding
45+
46+
Erlang/OTP publishes a source SBOM for Erlang/OTP using [SPDX v2.2](https://spdx.github.io/spdx-spec/v2.3/relationships-between-SPDX-elements/) format.
47+
The source SBOM can be seen as a tree data structure.
48+
49+
- `root`: the root of the tree is found under the key `documentDescribes`.
50+
The value is a single item that points to the SPDX `package` that represents the root node from where all packages converge.
51+
This root node contains mostly configuration files that do not belong to Erlang/OTP applications nor runtime applications.
52+
All SPDX packages (Erlang/OTP apps and runtime, explained later) are under the `packages` key in the SPDX document.
53+
54+
```json
55+
{
56+
"SPDXID": "SPDXRef-DOCUMENT",
57+
"creationInfo": { ... },
58+
"dataLicense": "CC0-1.0",
59+
"documentDescribes": [ "SPDXRef-Project-OTP" ], <----- ROOT NODE
60+
...,
61+
62+
"name": "Erlang/OTP",
63+
"packages": [
64+
{
65+
"SPDXID": "SPDXRef-Project-OTP", <----- DESCRIPTION OF ROOT NODE
66+
"downloadLocation": "https://github.com/erlang/otp/releases",
67+
"externalRefs": [ { "comment": "",
68+
"referenceCategory": "PACKAGE-MANAGER",
69+
"referenceLocator": "pkg:github/erlang/[email protected]",
70+
"referenceType": "purl"
71+
} ],
72+
"filesAnalyzed": true,
73+
"hasFiles": [ "SPDXRef-File-1", "SPDXRef-File-2", ...] <----- FILES IN ROOT NODE
74+
},
75+
... <----- OTHER PACKAGES LIKE ERTS
76+
]
77+
}
78+
```
79+
80+
- First level branches from `root` represent Erlang/OTP applications, the runtime system (`erts`), and
81+
some vendor build scripts (`SPDXRef-otp-make-install-sh`). As an example, we show below the `erts` package.
82+
83+
```json
84+
{
85+
"SPDXID": "SPDXRef-otp-erts",
86+
"downloadLocation": "https://github.com/erlang/otp/releases",
87+
"externalRefs": [ { "comment": "Erlang Runtime System",
88+
"referenceCategory": "PACKAGE-MANAGER",
89+
"referenceLocator": "pkg:otp/[email protected]?vcs_url=git+https://github.com/erlang/otp.git",
90+
"referenceType": "purl"}],
91+
...
92+
"filesAnalyzed": true,
93+
"hasFiles": [ "SPDXRef-File-380", ...],
94+
"name": "erts",
95+
"packageVerificationCode": { "packageVerificationCodeValue": "2568c51ee8756f36b6173037035ca4f77ed0d00b" },
96+
"supplier": "Organization: Ericsson AB",
97+
"versionInfo": "16.0.1"
98+
},
99+
```
100+
101+
- All Erlang/OTP application SPDX packages are named with the prefix
102+
`SPDXRef-otp-<appname>`. `<appname>` represents the name of an Erlang
103+
application, where the value is the name of the Erlang application with the
104+
underscores `_` dropped, e.g., `common_test` becomes `commontest`.
105+
106+
- Application packages have at least two sub packages. One for tests and one for docs.
107+
108+
The documentation and the tests packages add a suffix to the `SPDXRef-otp-<appname>`, namely `documentation` and `test`.
109+
We use `stdlib` as a running example to explain the package structure in the SPDX SBOM, where Erlang/OTP applications:
110+
- `SPDXRef-otp-stdlib-documentation` contains all documentation about `stdlib`, and
111+
- `SPDXRef-otp-stdlib-test` contains all tests about `stdlib`, and `SPDXRef-otp-stdlib` contains the source code of the `stdlib` application.
112+
113+
```json
114+
{
115+
"SPDXID": "SPDXRef-otp-stdlib", <------- stdlib PACKAGE
116+
"downloadLocation": "https://github.com/erlang/otp/releases",
117+
"externalRefs": [...],
118+
"filesAnalyzed": true,
119+
"hasFiles": [
120+
"SPDXRef-File-9022",
121+
"SPDXRef-File-9023",
122+
...
123+
],
124+
"name": "stdlib",
125+
"packageVerificationCode": { "packageVerificationCodeValue": "29200c1cd7da4a5c015cdafd6f71db538ae0a1c9" },
126+
"supplier": "Organization: Ericsson AB",
127+
"versionInfo": "7.0.2"
128+
},
129+
{
130+
"SPDXID": "SPDXRef-otp-stdlib-documentation", <------- stdlib DOCUMENTATION PACKAGE
131+
...
132+
"name": "stdlib-documentation",
133+
"packageVerificationCode": { "packageVerificationCodeValue": "ad443de0ca77bf6cbadc35813e0807494949f25c" },
134+
"supplier": "Organization: Ericsson AB",
135+
"versionInfo": "7.0.2"
136+
},
137+
{
138+
"SPDXID": "SPDXRef-otp-stdlib-test", <------- stdlib TEST PACKAGE
139+
...
140+
}
141+
```
142+
143+
- Application packages have the following fields:
144+
- `name` which represents the Erlang/OTP application name, e.g., `stdlib`, `erts`, etc,
145+
and/or the application name with the suffix `documentation` or `test`, e.g., `stdlib-test` and `stdlib-documentation`.
146+
- `copyrightText` includes the copyright of all the files under the given package.
147+
- `downloadLocation` specifies where the package can be downloaded from.
148+
- `versionInfo` specifies the version of the application, which in case of documentation or test
149+
packages, it refers to the top-level application. For example, the `stdlib` package has `versionInfo` equals to `7.0.2` and its corresponding `stdlib-documentation` and `stdlib-test` packages will have the same `versionInfo`, as this is the version of the package.
150+
- `licenseInfoFromFiles` contains the list of licenses found in the files that belong to the given package.
151+
- for other clarications, please check the SPDX 2.2 standard.
152+
153+
- The application package, application test package, and the application documentation package may all in turn contain one or more vendor packages. An example of this is the package `SPDXRef-otp-erts` who contains other packages, such as `SPDXRef-otp-erts-asmjit`.
154+
155+
- To remove non-needed applications from your SBOM, remove the first level packages (Erlang/OTP applications) that are not needed, including all of their transitive dependencies (other packages reachable from them), as well as all files reachable from these packages. For example, to remove the application `ftp`, one must remove the package `SPDXRef-otp-ftp`, `SPDXRef-otp-ftp-documentation`, and `SPDXRef-otp-ftp-test`, and all the files that they reference (including also [relationship items](https://spdx.github.io/spdx-spec/v2.3/relationships-between-SPDX-elements/)). In most ocassions, you may want to remove the first level Erlang/OTP applications and the keep first level vendor dependencies (identified by comment "vendor package" in the SPDX package). The reason for keeping the first level vendor dependencies is that those include Erlang/OTP building scripts.
156+
157+
Below we show how the `stdlib` packages are linked between them and against the root package, `"SPDXRef-Project-OTP"`.
158+
In this particular case, `stdlib` does not have any more relationships. But Erlang/OTP applications have dependencies
159+
in their `app.src` file and these are also captured in the source SBOM in the relationships field. If you remove packages,
160+
you need to remove relationships that do not exist anymore.
161+
162+
```json
163+
{
164+
"SPDXID": "SPDXRef-DOCUMENT",
165+
"creationInfo": { ... },
166+
"dataLicense": "CC0-1.0",
167+
"documentDescribes": [ "SPDXRef-Project-OTP" ], <----- ROOT NODE
168+
...,
169+
170+
"name": "Erlang/OTP",
171+
"packages": [ ... ],
172+
"relationships": [ <----- RELATIONSHIPS, OR, HOW EVERYTHING FITS TOGETHER
173+
{
174+
"relatedSpdxElement": "SPDXRef-otp-stdlib",
175+
"relationshipType": "TEST_OF", <----- THESE ARE TESTS
176+
"spdxElementId": "SPDXRef-otp-stdlib-test"
177+
},
178+
{
179+
"relatedSpdxElement": "SPDXRef-otp-stdlib",
180+
"relationshipType": "DOCUMENTATION_OF", <----- THESE ARE DOCUMENTS, EXAMPLES, ETC
181+
"spdxElementId": "SPDXRef-otp-stdlib-documentation"
182+
},
183+
{
184+
"relatedSpdxElement": "SPDXRef-Project-OTP",
185+
"relationshipType": "PACKAGE_OF", <------ THIS SPECIFIES THAT stdlib IS PART OF PROJECT-OTP
186+
"spdxElementId": "SPDXRef-otp-stdlib"
187+
},
188+
...
189+
]
190+
}
191+
```
192+
193+
194+
## Verification Of Source SBOM
195+
196+
In each release, Erlang/OTP releases a source SBOM together with a signed SBOM attestation artifact.
197+
This gives users the ability to verify the signed artefact.
198+
199+
Below we show how to do this for Erlang/OTP version `28.0.2` using Sigstore `cosign` ([installation](https://github.com/sigstore/cosign)) and/or Github `gh` tools ([installation](https://github.com/cli/cli)).
200+
201+
### Sigstore `cosign`
202+
203+
1. Download the SBOM for `28.0.2`, named `bom.spdx.json` ([here](https://github.com/erlang/otp/releases/download/OTP-28.0.2/bom.spdx.json))
204+
2. Download the sigstore file, `bom.spdx.json.sigstore` ([here](https://github.com/erlang/otp/releases/download/OTP-28.0.2/bom.spdx.json.sigstore))
205+
3. Run `cosign` with the following parameters
206+
207+
```bash
208+
cosign verify-blob-attestation \
209+
--bundle "bom.spdx.json.sigstore" \
210+
--new-bundle-format \
211+
--type "https://spdx.dev/Document/v2.2" \
212+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
213+
--certificate-identity "https://github.com/erlang/otp/.github/workflows/main.yaml@refs/tags/OTP-28.0.2" \
214+
"bom.spdx.json"
215+
```
216+
### Github CLI `gh`
217+
218+
1. Download the SBOM for `28.0.2`, named `bom.spdx.json` ([here](https://github.com/erlang/otp/releases/download/OTP-28.0.2/bom.spdx.json))
219+
2. Run `gh` with the following parameters
220+
221+
```bash
222+
gh attestation verify \
223+
--predicate-type "https://spdx.dev/Document/v2.2" \
224+
--repo "erlang/otp" \
225+
--source-ref "refs/tags/OTP-28.0.2" \
226+
"bom.spdx.json"
227+
```

0 commit comments

Comments
 (0)