@trustify-da/trustify-da-javascript-client 0.2.4-ea.13
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 +106 -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 +106 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { EOL } from "os";
|
|
2
|
+
import { PackageURL } from "packageurl-js";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param component {PackageURL}
|
|
6
|
+
* @param type type of package - application or library
|
|
7
|
+
* @param scope scope of the component - runtime or compile
|
|
8
|
+
* @return {{"bom-ref": string, name, purl: string, type, version, scope}}
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
function getComponent(component, type, scope) {
|
|
12
|
+
let componentObject;
|
|
13
|
+
if (component instanceof PackageURL) {
|
|
14
|
+
if (component.namespace) {
|
|
15
|
+
componentObject = {
|
|
16
|
+
"group": component.namespace,
|
|
17
|
+
"name": component.name,
|
|
18
|
+
"version": component.version,
|
|
19
|
+
"purl": component.toString(),
|
|
20
|
+
"type": type,
|
|
21
|
+
"bom-ref": component.toString(),
|
|
22
|
+
"scope": scope
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
componentObject = {
|
|
27
|
+
"name": component.name,
|
|
28
|
+
"version": component.version,
|
|
29
|
+
"purl": component.toString(),
|
|
30
|
+
"type": type,
|
|
31
|
+
"bom-ref": component.toString(),
|
|
32
|
+
"scope": scope
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
componentObject = component;
|
|
38
|
+
}
|
|
39
|
+
return componentObject;
|
|
40
|
+
}
|
|
41
|
+
function createDependency(dependency) {
|
|
42
|
+
return {
|
|
43
|
+
"ref": dependency,
|
|
44
|
+
"dependsOn": new Array()
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export default class CycloneDxSbom {
|
|
48
|
+
sbomObject;
|
|
49
|
+
rootComponent;
|
|
50
|
+
components;
|
|
51
|
+
dependencies;
|
|
52
|
+
sourceManifestForAuditTrail;
|
|
53
|
+
constructor() {
|
|
54
|
+
this.dependencies = new Array();
|
|
55
|
+
this.components = new Array();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* @param {PackageURL} root - add main/root component for sbom
|
|
59
|
+
* @return {CycloneDxSbom} the CycloneDxSbom Sbom Object
|
|
60
|
+
*/
|
|
61
|
+
addRoot(root) {
|
|
62
|
+
this.rootComponent =
|
|
63
|
+
getComponent(root, "application");
|
|
64
|
+
this.components.push(this.rootComponent);
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @return {{{"bom-ref": string, name, purl: string, type, version}}} root component of sbom.
|
|
69
|
+
*/
|
|
70
|
+
getRoot() {
|
|
71
|
+
return this.rootComponent;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Adds a dependency relationship between two components in the SBOM
|
|
75
|
+
* @param {PackageURL} sourceRef - The source component (parent)
|
|
76
|
+
* @param {PackageURL} targetRef - The target component (dependency)
|
|
77
|
+
* @return {CycloneDxSbom} The updated SBOM
|
|
78
|
+
*/
|
|
79
|
+
addDependency(sourceRef, targetRef, scope) {
|
|
80
|
+
const sourcePurl = sourceRef.toString();
|
|
81
|
+
const targetPurl = targetRef.toString();
|
|
82
|
+
// Ensure both components exist in the components list
|
|
83
|
+
[sourceRef, targetRef].forEach((ref, index) => {
|
|
84
|
+
const purl = index === 0 ? sourcePurl : targetPurl;
|
|
85
|
+
if (this.getComponentIndex(purl) < 0) {
|
|
86
|
+
this.components.push(getComponent(ref, "library", scope));
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// Ensure source dependency exists
|
|
90
|
+
let sourceDepIndex = this.getDependencyIndex(sourcePurl);
|
|
91
|
+
if (sourceDepIndex < 0) {
|
|
92
|
+
this.dependencies.push(createDependency(sourcePurl));
|
|
93
|
+
sourceDepIndex = this.dependencies.length - 1;
|
|
94
|
+
}
|
|
95
|
+
// Add target to source's dependencies if not already present
|
|
96
|
+
if (!this.dependencies[sourceDepIndex].dependsOn.includes(targetPurl)) {
|
|
97
|
+
this.dependencies[sourceDepIndex].dependsOn.push(targetPurl);
|
|
98
|
+
}
|
|
99
|
+
// Ensure target dependency exists
|
|
100
|
+
if (this.getDependencyIndex(targetPurl) < 0) {
|
|
101
|
+
this.dependencies.push(createDependency(targetPurl));
|
|
102
|
+
}
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
/** @param {{}} opts - various options, settings and configuration of application.
|
|
106
|
+
* @return String CycloneDx Sbom json object in a string format
|
|
107
|
+
*/
|
|
108
|
+
getAsJsonString(opts) {
|
|
109
|
+
let manifestType = opts["manifest-type"];
|
|
110
|
+
this.setSourceManifest(opts["source-manifest"]);
|
|
111
|
+
this.sbomObject = {
|
|
112
|
+
"bomFormat": "CycloneDX",
|
|
113
|
+
"specVersion": "1.4",
|
|
114
|
+
"version": 1,
|
|
115
|
+
"metadata": {
|
|
116
|
+
"timestamp": new Date(),
|
|
117
|
+
"component": this.rootComponent,
|
|
118
|
+
"properties": new Array()
|
|
119
|
+
},
|
|
120
|
+
"components": this.components,
|
|
121
|
+
"dependencies": this.dependencies
|
|
122
|
+
};
|
|
123
|
+
if (this.rootComponent === undefined) {
|
|
124
|
+
delete this.sbomObject.metadata.component;
|
|
125
|
+
}
|
|
126
|
+
if (this.sourceManifestForAuditTrail !== undefined && manifestType !== undefined) {
|
|
127
|
+
this.sbomObject.metadata.properties.push({ "name": "rhda:manifest:content", "value": this.sourceManifestForAuditTrail });
|
|
128
|
+
this.sbomObject.metadata.properties.push({ "name": "rhda:manifest:filename", "value": manifestType });
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
delete this.sbomObject.metadata.properties;
|
|
132
|
+
}
|
|
133
|
+
if (process.env["TRUSTIFY_DA_DEBUG"] === "true") {
|
|
134
|
+
console.log("SBOM Generated for manifest, to be sent to exhort service:" + EOL + JSON.stringify(this.sbomObject, null, 4));
|
|
135
|
+
}
|
|
136
|
+
return JSON.stringify(this.sbomObject);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
*
|
|
140
|
+
* @param {String} dependency - purl string of the component.
|
|
141
|
+
* @return {int} - the index of the dependency in dependencies Array, returns -1 if not found.
|
|
142
|
+
*/
|
|
143
|
+
getDependencyIndex(dependency) {
|
|
144
|
+
return this.dependencies.findIndex(dep => dep.ref === dependency);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
*
|
|
148
|
+
* @param {component} theComponent - Component Object with purl field.
|
|
149
|
+
* @return {int} index of the found component entry, if not found returns -1.
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
152
|
+
getComponentIndex(theComponent) {
|
|
153
|
+
return this.components.findIndex(component => component.purl === theComponent);
|
|
154
|
+
}
|
|
155
|
+
/** This method gets a PackageUrl, and returns a Component of CycloneDx Sbom
|
|
156
|
+
* @param purl {PackageURL}
|
|
157
|
+
* @return component
|
|
158
|
+
*/
|
|
159
|
+
purlToComponent(purl) {
|
|
160
|
+
return getComponent(purl, "library");
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* This method gets an array of dependencies to be ignored, and remove all of them from CycloneDx Sbom
|
|
164
|
+
* @param {Array[PackageURL]} dependencies to be removed from sbom
|
|
165
|
+
* @return {CycloneDxSbom} without ignored dependencies
|
|
166
|
+
*/
|
|
167
|
+
filterIgnoredDeps(deps) {
|
|
168
|
+
deps.forEach(dep => {
|
|
169
|
+
let index = this.components.findIndex(component => component.name === dep.name && component.group === dep.namespace);
|
|
170
|
+
if (index === -1) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const depPurl = this.components[index].purl;
|
|
174
|
+
this.components.splice(index, 1);
|
|
175
|
+
index = this.dependencies.findIndex(dependency => dependency.ref.includes(dep));
|
|
176
|
+
if (index === -1) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
this.dependencies.splice(index, 1);
|
|
180
|
+
this.dependencies.forEach(dependency => {
|
|
181
|
+
let indexDependsOn = dependency.dependsOn.findIndex(theDep => theDep.includes(depPurl));
|
|
182
|
+
if (indexDependsOn > -1) {
|
|
183
|
+
dependency.dependsOn.splice(indexDependsOn, 1);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* This method gets an array of dependencies with versions( purl string format) to be ignored, and remove all of them from CycloneDx Sbom
|
|
191
|
+
* @param {Array} dependencies to be removed from sbom
|
|
192
|
+
* @return {CycloneDxSbom} without ignored dependencies
|
|
193
|
+
*/
|
|
194
|
+
filterIgnoredDepsIncludingVersion(deps) {
|
|
195
|
+
deps.forEach(dep => {
|
|
196
|
+
let index = this.components.findIndex(component => component.purl === dep);
|
|
197
|
+
if (index >= 0) {
|
|
198
|
+
this.components.splice(index, 1);
|
|
199
|
+
}
|
|
200
|
+
index = this.dependencies.findIndex(dependency => dependency.ref === dep);
|
|
201
|
+
if (index >= 0) {
|
|
202
|
+
this.dependencies.splice(index, 1);
|
|
203
|
+
}
|
|
204
|
+
this.dependencies.forEach(dependency => {
|
|
205
|
+
let indexDependsOn = dependency.dependsOn.findIndex(theDep => theDep === dep);
|
|
206
|
+
if (indexDependsOn > -1) {
|
|
207
|
+
dependency.dependsOn.splice(indexDependsOn, 1);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
/** This method gets a component object, and a string name, and checks if the name is a substring of the component' purl.
|
|
214
|
+
* @param {} component to search in its dependencies
|
|
215
|
+
* @param {String} name to be checked.
|
|
216
|
+
*
|
|
217
|
+
* @return {boolean}
|
|
218
|
+
*/
|
|
219
|
+
checkIfPackageInsideDependsOnList(component, name) {
|
|
220
|
+
let dependencyIndex = this.getDependencyIndex(component.purl);
|
|
221
|
+
if (dependencyIndex < 0) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
//Only if the dependency doesn't exists on the dependency list of dependency, then add it to this list.
|
|
225
|
+
if (this.dependencies[dependencyIndex].dependsOn.findIndex(dep => dep.includes(name)) >= 0) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/** Removes the root component from the sbom
|
|
233
|
+
*/
|
|
234
|
+
removeRootComponent() {
|
|
235
|
+
let compIndex = this.getComponentIndex(this.rootComponent);
|
|
236
|
+
let depIndex = this.getDependencyIndex(this.rootComponent.purl);
|
|
237
|
+
this.components.splice(compIndex, 1);
|
|
238
|
+
this.dependencies.splice(depIndex, 1);
|
|
239
|
+
this.rootComponent = undefined;
|
|
240
|
+
}
|
|
241
|
+
setSourceManifest(manifestData) {
|
|
242
|
+
this.sourceManifestForAuditTrail = manifestData;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This function is used to determine exhort theUrl backend according to the following logic:
|
|
3
|
+
* If TRUSTIFY_DA_DEV_MODE = true, then take the value of the EXHORT BACKEND URL of dev/staging environment in such a way:
|
|
4
|
+
* take it as environment variable if exists, otherwise, take it from opts object if exists, otherwise, use the hardcoded default of DEV environment.
|
|
5
|
+
* If TRUSTIFY_DA_DEV_MODE = false , then select the production theUrl of EXHORT Backend, which is hardcoded.
|
|
6
|
+
* TRUSTIFY_DA_DEV_MODE evaluated in the following order and selected when it finds it first:
|
|
7
|
+
* 1. Environment Variable
|
|
8
|
+
* 2. (key,value) from opts object
|
|
9
|
+
* 3. Default False ( points to production URL )
|
|
10
|
+
* @param {{TRUSTIFY_DA_DEBUG?: string | undefined; TRUSTIFY_DA_BACKEND_URL?: string | undefined}} [opts={}]
|
|
11
|
+
* @return {string} - The selected exhort backend
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export function selectExhortBackend(opts?: {
|
|
15
|
+
TRUSTIFY_DA_DEBUG?: string | undefined;
|
|
16
|
+
TRUSTIFY_DA_BACKEND_URL?: string | undefined;
|
|
17
|
+
} | undefined): string;
|
|
18
|
+
export { parseImageRef } from "./oci_image/utils.js";
|
|
19
|
+
export { ImageRef } from "./oci_image/images.js";
|
|
20
|
+
declare namespace _default {
|
|
21
|
+
export { componentAnalysis };
|
|
22
|
+
export { stackAnalysis };
|
|
23
|
+
export { imageAnalysis };
|
|
24
|
+
export { validateToken };
|
|
25
|
+
}
|
|
26
|
+
export default _default;
|
|
27
|
+
export type Options = {
|
|
28
|
+
[key: string]: string | undefined;
|
|
29
|
+
TRUSTIFY_DA_DOCKER_PATH?: string | undefined;
|
|
30
|
+
TRUSTIFY_DA_GO_MVS_LOGIC_ENABLED?: string | undefined;
|
|
31
|
+
TRUSTIFY_DA_GO_PATH?: string | undefined;
|
|
32
|
+
TRUSTIFY_DA_GRADLE_PATH?: string | undefined;
|
|
33
|
+
TRUSTIFY_DA_IMAGE_PLATFORM?: string | undefined;
|
|
34
|
+
TRUSTIFY_DA_MVN_PATH?: string | undefined;
|
|
35
|
+
TRUSTIFY_DA_PIP_PATH?: string | undefined;
|
|
36
|
+
TRUSTIFY_DA_PIP_USE_DEP_TREE?: string | undefined;
|
|
37
|
+
TRUSTIFY_DA_PIP3_PATH?: string | undefined;
|
|
38
|
+
TRUSTIFY_DA_PNPM_PATH?: string | undefined;
|
|
39
|
+
TRUSTIFY_DA_PODMAN_PATH?: string | undefined;
|
|
40
|
+
TRUSTIFY_DA_PREFER_GRADLEW?: string | undefined;
|
|
41
|
+
TRUSTIFY_DA_PREFER_MVNW?: string | undefined;
|
|
42
|
+
TRUSTIFY_DA_PROXY_URL?: string | undefined;
|
|
43
|
+
TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS?: string | undefined;
|
|
44
|
+
TRUSTIFY_DA_PYTHON_PATH?: string | undefined;
|
|
45
|
+
TRUSTIFY_DA_PYTHON_VIRTUAL_ENV?: string | undefined;
|
|
46
|
+
TRUSTIFY_DA_PYTHON3_PATH?: string | undefined;
|
|
47
|
+
TRUSTIFY_DA_RECOMMENDATIONS_ENABLED?: string | undefined;
|
|
48
|
+
TRUSTIFY_DA_SKOPEO_CONFIG_PATH?: string | undefined;
|
|
49
|
+
TRUSTIFY_DA_SKOPEO_PATH?: string | undefined;
|
|
50
|
+
TRUSTIFY_DA_SYFT_CONFIG_PATH?: string | undefined;
|
|
51
|
+
TRUSTIFY_DA_SYFT_PATH?: string | undefined;
|
|
52
|
+
TRUSTIFY_DA_YARN_PATH?: string | undefined;
|
|
53
|
+
MATCH_MANIFEST_VERSIONS?: string | undefined;
|
|
54
|
+
RHDA_SOURCE?: string | undefined;
|
|
55
|
+
RHDA_TOKEN?: string | undefined;
|
|
56
|
+
RHDA_TELEMETRY_ID?: string | undefined;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Get component analysis report for a manifest content.
|
|
60
|
+
* @param {string} manifest - path to the manifest
|
|
61
|
+
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
62
|
+
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
63
|
+
* @throws {Error} if no matching provider, failed to get create content, or backend request failed
|
|
64
|
+
*/
|
|
65
|
+
declare function componentAnalysis(manifest: string, opts?: Options | undefined): Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>;
|
|
66
|
+
declare function stackAnalysis(manifest: string, html: true, opts?: Options | undefined): Promise<string>;
|
|
67
|
+
declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>;
|
|
68
|
+
declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>;
|
|
69
|
+
declare function imageAnalysis(imageRefs: Array<string>, html: true, opts?: Options | undefined): Promise<string>;
|
|
70
|
+
declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Options | undefined): Promise<{
|
|
71
|
+
[x: string]: import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport;
|
|
72
|
+
}>;
|
|
73
|
+
declare function imageAnalysis(imageRefs: Array<string>, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
|
|
74
|
+
[x: string]: import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport;
|
|
75
|
+
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Validates the Exhort token.
|
|
78
|
+
* @param {Options} [opts={}] - Optional parameters, potentially including token override.
|
|
79
|
+
* @returns {Promise<object>} A promise that resolves with the validation result from the backend.
|
|
80
|
+
* @throws {Error} if the backend request failed.
|
|
81
|
+
*/
|
|
82
|
+
declare function validateToken(opts?: Options | undefined): Promise<object>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { EOL } from "os";
|
|
3
|
+
import { availableProviders, match } from './provider.js';
|
|
4
|
+
import analysis from './analysis.js';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { getCustom } from "./tools.js";
|
|
7
|
+
import.meta.dirname;
|
|
8
|
+
import * as url from 'url';
|
|
9
|
+
export { parseImageRef } from "./oci_image/utils.js";
|
|
10
|
+
export { ImageRef } from "./oci_image/images.js";
|
|
11
|
+
export default { componentAnalysis, stackAnalysis, imageAnalysis, validateToken };
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {{
|
|
14
|
+
* TRUSTIFY_DA_DOCKER_PATH?: string | undefined,
|
|
15
|
+
* TRUSTIFY_DA_GO_MVS_LOGIC_ENABLED?: string | undefined,
|
|
16
|
+
* TRUSTIFY_DA_GO_PATH?: string | undefined,
|
|
17
|
+
* TRUSTIFY_DA_GRADLE_PATH?: string | undefined,
|
|
18
|
+
* TRUSTIFY_DA_IMAGE_PLATFORM?: string | undefined,
|
|
19
|
+
* TRUSTIFY_DA_MVN_PATH?: string | undefined,
|
|
20
|
+
* TRUSTIFY_DA_PIP_PATH?: string | undefined,
|
|
21
|
+
* TRUSTIFY_DA_PIP_USE_DEP_TREE?: string | undefined,
|
|
22
|
+
* TRUSTIFY_DA_PIP3_PATH?: string | undefined,
|
|
23
|
+
* TRUSTIFY_DA_PNPM_PATH?: string | undefined,
|
|
24
|
+
* TRUSTIFY_DA_PODMAN_PATH?: string | undefined,
|
|
25
|
+
* TRUSTIFY_DA_PREFER_GRADLEW?: string | undefined,
|
|
26
|
+
* TRUSTIFY_DA_PREFER_MVNW?: string | undefined,
|
|
27
|
+
* TRUSTIFY_DA_PROXY_URL?: string | undefined,
|
|
28
|
+
* TRUSTIFY_DA_PYTHON_INSTALL_BEST_EFFORTS?: string | undefined,
|
|
29
|
+
* TRUSTIFY_DA_PYTHON_PATH?: string | undefined,
|
|
30
|
+
* TRUSTIFY_DA_PYTHON_VIRTUAL_ENV?: string | undefined,
|
|
31
|
+
* TRUSTIFY_DA_PYTHON3_PATH?: string | undefined,
|
|
32
|
+
* TRUSTIFY_DA_RECOMMENDATIONS_ENABLED?: string | undefined,
|
|
33
|
+
* TRUSTIFY_DA_SKOPEO_CONFIG_PATH?: string | undefined,
|
|
34
|
+
* TRUSTIFY_DA_SKOPEO_PATH?: string | undefined,
|
|
35
|
+
* TRUSTIFY_DA_SYFT_CONFIG_PATH?: string | undefined,
|
|
36
|
+
* TRUSTIFY_DA_SYFT_PATH?: string | undefined,
|
|
37
|
+
* TRUSTIFY_DA_YARN_PATH?: string | undefined,
|
|
38
|
+
* MATCH_MANIFEST_VERSIONS?: string | undefined,
|
|
39
|
+
* RHDA_SOURCE?: string | undefined,
|
|
40
|
+
* RHDA_TOKEN?: string | undefined,
|
|
41
|
+
* RHDA_TELEMETRY_ID?: string | undefined,
|
|
42
|
+
* [key: string]: string | undefined,
|
|
43
|
+
* }} Options
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* Logs messages to the console if the TRUSTIFY_DA_DEBUG environment variable is set to "true".
|
|
47
|
+
* @param {string} alongsideText - The text to prepend to the log message.
|
|
48
|
+
* @param {any} valueToBePrinted - The value to log.
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
function logOptionsAndEnvironmentsVariables(alongsideText, valueToBePrinted) {
|
|
52
|
+
if (process.env["TRUSTIFY_DA_DEBUG"] === "true") {
|
|
53
|
+
console.log(`${alongsideText}: ${valueToBePrinted} ${EOL}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Reads the version from the package.json file and logs it if debug mode is enabled.
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
function readAndPrintVersionFromPackageJson() {
|
|
61
|
+
let dirName;
|
|
62
|
+
// new ESM way in nodeJS ( since node version 22 ) to bring module directory.
|
|
63
|
+
dirName = import.meta.dirname;
|
|
64
|
+
// old ESM way in nodeJS ( before node versions 22.00 to bring module directory)
|
|
65
|
+
if (!dirName) {
|
|
66
|
+
dirName = url.fileURLToPath(new URL('.', import.meta.url));
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
if (__dirname) {
|
|
70
|
+
dirName = __dirname;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
console.log("__dirname is not defined, continue with fileUrlPath");
|
|
75
|
+
}
|
|
76
|
+
let packageJson = JSON.parse(fs.readFileSync(path.join(dirName, "..", "package.json")).toString());
|
|
77
|
+
logOptionsAndEnvironmentsVariables("trustify-da-javascript-client analysis started, version: ", packageJson.version);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* This function is used to determine exhort theUrl backend according to the following logic:
|
|
81
|
+
* If TRUSTIFY_DA_DEV_MODE = true, then take the value of the EXHORT BACKEND URL of dev/staging environment in such a way:
|
|
82
|
+
* take it as environment variable if exists, otherwise, take it from opts object if exists, otherwise, use the hardcoded default of DEV environment.
|
|
83
|
+
* If TRUSTIFY_DA_DEV_MODE = false , then select the production theUrl of EXHORT Backend, which is hardcoded.
|
|
84
|
+
* TRUSTIFY_DA_DEV_MODE evaluated in the following order and selected when it finds it first:
|
|
85
|
+
* 1. Environment Variable
|
|
86
|
+
* 2. (key,value) from opts object
|
|
87
|
+
* 3. Default False ( points to production URL )
|
|
88
|
+
* @param {{TRUSTIFY_DA_DEBUG?: string | undefined; TRUSTIFY_DA_BACKEND_URL?: string | undefined}} [opts={}]
|
|
89
|
+
* @return {string} - The selected exhort backend
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
export function selectExhortBackend(opts = {}) {
|
|
93
|
+
if (getCustom("TRUSTIFY_DA_DEBUG", "false", opts) === "true") {
|
|
94
|
+
readAndPrintVersionFromPackageJson();
|
|
95
|
+
}
|
|
96
|
+
let url;
|
|
97
|
+
if (getCustom('TRUSTIFY_DA_DEV_MODE', 'false', opts) === 'true') {
|
|
98
|
+
url = getCustom('DEV_TRUSTIFY_DA_BACKEND_URL', undefined, opts);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
url = getCustom('TRUSTIFY_DA_BACKEND_URL', undefined, opts);
|
|
102
|
+
}
|
|
103
|
+
if (!url) {
|
|
104
|
+
throw new Error(`TRUSTIFY_DA_BACKEND_URL is unset`);
|
|
105
|
+
}
|
|
106
|
+
logOptionsAndEnvironmentsVariables("Chosen exhort backend URL:", url);
|
|
107
|
+
return url;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* @overload
|
|
111
|
+
* @param {string} manifest
|
|
112
|
+
* @param {true} html
|
|
113
|
+
* @param {Options} [opts={}]
|
|
114
|
+
* @returns {Promise<string>}
|
|
115
|
+
* @throws {Error}
|
|
116
|
+
*/
|
|
117
|
+
/**
|
|
118
|
+
* @overload
|
|
119
|
+
* @param {string} manifest
|
|
120
|
+
* @param {false} html
|
|
121
|
+
* @param {Options} [opts={}]
|
|
122
|
+
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
123
|
+
* @throws {Error}
|
|
124
|
+
*/
|
|
125
|
+
/**
|
|
126
|
+
* Get stack analysis report for a manifest file.
|
|
127
|
+
* @overload
|
|
128
|
+
* @param {string} manifest - path for the manifest
|
|
129
|
+
* @param {boolean} [html=false] - true will return a html string, false will return AnalysisReport object.
|
|
130
|
+
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
131
|
+
* @returns {Promise<string|import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
132
|
+
* @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
|
|
133
|
+
* or backend request failed
|
|
134
|
+
*/
|
|
135
|
+
async function stackAnalysis(manifest, html = false, opts = {}) {
|
|
136
|
+
const theUrl = selectExhortBackend(opts);
|
|
137
|
+
fs.accessSync(manifest, fs.constants.R_OK); // throws error if file unreadable
|
|
138
|
+
let provider = match(manifest, availableProviders); // throws error if no matching provider
|
|
139
|
+
return await analysis.requestStack(provider, manifest, theUrl, html, opts); // throws error request sending failed
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get component analysis report for a manifest content.
|
|
143
|
+
* @param {string} manifest - path to the manifest
|
|
144
|
+
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
145
|
+
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
146
|
+
* @throws {Error} if no matching provider, failed to get create content, or backend request failed
|
|
147
|
+
*/
|
|
148
|
+
async function componentAnalysis(manifest, opts = {}) {
|
|
149
|
+
const theUrl = selectExhortBackend(opts);
|
|
150
|
+
fs.accessSync(manifest, fs.constants.R_OK);
|
|
151
|
+
opts["manifest-type"] = path.basename(manifest);
|
|
152
|
+
let provider = match(manifest, availableProviders); // throws error if no matching provider
|
|
153
|
+
return await analysis.requestComponent(provider, manifest, theUrl, opts); // throws error request sending failed
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* @overload
|
|
157
|
+
* @param {Array<string>} imageRefs
|
|
158
|
+
* @param {true} html
|
|
159
|
+
* @param {Options} [opts={}]
|
|
160
|
+
* @returns {Promise<string>}
|
|
161
|
+
* @throws {Error}
|
|
162
|
+
*/
|
|
163
|
+
/**
|
|
164
|
+
* @overload
|
|
165
|
+
* @param {Array<string>} imageRefs
|
|
166
|
+
* @param {false} html
|
|
167
|
+
* @param {Options} [opts={}]
|
|
168
|
+
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
169
|
+
* @throws {Error}
|
|
170
|
+
*/
|
|
171
|
+
/**
|
|
172
|
+
* Get image analysis report for a set of OCI image references.
|
|
173
|
+
* @overload
|
|
174
|
+
* @param {Array<string>} imageRefs - OCI image references
|
|
175
|
+
* @param {boolean} [html=false] - true will return a html string, false will return AnalysisReport
|
|
176
|
+
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
177
|
+
* @returns {Promise<string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
178
|
+
* @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
|
|
179
|
+
* or backend request failed
|
|
180
|
+
*/
|
|
181
|
+
async function imageAnalysis(imageRefs, html = false, opts = {}) {
|
|
182
|
+
const theUrl = selectExhortBackend(opts);
|
|
183
|
+
return await analysis.requestImages(imageRefs, theUrl, html, opts);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Validates the Exhort token.
|
|
187
|
+
* @param {Options} [opts={}] - Optional parameters, potentially including token override.
|
|
188
|
+
* @returns {Promise<object>} A promise that resolves with the validation result from the backend.
|
|
189
|
+
* @throws {Error} if the backend request failed.
|
|
190
|
+
*/
|
|
191
|
+
async function validateToken(opts = {}) {
|
|
192
|
+
const theUrl = selectExhortBackend(opts);
|
|
193
|
+
return await analysis.validateToken(theUrl, opts); // throws error request sending failed
|
|
194
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/// <reference types="packageurl-js/src/package-url.js" />
|
|
2
|
+
/**
|
|
3
|
+
* Helper class for parsing docker repository/image names:
|
|
4
|
+
*
|
|
5
|
+
* - If the first part before the slash contains a "." or a ":" it is considered to be a registry URL
|
|
6
|
+
* - A last part starting with a ":" is considered to be a tag
|
|
7
|
+
* - The rest is considered the repository name (which might be separated via slashes)
|
|
8
|
+
*
|
|
9
|
+
* Example of valid names:
|
|
10
|
+
*
|
|
11
|
+
* - consol/tomcat-8.0
|
|
12
|
+
* - consol/tomcat-8.0:8.0.9
|
|
13
|
+
* - docker.consol.de:5000/tomcat-8.0
|
|
14
|
+
* - docker.consol.de:5000/jolokia/tomcat-8.0:8.0.9
|
|
15
|
+
*/
|
|
16
|
+
export class Image {
|
|
17
|
+
static NAME_COMPONENT_REGEXP: string;
|
|
18
|
+
static DOMAIN_COMPONENT_REGEXP: string;
|
|
19
|
+
static NAME_COMP_REGEXP: RegExp;
|
|
20
|
+
static IMAGE_NAME_REGEXP: RegExp;
|
|
21
|
+
static DOMAIN_REGEXP: RegExp;
|
|
22
|
+
static TAG_REGEXP: RegExp;
|
|
23
|
+
static DIGEST_REGEXP: RegExp;
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {string} fullName
|
|
27
|
+
* @param {string} [givenTag]
|
|
28
|
+
*/
|
|
29
|
+
constructor(fullName: string, givenTag?: string | undefined);
|
|
30
|
+
repository: string;
|
|
31
|
+
registry: string;
|
|
32
|
+
tag: string;
|
|
33
|
+
digest: string | null;
|
|
34
|
+
user: string;
|
|
35
|
+
/**
|
|
36
|
+
* @param {string[]} parts
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
joinTail(parts: string[]): string;
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} part
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
isRegistry(part: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* @param {string} [optionalRegistry]
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
getNameWithoutTag(optionalRegistry?: string | undefined): string;
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} [optionalRegistry]
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
getFullName(optionalRegistry?: string | undefined): string;
|
|
55
|
+
/**
|
|
56
|
+
* @returns {string}
|
|
57
|
+
*/
|
|
58
|
+
getSimpleName(): string;
|
|
59
|
+
/**
|
|
60
|
+
* @param {string} optionalRepository
|
|
61
|
+
* @returns {string}
|
|
62
|
+
*/
|
|
63
|
+
getNameWithOptionalRepository(optionalRepository: string): string;
|
|
64
|
+
doValidate(): void;
|
|
65
|
+
/**
|
|
66
|
+
* @param {string} rest
|
|
67
|
+
*/
|
|
68
|
+
parseComponentsBeforeTag(rest: string): void;
|
|
69
|
+
}
|
|
70
|
+
export class ImageRef {
|
|
71
|
+
static OCI_TYPE: string;
|
|
72
|
+
static REPOSITORY_QUALIFIER: string;
|
|
73
|
+
static TAG_QUALIFIER: string;
|
|
74
|
+
static ARCH_QUALIFIER: string;
|
|
75
|
+
static OS_QUALIFIER: string;
|
|
76
|
+
static VARIANT_QUALIFIER: string;
|
|
77
|
+
/**
|
|
78
|
+
* @param {string} image
|
|
79
|
+
* @param {string} [platform]
|
|
80
|
+
* @param {import("index.js").Options} [opts={}]
|
|
81
|
+
*/
|
|
82
|
+
constructor(image: string, platform?: string | undefined, opts?: import("index.js").Options | undefined);
|
|
83
|
+
/** @type {Image} */
|
|
84
|
+
image: Image;
|
|
85
|
+
/** @type {Platform} */
|
|
86
|
+
platform: Platform;
|
|
87
|
+
/**
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
private checkImageDigest;
|
|
91
|
+
/**
|
|
92
|
+
* @returns {PackageURL}
|
|
93
|
+
* @throws {Error}
|
|
94
|
+
* @see https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#oci
|
|
95
|
+
*/
|
|
96
|
+
getPackageURL(): PackageURL;
|
|
97
|
+
}
|
|
98
|
+
import { Platform } from "./platform.js";
|
|
99
|
+
import { PackageURL } from "packageurl-js";
|