Skip to content

Commit 7209db9

Browse files
authored
Generate a SBOM out of the vendored dependencies (#661)
Signed-off-by: Juan Cruz Viotti <[email protected]>
1 parent fb8d7ec commit 7209db9

File tree

3 files changed

+110
-3
lines changed

3 files changed

+110
-3
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ else()
5858
set(ONE_VERSION "${PROJECT_VERSION}+${PROJECT_GIT_SHA}")
5959
endif()
6060
message(STATUS "One version: ${ONE_VERSION}")
61+
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/VERSION" "${ONE_VERSION}")
6162

6263
if(ONE_INDEX OR ONE_SERVER)
6364
add_subdirectory(src/shared)

enterprise/Dockerfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ COPY test/unit /source/test/unit
3636
COPY test/js /source/test/js
3737

3838
RUN cd /source && npm ci
39-
RUN mkdir -p /usr/share/sourcemeta/one \
40-
&& cd /source && npm sbom --sbom-format spdx --sbom-type library --omit dev \
41-
> /usr/share/sourcemeta/one/npm-packages.spdx.json
4239

4340
ARG SOURCEMETA_ONE_BUILD_TYPE=Release
4441
ARG SOURCEMETA_ONE_PARALLEL=2
@@ -74,6 +71,12 @@ RUN cmake --build /build --config ${SOURCEMETA_ONE_BUILD_TYPE} \
7471
RUN ctest --test-dir /build --build-config ${SOURCEMETA_ONE_BUILD_TYPE} \
7572
--output-on-failure --parallel
7673

74+
RUN mkdir -p /usr/share/sourcemeta/one \
75+
&& cd /source && npm sbom --sbom-format spdx --sbom-type library --omit dev \
76+
> /usr/share/sourcemeta/one/npm-packages.spdx.json \
77+
&& node /source/enterprise/scripts/sbom-vendorpull.js /build/VERSION \
78+
> /usr/share/sourcemeta/one/vendor-packages.spdx.json
79+
7780
FROM debian:trixie-slim
7881

7982
RUN apt-get --yes update && apt-get install --yes --no-install-recommends \
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env node
2+
3+
// Generates an SPDX 2.3 JSON Software Bill of Materials (SBOM) for the
4+
// vendored C++ and frontend dependencies managed through DEPENDENCIES files
5+
6+
import { readFileSync, readdirSync, existsSync } from "node:fs";
7+
import { join, resolve, dirname } from "node:path";
8+
import { fileURLToPath } from "node:url";
9+
10+
const LICENSES = {
11+
"core": "AGPL-3.0-or-later OR LicenseRef-Commercial",
12+
"blaze": "AGPL-3.0-or-later OR LicenseRef-Commercial",
13+
"hydra": "AGPL-3.0-or-later OR LicenseRef-Commercial",
14+
"codegen": "AGPL-3.0-or-later OR LicenseRef-Commercial",
15+
"jsonbinpack": "AGPL-3.0-or-later OR LicenseRef-Commercial",
16+
"jsonschema": "AGPL-3.0-only",
17+
"uwebsockets": "Apache-2.0",
18+
"bootstrap": "MIT",
19+
"bootstrap-icons": "MIT",
20+
"pcre2": "BSD-3-Clause",
21+
"zlib": "Zlib",
22+
"curl": "curl",
23+
"nghttp2": "MIT",
24+
"cpr": "MIT",
25+
"c-ares": "MIT",
26+
"libpsl": "MIT",
27+
"openssl": "Apache-2.0"
28+
};
29+
30+
const versionFile = process.argv[2];
31+
if (!versionFile) {
32+
process.stderr.write(`Usage: ${process.argv[1]} <version-file>\n`);
33+
process.exit(1);
34+
}
35+
36+
const version = readFileSync(versionFile, "utf-8").trim();
37+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
38+
39+
const vendorDirectory = join(root, "vendor");
40+
const files = [
41+
join(root, "DEPENDENCIES"),
42+
...existsSync(vendorDirectory)
43+
? readdirSync(vendorDirectory, { withFileTypes: true })
44+
.filter((entry) => entry.isDirectory())
45+
.map((entry) => join(vendorDirectory, entry.name, "DEPENDENCIES"))
46+
: []
47+
].filter(existsSync).sort();
48+
49+
const seenUrls = new Set();
50+
const packages = [{
51+
name: "sourcemeta-one-enterprise",
52+
SPDXID: "SPDXRef-RootPackage",
53+
versionInfo: version,
54+
downloadLocation: "https://github.com/sourcemeta/one",
55+
filesAnalyzed: false,
56+
licenseConcluded: "NOASSERTION",
57+
licenseDeclared: "NOASSERTION"
58+
}];
59+
const relationships = [{
60+
spdxElementId: "SPDXRef-DOCUMENT",
61+
relationshipType: "DESCRIBES",
62+
relatedSpdxElement: "SPDXRef-RootPackage"
63+
}];
64+
65+
let index = 0;
66+
for (const file of files) {
67+
for (const line of readFileSync(file, "utf-8").split("\n")) {
68+
if (!line.trim()) continue;
69+
const [name, url, entryVersion] = line.split(/\s+/);
70+
const license = LICENSES[name];
71+
if (!license || seenUrls.has(url)) continue;
72+
seenUrls.add(url);
73+
index += 1;
74+
const spdxid = `SPDXRef-Vendor-${index}`;
75+
packages.push({
76+
name, SPDXID: spdxid,
77+
versionInfo: entryVersion,
78+
downloadLocation: url,
79+
filesAnalyzed: false,
80+
licenseConcluded: license,
81+
licenseDeclared: license
82+
});
83+
relationships.push({
84+
spdxElementId: "SPDXRef-RootPackage",
85+
relationshipType: "DEPENDS_ON",
86+
relatedSpdxElement: spdxid
87+
});
88+
}
89+
}
90+
91+
process.stdout.write(JSON.stringify({
92+
spdxVersion: "SPDX-2.3",
93+
dataLicense: "CC0-1.0",
94+
SPDXID: "SPDXRef-DOCUMENT",
95+
name: "sourcemeta-one-enterprise",
96+
documentNamespace: `https://one.sourcemeta.com/sbom/${version}`,
97+
creationInfo: {
98+
created: new Date().toISOString(),
99+
creators: [ "Tool: enterprise/scripts/sbom-vendorpull.js" ]
100+
},
101+
packages,
102+
relationships
103+
}, null, 2) + "\n");

0 commit comments

Comments
 (0)