@cyclonedx/cdxgen 9.0.1 → 9.1.1
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 +64 -25
- package/analyzer.js +1 -1
- package/bin/cdxgen.js +18 -24
- package/binary.js +7 -7
- package/data/bom-1.5.schema.json +3660 -0
- package/data/jsf-0.82.schema.json +211 -0
- package/data/pypi-pkg-aliases.json +84 -77
- package/data/spdx.schema.json +621 -0
- package/display.js +102 -0
- package/display.test.js +10 -0
- package/docker.js +12 -24
- package/docker.test.js +1 -1
- package/index.js +316 -300
- package/package.json +5 -3
- package/piptree.js +136 -0
- package/server.js +2 -2
- package/utils.js +500 -218
- package/utils.test.js +301 -35
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import Ajv from "ajv";
|
|
2
|
+
import addFormats from "ajv-formats";
|
|
1
3
|
import { platform as _platform, homedir, tmpdir } from "node:os";
|
|
2
|
-
import { join, dirname, sep } from "node:path";
|
|
4
|
+
import { basename, join, dirname, sep } from "node:path";
|
|
3
5
|
import { parse } from "ssri";
|
|
4
6
|
import {
|
|
7
|
+
lstatSync,
|
|
5
8
|
mkdtempSync,
|
|
6
9
|
rmSync,
|
|
7
10
|
existsSync,
|
|
@@ -50,7 +53,7 @@ import {
|
|
|
50
53
|
parseBdistMetadata,
|
|
51
54
|
readZipEntry,
|
|
52
55
|
parsePiplockData,
|
|
53
|
-
|
|
56
|
+
getPipFrozenTree,
|
|
54
57
|
parseReqFile,
|
|
55
58
|
getPyModules,
|
|
56
59
|
parseSetupPyFile,
|
|
@@ -148,7 +151,7 @@ if (process.env.SWIFT_CMD) {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
// Construct sbt cache directory
|
|
151
|
-
|
|
154
|
+
const SBT_CACHE_DIR =
|
|
152
155
|
process.env.SBT_CACHE_DIR || join(homedir(), ".ivy2", "cache");
|
|
153
156
|
|
|
154
157
|
// Debug mode flag
|
|
@@ -167,7 +170,10 @@ const TIMEOUT_MS = parseInt(process.env.CDXGEN_TIMEOUT_MS) || 10 * 60 * 1000;
|
|
|
167
170
|
|
|
168
171
|
const createDefaultParentComponent = (path) => {
|
|
169
172
|
// Create a parent component based on the directory name
|
|
170
|
-
let dirName =
|
|
173
|
+
let dirName =
|
|
174
|
+
existsSync(path) && lstatSync(path).isDirectory()
|
|
175
|
+
? basename(path)
|
|
176
|
+
: dirname(path);
|
|
171
177
|
const tmpA = dirName.split(sep);
|
|
172
178
|
dirName = tmpA[tmpA.length - 1];
|
|
173
179
|
const parentComponent = {
|
|
@@ -206,55 +212,14 @@ const determineParentComponent = (options) => {
|
|
|
206
212
|
return parentComponent;
|
|
207
213
|
};
|
|
208
214
|
|
|
209
|
-
/**
|
|
210
|
-
* Method to create global external references
|
|
211
|
-
*
|
|
212
|
-
* @param pkg
|
|
213
|
-
* @returns {Array}
|
|
214
|
-
*/
|
|
215
|
-
function addGlobalReferences(src, filename, format = "xml") {
|
|
216
|
-
let externalReferences = [];
|
|
217
|
-
if (format === "json") {
|
|
218
|
-
externalReferences.push({
|
|
219
|
-
type: "other",
|
|
220
|
-
url: src,
|
|
221
|
-
comment: "Base path"
|
|
222
|
-
});
|
|
223
|
-
} else {
|
|
224
|
-
externalReferences.push({
|
|
225
|
-
reference: { "@type": "other", url: src, comment: "Base path" }
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
let packageFileMeta = filename;
|
|
229
|
-
if (!filename.includes(src)) {
|
|
230
|
-
packageFileMeta = join(src, filename);
|
|
231
|
-
}
|
|
232
|
-
if (format === "json") {
|
|
233
|
-
externalReferences.push({
|
|
234
|
-
type: "other",
|
|
235
|
-
url: packageFileMeta,
|
|
236
|
-
comment: "Package file"
|
|
237
|
-
});
|
|
238
|
-
} else {
|
|
239
|
-
externalReferences.push({
|
|
240
|
-
reference: {
|
|
241
|
-
"@type": "other",
|
|
242
|
-
url: packageFileMeta,
|
|
243
|
-
comment: "Package file"
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
return externalReferences;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
215
|
/**
|
|
251
216
|
* Function to create the services block
|
|
252
217
|
*/
|
|
253
218
|
function addServices(services, format = "xml") {
|
|
254
|
-
|
|
219
|
+
const serv_list = [];
|
|
255
220
|
for (const aserv of services) {
|
|
256
221
|
if (format === "xml") {
|
|
257
|
-
|
|
222
|
+
const service = {
|
|
258
223
|
"@bom-ref": aserv["bom-ref"],
|
|
259
224
|
group: aserv.group || "",
|
|
260
225
|
name: aserv.name,
|
|
@@ -276,9 +241,9 @@ function addServices(services, format = "xml") {
|
|
|
276
241
|
* Function to create the dependency block
|
|
277
242
|
*/
|
|
278
243
|
function addDependencies(dependencies) {
|
|
279
|
-
|
|
244
|
+
const deps_list = [];
|
|
280
245
|
for (const adep of dependencies) {
|
|
281
|
-
|
|
246
|
+
const dependsOnList = adep.dependsOn.map((v) => ({
|
|
282
247
|
"@ref": v
|
|
283
248
|
}));
|
|
284
249
|
const aentry = {
|
|
@@ -299,7 +264,7 @@ function addDependencies(dependencies) {
|
|
|
299
264
|
function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
300
265
|
// DO NOT fork this project to just change the vendor or author's name
|
|
301
266
|
// Try to contribute to this project by sending PR or filing issues
|
|
302
|
-
|
|
267
|
+
const metadata = {
|
|
303
268
|
timestamp: new Date().toISOString(),
|
|
304
269
|
tools: {
|
|
305
270
|
components: [
|
|
@@ -359,11 +324,17 @@ function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
|
359
324
|
if (parentComponent && parentComponent.components) {
|
|
360
325
|
firstPComp.components = parentComponent.components;
|
|
361
326
|
}
|
|
327
|
+
if (firstPComp.evidence) {
|
|
328
|
+
delete firstPComp.evidence;
|
|
329
|
+
}
|
|
362
330
|
metadata.component = firstPComp;
|
|
363
331
|
}
|
|
364
332
|
} else {
|
|
365
333
|
// As a fallback, retain the parent component
|
|
366
334
|
if (format === "json") {
|
|
335
|
+
if (parentComponent.evidence) {
|
|
336
|
+
delete parentComponent.evidence;
|
|
337
|
+
}
|
|
367
338
|
metadata.component = parentComponent;
|
|
368
339
|
}
|
|
369
340
|
}
|
|
@@ -508,7 +479,7 @@ function addMetadata(parentComponent = {}, format = "xml", options = {}) {
|
|
|
508
479
|
* @returns {Array}
|
|
509
480
|
*/
|
|
510
481
|
function addExternalReferences(opkg, format = "xml") {
|
|
511
|
-
|
|
482
|
+
const externalReferences = [];
|
|
512
483
|
let pkgList = [];
|
|
513
484
|
if (Array.isArray(opkg)) {
|
|
514
485
|
pkgList = opkg;
|
|
@@ -549,7 +520,7 @@ function addExternalReferences(opkg, format = "xml") {
|
|
|
549
520
|
} else {
|
|
550
521
|
if (pkg.homepage && pkg.homepage.url) {
|
|
551
522
|
externalReferences.push({
|
|
552
|
-
type: "website",
|
|
523
|
+
type: pkg.homepage.url.includes("git") ? "vcs" : "website",
|
|
553
524
|
url: pkg.homepage.url
|
|
554
525
|
});
|
|
555
526
|
}
|
|
@@ -575,17 +546,15 @@ function addExternalReferences(opkg, format = "xml") {
|
|
|
575
546
|
* For all modules in the specified package, creates a list of
|
|
576
547
|
* component objects from each one.
|
|
577
548
|
*/
|
|
578
|
-
|
|
579
|
-
export { _listComponents as listComponents };
|
|
580
|
-
function listComponents(
|
|
549
|
+
export function listComponents(
|
|
581
550
|
options,
|
|
582
551
|
allImports,
|
|
583
552
|
pkg,
|
|
584
553
|
ptype = "npm",
|
|
585
554
|
format = "xml"
|
|
586
555
|
) {
|
|
587
|
-
|
|
588
|
-
|
|
556
|
+
const compMap = {};
|
|
557
|
+
const isRootPkg = ptype === "npm";
|
|
589
558
|
if (Array.isArray(pkg)) {
|
|
590
559
|
pkg.forEach((p) => {
|
|
591
560
|
addComponent(options, allImports, p, ptype, compMap, false, format);
|
|
@@ -616,13 +585,13 @@ function addComponent(
|
|
|
616
585
|
return;
|
|
617
586
|
}
|
|
618
587
|
if (!isRootPkg) {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
588
|
+
const pkgIdentifier = parsePackageJsonName(pkg.name);
|
|
589
|
+
const author = pkg.author || "";
|
|
590
|
+
const publisher = pkg.publisher || "";
|
|
622
591
|
let group = pkg.group || pkgIdentifier.scope;
|
|
623
592
|
// Create empty group
|
|
624
593
|
group = group || "";
|
|
625
|
-
|
|
594
|
+
const name = pkgIdentifier.fullName || pkg.name || "";
|
|
626
595
|
// name is mandatory
|
|
627
596
|
if (!name) {
|
|
628
597
|
return;
|
|
@@ -640,13 +609,13 @@ function addComponent(
|
|
|
640
609
|
) {
|
|
641
610
|
return;
|
|
642
611
|
}
|
|
643
|
-
|
|
612
|
+
const version = pkg.version;
|
|
644
613
|
if (!version || ["dummy", "ignore"].includes(version)) {
|
|
645
614
|
return;
|
|
646
615
|
}
|
|
647
|
-
|
|
616
|
+
const licenses = pkg.licenses || getLicenses(pkg, format);
|
|
648
617
|
|
|
649
|
-
|
|
618
|
+
const purl =
|
|
650
619
|
pkg.purl ||
|
|
651
620
|
new PackageURL(
|
|
652
621
|
ptype,
|
|
@@ -680,7 +649,7 @@ function addComponent(
|
|
|
680
649
|
if (options.requiredOnly && ["optional", "excluded"].includes(compScope)) {
|
|
681
650
|
return;
|
|
682
651
|
}
|
|
683
|
-
|
|
652
|
+
const component = {
|
|
684
653
|
author,
|
|
685
654
|
publisher,
|
|
686
655
|
group,
|
|
@@ -709,8 +678,14 @@ function addComponent(
|
|
|
709
678
|
|
|
710
679
|
processHashes(pkg, component, format);
|
|
711
680
|
// Retain any component properties
|
|
712
|
-
if (format === "json"
|
|
713
|
-
|
|
681
|
+
if (format === "json") {
|
|
682
|
+
// Retain evidence
|
|
683
|
+
if (pkg.evidence && Object.keys(pkg.evidence).length) {
|
|
684
|
+
component.evidence = pkg.evidence;
|
|
685
|
+
}
|
|
686
|
+
if (pkg.properties && pkg.properties.length) {
|
|
687
|
+
component.properties = pkg.properties;
|
|
688
|
+
}
|
|
714
689
|
}
|
|
715
690
|
if (compMap[component.purl]) return; //remove cycles
|
|
716
691
|
compMap[component.purl] = component;
|
|
@@ -735,7 +710,7 @@ function determinePackageType(pkg) {
|
|
|
735
710
|
}
|
|
736
711
|
if (pkg.purl) {
|
|
737
712
|
try {
|
|
738
|
-
|
|
713
|
+
const purl = PackageURL.fromString(pkg.purl);
|
|
739
714
|
if (purl.type) {
|
|
740
715
|
if (["docker", "oci", "container"].includes(purl.type)) {
|
|
741
716
|
return "container";
|
|
@@ -801,7 +776,7 @@ function determinePackageType(pkg) {
|
|
|
801
776
|
}
|
|
802
777
|
}
|
|
803
778
|
if (Object.prototype.hasOwnProperty.call(pkg, "keywords")) {
|
|
804
|
-
for (
|
|
779
|
+
for (const keyword of pkg.keywords) {
|
|
805
780
|
if (keyword.toLowerCase() === "framework") {
|
|
806
781
|
return "framework";
|
|
807
782
|
}
|
|
@@ -832,7 +807,7 @@ function processHashes(pkg, component, format = "xml") {
|
|
|
832
807
|
});
|
|
833
808
|
}
|
|
834
809
|
} else if (pkg._integrity) {
|
|
835
|
-
|
|
810
|
+
const integrity = parse(pkg._integrity) || {};
|
|
836
811
|
// Components may have multiple hashes with various lengths. Check each one
|
|
837
812
|
// that is supported by the CycloneDX specification.
|
|
838
813
|
if (Object.prototype.hasOwnProperty.call(integrity, "sha512")) {
|
|
@@ -919,11 +894,6 @@ const buildBomXml = (
|
|
|
919
894
|
bom.ele("metadata").ele(metadata);
|
|
920
895
|
if (components && components.length) {
|
|
921
896
|
bom.ele("components").ele(components);
|
|
922
|
-
if (context && context.src && context.filename) {
|
|
923
|
-
bom
|
|
924
|
-
.ele("externalReferences")
|
|
925
|
-
.ele(addGlobalReferences(context.src, context.filename, "xml"));
|
|
926
|
-
}
|
|
927
897
|
if (context) {
|
|
928
898
|
if (context.services && context.services.length) {
|
|
929
899
|
bom.ele("services").ele(addServices(context.services, "xml"));
|
|
@@ -987,13 +957,6 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
987
957
|
components: listComponents(options, allImports, pkgInfo, ptype, "json"),
|
|
988
958
|
dependencies
|
|
989
959
|
};
|
|
990
|
-
if (context && context.src && context.filename) {
|
|
991
|
-
jsonTpl.externalReferences = addGlobalReferences(
|
|
992
|
-
context.src,
|
|
993
|
-
context.filename,
|
|
994
|
-
"json"
|
|
995
|
-
);
|
|
996
|
-
}
|
|
997
960
|
bomNSData.bomXml = bomString;
|
|
998
961
|
bomNSData.bomJson = jsonTpl;
|
|
999
962
|
bomNSData.nsMapping = nsMapping;
|
|
@@ -1009,10 +972,7 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
1009
972
|
* @param path to the project
|
|
1010
973
|
* @param options Parse options from the cli
|
|
1011
974
|
*/
|
|
1012
|
-
const createJarBom = (path, options) => {
|
|
1013
|
-
console.log(
|
|
1014
|
-
`About to create SBoM for all jar files under ${path}. This would take a while ...`
|
|
1015
|
-
);
|
|
975
|
+
export const createJarBom = (path, options) => {
|
|
1016
976
|
let pkgList = [];
|
|
1017
977
|
let jarFiles = getAllFiles(
|
|
1018
978
|
path,
|
|
@@ -1026,8 +986,8 @@ const createJarBom = (path, options) => {
|
|
|
1026
986
|
if (hpiFiles.length) {
|
|
1027
987
|
jarFiles = jarFiles.concat(hpiFiles);
|
|
1028
988
|
}
|
|
1029
|
-
|
|
1030
|
-
for (
|
|
989
|
+
const tempDir = mkdtempSync(join(tmpdir(), "jar-deps-"));
|
|
990
|
+
for (const jar of jarFiles) {
|
|
1031
991
|
if (DEBUG_MODE) {
|
|
1032
992
|
console.log(`Parsing ${jar}`);
|
|
1033
993
|
}
|
|
@@ -1038,7 +998,6 @@ const createJarBom = (path, options) => {
|
|
|
1038
998
|
}
|
|
1039
999
|
// Clean up
|
|
1040
1000
|
if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
|
|
1041
|
-
console.log(`Cleaning up ${tempDir}`);
|
|
1042
1001
|
rmSync(tempDir, { recursive: true, force: true });
|
|
1043
1002
|
}
|
|
1044
1003
|
return buildBomNSData(options, pkgList, "maven", {
|
|
@@ -1054,7 +1013,7 @@ const createJarBom = (path, options) => {
|
|
|
1054
1013
|
* @param path to the project
|
|
1055
1014
|
* @param options Parse options from the cli
|
|
1056
1015
|
*/
|
|
1057
|
-
const createJavaBom = async (path, options) => {
|
|
1016
|
+
export const createJavaBom = async (path, options) => {
|
|
1058
1017
|
let jarNSMapping = {};
|
|
1059
1018
|
let pkgList = [];
|
|
1060
1019
|
let dependencies = [];
|
|
@@ -1068,7 +1027,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1068
1027
|
if (DEBUG_MODE) {
|
|
1069
1028
|
console.log(`Retrieving packages from ${path}`);
|
|
1070
1029
|
}
|
|
1071
|
-
|
|
1030
|
+
const tempDir = mkdtempSync(join(tmpdir(), "war-deps-"));
|
|
1072
1031
|
pkgList = extractJarArchive(path, tempDir);
|
|
1073
1032
|
if (pkgList.length) {
|
|
1074
1033
|
pkgList = await getMvnMetadata(pkgList);
|
|
@@ -1119,7 +1078,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1119
1078
|
const addArgs = process.env.MVN_ARGS.split(" ");
|
|
1120
1079
|
mvnArgs = mvnArgs.concat(addArgs);
|
|
1121
1080
|
}
|
|
1122
|
-
for (
|
|
1081
|
+
for (const f of pomFiles) {
|
|
1123
1082
|
const basePath = dirname(f);
|
|
1124
1083
|
const settingsXml = join(basePath, "settings.xml");
|
|
1125
1084
|
if (existsSync(settingsXml)) {
|
|
@@ -1127,7 +1086,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1127
1086
|
`maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`
|
|
1128
1087
|
);
|
|
1129
1088
|
}
|
|
1130
|
-
|
|
1089
|
+
const mavenCmd = getMavenCommand(basePath, path);
|
|
1131
1090
|
// Should we attempt to resolve class names
|
|
1132
1091
|
if (options.resolveClass) {
|
|
1133
1092
|
console.log(
|
|
@@ -1150,8 +1109,8 @@ const createJavaBom = async (path, options) => {
|
|
|
1150
1109
|
const bomJsonFiles = getAllFiles(path, "**/target/*.json");
|
|
1151
1110
|
const bomGenerated = bomJsonFiles.length;
|
|
1152
1111
|
if (!bomGenerated || result.status !== 0 || result.error) {
|
|
1153
|
-
|
|
1154
|
-
|
|
1112
|
+
const tempDir = mkdtempSync(join(tmpdir(), "cdxmvn-"));
|
|
1113
|
+
const tempMvnTree = join(tempDir, "mvn-tree.txt");
|
|
1155
1114
|
let mvnTreeArgs = ["dependency:tree", "-DoutputFile=" + tempMvnTree];
|
|
1156
1115
|
if (process.env.MVN_ARGS) {
|
|
1157
1116
|
const addArgs = process.env.MVN_ARGS.split(" ");
|
|
@@ -1281,18 +1240,18 @@ const createJavaBom = async (path, options) => {
|
|
|
1281
1240
|
}
|
|
1282
1241
|
}
|
|
1283
1242
|
// gradle
|
|
1284
|
-
|
|
1243
|
+
const gradleFiles = getAllFiles(
|
|
1285
1244
|
path,
|
|
1286
1245
|
(options.multiProject ? "**/" : "") + "build.gradle*"
|
|
1287
1246
|
);
|
|
1288
|
-
|
|
1247
|
+
const allProjects = [];
|
|
1289
1248
|
const allProjectsAddedPurls = [];
|
|
1290
1249
|
const rootDependsOn = [];
|
|
1291
1250
|
// Execute gradle properties
|
|
1292
1251
|
if (gradleFiles && gradleFiles.length) {
|
|
1293
1252
|
let retMap = executeGradleProperties(path, null, null);
|
|
1294
1253
|
const allProjectsStr = retMap.projects || [];
|
|
1295
|
-
|
|
1254
|
+
const rootProject = retMap.rootProject;
|
|
1296
1255
|
if (rootProject) {
|
|
1297
1256
|
parentComponent = {
|
|
1298
1257
|
name: rootProject,
|
|
@@ -1314,11 +1273,11 @@ const createJavaBom = async (path, options) => {
|
|
|
1314
1273
|
}
|
|
1315
1274
|
// Get the sub-project properties and set the root dependencies
|
|
1316
1275
|
if (allProjectsStr && allProjectsStr.length) {
|
|
1317
|
-
for (
|
|
1276
|
+
for (const spstr of allProjectsStr) {
|
|
1318
1277
|
retMap = executeGradleProperties(path, null, spstr);
|
|
1319
|
-
|
|
1278
|
+
const rootSubProject = retMap.rootProject;
|
|
1320
1279
|
if (rootSubProject) {
|
|
1321
|
-
|
|
1280
|
+
const rspName = rootSubProject.replace(/^:/, "").replace(/:/, "/");
|
|
1322
1281
|
const rootSubProjectObj = {
|
|
1323
1282
|
name: rspName,
|
|
1324
1283
|
type: "application",
|
|
@@ -1356,18 +1315,22 @@ const createJavaBom = async (path, options) => {
|
|
|
1356
1315
|
}
|
|
1357
1316
|
}
|
|
1358
1317
|
if (gradleFiles && gradleFiles.length && options.installDeps) {
|
|
1359
|
-
|
|
1318
|
+
const gradleCmd = getGradleCommand(path, null);
|
|
1319
|
+
const defaultDepTaskArgs = ["-q", "--console", "plain", "--build-cache"];
|
|
1360
1320
|
allProjects.push(parentComponent);
|
|
1361
|
-
|
|
1321
|
+
let depTaskWithArgs = ["dependencies"];
|
|
1322
|
+
if (process.env.GRADLE_DEPENDENCY_TASK) {
|
|
1323
|
+
depTaskWithArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" ");
|
|
1324
|
+
}
|
|
1325
|
+
for (const sp of allProjects) {
|
|
1362
1326
|
let gradleDepArgs = [
|
|
1363
1327
|
sp.purl === parentComponent.purl
|
|
1364
|
-
?
|
|
1365
|
-
: `:${sp.name}
|
|
1366
|
-
"-q",
|
|
1367
|
-
"--console",
|
|
1368
|
-
"plain",
|
|
1369
|
-
"--build-cache"
|
|
1328
|
+
? depTaskWithArgs[0]
|
|
1329
|
+
: `:${sp.name}:${depTaskWithArgs[0]}`
|
|
1370
1330
|
];
|
|
1331
|
+
gradleDepArgs = gradleDepArgs
|
|
1332
|
+
.concat(depTaskWithArgs.slice(1))
|
|
1333
|
+
.concat(defaultDepTaskArgs);
|
|
1371
1334
|
// Support custom GRADLE_ARGS such as --configuration runtimeClassPath
|
|
1372
1335
|
if (process.env.GRADLE_ARGS) {
|
|
1373
1336
|
const addArgs = process.env.GRADLE_ARGS.split(" ");
|
|
@@ -1452,13 +1415,13 @@ const createJavaBom = async (path, options) => {
|
|
|
1452
1415
|
|
|
1453
1416
|
// Bazel
|
|
1454
1417
|
// Look for the BUILD file only in the root directory
|
|
1455
|
-
|
|
1418
|
+
const bazelFiles = getAllFiles(path, "BUILD");
|
|
1456
1419
|
if (bazelFiles && bazelFiles.length) {
|
|
1457
1420
|
let BAZEL_CMD = "bazel";
|
|
1458
1421
|
if (process.env.BAZEL_HOME) {
|
|
1459
1422
|
BAZEL_CMD = join(process.env.BAZEL_HOME, "bin", "bazel");
|
|
1460
1423
|
}
|
|
1461
|
-
for (
|
|
1424
|
+
for (const f of bazelFiles) {
|
|
1462
1425
|
const basePath = dirname(f);
|
|
1463
1426
|
// Invoke bazel build first
|
|
1464
1427
|
const bazelTarget = process.env.BAZEL_TARGET || ":all";
|
|
@@ -1500,7 +1463,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1500
1463
|
console.error(result.stdout, result.stderr);
|
|
1501
1464
|
options.failOnError && process.exit(1);
|
|
1502
1465
|
}
|
|
1503
|
-
|
|
1466
|
+
const stdout = result.stdout;
|
|
1504
1467
|
if (stdout) {
|
|
1505
1468
|
const cmdOutput = Buffer.from(stdout).toString();
|
|
1506
1469
|
const dlist = parseBazelSkyframe(cmdOutput);
|
|
@@ -1545,7 +1508,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1545
1508
|
);
|
|
1546
1509
|
|
|
1547
1510
|
let sbtProjects = [];
|
|
1548
|
-
for (
|
|
1511
|
+
for (const i in sbtProjectFiles) {
|
|
1549
1512
|
// parent dir of sbtProjectFile is the `project` directory
|
|
1550
1513
|
// parent dir of `project` is the sbt root project directory
|
|
1551
1514
|
const baseDir = dirname(dirname(sbtProjectFiles[i]));
|
|
@@ -1558,7 +1521,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1558
1521
|
path,
|
|
1559
1522
|
(options.multiProject ? "**/" : "") + "*.sbt"
|
|
1560
1523
|
);
|
|
1561
|
-
for (
|
|
1524
|
+
for (const i in sbtProjectFiles) {
|
|
1562
1525
|
const baseDir = dirname(sbtProjectFiles[i]);
|
|
1563
1526
|
sbtProjects = sbtProjects.concat(baseDir);
|
|
1564
1527
|
}
|
|
@@ -1566,7 +1529,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1566
1529
|
|
|
1567
1530
|
sbtProjects = [...new Set(sbtProjects)]; // eliminate duplicates
|
|
1568
1531
|
|
|
1569
|
-
|
|
1532
|
+
const sbtLockFiles = getAllFiles(
|
|
1570
1533
|
path,
|
|
1571
1534
|
(options.multiProject ? "**/" : "") + "build.sbt.lock"
|
|
1572
1535
|
);
|
|
@@ -1575,15 +1538,15 @@ const createJavaBom = async (path, options) => {
|
|
|
1575
1538
|
let pkgList = [];
|
|
1576
1539
|
// If the project use sbt lock files
|
|
1577
1540
|
if (sbtLockFiles && sbtLockFiles.length) {
|
|
1578
|
-
for (
|
|
1541
|
+
for (const f of sbtLockFiles) {
|
|
1579
1542
|
const dlist = parseSbtLock(f);
|
|
1580
1543
|
if (dlist && dlist.length) {
|
|
1581
1544
|
pkgList = pkgList.concat(dlist);
|
|
1582
1545
|
}
|
|
1583
1546
|
}
|
|
1584
1547
|
} else {
|
|
1585
|
-
|
|
1586
|
-
|
|
1548
|
+
const SBT_CMD = process.env.SBT_CMD || "sbt";
|
|
1549
|
+
const sbtVersion = determineSbtVersion(path);
|
|
1587
1550
|
if (DEBUG_MODE) {
|
|
1588
1551
|
console.log("Detected sbt version: " + sbtVersion);
|
|
1589
1552
|
}
|
|
@@ -1596,11 +1559,11 @@ const createJavaBom = async (path, options) => {
|
|
|
1596
1559
|
const useSlashSyntax = gte(sbtVersion, "1.5.0");
|
|
1597
1560
|
const isDependencyTreeBuiltIn =
|
|
1598
1561
|
sbtVersion != null && gte(sbtVersion, "1.4.0");
|
|
1599
|
-
|
|
1600
|
-
|
|
1562
|
+
const tempDir = mkdtempSync(join(tmpdir(), "cdxsbt-"));
|
|
1563
|
+
const tempSbtgDir = mkdtempSync(join(tmpdir(), "cdxsbtg-"));
|
|
1601
1564
|
mkdirSync(tempSbtgDir, { recursive: true });
|
|
1602
1565
|
// Create temporary plugins file
|
|
1603
|
-
|
|
1566
|
+
const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt");
|
|
1604
1567
|
|
|
1605
1568
|
// Requires a custom version of `sbt-dependency-graph` that
|
|
1606
1569
|
// supports `--append` for `toFile` subtask.
|
|
@@ -1613,9 +1576,9 @@ const createJavaBom = async (path, options) => {
|
|
|
1613
1576
|
}
|
|
1614
1577
|
writeFileSync(tempSbtPlugins, sbtPluginDefinition);
|
|
1615
1578
|
|
|
1616
|
-
for (
|
|
1579
|
+
for (const i in sbtProjects) {
|
|
1617
1580
|
const basePath = sbtProjects[i];
|
|
1618
|
-
|
|
1581
|
+
const dlFile = join(tempDir, "dl-" + i + ".tmp");
|
|
1619
1582
|
console.log(
|
|
1620
1583
|
"Executing",
|
|
1621
1584
|
SBT_CMD,
|
|
@@ -1624,8 +1587,8 @@ const createJavaBom = async (path, options) => {
|
|
|
1624
1587
|
"using plugins",
|
|
1625
1588
|
tempSbtgDir
|
|
1626
1589
|
);
|
|
1627
|
-
|
|
1628
|
-
|
|
1590
|
+
let sbtArgs = [];
|
|
1591
|
+
let pluginFile = null;
|
|
1629
1592
|
if (standalonePluginFile) {
|
|
1630
1593
|
sbtArgs = [
|
|
1631
1594
|
`-addPluginSbtFile=${tempSbtPlugins}`,
|
|
@@ -1709,7 +1672,7 @@ const createJavaBom = async (path, options) => {
|
|
|
1709
1672
|
* @param path to the project
|
|
1710
1673
|
* @param options Parse options from the cli
|
|
1711
1674
|
*/
|
|
1712
|
-
const createNodejsBom = async (path, options) => {
|
|
1675
|
+
export const createNodejsBom = async (path, options) => {
|
|
1713
1676
|
let pkgList = [];
|
|
1714
1677
|
let manifestFiles = [];
|
|
1715
1678
|
let dependencies = [];
|
|
@@ -1720,7 +1683,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1720
1683
|
const pkgJsonFiles = getAllFiles(path, "**/package.json");
|
|
1721
1684
|
// Are there any package.json files in the container?
|
|
1722
1685
|
if (pkgJsonFiles.length) {
|
|
1723
|
-
for (
|
|
1686
|
+
for (const pj of pkgJsonFiles) {
|
|
1724
1687
|
const dlist = await parsePkgJson(pj);
|
|
1725
1688
|
if (dlist && dlist.length) {
|
|
1726
1689
|
pkgList = pkgList.concat(dlist);
|
|
@@ -1776,7 +1739,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1776
1739
|
// Parse min js files
|
|
1777
1740
|
if (minJsFiles && minJsFiles.length) {
|
|
1778
1741
|
manifestFiles = manifestFiles.concat(minJsFiles);
|
|
1779
|
-
for (
|
|
1742
|
+
for (const f of minJsFiles) {
|
|
1780
1743
|
const dlist = await parseMinJs(f);
|
|
1781
1744
|
if (dlist && dlist.length) {
|
|
1782
1745
|
pkgList = pkgList.concat(dlist);
|
|
@@ -1786,7 +1749,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1786
1749
|
// Parse bower json files
|
|
1787
1750
|
if (bowerFiles && bowerFiles.length) {
|
|
1788
1751
|
manifestFiles = manifestFiles.concat(bowerFiles);
|
|
1789
|
-
for (
|
|
1752
|
+
for (const f of bowerFiles) {
|
|
1790
1753
|
const dlist = await parseBowerJson(f);
|
|
1791
1754
|
if (dlist && dlist.length) {
|
|
1792
1755
|
pkgList = pkgList.concat(dlist);
|
|
@@ -1795,7 +1758,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1795
1758
|
}
|
|
1796
1759
|
if (pnpmLockFiles && pnpmLockFiles.length) {
|
|
1797
1760
|
manifestFiles = manifestFiles.concat(pnpmLockFiles);
|
|
1798
|
-
for (
|
|
1761
|
+
for (const f of pnpmLockFiles) {
|
|
1799
1762
|
const basePath = dirname(f);
|
|
1800
1763
|
// Determine the parent component
|
|
1801
1764
|
const packageJsonF = join(basePath, "package.json");
|
|
@@ -1841,7 +1804,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1841
1804
|
}
|
|
1842
1805
|
if (pkgLockFiles && pkgLockFiles.length) {
|
|
1843
1806
|
manifestFiles = manifestFiles.concat(pkgLockFiles);
|
|
1844
|
-
for (
|
|
1807
|
+
for (const f of pkgLockFiles) {
|
|
1845
1808
|
if (DEBUG_MODE) {
|
|
1846
1809
|
console.log(`Parsing ${f}`);
|
|
1847
1810
|
}
|
|
@@ -1917,7 +1880,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1917
1880
|
}
|
|
1918
1881
|
if (yarnLockFiles && yarnLockFiles.length) {
|
|
1919
1882
|
manifestFiles = manifestFiles.concat(yarnLockFiles);
|
|
1920
|
-
for (
|
|
1883
|
+
for (const f of yarnLockFiles) {
|
|
1921
1884
|
if (DEBUG_MODE) {
|
|
1922
1885
|
console.log(`Parsing ${f}`);
|
|
1923
1886
|
}
|
|
@@ -1993,7 +1956,7 @@ const createNodejsBom = async (path, options) => {
|
|
|
1993
1956
|
"**/package.json"
|
|
1994
1957
|
);
|
|
1995
1958
|
manifestFiles = manifestFiles.concat(pkgJsonFiles);
|
|
1996
|
-
for (
|
|
1959
|
+
for (const pkgjf of pkgJsonFiles) {
|
|
1997
1960
|
const dlist = await parsePkgJson(pkgjf);
|
|
1998
1961
|
if (dlist && dlist.length) {
|
|
1999
1962
|
pkgList = pkgList.concat(dlist);
|
|
@@ -2026,9 +1989,13 @@ const createNodejsBom = async (path, options) => {
|
|
|
2026
1989
|
* @param path to the project
|
|
2027
1990
|
* @param options Parse options from the cli
|
|
2028
1991
|
*/
|
|
2029
|
-
const createPythonBom = async (path, options) => {
|
|
1992
|
+
export const createPythonBom = async (path, options) => {
|
|
2030
1993
|
let allImports = {};
|
|
2031
1994
|
let metadataFilename = "";
|
|
1995
|
+
let dependencies = [];
|
|
1996
|
+
let pkgList = [];
|
|
1997
|
+
const tempDir = mkdtempSync(join(tmpdir(), "cdxgen-venv-"));
|
|
1998
|
+
const parentComponent = createDefaultParentComponent(path);
|
|
2032
1999
|
const pipenvMode = existsSync(join(path, "Pipfile"));
|
|
2033
2000
|
const poetryFiles = getAllFiles(
|
|
2034
2001
|
path,
|
|
@@ -2054,7 +2021,6 @@ const createPythonBom = async (path, options) => {
|
|
|
2054
2021
|
path,
|
|
2055
2022
|
(options.multiProject ? "**/" : "") + "*.egg-info"
|
|
2056
2023
|
);
|
|
2057
|
-
let pkgList = [];
|
|
2058
2024
|
const setupPy = join(path, "setup.py");
|
|
2059
2025
|
const pyProjectFile = join(path, "pyproject.toml");
|
|
2060
2026
|
const pyProjectMode = existsSync(pyProjectFile);
|
|
@@ -2065,7 +2031,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2065
2031
|
// Poetry sets up its own virtual env containing site-packages so
|
|
2066
2032
|
// we give preference to poetry lock file. Issue# 129
|
|
2067
2033
|
if (poetryMode) {
|
|
2068
|
-
for (
|
|
2034
|
+
for (const f of poetryFiles) {
|
|
2069
2035
|
const lockData = readFileSync(f, { encoding: "utf-8" });
|
|
2070
2036
|
const dlist = await parsePoetrylockData(lockData);
|
|
2071
2037
|
if (dlist && dlist.length) {
|
|
@@ -2078,7 +2044,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2078
2044
|
});
|
|
2079
2045
|
} else if (metadataFiles && metadataFiles.length) {
|
|
2080
2046
|
// dist-info directories
|
|
2081
|
-
for (
|
|
2047
|
+
for (const mf of metadataFiles) {
|
|
2082
2048
|
const mData = readFileSync(mf, {
|
|
2083
2049
|
encoding: "utf-8"
|
|
2084
2050
|
});
|
|
@@ -2090,7 +2056,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2090
2056
|
}
|
|
2091
2057
|
// .whl files. Zip file containing dist-info directory
|
|
2092
2058
|
if (whlFiles && whlFiles.length) {
|
|
2093
|
-
for (
|
|
2059
|
+
for (const wf of whlFiles) {
|
|
2094
2060
|
const mData = await readZipEntry(wf, "METADATA");
|
|
2095
2061
|
if (mData) {
|
|
2096
2062
|
const dlist = parseBdistMetadata(mData);
|
|
@@ -2102,7 +2068,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2102
2068
|
}
|
|
2103
2069
|
// .egg-info files
|
|
2104
2070
|
if (eggInfoFiles && eggInfoFiles.length) {
|
|
2105
|
-
for (
|
|
2071
|
+
for (const ef of eggInfoFiles) {
|
|
2106
2072
|
const dlist = parseBdistMetadata(readFileSync(ef, { encoding: "utf-8" }));
|
|
2107
2073
|
if (dlist && dlist.length) {
|
|
2108
2074
|
pkgList = pkgList.concat(dlist);
|
|
@@ -2126,15 +2092,15 @@ const createPythonBom = async (path, options) => {
|
|
|
2126
2092
|
} else if (requirementsMode) {
|
|
2127
2093
|
metadataFilename = "requirements.txt";
|
|
2128
2094
|
if (reqFiles && reqFiles.length) {
|
|
2129
|
-
for (
|
|
2095
|
+
for (const f of reqFiles) {
|
|
2130
2096
|
const basePath = dirname(f);
|
|
2131
2097
|
let reqData = undefined;
|
|
2132
2098
|
let frozen = false;
|
|
2133
2099
|
// Attempt to pip freeze in a virtualenv to improve precision
|
|
2134
2100
|
if (options.installDeps) {
|
|
2135
|
-
const
|
|
2136
|
-
if (
|
|
2137
|
-
pkgList = pkgList.concat(
|
|
2101
|
+
const pkgMap = getPipFrozenTree(basePath, f, tempDir);
|
|
2102
|
+
if (pkgMap.pkgList && pkgMap.pkgList.length) {
|
|
2103
|
+
pkgList = pkgList.concat(pkgMap.pkgList);
|
|
2138
2104
|
frozen = true;
|
|
2139
2105
|
}
|
|
2140
2106
|
}
|
|
@@ -2154,7 +2120,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2154
2120
|
} // for
|
|
2155
2121
|
metadataFilename = reqFiles.join(", ");
|
|
2156
2122
|
} else if (reqDirFiles && reqDirFiles.length) {
|
|
2157
|
-
for (
|
|
2123
|
+
for (const j in reqDirFiles) {
|
|
2158
2124
|
const f = reqDirFiles[j];
|
|
2159
2125
|
const reqData = readFileSync(f, { encoding: "utf-8" });
|
|
2160
2126
|
const dlist = await parseReqFile(reqData, false);
|
|
@@ -2168,27 +2134,48 @@ const createPythonBom = async (path, options) => {
|
|
|
2168
2134
|
}
|
|
2169
2135
|
// Use atom in requirements, setup.py and pyproject.toml mode
|
|
2170
2136
|
if (requirementsMode || setupPyMode || pyProjectMode) {
|
|
2171
|
-
let dlist = undefined;
|
|
2172
2137
|
/**
|
|
2173
2138
|
* The order of preference is pyproject.toml (newer) and then setup.py
|
|
2174
2139
|
*/
|
|
2175
2140
|
if (options.installDeps) {
|
|
2141
|
+
let pkgMap = undefined;
|
|
2176
2142
|
if (pyProjectMode) {
|
|
2177
|
-
|
|
2143
|
+
pkgMap = getPipFrozenTree(path, pyProjectFile, tempDir);
|
|
2178
2144
|
} else if (setupPyMode) {
|
|
2179
|
-
|
|
2145
|
+
pkgMap = getPipFrozenTree(path, setupPy, tempDir);
|
|
2146
|
+
} else {
|
|
2147
|
+
pkgMap = getPipFrozenTree(path, undefined, tempDir);
|
|
2148
|
+
}
|
|
2149
|
+
// Get the imported modules and a dedupe list of packages
|
|
2150
|
+
const parentDependsOn = [];
|
|
2151
|
+
const retMap = await getPyModules(path, pkgList);
|
|
2152
|
+
if (retMap.pkgList && retMap.pkgList.length) {
|
|
2153
|
+
pkgList = pkgList.concat(retMap.pkgList);
|
|
2154
|
+
for (const p of retMap.pkgList) {
|
|
2155
|
+
parentDependsOn.push(`pkg:pypi/${p.name}@${p.version}`);
|
|
2156
|
+
}
|
|
2180
2157
|
}
|
|
2181
|
-
if (
|
|
2182
|
-
|
|
2158
|
+
if (retMap.dependenciesList) {
|
|
2159
|
+
dependencies = mergeDependencies(dependencies, retMap.dependenciesList);
|
|
2183
2160
|
}
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2161
|
+
if (retMap.allImports) {
|
|
2162
|
+
allImports = { ...allImports, ...retMap.allImports };
|
|
2163
|
+
}
|
|
2164
|
+
// Complete the dependency tree by making parent component depend on the first level
|
|
2165
|
+
for (const p of pkgMap.rootList) {
|
|
2166
|
+
parentDependsOn.push(`pkg:pypi/${p.name}@${p.version}`);
|
|
2167
|
+
}
|
|
2168
|
+
if (pkgMap.pkgList && pkgMap.pkgList.length) {
|
|
2169
|
+
pkgList = pkgList.concat(pkgMap.pkgList);
|
|
2170
|
+
}
|
|
2171
|
+
if (pkgMap.dependenciesList) {
|
|
2172
|
+
dependencies = mergeDependencies(dependencies, pkgMap.dependenciesList);
|
|
2173
|
+
}
|
|
2174
|
+
const pdependencies = {
|
|
2175
|
+
ref: parentComponent.purl,
|
|
2176
|
+
dependsOn: parentDependsOn
|
|
2177
|
+
};
|
|
2178
|
+
dependencies.splice(0, 0, pdependencies);
|
|
2192
2179
|
}
|
|
2193
2180
|
}
|
|
2194
2181
|
// Final fallback is to manually parse setup.py if we still
|
|
@@ -2200,10 +2187,16 @@ const createPythonBom = async (path, options) => {
|
|
|
2200
2187
|
pkgList = pkgList.concat(dlist);
|
|
2201
2188
|
}
|
|
2202
2189
|
}
|
|
2190
|
+
// Clean up
|
|
2191
|
+
if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
|
|
2192
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
2193
|
+
}
|
|
2203
2194
|
return buildBomNSData(options, pkgList, "pypi", {
|
|
2204
2195
|
allImports,
|
|
2205
2196
|
src: path,
|
|
2206
|
-
filename: metadataFilename
|
|
2197
|
+
filename: metadataFilename,
|
|
2198
|
+
dependencies,
|
|
2199
|
+
parentComponent
|
|
2207
2200
|
});
|
|
2208
2201
|
};
|
|
2209
2202
|
|
|
@@ -2213,7 +2206,7 @@ const createPythonBom = async (path, options) => {
|
|
|
2213
2206
|
* @param path to the project
|
|
2214
2207
|
* @param options Parse options from the cli
|
|
2215
2208
|
*/
|
|
2216
|
-
const createGoBom = async (path, options) => {
|
|
2209
|
+
export const createGoBom = async (path, options) => {
|
|
2217
2210
|
let pkgList = [];
|
|
2218
2211
|
// Is this a binary file
|
|
2219
2212
|
let maybeBinary = false;
|
|
@@ -2230,8 +2223,8 @@ const createGoBom = async (path, options) => {
|
|
|
2230
2223
|
}
|
|
2231
2224
|
// Since this pkg list is derived from the binary mark them as used.
|
|
2232
2225
|
const allImports = {};
|
|
2233
|
-
for (
|
|
2234
|
-
|
|
2226
|
+
for (const mpkg of pkgList) {
|
|
2227
|
+
const pkgFullName = `${mpkg.group}/${mpkg.name}`;
|
|
2235
2228
|
allImports[pkgFullName] = true;
|
|
2236
2229
|
}
|
|
2237
2230
|
return buildBomNSData(options, pkgList, "golang", {
|
|
@@ -2255,7 +2248,7 @@ const createGoBom = async (path, options) => {
|
|
|
2255
2248
|
"Using go.sum to generate BOMs for go projects may return an inaccurate representation of transitive dependencies.\nSee: https://github.com/golang/go/wiki/Modules#is-gosum-a-lock-file-why-does-gosum-include-information-for-module-versions-i-am-no-longer-using\n",
|
|
2256
2249
|
"Set USE_GOSUM=false to generate BOMs using go.mod as the dependency source of truth."
|
|
2257
2250
|
);
|
|
2258
|
-
for (
|
|
2251
|
+
for (const f of gosumFiles) {
|
|
2259
2252
|
if (DEBUG_MODE) {
|
|
2260
2253
|
console.log(`Parsing ${f}`);
|
|
2261
2254
|
}
|
|
@@ -2274,7 +2267,7 @@ const createGoBom = async (path, options) => {
|
|
|
2274
2267
|
// If USE_GOSUM is false, generate BOM components using go.mod.
|
|
2275
2268
|
const gosumMap = {};
|
|
2276
2269
|
if (gosumFiles.length) {
|
|
2277
|
-
for (
|
|
2270
|
+
for (const f of gosumFiles) {
|
|
2278
2271
|
if (DEBUG_MODE) {
|
|
2279
2272
|
console.log(`Parsing ${f}`);
|
|
2280
2273
|
}
|
|
@@ -2303,7 +2296,7 @@ const createGoBom = async (path, options) => {
|
|
|
2303
2296
|
let shouldManuallyParse = false;
|
|
2304
2297
|
// Use the go list -deps and go mod why commands to generate a good quality BoM for non-docker invocations
|
|
2305
2298
|
if (!["docker", "oci", "os"].includes(options.projectType)) {
|
|
2306
|
-
for (
|
|
2299
|
+
for (const f of gomodFiles) {
|
|
2307
2300
|
const basePath = dirname(f);
|
|
2308
2301
|
// Ignore vendor packages
|
|
2309
2302
|
if (basePath.includes("/vendor/") || basePath.includes("/build/")) {
|
|
@@ -2349,11 +2342,11 @@ const createGoBom = async (path, options) => {
|
|
|
2349
2342
|
);
|
|
2350
2343
|
}
|
|
2351
2344
|
// Using go mod why detect required packages
|
|
2352
|
-
for (
|
|
2345
|
+
for (const apkg of pkgList) {
|
|
2353
2346
|
if (circuitBreak) {
|
|
2354
2347
|
break;
|
|
2355
2348
|
}
|
|
2356
|
-
|
|
2349
|
+
const pkgFullName = `${apkg.name}`;
|
|
2357
2350
|
if (apkg.scope === "required") {
|
|
2358
2351
|
allImports[pkgFullName] = true;
|
|
2359
2352
|
continue;
|
|
@@ -2375,7 +2368,7 @@ const createGoBom = async (path, options) => {
|
|
|
2375
2368
|
const mstdout = mresult.stdout;
|
|
2376
2369
|
if (mstdout) {
|
|
2377
2370
|
const cmdOutput = Buffer.from(mstdout).toString();
|
|
2378
|
-
|
|
2371
|
+
const whyPkg = parseGoModWhy(cmdOutput);
|
|
2379
2372
|
if (whyPkg == pkgFullName) {
|
|
2380
2373
|
allImports[pkgFullName] = true;
|
|
2381
2374
|
}
|
|
@@ -2399,7 +2392,7 @@ const createGoBom = async (path, options) => {
|
|
|
2399
2392
|
"Manually parsing go.mod files. The resultant BoM would be incomplete."
|
|
2400
2393
|
);
|
|
2401
2394
|
}
|
|
2402
|
-
for (
|
|
2395
|
+
for (const f of gomodFiles) {
|
|
2403
2396
|
if (DEBUG_MODE) {
|
|
2404
2397
|
console.log(`Parsing ${f}`);
|
|
2405
2398
|
}
|
|
@@ -2414,7 +2407,7 @@ const createGoBom = async (path, options) => {
|
|
|
2414
2407
|
filename: gomodFiles.join(", ")
|
|
2415
2408
|
});
|
|
2416
2409
|
} else if (gopkgLockFiles.length) {
|
|
2417
|
-
for (
|
|
2410
|
+
for (const f of gopkgLockFiles) {
|
|
2418
2411
|
if (DEBUG_MODE) {
|
|
2419
2412
|
console.log(`Parsing ${f}`);
|
|
2420
2413
|
}
|
|
@@ -2440,7 +2433,7 @@ const createGoBom = async (path, options) => {
|
|
|
2440
2433
|
* @param path to the project
|
|
2441
2434
|
* @param options Parse options from the cli
|
|
2442
2435
|
*/
|
|
2443
|
-
const createRustBom = async (path, options) => {
|
|
2436
|
+
export const createRustBom = async (path, options) => {
|
|
2444
2437
|
let pkgList = [];
|
|
2445
2438
|
// Is this a binary file
|
|
2446
2439
|
let maybeBinary = false;
|
|
@@ -2457,8 +2450,8 @@ const createRustBom = async (path, options) => {
|
|
|
2457
2450
|
}
|
|
2458
2451
|
// Since this pkg list is derived from the binary mark them as used.
|
|
2459
2452
|
const allImports = {};
|
|
2460
|
-
for (
|
|
2461
|
-
|
|
2453
|
+
for (const mpkg of pkgList) {
|
|
2454
|
+
const pkgFullName = `${mpkg.group}/${mpkg.name}`;
|
|
2462
2455
|
allImports[pkgFullName] = true;
|
|
2463
2456
|
}
|
|
2464
2457
|
return buildBomNSData(options, pkgList, "cargo", {
|
|
@@ -2476,9 +2469,9 @@ const createRustBom = async (path, options) => {
|
|
|
2476
2469
|
(options.multiProject ? "**/" : "") + "Cargo.toml"
|
|
2477
2470
|
);
|
|
2478
2471
|
const cargoMode = cargoFiles.length;
|
|
2479
|
-
|
|
2472
|
+
const cargoLockMode = cargoLockFiles.length;
|
|
2480
2473
|
if (cargoMode && !cargoLockMode) {
|
|
2481
|
-
for (
|
|
2474
|
+
for (const f of cargoFiles) {
|
|
2482
2475
|
if (DEBUG_MODE) {
|
|
2483
2476
|
console.log(`Parsing ${f}`);
|
|
2484
2477
|
}
|
|
@@ -2499,7 +2492,7 @@ const createRustBom = async (path, options) => {
|
|
|
2499
2492
|
(options.multiProject ? "**/" : "") + "Cargo.lock"
|
|
2500
2493
|
);
|
|
2501
2494
|
if (cargoLockFiles.length) {
|
|
2502
|
-
for (
|
|
2495
|
+
for (const f of cargoLockFiles) {
|
|
2503
2496
|
if (DEBUG_MODE) {
|
|
2504
2497
|
console.log(`Parsing ${f}`);
|
|
2505
2498
|
}
|
|
@@ -2523,7 +2516,7 @@ const createRustBom = async (path, options) => {
|
|
|
2523
2516
|
* @param path to the project
|
|
2524
2517
|
* @param options Parse options from the cli
|
|
2525
2518
|
*/
|
|
2526
|
-
const createDartBom = async (path, options) => {
|
|
2519
|
+
export const createDartBom = async (path, options) => {
|
|
2527
2520
|
const pubFiles = getAllFiles(
|
|
2528
2521
|
path,
|
|
2529
2522
|
(options.multiProject ? "**/" : "") + "pubspec.lock"
|
|
@@ -2534,7 +2527,7 @@ const createDartBom = async (path, options) => {
|
|
|
2534
2527
|
);
|
|
2535
2528
|
let pkgList = [];
|
|
2536
2529
|
if (pubFiles.length) {
|
|
2537
|
-
for (
|
|
2530
|
+
for (const f of pubFiles) {
|
|
2538
2531
|
if (DEBUG_MODE) {
|
|
2539
2532
|
console.log(`Parsing ${f}`);
|
|
2540
2533
|
}
|
|
@@ -2549,12 +2542,12 @@ const createDartBom = async (path, options) => {
|
|
|
2549
2542
|
filename: pubFiles.join(", ")
|
|
2550
2543
|
});
|
|
2551
2544
|
} else if (pubSpecYamlFiles.length) {
|
|
2552
|
-
for (
|
|
2545
|
+
for (const f of pubSpecYamlFiles) {
|
|
2553
2546
|
if (DEBUG_MODE) {
|
|
2554
2547
|
console.log(`Parsing ${f}`);
|
|
2555
2548
|
}
|
|
2556
2549
|
const pubYamlData = readFileSync(f, { encoding: "utf-8" });
|
|
2557
|
-
const dlist =
|
|
2550
|
+
const dlist = parsePubYamlData(pubYamlData);
|
|
2558
2551
|
if (dlist && dlist.length) {
|
|
2559
2552
|
pkgList = pkgList.concat(dlist);
|
|
2560
2553
|
}
|
|
@@ -2574,7 +2567,7 @@ const createDartBom = async (path, options) => {
|
|
|
2574
2567
|
* @param path to the project
|
|
2575
2568
|
* @param options Parse options from the cli
|
|
2576
2569
|
*/
|
|
2577
|
-
const createCppBom = async (path, options) => {
|
|
2570
|
+
export const createCppBom = async (path, options) => {
|
|
2578
2571
|
const conanLockFiles = getAllFiles(
|
|
2579
2572
|
path,
|
|
2580
2573
|
(options.multiProject ? "**/" : "") + "conan.lock"
|
|
@@ -2585,12 +2578,12 @@ const createCppBom = async (path, options) => {
|
|
|
2585
2578
|
);
|
|
2586
2579
|
let pkgList = [];
|
|
2587
2580
|
if (conanLockFiles.length) {
|
|
2588
|
-
for (
|
|
2581
|
+
for (const f of conanLockFiles) {
|
|
2589
2582
|
if (DEBUG_MODE) {
|
|
2590
2583
|
console.log(`Parsing ${f}`);
|
|
2591
2584
|
}
|
|
2592
2585
|
const conanLockData = readFileSync(f, { encoding: "utf-8" });
|
|
2593
|
-
const dlist =
|
|
2586
|
+
const dlist = parseConanLockData(conanLockData);
|
|
2594
2587
|
if (dlist && dlist.length) {
|
|
2595
2588
|
pkgList = pkgList.concat(dlist);
|
|
2596
2589
|
}
|
|
@@ -2600,12 +2593,12 @@ const createCppBom = async (path, options) => {
|
|
|
2600
2593
|
filename: conanLockFiles.join(", ")
|
|
2601
2594
|
});
|
|
2602
2595
|
} else if (conanFiles.length) {
|
|
2603
|
-
for (
|
|
2596
|
+
for (const f of conanFiles) {
|
|
2604
2597
|
if (DEBUG_MODE) {
|
|
2605
2598
|
console.log(`Parsing ${f}`);
|
|
2606
2599
|
}
|
|
2607
2600
|
const conanData = readFileSync(f, { encoding: "utf-8" });
|
|
2608
|
-
const dlist =
|
|
2601
|
+
const dlist = parseConanData(conanData);
|
|
2609
2602
|
if (dlist && dlist.length) {
|
|
2610
2603
|
pkgList = pkgList.concat(dlist);
|
|
2611
2604
|
}
|
|
@@ -2625,7 +2618,7 @@ const createCppBom = async (path, options) => {
|
|
|
2625
2618
|
* @param path to the project
|
|
2626
2619
|
* @param options Parse options from the cli
|
|
2627
2620
|
*/
|
|
2628
|
-
const createClojureBom =
|
|
2621
|
+
export const createClojureBom = (path, options) => {
|
|
2629
2622
|
const ednFiles = getAllFiles(
|
|
2630
2623
|
path,
|
|
2631
2624
|
(options.multiProject ? "**/" : "") + "deps.edn"
|
|
@@ -2640,7 +2633,7 @@ const createClojureBom = async (path, options) => {
|
|
|
2640
2633
|
if (process.env.LEIN_ARGS) {
|
|
2641
2634
|
LEIN_ARGS = process.env.LEIN_ARGS.split(" ");
|
|
2642
2635
|
}
|
|
2643
|
-
for (
|
|
2636
|
+
for (const f of leinFiles) {
|
|
2644
2637
|
if (DEBUG_MODE) {
|
|
2645
2638
|
console.log(`Parsing ${f}`);
|
|
2646
2639
|
}
|
|
@@ -2690,7 +2683,7 @@ const createClojureBom = async (path, options) => {
|
|
|
2690
2683
|
if (process.env.CLJ_ARGS) {
|
|
2691
2684
|
CLJ_ARGS = process.env.CLJ_ARGS.split(" ");
|
|
2692
2685
|
}
|
|
2693
|
-
for (
|
|
2686
|
+
for (const f of ednFiles) {
|
|
2694
2687
|
const basePath = dirname(f);
|
|
2695
2688
|
console.log("Executing", CLJ_CMD, CLJ_ARGS.join(" "), "in", basePath);
|
|
2696
2689
|
const result = spawnSync(CLJ_CMD, CLJ_ARGS, {
|
|
@@ -2743,19 +2736,19 @@ const createClojureBom = async (path, options) => {
|
|
|
2743
2736
|
* @param path to the project
|
|
2744
2737
|
* @param options Parse options from the cli
|
|
2745
2738
|
*/
|
|
2746
|
-
const createHaskellBom = async (path, options) => {
|
|
2739
|
+
export const createHaskellBom = async (path, options) => {
|
|
2747
2740
|
const cabalFiles = getAllFiles(
|
|
2748
2741
|
path,
|
|
2749
2742
|
(options.multiProject ? "**/" : "") + "cabal.project.freeze"
|
|
2750
2743
|
);
|
|
2751
2744
|
let pkgList = [];
|
|
2752
2745
|
if (cabalFiles.length) {
|
|
2753
|
-
for (
|
|
2746
|
+
for (const f of cabalFiles) {
|
|
2754
2747
|
if (DEBUG_MODE) {
|
|
2755
2748
|
console.log(`Parsing ${f}`);
|
|
2756
2749
|
}
|
|
2757
2750
|
const cabalData = readFileSync(f, { encoding: "utf-8" });
|
|
2758
|
-
const dlist =
|
|
2751
|
+
const dlist = parseCabalData(cabalData);
|
|
2759
2752
|
if (dlist && dlist.length) {
|
|
2760
2753
|
pkgList = pkgList.concat(dlist);
|
|
2761
2754
|
}
|
|
@@ -2774,19 +2767,19 @@ const createHaskellBom = async (path, options) => {
|
|
|
2774
2767
|
* @param path to the project
|
|
2775
2768
|
* @param options Parse options from the cli
|
|
2776
2769
|
*/
|
|
2777
|
-
const createElixirBom = async (path, options) => {
|
|
2770
|
+
export const createElixirBom = async (path, options) => {
|
|
2778
2771
|
const mixFiles = getAllFiles(
|
|
2779
2772
|
path,
|
|
2780
2773
|
(options.multiProject ? "**/" : "") + "mix.lock"
|
|
2781
2774
|
);
|
|
2782
2775
|
let pkgList = [];
|
|
2783
2776
|
if (mixFiles.length) {
|
|
2784
|
-
for (
|
|
2777
|
+
for (const f of mixFiles) {
|
|
2785
2778
|
if (DEBUG_MODE) {
|
|
2786
2779
|
console.log(`Parsing ${f}`);
|
|
2787
2780
|
}
|
|
2788
2781
|
const mixData = readFileSync(f, { encoding: "utf-8" });
|
|
2789
|
-
const dlist =
|
|
2782
|
+
const dlist = parseMixLockData(mixData);
|
|
2790
2783
|
if (dlist && dlist.length) {
|
|
2791
2784
|
pkgList = pkgList.concat(dlist);
|
|
2792
2785
|
}
|
|
@@ -2805,16 +2798,16 @@ const createElixirBom = async (path, options) => {
|
|
|
2805
2798
|
* @param path to the project
|
|
2806
2799
|
* @param options Parse options from the cli
|
|
2807
2800
|
*/
|
|
2808
|
-
const createGitHubBom = async (path, options) => {
|
|
2801
|
+
export const createGitHubBom = async (path, options) => {
|
|
2809
2802
|
const ghactionFiles = getAllFiles(path, ".github/workflows/" + "*.yml");
|
|
2810
2803
|
let pkgList = [];
|
|
2811
2804
|
if (ghactionFiles.length) {
|
|
2812
|
-
for (
|
|
2805
|
+
for (const f of ghactionFiles) {
|
|
2813
2806
|
if (DEBUG_MODE) {
|
|
2814
2807
|
console.log(`Parsing ${f}`);
|
|
2815
2808
|
}
|
|
2816
2809
|
const ghwData = readFileSync(f, { encoding: "utf-8" });
|
|
2817
|
-
const dlist =
|
|
2810
|
+
const dlist = parseGitHubWorkflowData(ghwData);
|
|
2818
2811
|
if (dlist && dlist.length) {
|
|
2819
2812
|
pkgList = pkgList.concat(dlist);
|
|
2820
2813
|
}
|
|
@@ -2833,16 +2826,16 @@ const createGitHubBom = async (path, options) => {
|
|
|
2833
2826
|
* @param path to the project
|
|
2834
2827
|
* @param options Parse options from the cli
|
|
2835
2828
|
*/
|
|
2836
|
-
const createCloudBuildBom = async (path, options) => {
|
|
2829
|
+
export const createCloudBuildBom = async (path, options) => {
|
|
2837
2830
|
const cbFiles = getAllFiles(path, "cloudbuild.yml");
|
|
2838
2831
|
let pkgList = [];
|
|
2839
2832
|
if (cbFiles.length) {
|
|
2840
|
-
for (
|
|
2833
|
+
for (const f of cbFiles) {
|
|
2841
2834
|
if (DEBUG_MODE) {
|
|
2842
2835
|
console.log(`Parsing ${f}`);
|
|
2843
2836
|
}
|
|
2844
2837
|
const cbwData = readFileSync(f, { encoding: "utf-8" });
|
|
2845
|
-
const dlist =
|
|
2838
|
+
const dlist = parseCloudBuildData(cbwData);
|
|
2846
2839
|
if (dlist && dlist.length) {
|
|
2847
2840
|
pkgList = pkgList.concat(dlist);
|
|
2848
2841
|
}
|
|
@@ -2861,7 +2854,7 @@ const createCloudBuildBom = async (path, options) => {
|
|
|
2861
2854
|
* @param path to the project
|
|
2862
2855
|
* @param options Parse options from the cli
|
|
2863
2856
|
*/
|
|
2864
|
-
const createOSBom =
|
|
2857
|
+
export const createOSBom = (path, options) => {
|
|
2865
2858
|
console.warn(
|
|
2866
2859
|
"About to generate SBoM for the current OS installation. This would take several minutes ..."
|
|
2867
2860
|
);
|
|
@@ -2893,7 +2886,7 @@ const createOSBom = async (path, options) => {
|
|
|
2893
2886
|
allLayersDir: options.allLayersExplodedDir,
|
|
2894
2887
|
allLayersExplodedDir: options.allLayersExplodedDir
|
|
2895
2888
|
};
|
|
2896
|
-
|
|
2889
|
+
const pkgPathList = [];
|
|
2897
2890
|
if (options.deep) {
|
|
2898
2891
|
getPkgPathList(exportData, undefined);
|
|
2899
2892
|
}
|
|
@@ -2906,15 +2899,15 @@ const createOSBom = async (path, options) => {
|
|
|
2906
2899
|
* @param path to the project
|
|
2907
2900
|
* @param options Parse options from the cli
|
|
2908
2901
|
*/
|
|
2909
|
-
const createJenkinsBom = async (path, options) => {
|
|
2902
|
+
export const createJenkinsBom = async (path, options) => {
|
|
2910
2903
|
let pkgList = [];
|
|
2911
2904
|
const hpiFiles = getAllFiles(
|
|
2912
2905
|
path,
|
|
2913
2906
|
(options.multiProject ? "**/" : "") + "*.hpi"
|
|
2914
2907
|
);
|
|
2915
|
-
|
|
2908
|
+
const tempDir = mkdtempSync(join(tmpdir(), "hpi-deps-"));
|
|
2916
2909
|
if (hpiFiles.length) {
|
|
2917
|
-
for (
|
|
2910
|
+
for (const f of hpiFiles) {
|
|
2918
2911
|
if (DEBUG_MODE) {
|
|
2919
2912
|
console.log(`Parsing ${f}`);
|
|
2920
2913
|
}
|
|
@@ -2926,7 +2919,7 @@ const createJenkinsBom = async (path, options) => {
|
|
|
2926
2919
|
}
|
|
2927
2920
|
const jsFiles = getAllFiles(tempDir, "**/*.js");
|
|
2928
2921
|
if (jsFiles.length) {
|
|
2929
|
-
for (
|
|
2922
|
+
for (const f of jsFiles) {
|
|
2930
2923
|
if (DEBUG_MODE) {
|
|
2931
2924
|
console.log(`Parsing ${f}`);
|
|
2932
2925
|
}
|
|
@@ -2954,19 +2947,19 @@ const createJenkinsBom = async (path, options) => {
|
|
|
2954
2947
|
* @param path to the project
|
|
2955
2948
|
* @param options Parse options from the cli
|
|
2956
2949
|
*/
|
|
2957
|
-
const createHelmBom = async (path, options) => {
|
|
2950
|
+
export const createHelmBom = async (path, options) => {
|
|
2958
2951
|
let pkgList = [];
|
|
2959
2952
|
const yamlFiles = getAllFiles(
|
|
2960
2953
|
path,
|
|
2961
2954
|
(options.multiProject ? "**/" : "") + "*.yaml"
|
|
2962
2955
|
);
|
|
2963
2956
|
if (yamlFiles.length) {
|
|
2964
|
-
for (
|
|
2957
|
+
for (const f of yamlFiles) {
|
|
2965
2958
|
if (DEBUG_MODE) {
|
|
2966
2959
|
console.log(`Parsing ${f}`);
|
|
2967
2960
|
}
|
|
2968
2961
|
const helmData = readFileSync(f, { encoding: "utf-8" });
|
|
2969
|
-
const dlist =
|
|
2962
|
+
const dlist = parseHelmYamlData(helmData);
|
|
2970
2963
|
if (dlist && dlist.length) {
|
|
2971
2964
|
pkgList = pkgList.concat(dlist);
|
|
2972
2965
|
}
|
|
@@ -2985,7 +2978,7 @@ const createHelmBom = async (path, options) => {
|
|
|
2985
2978
|
* @param path to the project
|
|
2986
2979
|
* @param options Parse options from the cli
|
|
2987
2980
|
*/
|
|
2988
|
-
const createSwiftBom =
|
|
2981
|
+
export const createSwiftBom = (path, options) => {
|
|
2989
2982
|
const swiftFiles = getAllFiles(
|
|
2990
2983
|
path,
|
|
2991
2984
|
(options.multiProject ? "**/" : "") + "Package*.swift"
|
|
@@ -2997,9 +2990,9 @@ const createSwiftBom = async (path, options) => {
|
|
|
2997
2990
|
let pkgList = [];
|
|
2998
2991
|
let dependencies = [];
|
|
2999
2992
|
let parentComponent = {};
|
|
3000
|
-
|
|
2993
|
+
const completedPath = [];
|
|
3001
2994
|
if (pkgResolvedFiles.length) {
|
|
3002
|
-
for (
|
|
2995
|
+
for (const f of pkgResolvedFiles) {
|
|
3003
2996
|
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
3004
2997
|
parentComponent = createDefaultParentComponent(f);
|
|
3005
2998
|
}
|
|
@@ -3013,7 +3006,7 @@ const createSwiftBom = async (path, options) => {
|
|
|
3013
3006
|
}
|
|
3014
3007
|
}
|
|
3015
3008
|
if (swiftFiles.length) {
|
|
3016
|
-
for (
|
|
3009
|
+
for (const f of swiftFiles) {
|
|
3017
3010
|
const basePath = dirname(f);
|
|
3018
3011
|
if (completedPath.includes(basePath)) {
|
|
3019
3012
|
continue;
|
|
@@ -3071,16 +3064,16 @@ const createSwiftBom = async (path, options) => {
|
|
|
3071
3064
|
* @param path to the project
|
|
3072
3065
|
* @param options Parse options from the cli
|
|
3073
3066
|
*/
|
|
3074
|
-
const createContainerSpecLikeBom = async (path, options) => {
|
|
3067
|
+
export const createContainerSpecLikeBom = async (path, options) => {
|
|
3075
3068
|
let services = [];
|
|
3076
|
-
|
|
3069
|
+
const ociSpecs = [];
|
|
3077
3070
|
let components = [];
|
|
3078
3071
|
let componentsXmls = [];
|
|
3079
|
-
|
|
3072
|
+
const parentComponent = {};
|
|
3080
3073
|
let dependencies = [];
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3074
|
+
const doneimages = [];
|
|
3075
|
+
const doneservices = [];
|
|
3076
|
+
const origProjectType = options.projectType;
|
|
3084
3077
|
let dcFiles = getAllFiles(
|
|
3085
3078
|
path,
|
|
3086
3079
|
(options.multiProject ? "**/" : "") + "*.yml"
|
|
@@ -3093,7 +3086,7 @@ const createContainerSpecLikeBom = async (path, options) => {
|
|
|
3093
3086
|
path,
|
|
3094
3087
|
(options.multiProject ? "**/" : "") + "open*.json"
|
|
3095
3088
|
);
|
|
3096
|
-
|
|
3089
|
+
const oapiYamlFiles = getAllFiles(
|
|
3097
3090
|
path,
|
|
3098
3091
|
(options.multiProject ? "**/" : "") + "open*.yaml"
|
|
3099
3092
|
);
|
|
@@ -3107,18 +3100,18 @@ const createContainerSpecLikeBom = async (path, options) => {
|
|
|
3107
3100
|
const privadoFiles = getAllFiles(path, ".privado/" + "*.json");
|
|
3108
3101
|
// parse yaml manifest files
|
|
3109
3102
|
if (dcFiles.length) {
|
|
3110
|
-
for (
|
|
3103
|
+
for (const f of dcFiles) {
|
|
3111
3104
|
if (DEBUG_MODE) {
|
|
3112
3105
|
console.log(`Parsing ${f}`);
|
|
3113
3106
|
}
|
|
3114
3107
|
const dcData = readFileSync(f, { encoding: "utf-8" });
|
|
3115
|
-
const imglist =
|
|
3108
|
+
const imglist = parseContainerSpecData(dcData);
|
|
3116
3109
|
if (imglist && imglist.length) {
|
|
3117
3110
|
if (DEBUG_MODE) {
|
|
3118
3111
|
console.log("Images identified in", f, "are", imglist);
|
|
3119
3112
|
}
|
|
3120
3113
|
for (const img of imglist) {
|
|
3121
|
-
|
|
3114
|
+
const commonProperties = [
|
|
3122
3115
|
{
|
|
3123
3116
|
name: "SrcFile",
|
|
3124
3117
|
value: f
|
|
@@ -3239,12 +3232,12 @@ const createContainerSpecLikeBom = async (path, options) => {
|
|
|
3239
3232
|
} // if
|
|
3240
3233
|
// Parse openapi files
|
|
3241
3234
|
if (oapiFiles.length) {
|
|
3242
|
-
for (
|
|
3235
|
+
for (const af of oapiFiles) {
|
|
3243
3236
|
if (DEBUG_MODE) {
|
|
3244
3237
|
console.log(`Parsing ${af}`);
|
|
3245
3238
|
}
|
|
3246
3239
|
const oaData = readFileSync(af, { encoding: "utf-8" });
|
|
3247
|
-
const servlist =
|
|
3240
|
+
const servlist = parseOpenapiSpecData(oaData);
|
|
3248
3241
|
if (servlist && servlist.length) {
|
|
3249
3242
|
// Inject SrcFile property
|
|
3250
3243
|
for (const se of servlist) {
|
|
@@ -3265,14 +3258,14 @@ const createContainerSpecLikeBom = async (path, options) => {
|
|
|
3265
3258
|
"Enriching your SBoM with information from privado.ai scan reports"
|
|
3266
3259
|
);
|
|
3267
3260
|
let rows = [["Classification", "Flow"]];
|
|
3268
|
-
|
|
3261
|
+
const config = {
|
|
3269
3262
|
header: {
|
|
3270
3263
|
alignment: "center",
|
|
3271
3264
|
content: "Data Privacy Insights from privado.ai"
|
|
3272
3265
|
},
|
|
3273
3266
|
columns: [{ width: 50 }, { width: 10 }]
|
|
3274
3267
|
};
|
|
3275
|
-
for (
|
|
3268
|
+
for (const f of privadoFiles) {
|
|
3276
3269
|
if (DEBUG_MODE) {
|
|
3277
3270
|
console.log(`Parsing ${f}`);
|
|
3278
3271
|
}
|
|
@@ -3281,14 +3274,14 @@ const createContainerSpecLikeBom = async (path, options) => {
|
|
|
3281
3274
|
if (servlist.length) {
|
|
3282
3275
|
const aservice = servlist[0];
|
|
3283
3276
|
if (aservice.data) {
|
|
3284
|
-
for (
|
|
3277
|
+
for (const d of aservice.data) {
|
|
3285
3278
|
rows.push([d.classification, d.flow]);
|
|
3286
3279
|
}
|
|
3287
3280
|
console.log(table(rows, config));
|
|
3288
3281
|
}
|
|
3289
3282
|
if (aservice.endpoints) {
|
|
3290
3283
|
rows = [["Leaky Endpoints"]];
|
|
3291
|
-
for (
|
|
3284
|
+
for (const e of aservice.endpoints) {
|
|
3292
3285
|
rows.push([e]);
|
|
3293
3286
|
}
|
|
3294
3287
|
console.log(
|
|
@@ -3350,7 +3343,7 @@ const createContainerSpecLikeBom = async (path, options) => {
|
|
|
3350
3343
|
* @param path to the project
|
|
3351
3344
|
* @param options Parse options from the cli
|
|
3352
3345
|
*/
|
|
3353
|
-
const createPHPBom =
|
|
3346
|
+
export const createPHPBom = (path, options) => {
|
|
3354
3347
|
const composerJsonFiles = getAllFiles(
|
|
3355
3348
|
path,
|
|
3356
3349
|
(options.multiProject ? "**/" : "") + "composer.json"
|
|
@@ -3383,14 +3376,14 @@ const createPHPBom = async (path, options) => {
|
|
|
3383
3376
|
if (DEBUG_MODE) {
|
|
3384
3377
|
console.log("Parsing version", versionResult.stdout);
|
|
3385
3378
|
}
|
|
3386
|
-
|
|
3379
|
+
const tmpV = undefined;
|
|
3387
3380
|
if (versionResult && versionResult.stdout) {
|
|
3388
3381
|
versionResult.stdout.split(" ");
|
|
3389
3382
|
}
|
|
3390
3383
|
if (tmpV && tmpV.length > 1) {
|
|
3391
3384
|
composerVersion = tmpV[1];
|
|
3392
3385
|
}
|
|
3393
|
-
for (
|
|
3386
|
+
for (const f of composerJsonFiles) {
|
|
3394
3387
|
const basePath = dirname(f);
|
|
3395
3388
|
let args = [];
|
|
3396
3389
|
if (composerVersion && !composerVersion.startsWith("1")) {
|
|
@@ -3416,11 +3409,11 @@ const createPHPBom = async (path, options) => {
|
|
|
3416
3409
|
(options.multiProject ? "**/" : "") + "composer.lock"
|
|
3417
3410
|
);
|
|
3418
3411
|
if (composerLockFiles.length) {
|
|
3419
|
-
for (
|
|
3412
|
+
for (const f of composerLockFiles) {
|
|
3420
3413
|
if (DEBUG_MODE) {
|
|
3421
3414
|
console.log(`Parsing ${f}`);
|
|
3422
3415
|
}
|
|
3423
|
-
|
|
3416
|
+
const dlist = parseComposerLock(f);
|
|
3424
3417
|
if (dlist && dlist.length) {
|
|
3425
3418
|
pkgList = pkgList.concat(dlist);
|
|
3426
3419
|
}
|
|
@@ -3439,7 +3432,7 @@ const createPHPBom = async (path, options) => {
|
|
|
3439
3432
|
* @param path to the project
|
|
3440
3433
|
* @param options Parse options from the cli
|
|
3441
3434
|
*/
|
|
3442
|
-
const createRubyBom = async (path, options) => {
|
|
3435
|
+
export const createRubyBom = async (path, options) => {
|
|
3443
3436
|
const gemFiles = getAllFiles(
|
|
3444
3437
|
path,
|
|
3445
3438
|
(options.multiProject ? "**/" : "") + "Gemfile"
|
|
@@ -3450,9 +3443,9 @@ const createRubyBom = async (path, options) => {
|
|
|
3450
3443
|
);
|
|
3451
3444
|
let pkgList = [];
|
|
3452
3445
|
const gemFileMode = gemFiles.length;
|
|
3453
|
-
|
|
3446
|
+
const gemLockMode = gemLockFiles.length;
|
|
3454
3447
|
if (gemFileMode && !gemLockMode && options.installDeps) {
|
|
3455
|
-
for (
|
|
3448
|
+
for (const f of gemFiles) {
|
|
3456
3449
|
const basePath = dirname(f);
|
|
3457
3450
|
console.log("Executing 'bundle install' in", basePath);
|
|
3458
3451
|
const result = spawnSync("bundle", ["install"], {
|
|
@@ -3473,11 +3466,11 @@ const createRubyBom = async (path, options) => {
|
|
|
3473
3466
|
(options.multiProject ? "**/" : "") + "Gemfile.lock"
|
|
3474
3467
|
);
|
|
3475
3468
|
if (gemLockFiles.length) {
|
|
3476
|
-
for (
|
|
3469
|
+
for (const f of gemLockFiles) {
|
|
3477
3470
|
if (DEBUG_MODE) {
|
|
3478
3471
|
console.log(`Parsing ${f}`);
|
|
3479
3472
|
}
|
|
3480
|
-
|
|
3473
|
+
const gemLockData = readFileSync(f, { encoding: "utf-8" });
|
|
3481
3474
|
const dlist = await parseGemfileLockData(gemLockData);
|
|
3482
3475
|
if (dlist && dlist.length) {
|
|
3483
3476
|
pkgList = pkgList.concat(dlist);
|
|
@@ -3497,8 +3490,9 @@ const createRubyBom = async (path, options) => {
|
|
|
3497
3490
|
* @param path to the project
|
|
3498
3491
|
* @param options Parse options from the cli
|
|
3499
3492
|
*/
|
|
3500
|
-
const createCsharpBom = async (path, options) => {
|
|
3493
|
+
export const createCsharpBom = async (path, options) => {
|
|
3501
3494
|
let manifestFiles = [];
|
|
3495
|
+
let pkgData = undefined;
|
|
3502
3496
|
const csProjFiles = getAllFiles(
|
|
3503
3497
|
path,
|
|
3504
3498
|
(options.multiProject ? "**/" : "") + "*.csproj"
|
|
@@ -3522,7 +3516,7 @@ const createCsharpBom = async (path, options) => {
|
|
|
3522
3516
|
let pkgList = [];
|
|
3523
3517
|
if (nupkgFiles.length) {
|
|
3524
3518
|
manifestFiles = manifestFiles.concat(nupkgFiles);
|
|
3525
|
-
for (
|
|
3519
|
+
for (const nf of nupkgFiles) {
|
|
3526
3520
|
if (DEBUG_MODE) {
|
|
3527
3521
|
console.log(`Parsing ${nf}`);
|
|
3528
3522
|
}
|
|
@@ -3535,11 +3529,11 @@ const createCsharpBom = async (path, options) => {
|
|
|
3535
3529
|
// project.assets.json parsing
|
|
3536
3530
|
if (projAssetsFiles.length) {
|
|
3537
3531
|
manifestFiles = manifestFiles.concat(projAssetsFiles);
|
|
3538
|
-
for (
|
|
3532
|
+
for (const af of projAssetsFiles) {
|
|
3539
3533
|
if (DEBUG_MODE) {
|
|
3540
3534
|
console.log(`Parsing ${af}`);
|
|
3541
3535
|
}
|
|
3542
|
-
|
|
3536
|
+
pkgData = readFileSync(af, { encoding: "utf-8" });
|
|
3543
3537
|
const dlist = await parseCsProjAssetsData(pkgData);
|
|
3544
3538
|
if (dlist && dlist.length) {
|
|
3545
3539
|
pkgList = pkgList.concat(dlist);
|
|
@@ -3548,11 +3542,11 @@ const createCsharpBom = async (path, options) => {
|
|
|
3548
3542
|
} else if (pkgLockFiles.length) {
|
|
3549
3543
|
manifestFiles = manifestFiles.concat(pkgLockFiles);
|
|
3550
3544
|
// packages.lock.json from nuget
|
|
3551
|
-
for (
|
|
3545
|
+
for (const af of pkgLockFiles) {
|
|
3552
3546
|
if (DEBUG_MODE) {
|
|
3553
3547
|
console.log(`Parsing ${af}`);
|
|
3554
3548
|
}
|
|
3555
|
-
|
|
3549
|
+
pkgData = readFileSync(af, { encoding: "utf-8" });
|
|
3556
3550
|
const dlist = await parseCsPkgLockData(pkgData);
|
|
3557
3551
|
if (dlist && dlist.length) {
|
|
3558
3552
|
pkgList = pkgList.concat(dlist);
|
|
@@ -3561,11 +3555,11 @@ const createCsharpBom = async (path, options) => {
|
|
|
3561
3555
|
} else if (pkgConfigFiles.length) {
|
|
3562
3556
|
manifestFiles = manifestFiles.concat(pkgConfigFiles);
|
|
3563
3557
|
// packages.config parsing
|
|
3564
|
-
for (
|
|
3558
|
+
for (const f of pkgConfigFiles) {
|
|
3565
3559
|
if (DEBUG_MODE) {
|
|
3566
3560
|
console.log(`Parsing ${f}`);
|
|
3567
3561
|
}
|
|
3568
|
-
|
|
3562
|
+
pkgData = readFileSync(f, { encoding: "utf-8" });
|
|
3569
3563
|
// Remove byte order mark
|
|
3570
3564
|
if (pkgData.charCodeAt(0) === 0xfeff) {
|
|
3571
3565
|
pkgData = pkgData.slice(1);
|
|
@@ -3578,7 +3572,7 @@ const createCsharpBom = async (path, options) => {
|
|
|
3578
3572
|
} else if (csProjFiles.length) {
|
|
3579
3573
|
manifestFiles = manifestFiles.concat(csProjFiles);
|
|
3580
3574
|
// .csproj parsing
|
|
3581
|
-
for (
|
|
3575
|
+
for (const f of csProjFiles) {
|
|
3582
3576
|
if (DEBUG_MODE) {
|
|
3583
3577
|
console.log(`Parsing ${f}`);
|
|
3584
3578
|
}
|
|
@@ -3602,9 +3596,9 @@ const createCsharpBom = async (path, options) => {
|
|
|
3602
3596
|
return {};
|
|
3603
3597
|
};
|
|
3604
3598
|
|
|
3605
|
-
const mergeDependencies = (dependencies, newDependencies) => {
|
|
3599
|
+
export const mergeDependencies = (dependencies, newDependencies) => {
|
|
3606
3600
|
const deps_map = {};
|
|
3607
|
-
|
|
3601
|
+
const combinedDeps = dependencies.concat(newDependencies || []);
|
|
3608
3602
|
for (const adep of combinedDeps) {
|
|
3609
3603
|
if (!deps_map[adep.ref]) {
|
|
3610
3604
|
deps_map[adep.ref] = new Set();
|
|
@@ -3613,7 +3607,7 @@ const mergeDependencies = (dependencies, newDependencies) => {
|
|
|
3613
3607
|
deps_map[adep.ref].add(eachDepends);
|
|
3614
3608
|
}
|
|
3615
3609
|
}
|
|
3616
|
-
|
|
3610
|
+
const retlist = [];
|
|
3617
3611
|
for (const akey of Object.keys(deps_map)) {
|
|
3618
3612
|
retlist.push({
|
|
3619
3613
|
ref: akey,
|
|
@@ -3622,13 +3616,11 @@ const mergeDependencies = (dependencies, newDependencies) => {
|
|
|
3622
3616
|
}
|
|
3623
3617
|
return retlist;
|
|
3624
3618
|
};
|
|
3625
|
-
const _mergeDependencies = mergeDependencies;
|
|
3626
|
-
export { _mergeDependencies as mergeDependencies };
|
|
3627
3619
|
|
|
3628
|
-
const trimComponents = (components, format) => {
|
|
3620
|
+
export const trimComponents = (components, format) => {
|
|
3629
3621
|
const keyCache = {};
|
|
3630
3622
|
const filteredComponents = [];
|
|
3631
|
-
for (
|
|
3623
|
+
for (const comp of components) {
|
|
3632
3624
|
if (format === "xml" && comp.component) {
|
|
3633
3625
|
if (!keyCache[comp.component.purl]) {
|
|
3634
3626
|
keyCache[comp.component.purl] = true;
|
|
@@ -3643,10 +3635,8 @@ const trimComponents = (components, format) => {
|
|
|
3643
3635
|
}
|
|
3644
3636
|
return filteredComponents;
|
|
3645
3637
|
};
|
|
3646
|
-
const _trimComponents = trimComponents;
|
|
3647
|
-
export { _trimComponents as trimComponents };
|
|
3648
3638
|
|
|
3649
|
-
const dedupeBom = (
|
|
3639
|
+
export const dedupeBom = (
|
|
3650
3640
|
options,
|
|
3651
3641
|
components,
|
|
3652
3642
|
componentsXmls,
|
|
@@ -3694,8 +3684,6 @@ const dedupeBom = (
|
|
|
3694
3684
|
}
|
|
3695
3685
|
};
|
|
3696
3686
|
};
|
|
3697
|
-
const _dedupeBom = dedupeBom;
|
|
3698
|
-
export { _dedupeBom as dedupeBom };
|
|
3699
3687
|
|
|
3700
3688
|
/**
|
|
3701
3689
|
* Function to create bom string for all languages
|
|
@@ -3703,7 +3691,7 @@ export { _dedupeBom as dedupeBom };
|
|
|
3703
3691
|
* @param pathList list of to the project
|
|
3704
3692
|
* @param options Parse options from the cli
|
|
3705
3693
|
*/
|
|
3706
|
-
const createMultiXBom = async (pathList, options) => {
|
|
3694
|
+
export const createMultiXBom = async (pathList, options) => {
|
|
3707
3695
|
let components = [];
|
|
3708
3696
|
let dependencies = [];
|
|
3709
3697
|
let componentsXmls = [];
|
|
@@ -3741,7 +3729,7 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
3741
3729
|
);
|
|
3742
3730
|
}
|
|
3743
3731
|
}
|
|
3744
|
-
for (
|
|
3732
|
+
for (const path of pathList) {
|
|
3745
3733
|
if (DEBUG_MODE) {
|
|
3746
3734
|
console.log("Scanning", path);
|
|
3747
3735
|
}
|
|
@@ -3830,7 +3818,7 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
3830
3818
|
listComponents(options, {}, bomData.bomJson.components, "cargo", "xml")
|
|
3831
3819
|
);
|
|
3832
3820
|
}
|
|
3833
|
-
bomData =
|
|
3821
|
+
bomData = createPHPBom(path, options);
|
|
3834
3822
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3835
3823
|
if (DEBUG_MODE) {
|
|
3836
3824
|
console.log(
|
|
@@ -3954,7 +3942,7 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
3954
3942
|
listComponents(options, {}, bomData.bomJson.components, "conan", "xml")
|
|
3955
3943
|
);
|
|
3956
3944
|
}
|
|
3957
|
-
bomData =
|
|
3945
|
+
bomData = createClojureBom(path, options);
|
|
3958
3946
|
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
3959
3947
|
if (DEBUG_MODE) {
|
|
3960
3948
|
console.log(
|
|
@@ -4014,7 +4002,7 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
4014
4002
|
)
|
|
4015
4003
|
);
|
|
4016
4004
|
}
|
|
4017
|
-
bomData =
|
|
4005
|
+
bomData = createSwiftBom(path, options);
|
|
4018
4006
|
if (
|
|
4019
4007
|
bomData &&
|
|
4020
4008
|
bomData.bomJson &&
|
|
@@ -4035,30 +4023,23 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
4035
4023
|
listComponents(options, {}, bomData.bomJson.components, "swift", "xml")
|
|
4036
4024
|
);
|
|
4037
4025
|
}
|
|
4038
|
-
//
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
);
|
|
4046
|
-
}
|
|
4047
|
-
components = components.concat(bomData.bomJson.components);
|
|
4048
|
-
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
4049
|
-
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
4050
|
-
parentComponent = bomData.parentComponent;
|
|
4051
|
-
}
|
|
4052
|
-
componentsXmls = componentsXmls.concat(
|
|
4053
|
-
listComponents(
|
|
4054
|
-
options,
|
|
4055
|
-
{},
|
|
4056
|
-
bomData.bomJson.components,
|
|
4057
|
-
"maven",
|
|
4058
|
-
"xml"
|
|
4059
|
-
)
|
|
4026
|
+
// Jar scanning is enabled by default
|
|
4027
|
+
// See #330
|
|
4028
|
+
bomData = createJarBom(path, options);
|
|
4029
|
+
if (bomData && bomData.bomJson && bomData.bomJson.components) {
|
|
4030
|
+
if (DEBUG_MODE) {
|
|
4031
|
+
console.log(
|
|
4032
|
+
`Found ${bomData.bomJson.components.length} jar packages at ${path}`
|
|
4060
4033
|
);
|
|
4061
4034
|
}
|
|
4035
|
+
components = components.concat(bomData.bomJson.components);
|
|
4036
|
+
dependencies = dependencies.concat(bomData.bomJson.dependencies);
|
|
4037
|
+
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
4038
|
+
parentComponent = bomData.parentComponent;
|
|
4039
|
+
}
|
|
4040
|
+
componentsXmls = componentsXmls.concat(
|
|
4041
|
+
listComponents(options, {}, bomData.bomJson.components, "maven", "xml")
|
|
4042
|
+
);
|
|
4062
4043
|
}
|
|
4063
4044
|
} // for
|
|
4064
4045
|
if (options.lastWorkingDir && options.lastWorkingDir !== "") {
|
|
@@ -4094,7 +4075,7 @@ const createMultiXBom = async (pathList, options) => {
|
|
|
4094
4075
|
* @param path to the project
|
|
4095
4076
|
* @param options Parse options from the cli
|
|
4096
4077
|
*/
|
|
4097
|
-
const createXBom = async (path, options) => {
|
|
4078
|
+
export const createXBom = async (path, options) => {
|
|
4098
4079
|
try {
|
|
4099
4080
|
accessSync(path, constants.R_OK);
|
|
4100
4081
|
} catch (err) {
|
|
@@ -4115,12 +4096,12 @@ const createXBom = async (path, options) => {
|
|
|
4115
4096
|
(options.multiProject ? "**/" : "") + "pom.xml"
|
|
4116
4097
|
);
|
|
4117
4098
|
// gradle
|
|
4118
|
-
|
|
4099
|
+
const gradleFiles = getAllFiles(
|
|
4119
4100
|
path,
|
|
4120
4101
|
(options.multiProject ? "**/" : "") + "build.gradle*"
|
|
4121
4102
|
);
|
|
4122
4103
|
// scala sbt
|
|
4123
|
-
|
|
4104
|
+
const sbtFiles = getAllFiles(
|
|
4124
4105
|
path,
|
|
4125
4106
|
(options.multiProject ? "**/" : "") + "{build.sbt,Build.scala}*"
|
|
4126
4107
|
);
|
|
@@ -4192,7 +4173,7 @@ const createXBom = async (path, options) => {
|
|
|
4192
4173
|
(options.multiProject ? "**/" : "") + "composer.lock"
|
|
4193
4174
|
);
|
|
4194
4175
|
if (composerJsonFiles.length || composerLockFiles.length) {
|
|
4195
|
-
return
|
|
4176
|
+
return createPHPBom(path, options);
|
|
4196
4177
|
}
|
|
4197
4178
|
|
|
4198
4179
|
// Ruby
|
|
@@ -4271,7 +4252,7 @@ const createXBom = async (path, options) => {
|
|
|
4271
4252
|
(options.multiProject ? "**/" : "") + "project.clj"
|
|
4272
4253
|
);
|
|
4273
4254
|
if (ednFiles.length || leinFiles.length) {
|
|
4274
|
-
return
|
|
4255
|
+
return createClojureBom(path, options);
|
|
4275
4256
|
}
|
|
4276
4257
|
|
|
4277
4258
|
// GitHub actions
|
|
@@ -4338,7 +4319,7 @@ const createXBom = async (path, options) => {
|
|
|
4338
4319
|
(options.multiProject ? "**/" : "") + "Package.resolved"
|
|
4339
4320
|
);
|
|
4340
4321
|
if (swiftFiles.length || pkgResolvedFiles.length) {
|
|
4341
|
-
return
|
|
4322
|
+
return createSwiftBom(path, options);
|
|
4342
4323
|
}
|
|
4343
4324
|
};
|
|
4344
4325
|
|
|
@@ -4474,20 +4455,20 @@ export const createBom = async (path, options) => {
|
|
|
4474
4455
|
return await createJavaBom(path, options);
|
|
4475
4456
|
case "jar":
|
|
4476
4457
|
options.multiProject = true;
|
|
4477
|
-
return
|
|
4458
|
+
return createJarBom(path, options);
|
|
4478
4459
|
case "gradle-index":
|
|
4479
4460
|
case "gradle-cache":
|
|
4480
4461
|
options.multiProject = true;
|
|
4481
|
-
return
|
|
4462
|
+
return createJarBom(GRADLE_CACHE_DIR, options);
|
|
4482
4463
|
case "sbt-index":
|
|
4483
4464
|
case "sbt-cache":
|
|
4484
4465
|
options.multiProject = true;
|
|
4485
|
-
return
|
|
4466
|
+
return createJarBom(SBT_CACHE_DIR, options);
|
|
4486
4467
|
case "maven-index":
|
|
4487
4468
|
case "maven-cache":
|
|
4488
4469
|
case "maven-repo":
|
|
4489
4470
|
options.multiProject = true;
|
|
4490
|
-
return
|
|
4471
|
+
return createJarBom(join(homedir(), ".m2", "repository"), options);
|
|
4491
4472
|
case "nodejs":
|
|
4492
4473
|
case "js":
|
|
4493
4474
|
case "javascript":
|
|
@@ -4510,7 +4491,7 @@ export const createBom = async (path, options) => {
|
|
|
4510
4491
|
return await createRustBom(path, options);
|
|
4511
4492
|
case "php":
|
|
4512
4493
|
options.multiProject = true;
|
|
4513
|
-
return
|
|
4494
|
+
return createPHPBom(path, options);
|
|
4514
4495
|
case "ruby":
|
|
4515
4496
|
options.multiProject = true;
|
|
4516
4497
|
return await createRubyBom(path, options);
|
|
@@ -4545,7 +4526,7 @@ export const createBom = async (path, options) => {
|
|
|
4545
4526
|
case "clj":
|
|
4546
4527
|
case "leiningen":
|
|
4547
4528
|
options.multiProject = true;
|
|
4548
|
-
return
|
|
4529
|
+
return createClojureBom(path, options);
|
|
4549
4530
|
case "github":
|
|
4550
4531
|
case "actions":
|
|
4551
4532
|
options.multiProject = true;
|
|
@@ -4587,7 +4568,7 @@ export const createBom = async (path, options) => {
|
|
|
4587
4568
|
return await createCloudBuildBom(path, options);
|
|
4588
4569
|
case "swift":
|
|
4589
4570
|
options.multiProject = true;
|
|
4590
|
-
return
|
|
4571
|
+
return createSwiftBom(path, options);
|
|
4591
4572
|
default:
|
|
4592
4573
|
// In recurse mode return multi-language Bom
|
|
4593
4574
|
// https://github.com/cyclonedx/cdxgen/issues/95
|
|
@@ -4606,7 +4587,7 @@ export const createBom = async (path, options) => {
|
|
|
4606
4587
|
* @param bomContents BOM Json
|
|
4607
4588
|
*/
|
|
4608
4589
|
export async function submitBom(args, bomContents) {
|
|
4609
|
-
|
|
4590
|
+
const serverUrl = args.serverUrl.replace(/\/$/, "") + "/api/v1/bom";
|
|
4610
4591
|
let encodedBomContents = Buffer.from(JSON.stringify(bomContents)).toString(
|
|
4611
4592
|
"base64"
|
|
4612
4593
|
);
|
|
@@ -4681,3 +4662,38 @@ export async function submitBom(args, bomContents) {
|
|
|
4681
4662
|
}
|
|
4682
4663
|
}
|
|
4683
4664
|
}
|
|
4665
|
+
|
|
4666
|
+
/**
|
|
4667
|
+
* Validate the generated bom using jsonschema
|
|
4668
|
+
*
|
|
4669
|
+
* @param {object} bomJson content
|
|
4670
|
+
*/
|
|
4671
|
+
export const validateBom = (bomJson) => {
|
|
4672
|
+
if (!bomJson) {
|
|
4673
|
+
return true;
|
|
4674
|
+
}
|
|
4675
|
+
const schema = JSON.parse(
|
|
4676
|
+
readFileSync(join(dirName, "data", "bom-1.5.schema.json"))
|
|
4677
|
+
);
|
|
4678
|
+
const defsSchema = JSON.parse(
|
|
4679
|
+
readFileSync(join(dirName, "data", "jsf-0.82.schema.json"))
|
|
4680
|
+
);
|
|
4681
|
+
const spdxSchema = JSON.parse(
|
|
4682
|
+
readFileSync(join(dirName, "data", "spdx.schema.json"))
|
|
4683
|
+
);
|
|
4684
|
+
const ajv = new Ajv({
|
|
4685
|
+
schemas: [schema, defsSchema, spdxSchema],
|
|
4686
|
+
strict: false,
|
|
4687
|
+
logger: false
|
|
4688
|
+
});
|
|
4689
|
+
addFormats(ajv);
|
|
4690
|
+
const validate = ajv.getSchema(
|
|
4691
|
+
"http://cyclonedx.org/schema/bom-1.5.schema.json"
|
|
4692
|
+
);
|
|
4693
|
+
const isValid = validate(bomJson);
|
|
4694
|
+
if (!isValid) {
|
|
4695
|
+
console.log(validate.errors);
|
|
4696
|
+
return false;
|
|
4697
|
+
}
|
|
4698
|
+
return true;
|
|
4699
|
+
};
|