@cyclonedx/cdxgen 9.1.0 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/bin/cdxgen.js +16 -4
- package/binary.js +4 -10
- package/data/bom-1.4.schema.json +1605 -0
- package/data/pypi-pkg-aliases.json +487 -485
- package/docker.js +1 -9
- package/index.js +323 -224
- package/package.json +1 -1
- package/utils.js +82 -39
- package/utils.test.js +34 -9
- package/validator.js +199 -0
package/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import Ajv from "ajv";
|
|
2
|
-
import addFormats from "ajv-formats";
|
|
3
1
|
import { platform as _platform, homedir, tmpdir } from "node:os";
|
|
4
|
-
import { basename, join, dirname, sep } from "node:path";
|
|
2
|
+
import { basename, join, dirname, sep, resolve } from "node:path";
|
|
5
3
|
import { parse } from "ssri";
|
|
6
4
|
import {
|
|
7
5
|
lstatSync,
|
|
@@ -91,7 +89,8 @@ import {
|
|
|
91
89
|
parseCsProjAssetsData,
|
|
92
90
|
parseCsPkgLockData,
|
|
93
91
|
parseCsPkgData,
|
|
94
|
-
parseCsProjData
|
|
92
|
+
parseCsProjData,
|
|
93
|
+
DEBUG_MODE
|
|
95
94
|
} from "./utils.js";
|
|
96
95
|
import { spawnSync } from "node:child_process";
|
|
97
96
|
import { fileURLToPath } from "node:url";
|
|
@@ -154,13 +153,6 @@ if (process.env.SWIFT_CMD) {
|
|
|
154
153
|
const SBT_CACHE_DIR =
|
|
155
154
|
process.env.SBT_CACHE_DIR || join(homedir(), ".ivy2", "cache");
|
|
156
155
|
|
|
157
|
-
// Debug mode flag
|
|
158
|
-
const DEBUG_MODE =
|
|
159
|
-
process.env.CDXGEN_DEBUG_MODE === "debug" ||
|
|
160
|
-
process.env.SCAN_DEBUG_MODE === "debug" ||
|
|
161
|
-
process.env.SHIFTLEFT_LOGGING_LEVEL === "debug" ||
|
|
162
|
-
process.env.NODE_ENV === "development";
|
|
163
|
-
|
|
164
156
|
// CycloneDX Hash pattern
|
|
165
157
|
const HASH_PATTERN =
|
|
166
158
|
"^([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128})$";
|
|
@@ -168,7 +160,16 @@ const HASH_PATTERN =
|
|
|
168
160
|
// Timeout milliseconds. Default 10 mins
|
|
169
161
|
const TIMEOUT_MS = parseInt(process.env.CDXGEN_TIMEOUT_MS) || 10 * 60 * 1000;
|
|
170
162
|
|
|
171
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Creates a default parent component based on the directory name.
|
|
165
|
+
*
|
|
166
|
+
* @param {string} path Directory or file name
|
|
167
|
+
* @param {string} type Package type
|
|
168
|
+
* @returns component object
|
|
169
|
+
*/
|
|
170
|
+
const createDefaultParentComponent = (path, type = "application") => {
|
|
171
|
+
// Expands any relative path such as dot
|
|
172
|
+
path = resolve(path);
|
|
172
173
|
// Create a parent component based on the directory name
|
|
173
174
|
let dirName =
|
|
174
175
|
existsSync(path) && lstatSync(path).isDirectory()
|
|
@@ -182,7 +183,7 @@ const createDefaultParentComponent = (path) => {
|
|
|
182
183
|
type: "application"
|
|
183
184
|
};
|
|
184
185
|
const ppurl = new PackageURL(
|
|
185
|
-
|
|
186
|
+
type,
|
|
186
187
|
parentComponent.group,
|
|
187
188
|
parentComponent.name,
|
|
188
189
|
parentComponent.version,
|
|
@@ -257,6 +258,41 @@ function addDependencies(dependencies) {
|
|
|
257
258
|
return deps_list;
|
|
258
259
|
}
|
|
259
260
|
|
|
261
|
+
const addToolsSection = (options, format) => {
|
|
262
|
+
if (options.specVersion === 1.4) {
|
|
263
|
+
if (format === "json") {
|
|
264
|
+
return [
|
|
265
|
+
{
|
|
266
|
+
vendor: "cyclonedx",
|
|
267
|
+
name: "cdxgen",
|
|
268
|
+
version: _version
|
|
269
|
+
}
|
|
270
|
+
];
|
|
271
|
+
} else {
|
|
272
|
+
return [
|
|
273
|
+
{
|
|
274
|
+
tool: {
|
|
275
|
+
vendor: "cyclonedx",
|
|
276
|
+
name: "cdxgen",
|
|
277
|
+
version: _version
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
components: [
|
|
285
|
+
{
|
|
286
|
+
group: "@cyclonedx",
|
|
287
|
+
name: "cdxgen",
|
|
288
|
+
version: _version,
|
|
289
|
+
purl: `pkg:npm/%40cyclonedx/cdxgen@${_version}`,
|
|
290
|
+
type: "application",
|
|
291
|
+
"bom-ref": `pkg:npm/@cyclonedx/cdxgen@${_version}`
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
};
|
|
295
|
+
};
|
|
260
296
|
/**
|
|
261
297
|
* Function to create metadata block
|
|
262
298
|
*
|
|
@@ -264,20 +300,10 @@ function addDependencies(dependencies) {
|
|
|
264
300
|
function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
265
301
|
// DO NOT fork this project to just change the vendor or author's name
|
|
266
302
|
// Try to contribute to this project by sending PR or filing issues
|
|
303
|
+
const tools = addToolsSection(options, format);
|
|
267
304
|
const metadata = {
|
|
268
305
|
timestamp: new Date().toISOString(),
|
|
269
|
-
tools
|
|
270
|
-
components: [
|
|
271
|
-
{
|
|
272
|
-
group: "@cyclonedx",
|
|
273
|
-
name: "cdxgen",
|
|
274
|
-
version: _version,
|
|
275
|
-
purl: `pkg:npm/%40cyclonedx/cdxgen@${_version}`,
|
|
276
|
-
type: "application",
|
|
277
|
-
"bom-ref": `pkg:npm/%40cyclonedx/cdxgen@${_version}`
|
|
278
|
-
}
|
|
279
|
-
]
|
|
280
|
-
},
|
|
306
|
+
tools,
|
|
281
307
|
authors: [
|
|
282
308
|
{
|
|
283
309
|
author: { name: "Prabhu Subramanian", email: "prabhu@appthreat.com" }
|
|
@@ -286,58 +312,35 @@ function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
|
286
312
|
supplier: undefined
|
|
287
313
|
};
|
|
288
314
|
if (format === "json") {
|
|
289
|
-
metadata.tools =
|
|
290
|
-
components: [
|
|
291
|
-
{
|
|
292
|
-
group: "@cyclonedx",
|
|
293
|
-
name: "cdxgen",
|
|
294
|
-
version: _version,
|
|
295
|
-
purl: `pkg:npm/%40cyclonedx/cdxgen@${_version}`,
|
|
296
|
-
type: "application",
|
|
297
|
-
"bom-ref": `pkg:npm/%40cyclonedx/cdxgen@${_version}`
|
|
298
|
-
}
|
|
299
|
-
]
|
|
300
|
-
};
|
|
315
|
+
metadata.tools = tools;
|
|
301
316
|
metadata.authors = [
|
|
302
317
|
{ name: "Prabhu Subramanian", email: "prabhu@appthreat.com" }
|
|
303
318
|
];
|
|
304
319
|
}
|
|
305
|
-
if (
|
|
306
|
-
parentComponent
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
// Bug #317 fix
|
|
324
|
-
if (parentComponent && parentComponent.components) {
|
|
325
|
-
firstPComp.components = parentComponent.components;
|
|
326
|
-
}
|
|
327
|
-
if (firstPComp.evidence) {
|
|
328
|
-
delete firstPComp.evidence;
|
|
329
|
-
}
|
|
330
|
-
metadata.component = firstPComp;
|
|
331
|
-
}
|
|
332
|
-
} else {
|
|
333
|
-
// As a fallback, retain the parent component
|
|
334
|
-
if (format === "json") {
|
|
335
|
-
if (parentComponent.evidence) {
|
|
336
|
-
delete parentComponent.evidence;
|
|
320
|
+
if (parentComponent && Object.keys(parentComponent).length) {
|
|
321
|
+
if (parentComponent) {
|
|
322
|
+
delete parentComponent.evidence;
|
|
323
|
+
delete parentComponent._integrity;
|
|
324
|
+
}
|
|
325
|
+
if (parentComponent && parentComponent.components) {
|
|
326
|
+
for (const comp of parentComponent.components) {
|
|
327
|
+
delete comp.evidence;
|
|
328
|
+
delete comp._integrity;
|
|
329
|
+
if (!comp["bom-ref"] && comp.name && comp.type) {
|
|
330
|
+
let fullName =
|
|
331
|
+
comp.group && comp.group.length
|
|
332
|
+
? `${comp.group}/${comp.name}`
|
|
333
|
+
: comp.name;
|
|
334
|
+
if (comp.version && comp.version.length) {
|
|
335
|
+
fullName = `${fullName}@${comp.version}`;
|
|
336
|
+
}
|
|
337
|
+
comp["bom-ref"] = `pkg:${comp.type}/${fullName}`;
|
|
337
338
|
}
|
|
338
|
-
metadata.component = parentComponent;
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
+
if (format === "json") {
|
|
342
|
+
metadata.component = parentComponent;
|
|
343
|
+
}
|
|
341
344
|
}
|
|
342
345
|
if (options) {
|
|
343
346
|
const mproperties = [];
|
|
@@ -599,16 +602,6 @@ function addComponent(
|
|
|
599
602
|
if (!ptype && pkg.qualifiers && pkg.qualifiers.type === "jar") {
|
|
600
603
|
ptype = "maven";
|
|
601
604
|
}
|
|
602
|
-
// Skip @types package for npm
|
|
603
|
-
if (
|
|
604
|
-
ptype == "npm" &&
|
|
605
|
-
(group === "types" ||
|
|
606
|
-
group === "@types" ||
|
|
607
|
-
!name ||
|
|
608
|
-
name.startsWith("@types"))
|
|
609
|
-
) {
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
605
|
const version = pkg.version;
|
|
613
606
|
if (!version || ["dummy", "ignore"].includes(version)) {
|
|
614
607
|
return;
|
|
@@ -664,10 +657,10 @@ function addComponent(
|
|
|
664
657
|
};
|
|
665
658
|
if (format === "xml") {
|
|
666
659
|
component["@type"] = determinePackageType(pkg);
|
|
667
|
-
component["@bom-ref"] = purlString;
|
|
660
|
+
component["@bom-ref"] = decodeURIComponent(purlString);
|
|
668
661
|
} else {
|
|
669
662
|
component["type"] = determinePackageType(pkg);
|
|
670
|
-
component["bom-ref"] = purlString;
|
|
663
|
+
component["bom-ref"] = decodeURIComponent(purlString);
|
|
671
664
|
}
|
|
672
665
|
if (
|
|
673
666
|
component.externalReferences === undefined ||
|
|
@@ -680,7 +673,11 @@ function addComponent(
|
|
|
680
673
|
// Retain any component properties
|
|
681
674
|
if (format === "json") {
|
|
682
675
|
// Retain evidence
|
|
683
|
-
if (
|
|
676
|
+
if (
|
|
677
|
+
options.specVersion >= 1.5 &&
|
|
678
|
+
pkg.evidence &&
|
|
679
|
+
Object.keys(pkg.evidence).length
|
|
680
|
+
) {
|
|
684
681
|
component.evidence = pkg.evidence;
|
|
685
682
|
}
|
|
686
683
|
if (pkg.properties && pkg.properties.length) {
|
|
@@ -887,7 +884,10 @@ const buildBomXml = (
|
|
|
887
884
|
const bom = create("bom", {
|
|
888
885
|
encoding: "utf-8",
|
|
889
886
|
separateArrayItems: true
|
|
890
|
-
}).att(
|
|
887
|
+
}).att(
|
|
888
|
+
"xmlns",
|
|
889
|
+
`http://cyclonedx.org/schema/bom/${"" + (options.specVersion || 1.5)}`
|
|
890
|
+
);
|
|
891
891
|
bom.att("serialNumber", serialNum);
|
|
892
892
|
bom.att("version", 1);
|
|
893
893
|
const metadata = addMetadata(parentComponent, "xml", options);
|
|
@@ -934,7 +934,7 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
934
934
|
allImports = context.allImports;
|
|
935
935
|
}
|
|
936
936
|
const nsMapping = context.nsMapping || {};
|
|
937
|
-
const dependencies = context.dependencies || [];
|
|
937
|
+
const dependencies = !options.requiredOnly ? context.dependencies || [] : [];
|
|
938
938
|
const parentComponent =
|
|
939
939
|
determineParentComponent(options) || context.parentComponent;
|
|
940
940
|
const metadata = addMetadata(parentComponent, "json", options);
|
|
@@ -950,7 +950,7 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
950
950
|
// CycloneDX 1.5 Json Template
|
|
951
951
|
const jsonTpl = {
|
|
952
952
|
bomFormat: "CycloneDX",
|
|
953
|
-
specVersion: "1.5",
|
|
953
|
+
specVersion: "" + (options.specVersion || "1.5"),
|
|
954
954
|
serialNumber: serialNum,
|
|
955
955
|
version: 1,
|
|
956
956
|
metadata: metadata,
|
|
@@ -1131,11 +1131,17 @@ export const createJavaBom = async (path, options) => {
|
|
|
1131
1131
|
"Resolve the above maven error. This could be due to the following:\n"
|
|
1132
1132
|
);
|
|
1133
1133
|
if (
|
|
1134
|
-
result.
|
|
1135
|
-
result.
|
|
1136
|
-
"
|
|
1137
|
-
|
|
1138
|
-
|
|
1134
|
+
result.stdout &&
|
|
1135
|
+
(result.stdout.includes("Non-resolvable parent POM") ||
|
|
1136
|
+
result.stdout.includes("points at wrong local POM"))
|
|
1137
|
+
) {
|
|
1138
|
+
console.log(
|
|
1139
|
+
"1. Check if the pom.xml contains valid settings such `parent.relativePath` to make mvn command work from within the sub-directory."
|
|
1140
|
+
);
|
|
1141
|
+
} else if (
|
|
1142
|
+
result.stdout &&
|
|
1143
|
+
(result.stdout.includes("Could not resolve dependencies") ||
|
|
1144
|
+
result.stdout.includes("no dependency information available"))
|
|
1139
1145
|
) {
|
|
1140
1146
|
console.log(
|
|
1141
1147
|
"1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen."
|
|
@@ -1316,17 +1322,21 @@ export const createJavaBom = async (path, options) => {
|
|
|
1316
1322
|
}
|
|
1317
1323
|
if (gradleFiles && gradleFiles.length && options.installDeps) {
|
|
1318
1324
|
const gradleCmd = getGradleCommand(path, null);
|
|
1325
|
+
const defaultDepTaskArgs = ["-q", "--console", "plain", "--build-cache"];
|
|
1319
1326
|
allProjects.push(parentComponent);
|
|
1327
|
+
let depTaskWithArgs = ["dependencies"];
|
|
1328
|
+
if (process.env.GRADLE_DEPENDENCY_TASK) {
|
|
1329
|
+
depTaskWithArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" ");
|
|
1330
|
+
}
|
|
1320
1331
|
for (const sp of allProjects) {
|
|
1321
1332
|
let gradleDepArgs = [
|
|
1322
1333
|
sp.purl === parentComponent.purl
|
|
1323
|
-
?
|
|
1324
|
-
: `:${sp.name}
|
|
1325
|
-
"-q",
|
|
1326
|
-
"--console",
|
|
1327
|
-
"plain",
|
|
1328
|
-
"--build-cache"
|
|
1334
|
+
? depTaskWithArgs[0]
|
|
1335
|
+
: `:${sp.name}:${depTaskWithArgs[0]}`
|
|
1329
1336
|
];
|
|
1337
|
+
gradleDepArgs = gradleDepArgs
|
|
1338
|
+
.concat(depTaskWithArgs.slice(1))
|
|
1339
|
+
.concat(defaultDepTaskArgs);
|
|
1330
1340
|
// Support custom GRADLE_ARGS such as --configuration runtimeClassPath
|
|
1331
1341
|
if (process.env.GRADLE_ARGS) {
|
|
1332
1342
|
const addArgs = process.env.GRADLE_ARGS.split(" ");
|
|
@@ -1673,6 +1683,7 @@ export const createNodejsBom = async (path, options) => {
|
|
|
1673
1683
|
let manifestFiles = [];
|
|
1674
1684
|
let dependencies = [];
|
|
1675
1685
|
let parentComponent = {};
|
|
1686
|
+
const parentSubComponents = [];
|
|
1676
1687
|
let ppurl = "";
|
|
1677
1688
|
// Docker mode requires special handling
|
|
1678
1689
|
if (["docker", "oci", "os"].includes(options.projectType)) {
|
|
@@ -1807,8 +1818,14 @@ export const createNodejsBom = async (path, options) => {
|
|
|
1807
1818
|
// Parse package-lock.json if available
|
|
1808
1819
|
const parsedList = await parsePkgLock(f);
|
|
1809
1820
|
const dlist = parsedList.pkgList;
|
|
1810
|
-
|
|
1811
|
-
|
|
1821
|
+
const tmpParentComponent = dlist.splice(0, 1)[0] || {};
|
|
1822
|
+
tmpParentComponent.type = "application";
|
|
1823
|
+
// Create a default parent component based on directory name
|
|
1824
|
+
if (!Object.keys(parentComponent).length) {
|
|
1825
|
+
parentComponent = tmpParentComponent;
|
|
1826
|
+
} else {
|
|
1827
|
+
parentSubComponents.push(tmpParentComponent);
|
|
1828
|
+
}
|
|
1812
1829
|
if (dlist && dlist.length) {
|
|
1813
1830
|
pkgList = pkgList.concat(dlist);
|
|
1814
1831
|
}
|
|
@@ -1886,28 +1903,38 @@ export const createNodejsBom = async (path, options) => {
|
|
|
1886
1903
|
if (existsSync(packageJsonF)) {
|
|
1887
1904
|
const pcs = await parsePkgJson(packageJsonF);
|
|
1888
1905
|
if (pcs.length) {
|
|
1889
|
-
|
|
1890
|
-
|
|
1906
|
+
const tmpParentComponent = pcs[0];
|
|
1907
|
+
tmpParentComponent.type = "application";
|
|
1908
|
+
if (!Object.keys(parentComponent).length) {
|
|
1909
|
+
parentComponent = tmpParentComponent;
|
|
1910
|
+
} else {
|
|
1911
|
+
parentSubComponents.push(tmpParentComponent);
|
|
1912
|
+
}
|
|
1891
1913
|
}
|
|
1892
1914
|
} else {
|
|
1893
1915
|
let dirName = dirname(f);
|
|
1894
1916
|
const tmpA = dirName.split(sep);
|
|
1895
1917
|
dirName = tmpA[tmpA.length - 1];
|
|
1896
|
-
|
|
1918
|
+
const tmpParentComponent = {
|
|
1897
1919
|
group: "",
|
|
1898
1920
|
name: dirName,
|
|
1899
1921
|
type: "application"
|
|
1900
1922
|
};
|
|
1901
1923
|
ppurl = new PackageURL(
|
|
1902
1924
|
"npm",
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1925
|
+
tmpParentComponent.group,
|
|
1926
|
+
tmpParentComponent.name,
|
|
1927
|
+
tmpParentComponent.version,
|
|
1906
1928
|
null,
|
|
1907
1929
|
null
|
|
1908
1930
|
).toString();
|
|
1909
|
-
|
|
1910
|
-
|
|
1931
|
+
tmpParentComponent["bom-ref"] = ppurl;
|
|
1932
|
+
tmpParentComponent["purl"] = ppurl;
|
|
1933
|
+
if (!Object.keys(parentComponent).length) {
|
|
1934
|
+
parentComponent = tmpParentComponent;
|
|
1935
|
+
} else {
|
|
1936
|
+
parentSubComponents.push(tmpParentComponent);
|
|
1937
|
+
}
|
|
1911
1938
|
}
|
|
1912
1939
|
// Parse yarn.lock if available. This check is after rush.json since
|
|
1913
1940
|
// rush.js could include yarn.lock :(
|
|
@@ -1966,17 +1993,17 @@ export const createNodejsBom = async (path, options) => {
|
|
|
1966
1993
|
parentComponent
|
|
1967
1994
|
});
|
|
1968
1995
|
}
|
|
1969
|
-
//
|
|
1970
|
-
if (
|
|
1971
|
-
|
|
1972
|
-
allImports,
|
|
1973
|
-
src: path,
|
|
1974
|
-
filename: manifestFiles.join(", "),
|
|
1975
|
-
dependencies,
|
|
1976
|
-
parentComponent
|
|
1977
|
-
});
|
|
1996
|
+
// Retain the components of parent component
|
|
1997
|
+
if (parentSubComponents.length) {
|
|
1998
|
+
parentComponent.components = parentSubComponents;
|
|
1978
1999
|
}
|
|
1979
|
-
return {
|
|
2000
|
+
return buildBomNSData(options, pkgList, "npm", {
|
|
2001
|
+
allImports,
|
|
2002
|
+
src: path,
|
|
2003
|
+
filename: manifestFiles.join(", "),
|
|
2004
|
+
dependencies,
|
|
2005
|
+
parentComponent
|
|
2006
|
+
});
|
|
1980
2007
|
};
|
|
1981
2008
|
|
|
1982
2009
|
/**
|
|
@@ -1991,7 +2018,7 @@ export const createPythonBom = async (path, options) => {
|
|
|
1991
2018
|
let dependencies = [];
|
|
1992
2019
|
let pkgList = [];
|
|
1993
2020
|
const tempDir = mkdtempSync(join(tmpdir(), "cdxgen-venv-"));
|
|
1994
|
-
const parentComponent = createDefaultParentComponent(path);
|
|
2021
|
+
const parentComponent = createDefaultParentComponent(path, "pypi");
|
|
1995
2022
|
const pipenvMode = existsSync(join(path, "Pipfile"));
|
|
1996
2023
|
const poetryFiles = getAllFiles(
|
|
1997
2024
|
path,
|
|
@@ -2099,6 +2126,12 @@ export const createPythonBom = async (path, options) => {
|
|
|
2099
2126
|
pkgList = pkgList.concat(pkgMap.pkgList);
|
|
2100
2127
|
frozen = true;
|
|
2101
2128
|
}
|
|
2129
|
+
if (pkgMap.dependenciesList) {
|
|
2130
|
+
dependencies = mergeDependencies(
|
|
2131
|
+
dependencies,
|
|
2132
|
+
pkgMap.dependenciesList
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2102
2135
|
}
|
|
2103
2136
|
// Fallback to parsing manually
|
|
2104
2137
|
if (!pkgList.length || !frozen) {
|
|
@@ -2148,7 +2181,9 @@ export const createPythonBom = async (path, options) => {
|
|
|
2148
2181
|
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2149
2182
|
pkgList = pkgList.concat(retMap.pkgList);
|
|
2150
2183
|
for (const p of retMap.pkgList) {
|
|
2151
|
-
|
|
2184
|
+
if (p.version) {
|
|
2185
|
+
parentDependsOn.push(`pkg:pypi/${p.name}@${p.version}`);
|
|
2186
|
+
}
|
|
2152
2187
|
}
|
|
2153
2188
|
}
|
|
2154
2189
|
if (retMap.dependenciesList) {
|
|
@@ -2563,7 +2598,7 @@ export const createDartBom = async (path, options) => {
|
|
|
2563
2598
|
* @param path to the project
|
|
2564
2599
|
* @param options Parse options from the cli
|
|
2565
2600
|
*/
|
|
2566
|
-
export const createCppBom =
|
|
2601
|
+
export const createCppBom = (path, options) => {
|
|
2567
2602
|
const conanLockFiles = getAllFiles(
|
|
2568
2603
|
path,
|
|
2569
2604
|
(options.multiProject ? "**/" : "") + "conan.lock"
|
|
@@ -2732,7 +2767,7 @@ export const createClojureBom = (path, options) => {
|
|
|
2732
2767
|
* @param path to the project
|
|
2733
2768
|
* @param options Parse options from the cli
|
|
2734
2769
|
*/
|
|
2735
|
-
export const createHaskellBom =
|
|
2770
|
+
export const createHaskellBom = (path, options) => {
|
|
2736
2771
|
const cabalFiles = getAllFiles(
|
|
2737
2772
|
path,
|
|
2738
2773
|
(options.multiProject ? "**/" : "") + "cabal.project.freeze"
|
|
@@ -2763,7 +2798,7 @@ export const createHaskellBom = async (path, options) => {
|
|
|
2763
2798
|
* @param path to the project
|
|
2764
2799
|
* @param options Parse options from the cli
|
|
2765
2800
|
*/
|
|
2766
|
-
export const createElixirBom =
|
|
2801
|
+
export const createElixirBom = (path, options) => {
|
|
2767
2802
|
const mixFiles = getAllFiles(
|
|
2768
2803
|
path,
|
|
2769
2804
|
(options.multiProject ? "**/" : "") + "mix.lock"
|
|
@@ -2794,7 +2829,7 @@ export const createElixirBom = async (path, options) => {
|
|
|
2794
2829
|
* @param path to the project
|
|
2795
2830
|
* @param options Parse options from the cli
|
|
2796
2831
|
*/
|
|
2797
|
-
export const createGitHubBom =
|
|
2832
|
+
export const createGitHubBom = (path, options) => {
|
|
2798
2833
|
const ghactionFiles = getAllFiles(path, ".github/workflows/" + "*.yml");
|
|
2799
2834
|
let pkgList = [];
|
|
2800
2835
|
if (ghactionFiles.length) {
|
|
@@ -2822,7 +2857,7 @@ export const createGitHubBom = async (path, options) => {
|
|
|
2822
2857
|
* @param path to the project
|
|
2823
2858
|
* @param options Parse options from the cli
|
|
2824
2859
|
*/
|
|
2825
|
-
export const createCloudBuildBom =
|
|
2860
|
+
export const createCloudBuildBom = (path, options) => {
|
|
2826
2861
|
const cbFiles = getAllFiles(path, "cloudbuild.yml");
|
|
2827
2862
|
let pkgList = [];
|
|
2828
2863
|
if (cbFiles.length) {
|
|
@@ -2943,7 +2978,7 @@ export const createJenkinsBom = async (path, options) => {
|
|
|
2943
2978
|
* @param path to the project
|
|
2944
2979
|
* @param options Parse options from the cli
|
|
2945
2980
|
*/
|
|
2946
|
-
export const createHelmBom =
|
|
2981
|
+
export const createHelmBom = (path, options) => {
|
|
2947
2982
|
let pkgList = [];
|
|
2948
2983
|
const yamlFiles = getAllFiles(
|
|
2949
2984
|
path,
|
|
@@ -2990,7 +3025,7 @@ export const createSwiftBom = (path, options) => {
|
|
|
2990
3025
|
if (pkgResolvedFiles.length) {
|
|
2991
3026
|
for (const f of pkgResolvedFiles) {
|
|
2992
3027
|
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
2993
|
-
parentComponent = createDefaultParentComponent(f);
|
|
3028
|
+
parentComponent = createDefaultParentComponent(f, "swift");
|
|
2994
3029
|
}
|
|
2995
3030
|
if (DEBUG_MODE) {
|
|
2996
3031
|
console.log("Parsing", f);
|
|
@@ -3618,13 +3653,15 @@ export const trimComponents = (components, format) => {
|
|
|
3618
3653
|
const filteredComponents = [];
|
|
3619
3654
|
for (const comp of components) {
|
|
3620
3655
|
if (format === "xml" && comp.component) {
|
|
3621
|
-
|
|
3622
|
-
|
|
3656
|
+
const key = comp.component.purl || comp.component["bom-ref"];
|
|
3657
|
+
if (!keyCache[key]) {
|
|
3658
|
+
keyCache[key] = true;
|
|
3623
3659
|
filteredComponents.push(comp);
|
|
3624
3660
|
}
|
|
3625
3661
|
} else {
|
|
3626
|
-
|
|
3627
|
-
|
|
3662
|
+
const key = comp.purl || comp["bom-ref"];
|
|
3663
|
+
if (!keyCache[key]) {
|
|
3664
|
+
keyCache[key] = true;
|
|
3628
3665
|
filteredComponents.push(comp);
|
|
3629
3666
|
}
|
|
3630
3667
|
}
|
|
@@ -3670,7 +3707,7 @@ export const dedupeBom = (
|
|
|
3670
3707
|
),
|
|
3671
3708
|
bomJson: {
|
|
3672
3709
|
bomFormat: "CycloneDX",
|
|
3673
|
-
specVersion: "1.5
|
|
3710
|
+
specVersion: "" + (options.specVersion || 1.5),
|
|
3674
3711
|
serialNumber: serialNum,
|
|
3675
3712
|
version: 1,
|
|
3676
3713
|
metadata: addMetadata(parentComponent, "json", options),
|
|
@@ -3692,7 +3729,8 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3692
3729
|
let dependencies = [];
|
|
3693
3730
|
let componentsXmls = [];
|
|
3694
3731
|
let bomData = undefined;
|
|
3695
|
-
let parentComponent = determineParentComponent(options);
|
|
3732
|
+
let parentComponent = determineParentComponent(options) || {};
|
|
3733
|
+
let parentSubComponents = [];
|
|
3696
3734
|
if (
|
|
3697
3735
|
["docker", "oci", "container"].includes(options.projectType) &&
|
|
3698
3736
|
options.allLayersExplodedDir
|
|
@@ -3743,15 +3781,31 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3743
3781
|
}
|
|
3744
3782
|
components = components.concat(bomData.bomJson.components);
|
|
3745
3783
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3746
|
-
if (
|
|
3747
|
-
|
|
3784
|
+
if (
|
|
3785
|
+
bomData.parentComponent &&
|
|
3786
|
+
Object.keys(bomData.parentComponent).length
|
|
3787
|
+
) {
|
|
3788
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3789
|
+
}
|
|
3790
|
+
if (
|
|
3791
|
+
bomData.parentComponent.components &&
|
|
3792
|
+
bomData.parentComponent.components.length
|
|
3793
|
+
) {
|
|
3794
|
+
parentSubComponents = parentSubComponents.concat(
|
|
3795
|
+
bomData.parentComponent.components
|
|
3796
|
+
);
|
|
3748
3797
|
}
|
|
3749
3798
|
componentsXmls = componentsXmls.concat(
|
|
3750
3799
|
listComponents(options, {}, bomData.bomJson.components, "npm", "xml")
|
|
3751
3800
|
);
|
|
3752
3801
|
}
|
|
3753
3802
|
bomData = await createJavaBom(path, options);
|
|
3754
|
-
if (
|
|
3803
|
+
if (
|
|
3804
|
+
bomData &&
|
|
3805
|
+
bomData.bomJson &&
|
|
3806
|
+
bomData.bomJson.components &&
|
|
3807
|
+
bomData.bomJson.components.length
|
|
3808
|
+
) {
|
|
3755
3809
|
if (DEBUG_MODE) {
|
|
3756
3810
|
console.log(
|
|
3757
3811
|
`Found ${bomData.bomJson.components.length} java packages at ${path}`
|
|
@@ -3759,15 +3813,23 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3759
3813
|
}
|
|
3760
3814
|
components = components.concat(bomData.bomJson.components);
|
|
3761
3815
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3762
|
-
if (
|
|
3763
|
-
|
|
3816
|
+
if (
|
|
3817
|
+
bomData.parentComponent &&
|
|
3818
|
+
Object.keys(bomData.parentComponent).length
|
|
3819
|
+
) {
|
|
3820
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3764
3821
|
}
|
|
3765
3822
|
componentsXmls = componentsXmls.concat(
|
|
3766
3823
|
listComponents(options, {}, bomData.bomJson.components, "maven", "xml")
|
|
3767
3824
|
);
|
|
3768
3825
|
}
|
|
3769
3826
|
bomData = await createPythonBom(path, options);
|
|
3770
|
-
if (
|
|
3827
|
+
if (
|
|
3828
|
+
bomData &&
|
|
3829
|
+
bomData.bomJson &&
|
|
3830
|
+
bomData.bomJson.components &&
|
|
3831
|
+
bomData.bomJson.components.length
|
|
3832
|
+
) {
|
|
3771
3833
|
if (DEBUG_MODE) {
|
|
3772
3834
|
console.log(
|
|
3773
3835
|
`Found ${bomData.bomJson.components.length} python packages at ${path}`
|
|
@@ -3775,15 +3837,23 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3775
3837
|
}
|
|
3776
3838
|
components = components.concat(bomData.bomJson.components);
|
|
3777
3839
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3778
|
-
if (
|
|
3779
|
-
|
|
3840
|
+
if (
|
|
3841
|
+
bomData.parentComponent &&
|
|
3842
|
+
Object.keys(bomData.parentComponent).length
|
|
3843
|
+
) {
|
|
3844
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3780
3845
|
}
|
|
3781
3846
|
componentsXmls = componentsXmls.concat(
|
|
3782
3847
|
listComponents(options, {}, bomData.bomJson.components, "pypi", "xml")
|
|
3783
3848
|
);
|
|
3784
3849
|
}
|
|
3785
3850
|
bomData = await createGoBom(path, options);
|
|
3786
|
-
if (
|
|
3851
|
+
if (
|
|
3852
|
+
bomData &&
|
|
3853
|
+
bomData.bomJson &&
|
|
3854
|
+
bomData.bomJson.components &&
|
|
3855
|
+
bomData.bomJson.components.length
|
|
3856
|
+
) {
|
|
3787
3857
|
if (DEBUG_MODE) {
|
|
3788
3858
|
console.log(
|
|
3789
3859
|
`Found ${bomData.bomJson.components.length} go packages at ${path}`
|
|
@@ -3791,8 +3861,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3791
3861
|
}
|
|
3792
3862
|
components = components.concat(bomData.bomJson.components);
|
|
3793
3863
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3794
|
-
if (
|
|
3795
|
-
|
|
3864
|
+
if (
|
|
3865
|
+
bomData.parentComponent &&
|
|
3866
|
+
Object.keys(bomData.parentComponent).length
|
|
3867
|
+
) {
|
|
3868
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3796
3869
|
}
|
|
3797
3870
|
componentsXmls = componentsXmls.concat(
|
|
3798
3871
|
listComponents(options, {}, bomData.bomJson.components, "golang", "xml")
|
|
@@ -3807,8 +3880,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3807
3880
|
}
|
|
3808
3881
|
components = components.concat(bomData.bomJson.components);
|
|
3809
3882
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3810
|
-
if (
|
|
3811
|
-
|
|
3883
|
+
if (
|
|
3884
|
+
bomData.parentComponent &&
|
|
3885
|
+
Object.keys(bomData.parentComponent).length
|
|
3886
|
+
) {
|
|
3887
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3812
3888
|
}
|
|
3813
3889
|
componentsXmls = componentsXmls.concat(
|
|
3814
3890
|
listComponents(options, {}, bomData.bomJson.components, "cargo", "xml")
|
|
@@ -3823,8 +3899,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3823
3899
|
}
|
|
3824
3900
|
components = components.concat(bomData.bomJson.components);
|
|
3825
3901
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3826
|
-
if (
|
|
3827
|
-
|
|
3902
|
+
if (
|
|
3903
|
+
bomData.parentComponent &&
|
|
3904
|
+
Object.keys(bomData.parentComponent).length
|
|
3905
|
+
) {
|
|
3906
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3828
3907
|
}
|
|
3829
3908
|
componentsXmls = componentsXmls.concat(
|
|
3830
3909
|
listComponents(
|
|
@@ -3845,8 +3924,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3845
3924
|
}
|
|
3846
3925
|
components = components.concat(bomData.bomJson.components);
|
|
3847
3926
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3848
|
-
if (
|
|
3849
|
-
|
|
3927
|
+
if (
|
|
3928
|
+
bomData.parentComponent &&
|
|
3929
|
+
Object.keys(bomData.parentComponent).length
|
|
3930
|
+
) {
|
|
3931
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3850
3932
|
}
|
|
3851
3933
|
componentsXmls = componentsXmls.concat(
|
|
3852
3934
|
listComponents(options, {}, bomData.bomJson.components, "gem", "xml")
|
|
@@ -3861,8 +3943,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3861
3943
|
}
|
|
3862
3944
|
components = components.concat(bomData.bomJson.components);
|
|
3863
3945
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3864
|
-
if (
|
|
3865
|
-
|
|
3946
|
+
if (
|
|
3947
|
+
bomData.parentComponent &&
|
|
3948
|
+
Object.keys(bomData.parentComponent).length
|
|
3949
|
+
) {
|
|
3950
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3866
3951
|
}
|
|
3867
3952
|
componentsXmls = componentsXmls.concat(
|
|
3868
3953
|
listComponents(options, {}, bomData.bomJson.components, "nuget", "xml")
|
|
@@ -3877,14 +3962,17 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3877
3962
|
}
|
|
3878
3963
|
components = components.concat(bomData.bomJson.components);
|
|
3879
3964
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3880
|
-
if (
|
|
3881
|
-
|
|
3965
|
+
if (
|
|
3966
|
+
bomData.parentComponent &&
|
|
3967
|
+
Object.keys(bomData.parentComponent).length
|
|
3968
|
+
) {
|
|
3969
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3882
3970
|
}
|
|
3883
3971
|
componentsXmls = componentsXmls.concat(
|
|
3884
3972
|
listComponents(options, {}, bomData.bomJson.components, "pub", "xml")
|
|
3885
3973
|
);
|
|
3886
3974
|
}
|
|
3887
|
-
bomData =
|
|
3975
|
+
bomData = createHaskellBom(path, options);
|
|
3888
3976
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3889
3977
|
if (DEBUG_MODE) {
|
|
3890
3978
|
console.log(
|
|
@@ -3893,8 +3981,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3893
3981
|
}
|
|
3894
3982
|
components = components.concat(bomData.bomJson.components);
|
|
3895
3983
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3896
|
-
if (
|
|
3897
|
-
|
|
3984
|
+
if (
|
|
3985
|
+
bomData.parentComponent &&
|
|
3986
|
+
Object.keys(bomData.parentComponent).length
|
|
3987
|
+
) {
|
|
3988
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3898
3989
|
}
|
|
3899
3990
|
componentsXmls = componentsXmls.concat(
|
|
3900
3991
|
listComponents(
|
|
@@ -3906,7 +3997,7 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3906
3997
|
)
|
|
3907
3998
|
);
|
|
3908
3999
|
}
|
|
3909
|
-
bomData =
|
|
4000
|
+
bomData = createElixirBom(path, options);
|
|
3910
4001
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3911
4002
|
if (DEBUG_MODE) {
|
|
3912
4003
|
console.log(
|
|
@@ -3915,14 +4006,17 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3915
4006
|
}
|
|
3916
4007
|
components = components.concat(bomData.bomJson.components);
|
|
3917
4008
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3918
|
-
if (
|
|
3919
|
-
|
|
4009
|
+
if (
|
|
4010
|
+
bomData.parentComponent &&
|
|
4011
|
+
Object.keys(bomData.parentComponent).length
|
|
4012
|
+
) {
|
|
4013
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3920
4014
|
}
|
|
3921
4015
|
componentsXmls = componentsXmls.concat(
|
|
3922
4016
|
listComponents(options, {}, bomData.bomJson.components, "hex", "xml")
|
|
3923
4017
|
);
|
|
3924
4018
|
}
|
|
3925
|
-
bomData =
|
|
4019
|
+
bomData = createCppBom(path, options);
|
|
3926
4020
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3927
4021
|
if (DEBUG_MODE) {
|
|
3928
4022
|
console.log(
|
|
@@ -3931,8 +4025,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3931
4025
|
}
|
|
3932
4026
|
components = components.concat(bomData.bomJson.components);
|
|
3933
4027
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3934
|
-
if (
|
|
3935
|
-
|
|
4028
|
+
if (
|
|
4029
|
+
bomData.parentComponent &&
|
|
4030
|
+
Object.keys(bomData.parentComponent).length
|
|
4031
|
+
) {
|
|
4032
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3936
4033
|
}
|
|
3937
4034
|
componentsXmls = componentsXmls.concat(
|
|
3938
4035
|
listComponents(options, {}, bomData.bomJson.components, "conan", "xml")
|
|
@@ -3947,8 +4044,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3947
4044
|
}
|
|
3948
4045
|
components = components.concat(bomData.bomJson.components);
|
|
3949
4046
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3950
|
-
if (
|
|
3951
|
-
|
|
4047
|
+
if (
|
|
4048
|
+
bomData.parentComponent &&
|
|
4049
|
+
Object.keys(bomData.parentComponent).length
|
|
4050
|
+
) {
|
|
4051
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3952
4052
|
}
|
|
3953
4053
|
componentsXmls = componentsXmls.concat(
|
|
3954
4054
|
listComponents(
|
|
@@ -3960,7 +4060,7 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3960
4060
|
)
|
|
3961
4061
|
);
|
|
3962
4062
|
}
|
|
3963
|
-
bomData =
|
|
4063
|
+
bomData = createGitHubBom(path, options);
|
|
3964
4064
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3965
4065
|
if (DEBUG_MODE) {
|
|
3966
4066
|
console.log(
|
|
@@ -3969,14 +4069,17 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3969
4069
|
}
|
|
3970
4070
|
components = components.concat(bomData.bomJson.components);
|
|
3971
4071
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3972
|
-
if (
|
|
3973
|
-
|
|
4072
|
+
if (
|
|
4073
|
+
bomData.parentComponent &&
|
|
4074
|
+
Object.keys(bomData.parentComponent).length
|
|
4075
|
+
) {
|
|
4076
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3974
4077
|
}
|
|
3975
4078
|
componentsXmls = componentsXmls.concat(
|
|
3976
4079
|
listComponents(options, {}, bomData.bomJson.components, "github", "xml")
|
|
3977
4080
|
);
|
|
3978
4081
|
}
|
|
3979
|
-
bomData =
|
|
4082
|
+
bomData = createCloudBuildBom(path, options);
|
|
3980
4083
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3981
4084
|
if (DEBUG_MODE) {
|
|
3982
4085
|
console.log(
|
|
@@ -3985,8 +4088,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
3985
4088
|
}
|
|
3986
4089
|
components = components.concat(bomData.bomJson.components);
|
|
3987
4090
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
3988
|
-
if (
|
|
3989
|
-
|
|
4091
|
+
if (
|
|
4092
|
+
bomData.parentComponent &&
|
|
4093
|
+
Object.keys(bomData.parentComponent).length
|
|
4094
|
+
) {
|
|
4095
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
3990
4096
|
}
|
|
3991
4097
|
componentsXmls = componentsXmls.concat(
|
|
3992
4098
|
listComponents(
|
|
@@ -4012,8 +4118,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4012
4118
|
}
|
|
4013
4119
|
components = components.concat(bomData.bomJson.components);
|
|
4014
4120
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
4015
|
-
if (
|
|
4016
|
-
|
|
4121
|
+
if (
|
|
4122
|
+
bomData.parentComponent &&
|
|
4123
|
+
Object.keys(bomData.parentComponent).length
|
|
4124
|
+
) {
|
|
4125
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
4017
4126
|
}
|
|
4018
4127
|
componentsXmls = componentsXmls.concat(
|
|
4019
4128
|
listComponents(options, {}, bomData.bomJson.components, "swift", "xml")
|
|
@@ -4030,8 +4139,11 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4030
4139
|
}
|
|
4031
4140
|
components = components.concat(bomData.bomJson.components);
|
|
4032
4141
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
4033
|
-
if (
|
|
4034
|
-
|
|
4142
|
+
if (
|
|
4143
|
+
bomData.parentComponent &&
|
|
4144
|
+
Object.keys(bomData.parentComponent).length
|
|
4145
|
+
) {
|
|
4146
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
4035
4147
|
}
|
|
4036
4148
|
componentsXmls = componentsXmls.concat(
|
|
4037
4149
|
listComponents(options, {}, bomData.bomJson.components, "maven", "xml")
|
|
@@ -4048,14 +4160,36 @@ export const createMultiXBom = async (pathList, options) => {
|
|
|
4048
4160
|
}
|
|
4049
4161
|
components = components.concat(bomData.bomJson.components);
|
|
4050
4162
|
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
4051
|
-
if (
|
|
4052
|
-
|
|
4163
|
+
if (
|
|
4164
|
+
bomData.parentComponent &&
|
|
4165
|
+
Object.keys(bomData.parentComponent).length
|
|
4166
|
+
) {
|
|
4167
|
+
parentSubComponents.push(bomData.parentComponent);
|
|
4053
4168
|
}
|
|
4054
4169
|
componentsXmls = componentsXmls.concat(
|
|
4055
4170
|
listComponents(options, {}, bomData.bomJson.components, "maven", "xml")
|
|
4056
4171
|
);
|
|
4057
4172
|
}
|
|
4058
4173
|
}
|
|
4174
|
+
// Retain the components of parent component
|
|
4175
|
+
if (parentSubComponents.length) {
|
|
4176
|
+
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
4177
|
+
parentComponent = parentSubComponents[0];
|
|
4178
|
+
}
|
|
4179
|
+
// Our naive approach to appending to sub-components could result in same parent being included as a child
|
|
4180
|
+
// This is filtered out here
|
|
4181
|
+
parentSubComponents = parentSubComponents.filter(
|
|
4182
|
+
(c) => c["bom-ref"] !== parentComponent["bom-ref"]
|
|
4183
|
+
);
|
|
4184
|
+
parentComponent.components = trimComponents(parentSubComponents, "json");
|
|
4185
|
+
if (
|
|
4186
|
+
parentComponent.components.length == 1 &&
|
|
4187
|
+
parentComponent.components[0].name == parentComponent.name
|
|
4188
|
+
) {
|
|
4189
|
+
parentComponent = parentComponent.components[0];
|
|
4190
|
+
delete parentComponent.components;
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4059
4193
|
return dedupeBom(
|
|
4060
4194
|
options,
|
|
4061
4195
|
components,
|
|
@@ -4213,7 +4347,7 @@ export const createXBom = async (path, options) => {
|
|
|
4213
4347
|
(options.multiProject ? "**/" : "") + "cabal.project.freeze"
|
|
4214
4348
|
);
|
|
4215
4349
|
if (hackageFiles.length) {
|
|
4216
|
-
return
|
|
4350
|
+
return createHaskellBom(path, options);
|
|
4217
4351
|
}
|
|
4218
4352
|
|
|
4219
4353
|
// Elixir
|
|
@@ -4222,7 +4356,7 @@ export const createXBom = async (path, options) => {
|
|
|
4222
4356
|
(options.multiProject ? "**/" : "") + "mix.lock"
|
|
4223
4357
|
);
|
|
4224
4358
|
if (mixFiles.length) {
|
|
4225
|
-
return
|
|
4359
|
+
return createElixirBom(path, options);
|
|
4226
4360
|
}
|
|
4227
4361
|
|
|
4228
4362
|
// cpp
|
|
@@ -4235,7 +4369,7 @@ export const createXBom = async (path, options) => {
|
|
|
4235
4369
|
(options.multiProject ? "**/" : "") + "conanfile.txt"
|
|
4236
4370
|
);
|
|
4237
4371
|
if (conanLockFiles.length || conanFiles.length) {
|
|
4238
|
-
return
|
|
4372
|
+
return createCppBom(path, options);
|
|
4239
4373
|
}
|
|
4240
4374
|
|
|
4241
4375
|
// clojure
|
|
@@ -4254,7 +4388,7 @@ export const createXBom = async (path, options) => {
|
|
|
4254
4388
|
// GitHub actions
|
|
4255
4389
|
const ghactionFiles = getAllFiles(path, ".github/workflows/" + "*.yml");
|
|
4256
4390
|
if (ghactionFiles.length) {
|
|
4257
|
-
return
|
|
4391
|
+
return createGitHubBom(path, options);
|
|
4258
4392
|
}
|
|
4259
4393
|
|
|
4260
4394
|
// Jenkins plugins
|
|
@@ -4276,7 +4410,7 @@ export const createXBom = async (path, options) => {
|
|
|
4276
4410
|
(options.multiProject ? "**/" : "") + "values.yaml"
|
|
4277
4411
|
);
|
|
4278
4412
|
if (chartFiles.length || yamlFiles.length) {
|
|
4279
|
-
return
|
|
4413
|
+
return createHelmBom(path, options);
|
|
4280
4414
|
}
|
|
4281
4415
|
|
|
4282
4416
|
// Docker compose, kubernetes and skaffold
|
|
@@ -4302,7 +4436,7 @@ export const createXBom = async (path, options) => {
|
|
|
4302
4436
|
(options.multiProject ? "**/" : "") + "cloudbuild.yaml"
|
|
4303
4437
|
);
|
|
4304
4438
|
if (cbFiles.length) {
|
|
4305
|
-
return
|
|
4439
|
+
return createCloudBuildBom(path, options);
|
|
4306
4440
|
}
|
|
4307
4441
|
|
|
4308
4442
|
// Swift
|
|
@@ -4505,18 +4639,18 @@ export const createBom = async (path, options) => {
|
|
|
4505
4639
|
case "hackage":
|
|
4506
4640
|
case "cabal":
|
|
4507
4641
|
options.multiProject = true;
|
|
4508
|
-
return
|
|
4642
|
+
return createHaskellBom(path, options);
|
|
4509
4643
|
case "elixir":
|
|
4510
4644
|
case "hex":
|
|
4511
4645
|
case "mix":
|
|
4512
4646
|
options.multiProject = true;
|
|
4513
|
-
return
|
|
4647
|
+
return createElixirBom(path, options);
|
|
4514
4648
|
case "c":
|
|
4515
4649
|
case "cpp":
|
|
4516
4650
|
case "c++":
|
|
4517
4651
|
case "conan":
|
|
4518
4652
|
options.multiProject = true;
|
|
4519
|
-
return
|
|
4653
|
+
return createCppBom(path, options);
|
|
4520
4654
|
case "clojure":
|
|
4521
4655
|
case "edn":
|
|
4522
4656
|
case "clj":
|
|
@@ -4526,7 +4660,7 @@ export const createBom = async (path, options) => {
|
|
|
4526
4660
|
case "github":
|
|
4527
4661
|
case "actions":
|
|
4528
4662
|
options.multiProject = true;
|
|
4529
|
-
return
|
|
4663
|
+
return createGitHubBom(path, options);
|
|
4530
4664
|
case "os":
|
|
4531
4665
|
case "osquery":
|
|
4532
4666
|
case "windows":
|
|
@@ -4539,11 +4673,11 @@ export const createBom = async (path, options) => {
|
|
|
4539
4673
|
case "helm":
|
|
4540
4674
|
case "charts":
|
|
4541
4675
|
options.multiProject = true;
|
|
4542
|
-
return
|
|
4676
|
+
return createHelmBom(path, options);
|
|
4543
4677
|
case "helm-index":
|
|
4544
4678
|
case "helm-repo":
|
|
4545
4679
|
options.multiProject = true;
|
|
4546
|
-
return
|
|
4680
|
+
return createHelmBom(
|
|
4547
4681
|
join(homedir(), ".cache", "helm", "repository"),
|
|
4548
4682
|
options
|
|
4549
4683
|
);
|
|
@@ -4561,7 +4695,7 @@ export const createBom = async (path, options) => {
|
|
|
4561
4695
|
return await createContainerSpecLikeBom(path, options);
|
|
4562
4696
|
case "cloudbuild":
|
|
4563
4697
|
options.multiProject = true;
|
|
4564
|
-
return
|
|
4698
|
+
return createCloudBuildBom(path, options);
|
|
4565
4699
|
case "swift":
|
|
4566
4700
|
options.multiProject = true;
|
|
4567
4701
|
return createSwiftBom(path, options);
|
|
@@ -4658,38 +4792,3 @@ export async function submitBom(args, bomContents) {
|
|
|
4658
4792
|
}
|
|
4659
4793
|
}
|
|
4660
4794
|
}
|
|
4661
|
-
|
|
4662
|
-
/**
|
|
4663
|
-
* Validate the generated bom using jsonschema
|
|
4664
|
-
*
|
|
4665
|
-
* @param {object} bomJson content
|
|
4666
|
-
*/
|
|
4667
|
-
export const validateBom = (bomJson) => {
|
|
4668
|
-
if (!bomJson) {
|
|
4669
|
-
return true;
|
|
4670
|
-
}
|
|
4671
|
-
const schema = JSON.parse(
|
|
4672
|
-
readFileSync(join(dirName, "data", "bom-1.5.schema.json"))
|
|
4673
|
-
);
|
|
4674
|
-
const defsSchema = JSON.parse(
|
|
4675
|
-
readFileSync(join(dirName, "data", "jsf-0.82.schema.json"))
|
|
4676
|
-
);
|
|
4677
|
-
const spdxSchema = JSON.parse(
|
|
4678
|
-
readFileSync(join(dirName, "data", "spdx.schema.json"))
|
|
4679
|
-
);
|
|
4680
|
-
const ajv = new Ajv({
|
|
4681
|
-
schemas: [schema, defsSchema, spdxSchema],
|
|
4682
|
-
strict: false,
|
|
4683
|
-
logger: false
|
|
4684
|
-
});
|
|
4685
|
-
addFormats(ajv);
|
|
4686
|
-
const validate = ajv.getSchema(
|
|
4687
|
-
"http://cyclonedx.org/schema/bom-1.5.schema.json"
|
|
4688
|
-
);
|
|
4689
|
-
const isValid = validate(bomJson);
|
|
4690
|
-
if (!isValid) {
|
|
4691
|
-
console.log(validate.errors);
|
|
4692
|
-
return false;
|
|
4693
|
-
}
|
|
4694
|
-
return true;
|
|
4695
|
-
};
|