@trustify-da/trustify-da-javascript-client 0.2.4-ea-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/LICENSE +201 -0
- package/README.md +482 -0
- package/config/config.properties +1 -0
- package/dist/package.json +110 -0
- package/dist/src/analysis.d.ts +43 -0
- package/dist/src/analysis.js +252 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +102 -0
- package/dist/src/cyclone_dx_sbom.d.ts +77 -0
- package/dist/src/cyclone_dx_sbom.js +244 -0
- package/dist/src/index.d.ts +82 -0
- package/dist/src/index.js +194 -0
- package/dist/src/oci_image/images.d.ts +99 -0
- package/dist/src/oci_image/images.js +263 -0
- package/dist/src/oci_image/platform.d.ts +59 -0
- package/dist/src/oci_image/platform.js +138 -0
- package/dist/src/oci_image/utils.d.ts +42 -0
- package/dist/src/oci_image/utils.js +496 -0
- package/dist/src/provider.d.ts +29 -0
- package/dist/src/provider.js +47 -0
- package/dist/src/providers/base_java.d.ts +85 -0
- package/dist/src/providers/base_java.js +191 -0
- package/dist/src/providers/base_javascript.d.ts +127 -0
- package/dist/src/providers/base_javascript.js +350 -0
- package/dist/src/providers/golang_gomodules.d.ts +42 -0
- package/dist/src/providers/golang_gomodules.js +403 -0
- package/dist/src/providers/java_gradle.d.ts +35 -0
- package/dist/src/providers/java_gradle.js +399 -0
- package/dist/src/providers/java_gradle_groovy.d.ts +7 -0
- package/dist/src/providers/java_gradle_groovy.js +19 -0
- package/dist/src/providers/java_gradle_kotlin.d.ts +11 -0
- package/dist/src/providers/java_gradle_kotlin.js +23 -0
- package/dist/src/providers/java_maven.d.ts +52 -0
- package/dist/src/providers/java_maven.js +263 -0
- package/dist/src/providers/javascript_npm.d.ts +4 -0
- package/dist/src/providers/javascript_npm.js +15 -0
- package/dist/src/providers/javascript_pnpm.d.ts +5 -0
- package/dist/src/providers/javascript_pnpm.js +22 -0
- package/dist/src/providers/javascript_yarn.d.ts +11 -0
- package/dist/src/providers/javascript_yarn.js +39 -0
- package/dist/src/providers/manifest.d.ts +11 -0
- package/dist/src/providers/manifest.js +48 -0
- package/dist/src/providers/processors/yarn_berry_processor.d.ts +41 -0
- package/dist/src/providers/processors/yarn_berry_processor.js +130 -0
- package/dist/src/providers/processors/yarn_classic_processor.d.ts +37 -0
- package/dist/src/providers/processors/yarn_classic_processor.js +109 -0
- package/dist/src/providers/processors/yarn_processor.d.ts +9 -0
- package/dist/src/providers/processors/yarn_processor.js +20 -0
- package/dist/src/providers/python_controller.d.ts +31 -0
- package/dist/src/providers/python_controller.js +406 -0
- package/dist/src/providers/python_pip.d.ts +35 -0
- package/dist/src/providers/python_pip.js +227 -0
- package/dist/src/sbom.d.ts +59 -0
- package/dist/src/sbom.js +84 -0
- package/dist/src/tools.d.ts +74 -0
- package/dist/src/tools.js +159 -0
- package/package.json +110 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { EOL } from 'os';
|
|
3
|
+
import { PackageURL } from 'packageurl-js';
|
|
4
|
+
import Sbom from '../sbom.js';
|
|
5
|
+
import { environmentVariableIsPopulated, getCustom, getCustomPath, invokeCommand } from "../tools.js";
|
|
6
|
+
import Python_controller from './python_controller.js';
|
|
7
|
+
export default { isSupported, validateLockFile, provideComponent, provideStack };
|
|
8
|
+
/** @typedef {{name: string, version: string, dependencies: DependencyEntry[]}} DependencyEntry */
|
|
9
|
+
/**
|
|
10
|
+
* @type {string} ecosystem for python-pip is 'pip'
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
const ecosystem = 'pip';
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} manifestName - the subject manifest name-type
|
|
16
|
+
* @returns {boolean} - return true if `requirements.txt` is the manifest name-type
|
|
17
|
+
*/
|
|
18
|
+
function isSupported(manifestName) {
|
|
19
|
+
return 'requirements.txt' === manifestName;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} manifestDir - the directory where the manifest lies
|
|
23
|
+
*/
|
|
24
|
+
function validateLockFile() { return true; }
|
|
25
|
+
/**
|
|
26
|
+
* Provide content and content type for python-pip stack analysis.
|
|
27
|
+
* @param {string} manifest - the manifest path or name
|
|
28
|
+
* @param {{}} [opts={}] - optional various options to pass along the application
|
|
29
|
+
* @returns {Provided}
|
|
30
|
+
*/
|
|
31
|
+
function provideStack(manifest, opts = {}) {
|
|
32
|
+
return {
|
|
33
|
+
ecosystem,
|
|
34
|
+
content: createSbomStackAnalysis(manifest, opts),
|
|
35
|
+
contentType: 'application/vnd.cyclonedx+json'
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Provide content and content type for python-pip component analysis.
|
|
40
|
+
* @param {string} manifest - path to requirements.txt for component report
|
|
41
|
+
* @param {{}} [opts={}] - optional various options to pass along the application
|
|
42
|
+
* @returns {Provided}
|
|
43
|
+
*/
|
|
44
|
+
function provideComponent(manifest, opts = {}) {
|
|
45
|
+
return {
|
|
46
|
+
ecosystem,
|
|
47
|
+
content: getSbomForComponentAnalysis(manifest, opts),
|
|
48
|
+
contentType: 'application/vnd.cyclonedx+json'
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** @typedef {{name: string, , version: string, dependencies: DependencyEntry[]}} DependencyEntry */
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param {PackageURL}source
|
|
55
|
+
* @param {DependencyEntry} dep
|
|
56
|
+
* @param {Sbom} sbom
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
function addAllDependencies(source, dep, sbom) {
|
|
60
|
+
let targetPurl = toPurl(dep["name"], dep["version"]);
|
|
61
|
+
sbom.addDependency(source, targetPurl);
|
|
62
|
+
let directDeps = dep["dependencies"];
|
|
63
|
+
if (directDeps !== undefined && directDeps.length > 0) {
|
|
64
|
+
directDeps.forEach((dependency) => { addAllDependencies(toPurl(dep["name"], dep["version"]), dependency, sbom); });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @param nameVersion
|
|
70
|
+
* @return {string}
|
|
71
|
+
*/
|
|
72
|
+
function splitToNameVersion(nameVersion) {
|
|
73
|
+
let result = [];
|
|
74
|
+
if (nameVersion.includes("==")) {
|
|
75
|
+
return nameVersion.split("==");
|
|
76
|
+
}
|
|
77
|
+
const regex = /[^\w\s-_]/g;
|
|
78
|
+
let endIndex = nameVersion.search(regex);
|
|
79
|
+
if (endIndex === -1) {
|
|
80
|
+
return [nameVersion.trim()];
|
|
81
|
+
}
|
|
82
|
+
result.push(nameVersion.substring(0, endIndex).trim());
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
* @param {string} requirementTxtContent
|
|
88
|
+
* @return {PackageURL []}
|
|
89
|
+
*/
|
|
90
|
+
function getIgnoredDependencies(requirementTxtContent) {
|
|
91
|
+
let requirementsLines = requirementTxtContent.split(EOL);
|
|
92
|
+
return requirementsLines
|
|
93
|
+
.filter(line => line.includes("#exhortignore") || line.includes("# exhortignore"))
|
|
94
|
+
.map((line) => line.substring(0, line.indexOf("#")).trim())
|
|
95
|
+
.map((name) => {
|
|
96
|
+
let nameVersion = splitToNameVersion(name);
|
|
97
|
+
if (nameVersion.length === 2) {
|
|
98
|
+
return toPurl(nameVersion[0], nameVersion[1]);
|
|
99
|
+
}
|
|
100
|
+
return toPurl(nameVersion[0], undefined);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @param {string} requirementTxtContent content of requirments.txt in string
|
|
106
|
+
* @param {Sbom} sbom object to filter out from it exhortignore dependencies.
|
|
107
|
+
* @param {{Object}} opts - various options and settings for the application
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
function handleIgnoredDependencies(requirementTxtContent, sbom, opts = {}) {
|
|
111
|
+
let ignoredDeps = getIgnoredDependencies(requirementTxtContent);
|
|
112
|
+
let matchManifestVersions = getCustom("MATCH_MANIFEST_VERSIONS", "true", opts);
|
|
113
|
+
if (matchManifestVersions === "true") {
|
|
114
|
+
const ignoredDepsVersion = ignoredDeps.filter(dep => dep.version !== undefined);
|
|
115
|
+
sbom.filterIgnoredDepsIncludingVersion(ignoredDepsVersion.map(dep => dep.toString()));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// in case of version mismatch, need to parse the name of package from the purl, and remove the package name from sbom according to name only
|
|
119
|
+
// without version
|
|
120
|
+
sbom.filterIgnoredDeps(ignoredDeps);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** get python and pip binaries, python3/pip3 get precedence if exists on the system path
|
|
124
|
+
* @param {object}binaries
|
|
125
|
+
* @param {{}} [opts={}]
|
|
126
|
+
*/
|
|
127
|
+
function getPythonPipBinaries(binaries, opts) {
|
|
128
|
+
let python = getCustomPath("python3", opts);
|
|
129
|
+
let pip = getCustomPath("pip3", opts);
|
|
130
|
+
try {
|
|
131
|
+
invokeCommand(python, ['--version']);
|
|
132
|
+
invokeCommand(pip, ['--version']);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
python = getCustomPath("python", opts);
|
|
136
|
+
pip = getCustomPath("pip", opts);
|
|
137
|
+
try {
|
|
138
|
+
invokeCommand(python, ['--version']);
|
|
139
|
+
invokeCommand(pip, ['--version']);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new Error(`Failed checking for python/pip binaries from supplied environment variables`, { cause: error });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
binaries.pip = pip;
|
|
146
|
+
binaries.python = python;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
*
|
|
150
|
+
* @param binaries
|
|
151
|
+
* @param opts
|
|
152
|
+
* @return {string}
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
function handlePythonEnvironment(binaries, opts) {
|
|
156
|
+
let createVirtualPythonEnv;
|
|
157
|
+
if (!environmentVariableIsPopulated("TRUSTIFY_DA_PIP_SHOW") && !environmentVariableIsPopulated("TRUSTIFY_DA_PIP_FREEZE")) {
|
|
158
|
+
getPythonPipBinaries(binaries, opts);
|
|
159
|
+
createVirtualPythonEnv = getCustom("TRUSTIFY_DA_PYTHON_VIRTUAL_ENV", "false", opts);
|
|
160
|
+
}
|
|
161
|
+
// bypass invoking python and pip, as we get all information needed to build the dependency tree from these Environment variables.
|
|
162
|
+
else {
|
|
163
|
+
binaries.pip = "pip";
|
|
164
|
+
binaries.python = "python";
|
|
165
|
+
createVirtualPythonEnv = "false";
|
|
166
|
+
}
|
|
167
|
+
return createVirtualPythonEnv;
|
|
168
|
+
}
|
|
169
|
+
const DEFAULT_PIP_ROOT_COMPONENT_NAME = "default-pip-root";
|
|
170
|
+
const DEFAULT_PIP_ROOT_COMPONENT_VERSION = "0.0.0";
|
|
171
|
+
/**
|
|
172
|
+
* Create sbom json string out of a manifest path for stack analysis.
|
|
173
|
+
* @param {string} manifest - path for requirements.txt
|
|
174
|
+
* @param {{}} [opts={}] - optional various options to pass along the application
|
|
175
|
+
* @returns {string} the sbom json string content
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
function createSbomStackAnalysis(manifest, opts = {}) {
|
|
179
|
+
let binaries = {};
|
|
180
|
+
let createVirtualPythonEnv = handlePythonEnvironment(binaries, opts);
|
|
181
|
+
let pythonController = new Python_controller(createVirtualPythonEnv === "false", binaries.pip, binaries.python, manifest, opts);
|
|
182
|
+
let dependencies = pythonController.getDependencies(true);
|
|
183
|
+
let sbom = new Sbom();
|
|
184
|
+
const rootPurl = toPurl(DEFAULT_PIP_ROOT_COMPONENT_NAME, DEFAULT_PIP_ROOT_COMPONENT_VERSION);
|
|
185
|
+
sbom.addRoot(rootPurl);
|
|
186
|
+
dependencies.forEach(dep => {
|
|
187
|
+
addAllDependencies(rootPurl, dep, sbom);
|
|
188
|
+
});
|
|
189
|
+
let requirementTxtContent = fs.readFileSync(manifest).toString();
|
|
190
|
+
handleIgnoredDependencies(requirementTxtContent, sbom, opts);
|
|
191
|
+
// In python there is no root component, then we must remove the dummy root we added, so the sbom json will be accepted by exhort backend
|
|
192
|
+
// sbom.removeRootComponent()
|
|
193
|
+
return sbom.getAsJsonString(opts);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Create a sbom json string out of a manifest content for component analysis
|
|
197
|
+
* @param {string} manifest - path to requirements.txt
|
|
198
|
+
* @param {{}} [opts={}] - optional various options to pass along the application
|
|
199
|
+
* @returns {string} the sbom json string content
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
function getSbomForComponentAnalysis(manifest, opts = {}) {
|
|
203
|
+
let binaries = {};
|
|
204
|
+
let createVirtualPythonEnv = handlePythonEnvironment(binaries, opts);
|
|
205
|
+
let pythonController = new Python_controller(createVirtualPythonEnv === "false", binaries.pip, binaries.python, manifest, opts);
|
|
206
|
+
let dependencies = pythonController.getDependencies(false);
|
|
207
|
+
let sbom = new Sbom();
|
|
208
|
+
const rootPurl = toPurl(DEFAULT_PIP_ROOT_COMPONENT_NAME, DEFAULT_PIP_ROOT_COMPONENT_VERSION);
|
|
209
|
+
sbom.addRoot(rootPurl);
|
|
210
|
+
dependencies.forEach(dep => {
|
|
211
|
+
sbom.addDependency(rootPurl, toPurl(dep.name, dep.version));
|
|
212
|
+
});
|
|
213
|
+
let requirementTxtContent = fs.readFileSync(manifest).toString();
|
|
214
|
+
handleIgnoredDependencies(requirementTxtContent, sbom, opts);
|
|
215
|
+
// In python there is no root component, then we must remove the dummy root we added, so the sbom json will be accepted by exhort backend
|
|
216
|
+
// sbom.removeRootComponent()
|
|
217
|
+
return sbom.getAsJsonString(opts);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Returns a PackageUrl For pip dependencies
|
|
221
|
+
* @param name
|
|
222
|
+
* @param version
|
|
223
|
+
* @return {PackageURL}
|
|
224
|
+
*/
|
|
225
|
+
function toPurl(name, version) {
|
|
226
|
+
return new PackageURL('pypi', undefined, name, version, undefined, undefined);
|
|
227
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export default class Sbom {
|
|
2
|
+
sbomModel: CycloneDxSbom;
|
|
3
|
+
/**
|
|
4
|
+
* @param {PackageURL} root - add main/root component for sbom
|
|
5
|
+
* @return Sbom
|
|
6
|
+
*/
|
|
7
|
+
addRoot(root: PackageURL): CycloneDxSbom;
|
|
8
|
+
/**
|
|
9
|
+
* @return {{{"bom-ref": string, name, purl: string, type, version}}} root component of sbom.
|
|
10
|
+
*/
|
|
11
|
+
getRoot(): {};
|
|
12
|
+
/**
|
|
13
|
+
* This method gets an array of dependencies to be ignored, and remove all of them from sbom
|
|
14
|
+
* @param {Array} dependencies to be removed from sbom
|
|
15
|
+
* @return {Sbom} without ignored dependencies
|
|
16
|
+
*/
|
|
17
|
+
filterIgnoredDeps(deps: any): Sbom;
|
|
18
|
+
/**
|
|
19
|
+
* This method gets an array of dependencies with versions( purl string format) to be ignored, and remove all of them from CycloneDx Sbom
|
|
20
|
+
* @param {Array} dependencies to be removed from sbom
|
|
21
|
+
* @return {CycloneDxSbom} without ignored dependencies
|
|
22
|
+
*/
|
|
23
|
+
filterIgnoredDepsIncludingVersion(deps: any): CycloneDxSbom;
|
|
24
|
+
/**
|
|
25
|
+
* @param {component} sourceRef current source Component ( Starting from root component by clients)
|
|
26
|
+
* @param {PackageURL} targetRef current dependency to add to Dependencies list of component sourceRef
|
|
27
|
+
* @return Sbom
|
|
28
|
+
*/
|
|
29
|
+
addDependency(sourceRef: component, targetRef: PackageURL, scope: any): CycloneDxSbom;
|
|
30
|
+
/**
|
|
31
|
+
* @return String sbom json in a string format
|
|
32
|
+
*/
|
|
33
|
+
getAsJsonString(opts?: {}): string;
|
|
34
|
+
/**
|
|
35
|
+
* This method gets a PackageUrl, and returns a Component of Sbom
|
|
36
|
+
* @param purl {PackageURL}
|
|
37
|
+
* @return component
|
|
38
|
+
*/
|
|
39
|
+
purlToComponent(purl: PackageURL): {
|
|
40
|
+
"bom-ref": string;
|
|
41
|
+
name: any;
|
|
42
|
+
purl: string;
|
|
43
|
+
type: any;
|
|
44
|
+
version: any;
|
|
45
|
+
scope: any;
|
|
46
|
+
};
|
|
47
|
+
/** This method gets a component object, and a string name, and checks if the name is a substring of the component' purl.
|
|
48
|
+
* @param {} component to search in its dependencies
|
|
49
|
+
* @param {String} name to be checked.
|
|
50
|
+
*
|
|
51
|
+
* @return {boolean}
|
|
52
|
+
*/
|
|
53
|
+
checkIfPackageInsideDependsOnList(component: any, name: string): boolean;
|
|
54
|
+
/** Removes the root component from the sbom
|
|
55
|
+
*/
|
|
56
|
+
removeRootComponent(): void;
|
|
57
|
+
#private;
|
|
58
|
+
}
|
|
59
|
+
import CycloneDxSbom from "./cyclone_dx_sbom.js";
|
package/dist/src/sbom.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import CycloneDxSbom from "./cyclone_dx_sbom.js";
|
|
2
|
+
export default class Sbom {
|
|
3
|
+
sbomModel;
|
|
4
|
+
#startTime;
|
|
5
|
+
#endTime;
|
|
6
|
+
constructor() {
|
|
7
|
+
if (process.env["TRUSTIFY_DA_DEBUG"] === "true") {
|
|
8
|
+
this.#startTime = new Date();
|
|
9
|
+
console.log("Starting time to create sbom = " + this.#startTime);
|
|
10
|
+
}
|
|
11
|
+
this.sbomModel = new CycloneDxSbom();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @param {PackageURL} root - add main/root component for sbom
|
|
15
|
+
* @return Sbom
|
|
16
|
+
*/
|
|
17
|
+
addRoot(root) {
|
|
18
|
+
return this.sbomModel.addRoot(root);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @return {{{"bom-ref": string, name, purl: string, type, version}}} root component of sbom.
|
|
22
|
+
*/
|
|
23
|
+
getRoot() {
|
|
24
|
+
return this.sbomModel.getRoot();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* This method gets an array of dependencies to be ignored, and remove all of them from sbom
|
|
28
|
+
* @param {Array} dependencies to be removed from sbom
|
|
29
|
+
* @return {Sbom} without ignored dependencies
|
|
30
|
+
*/
|
|
31
|
+
filterIgnoredDeps(deps) {
|
|
32
|
+
return this.sbomModel.filterIgnoredDeps(deps);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* This method gets an array of dependencies with versions( purl string format) to be ignored, and remove all of them from CycloneDx Sbom
|
|
36
|
+
* @param {Array} dependencies to be removed from sbom
|
|
37
|
+
* @return {CycloneDxSbom} without ignored dependencies
|
|
38
|
+
*/
|
|
39
|
+
filterIgnoredDepsIncludingVersion(deps) {
|
|
40
|
+
return this.sbomModel.filterIgnoredDepsIncludingVersion(deps);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @param {component} sourceRef current source Component ( Starting from root component by clients)
|
|
44
|
+
* @param {PackageURL} targetRef current dependency to add to Dependencies list of component sourceRef
|
|
45
|
+
* @return Sbom
|
|
46
|
+
*/
|
|
47
|
+
addDependency(sourceRef, targetRef, scope) {
|
|
48
|
+
return this.sbomModel.addDependency(sourceRef, targetRef, scope);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @return String sbom json in a string format
|
|
52
|
+
*/
|
|
53
|
+
getAsJsonString(opts = {}) {
|
|
54
|
+
if (process.env["TRUSTIFY_DA_DEBUG"] === "true") {
|
|
55
|
+
this.#endTime = new Date();
|
|
56
|
+
console.log("Ending time to create sbom = " + this.#endTime);
|
|
57
|
+
let time = (this.#endTime - this.#startTime) / 1000;
|
|
58
|
+
console.log("Total time in seconds to create sbom = " + time);
|
|
59
|
+
}
|
|
60
|
+
return this.sbomModel.getAsJsonString(opts);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* This method gets a PackageUrl, and returns a Component of Sbom
|
|
64
|
+
* @param purl {PackageURL}
|
|
65
|
+
* @return component
|
|
66
|
+
*/
|
|
67
|
+
purlToComponent(purl) {
|
|
68
|
+
return this.sbomModel.purlToComponent(purl);
|
|
69
|
+
}
|
|
70
|
+
/** This method gets a component object, and a string name, and checks if the name is a substring of the component' purl.
|
|
71
|
+
* @param {} component to search in its dependencies
|
|
72
|
+
* @param {String} name to be checked.
|
|
73
|
+
*
|
|
74
|
+
* @return {boolean}
|
|
75
|
+
*/
|
|
76
|
+
checkIfPackageInsideDependsOnList(component, name) {
|
|
77
|
+
return this.sbomModel.checkIfPackageInsideDependsOnList(component, name);
|
|
78
|
+
}
|
|
79
|
+
/** Removes the root component from the sbom
|
|
80
|
+
*/
|
|
81
|
+
removeRootComponent() {
|
|
82
|
+
return this.sbomModel.removeRootComponent();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="packageurl-js/src/package-url" />
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {string} key to log its value from environment variables and from opts, if it exists
|
|
6
|
+
* @param {{}} [opts={}] different options of application, if key in it, log it.
|
|
7
|
+
* @param {string }defValue default value of key in case there is no option and environment variable values for key
|
|
8
|
+
*/
|
|
9
|
+
export function logValueFromObjects(key: string, opts?: {} | undefined, defValue: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Utility function will return the value for key from the environment variables,
|
|
12
|
+
* if not present will return the value for key from the opts objects only if it's a string,
|
|
13
|
+
* if not present, or not string will return the default value supplied which default to null.
|
|
14
|
+
* @param {string} key the key to look for in the environment variables and the opts object
|
|
15
|
+
* @param {string|null} [def=null] the value to return if nothing else found
|
|
16
|
+
* @param {{}} [opts={}] the options object to look for the key in if not found in environment
|
|
17
|
+
* @returns {string|null} the value of the key found in the environment, options object, or the
|
|
18
|
+
* default supplied
|
|
19
|
+
*/
|
|
20
|
+
export function getCustom(key: string, def?: string | null | undefined, opts?: {} | undefined): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Utility function for looking up custom variable for a binary path.
|
|
23
|
+
* Will look in the environment variables (1) or in opts (2) for a key with TRUSTIFY_DA_x_PATH, x is an
|
|
24
|
+
* uppercase version of passed name to look for. The name will also be returned if nothing else was
|
|
25
|
+
* found.
|
|
26
|
+
* @param name the binary name to look for, will be returned as value in nothing else found
|
|
27
|
+
* @param {{}} [opts={}] the options object to look for the key in if not found in environment
|
|
28
|
+
* @returns {string|null} the value of the key found in the environment, options object, or the
|
|
29
|
+
* original name supplied
|
|
30
|
+
*/
|
|
31
|
+
export function getCustomPath(name: any, opts?: {} | undefined): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Utility function for determining whether wrappers for build tools such as gradlew/mvnw should be
|
|
34
|
+
* preferred over invoking the binary directly.
|
|
35
|
+
* @param {string} name - binary for which to search for its wrapper
|
|
36
|
+
* @param {{}} opts - the options object to look for the key in if not found in environment
|
|
37
|
+
* @returns {boolean} whether to prefer the wrapper if exists or not
|
|
38
|
+
*/
|
|
39
|
+
export function getWrapperPreference(name: string, opts?: {}): boolean;
|
|
40
|
+
export function environmentVariableIsPopulated(envVariableName: any): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Utility function for handling spaces in paths on Windows
|
|
43
|
+
* @param {string} path - path to be checked if contains spaces
|
|
44
|
+
* @return {string} a path with all spaces escaped or manipulated so it will be able to be part
|
|
45
|
+
* of commands that will be invoked without errors in os' shell.
|
|
46
|
+
*/
|
|
47
|
+
export function handleSpacesInPath(path: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Utility function for creating Purl String
|
|
50
|
+
* @param name the name of the artifact, can include a namespace(group) or not - namespace/artifactName.
|
|
51
|
+
* @param version the version of the artifact
|
|
52
|
+
* @returns {PackageURL|null} PackageUrl Object ready to be used in SBOM
|
|
53
|
+
*/
|
|
54
|
+
export function toPurl(type: any, name: any, version: any): PackageURL | null;
|
|
55
|
+
/**
|
|
56
|
+
* Utility function for creating Purl Object from a Purl String
|
|
57
|
+
* @param strPurl the Purl String
|
|
58
|
+
* @returns {PackageURL|null} PackageUrl Object ready to be used in SBOM
|
|
59
|
+
*/
|
|
60
|
+
export function toPurlFromString(strPurl: any): PackageURL | null;
|
|
61
|
+
/**
|
|
62
|
+
*
|
|
63
|
+
* @param {string} cwd - directory for which to find the root of the git repository.
|
|
64
|
+
*/
|
|
65
|
+
export function getGitRootDir(cwd: string): string | undefined;
|
|
66
|
+
/** this method invokes command string in a process in a synchronous way.
|
|
67
|
+
* @param {string} bin - the command to be invoked
|
|
68
|
+
* @param {Array<string>} args - the args to pass to the binary
|
|
69
|
+
* @param {import('child_process').ExecFileOptionsWithStringEncoding} [opts={}]
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
export function invokeCommand(bin: string, args: Array<string>, opts?: import("child_process").ExecFileOptionsWithStringEncoding | undefined): string;
|
|
73
|
+
export const RegexNotToBeLogged: RegExp;
|
|
74
|
+
import { PackageURL } from "packageurl-js";
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { EOL } from "os";
|
|
3
|
+
import { PackageURL } from "packageurl-js";
|
|
4
|
+
export const RegexNotToBeLogged = /TRUSTIFY_DA_.*_TOKEN|ex-.*-token/;
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {string} key to log its value from environment variables and from opts, if it exists
|
|
8
|
+
* @param {{}} [opts={}] different options of application, if key in it, log it.
|
|
9
|
+
* @param {string }defValue default value of key in case there is no option and environment variable values for key
|
|
10
|
+
*/
|
|
11
|
+
export function logValueFromObjects(key, opts, defValue) {
|
|
12
|
+
if (key in opts) {
|
|
13
|
+
console.log(`value of option with key ${key} = ${opts[key]} ${EOL}`);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
console.log(`key ${key} doesn't exists on opts object ${EOL}`);
|
|
17
|
+
}
|
|
18
|
+
if (key in process.env) {
|
|
19
|
+
console.log(`value of environment variable ${key} = ${process.env[key]} ${EOL}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log(`environment variable ${key} doesn't exists ${EOL}`);
|
|
23
|
+
}
|
|
24
|
+
console.log(`default value for ${key} = ${defValue} ${EOL}`);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Utility function will return the value for key from the environment variables,
|
|
28
|
+
* if not present will return the value for key from the opts objects only if it's a string,
|
|
29
|
+
* if not present, or not string will return the default value supplied which default to null.
|
|
30
|
+
* @param {string} key the key to look for in the environment variables and the opts object
|
|
31
|
+
* @param {string|null} [def=null] the value to return if nothing else found
|
|
32
|
+
* @param {{}} [opts={}] the options object to look for the key in if not found in environment
|
|
33
|
+
* @returns {string|null} the value of the key found in the environment, options object, or the
|
|
34
|
+
* default supplied
|
|
35
|
+
*/
|
|
36
|
+
export function getCustom(key, def = null, opts = {}) {
|
|
37
|
+
if (process.env["TRUSTIFY_DA_DEBUG"] === "true" && !key.match(RegexNotToBeLogged)) {
|
|
38
|
+
logValueFromObjects(key, opts, def);
|
|
39
|
+
}
|
|
40
|
+
return key in process.env ? process.env[key] : key in opts && typeof opts[key] === 'string' ? opts[key] : def;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Utility function for looking up custom variable for a binary path.
|
|
44
|
+
* Will look in the environment variables (1) or in opts (2) for a key with TRUSTIFY_DA_x_PATH, x is an
|
|
45
|
+
* uppercase version of passed name to look for. The name will also be returned if nothing else was
|
|
46
|
+
* found.
|
|
47
|
+
* @param name the binary name to look for, will be returned as value in nothing else found
|
|
48
|
+
* @param {{}} [opts={}] the options object to look for the key in if not found in environment
|
|
49
|
+
* @returns {string|null} the value of the key found in the environment, options object, or the
|
|
50
|
+
* original name supplied
|
|
51
|
+
*/
|
|
52
|
+
export function getCustomPath(name, opts = {}) {
|
|
53
|
+
return getCustom(`TRUSTIFY_DA_${name.toUpperCase()}_PATH`, name, opts);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Utility function for determining whether wrappers for build tools such as gradlew/mvnw should be
|
|
57
|
+
* preferred over invoking the binary directly.
|
|
58
|
+
* @param {string} name - binary for which to search for its wrapper
|
|
59
|
+
* @param {{}} opts - the options object to look for the key in if not found in environment
|
|
60
|
+
* @returns {boolean} whether to prefer the wrapper if exists or not
|
|
61
|
+
*/
|
|
62
|
+
export function getWrapperPreference(name, opts = {}) {
|
|
63
|
+
return getCustom(`TRUSTIFY_DA_PREFER_${name.toUpperCase()}W`, 'true', opts) === 'true';
|
|
64
|
+
}
|
|
65
|
+
export function environmentVariableIsPopulated(envVariableName) {
|
|
66
|
+
return envVariableName in process.env && process.env[envVariableName].trim() !== "";
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Utility function for handling spaces in paths on Windows
|
|
70
|
+
* @param {string} path - path to be checked if contains spaces
|
|
71
|
+
* @return {string} a path with all spaces escaped or manipulated so it will be able to be part
|
|
72
|
+
* of commands that will be invoked without errors in os' shell.
|
|
73
|
+
*/
|
|
74
|
+
export function handleSpacesInPath(path) {
|
|
75
|
+
let transformedPath = path;
|
|
76
|
+
// if operating system is windows
|
|
77
|
+
if (hasSpaces(path)) {
|
|
78
|
+
transformedPath = `"${path}"`;
|
|
79
|
+
}
|
|
80
|
+
return transformedPath;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* @param {string} path the path to check if contains spaces
|
|
85
|
+
* @return {boolean} returns true if path contains spaces
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
function hasSpaces(path) {
|
|
89
|
+
return path.trim().includes(" ");
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Utility function for creating Purl String
|
|
93
|
+
* @param name the name of the artifact, can include a namespace(group) or not - namespace/artifactName.
|
|
94
|
+
* @param version the version of the artifact
|
|
95
|
+
* @returns {PackageURL|null} PackageUrl Object ready to be used in SBOM
|
|
96
|
+
*/
|
|
97
|
+
export function toPurl(type, name, version) {
|
|
98
|
+
let parts = name.split("/");
|
|
99
|
+
var purlNs, purlName;
|
|
100
|
+
if (parts.length === 2) {
|
|
101
|
+
purlNs = parts[0];
|
|
102
|
+
purlName = parts[1];
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
purlName = parts[0];
|
|
106
|
+
}
|
|
107
|
+
return new PackageURL(type, purlNs, purlName, version, undefined, undefined);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Utility function for creating Purl Object from a Purl String
|
|
111
|
+
* @param strPurl the Purl String
|
|
112
|
+
* @returns {PackageURL|null} PackageUrl Object ready to be used in SBOM
|
|
113
|
+
*/
|
|
114
|
+
export function toPurlFromString(strPurl) {
|
|
115
|
+
return PackageURL.fromString(strPurl);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param {string} cwd - directory for which to find the root of the git repository.
|
|
120
|
+
*/
|
|
121
|
+
export function getGitRootDir(cwd) {
|
|
122
|
+
try {
|
|
123
|
+
const root = invokeCommand('git', ['rev-parse', '--show-toplevel'], { cwd: cwd });
|
|
124
|
+
return root.toString().trim();
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** this method invokes command string in a process in a synchronous way.
|
|
131
|
+
* @param {string} bin - the command to be invoked
|
|
132
|
+
* @param {Array<string>} args - the args to pass to the binary
|
|
133
|
+
* @param {import('child_process').ExecFileOptionsWithStringEncoding} [opts={}]
|
|
134
|
+
* @returns {string}
|
|
135
|
+
*/
|
|
136
|
+
export function invokeCommand(bin, args, opts = {}) {
|
|
137
|
+
// .bat and .cmd files can't be executed in windows with execFileSync without {shell: true}, so we
|
|
138
|
+
// special case them here to keep the amount of escaping we need to do to a minimum.
|
|
139
|
+
// https://nodejs.org/docs/latest-v20.x/api/child_process.html#spawning-bat-and-cmd-files-on-windows
|
|
140
|
+
// https://github.com/nodejs/node/issues/52681#issuecomment-2076426887
|
|
141
|
+
if (process.platform === 'win32') {
|
|
142
|
+
opts = { ...opts, shell: true };
|
|
143
|
+
args = args.map(arg => handleSpacesInPath(arg));
|
|
144
|
+
bin = handleSpacesInPath(bin);
|
|
145
|
+
}
|
|
146
|
+
opts = {
|
|
147
|
+
...opts,
|
|
148
|
+
env: {
|
|
149
|
+
...process.env,
|
|
150
|
+
PATH: process.env.PATH
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
// Add maxBuffer option to handle large outputs
|
|
154
|
+
opts = {
|
|
155
|
+
...opts,
|
|
156
|
+
maxBuffer: 10 * 1024 * 1024 // 10MB buffer
|
|
157
|
+
};
|
|
158
|
+
return execFileSync(bin, args, { ...{ stdio: 'pipe', encoding: 'utf-8' }, ...opts });
|
|
159
|
+
}
|