diff --git a/src/analysis.js b/src/analysis.js index 20e0586..93cc55c 100644 --- a/src/analysis.js +++ b/src/analysis.js @@ -12,6 +12,7 @@ export default { requestComponent, requestStack, requestImages, validateToken } const rhdaTokenHeader = "rhda-token"; const rhdaSourceHeader = "rhda-source" const rhdaOperationTypeHeader = "rhda-operation-type" +const rhdaPackageManagerHeader = "rhda-pkg-manager" /** * Adds proxy agent configuration to fetch options if a proxy URL is specified @@ -29,7 +30,7 @@ function addProxyAgent(options, opts) { /** * Send a stack analysis request and get the report as 'text/html' or 'application/json'. - * @param {import('./provider').Provider | import('./providers/base_java.js').default } provider - the provided data for constructing the request + * @param {import('./provider').Provider} provider - the provided data for constructing the request * @param {string} manifest - path for the manifest * @param {string} url - the backend url to send the request to * @param {boolean} [html=false] - true will return 'text/html', false will return 'application/json' @@ -43,17 +44,18 @@ async function requestStack(provider, manifest, url, html = false, opts = {}) { opts["source-manifest"] = "" opts[rhdaOperationTypeHeader.toUpperCase().replaceAll("-", "_")] = "stack-analysis" let startTime = new Date() - let EndTime + let endTime if (process.env["EXHORT_DEBUG"] === "true") { console.log("Starting time of sending stack analysis request to exhort server= " + startTime) } + opts[rhdaPackageManagerHeader.toUpperCase().replaceAll("-", "_")] = provided.ecosystem const fetchOptions = addProxyAgent({ method: 'POST', headers: { 'Accept': html ? 'text/html' : 'application/json', 'Content-Type': provided.contentType, - ...getTokenHeaders(opts) + ...getTokenHeaders(opts), }, body: provided.content }, opts); @@ -76,11 +78,11 @@ async function requestStack(provider, manifest, url, html = false, opts = {}) { if (exRequestId) { console.log("Unique Identifier associated with this request - ex-request-id=" + exRequestId) } - EndTime = new Date() + endTime = new Date() console.log("Response body received from exhort server : " + EOL + EOL) console.log(console.log(JSON.stringify(result, null, 4))) - console.log("Ending time of sending stack analysis request to exhort server= " + EndTime) - let time = (EndTime - startTime) / 1000 + console.log("Ending time of sending stack analysis request to exhort server= " + endTime) + let time = (endTime - startTime) / 1000 console.log("Total Time in seconds: " + time) } @@ -108,6 +110,7 @@ async function requestComponent(provider, manifest, url, opts = {}) { if (process.env["EXHORT_DEBUG"] === "true") { console.log("Starting time of sending component analysis request to exhort server= " + new Date()) } + opts[rhdaPackageManagerHeader.toUpperCase().replaceAll("-", "_")] = provided.ecosystem const fetchOptions = addProxyAgent({ method: 'POST', @@ -256,6 +259,8 @@ function getTokenHeaders(opts = {}) { setRhdaHeader(rhdaTokenHeader, headers, opts); setRhdaHeader(rhdaSourceHeader, headers, opts); setRhdaHeader(rhdaOperationTypeHeader, headers, opts); + setRhdaHeader(rhdaPackageManagerHeader, headers, opts) + if (process.env["EXHORT_DEBUG"] === "true") { console.log("Headers Values to be sent to exhort:" + EOL) for (const headerKey in headers) { diff --git a/src/providers/base_javascript.js b/src/providers/base_javascript.js index fcb5d44..365adb9 100644 --- a/src/providers/base_javascript.js +++ b/src/providers/base_javascript.js @@ -15,7 +15,7 @@ import Manifest from './manifest.js'; * The ecosystem identifier for JavaScript/npm packages * @type {string} */ -export const ecosystem = 'npm'; +export const purlType = 'npm'; /** * Base class for JavaScript package manager providers. @@ -28,6 +28,8 @@ export default class Base_javascript { #manifest; /** @type {string} */ #cmd; + /** @type {string} */ + #ecosystem; /** * Sets up the provider with the manifest path and options @@ -38,17 +40,27 @@ export default class Base_javascript { _setUp(manifestPath, opts) { this.#cmd = getCustomPath(this._cmdName(), opts); this.#manifest = new Manifest(manifestPath); + this.#ecosystem = purlType; } /** - * Gets the current manifest object - * @returns {Manifest} The manifest object - * @protected - */ + * Gets the current manifest object + * @returns {Manifest} The manifest object + * @protected + */ _getManifest() { return this.#manifest; } + /** + * Sets the ecosystem value + * @param {string} ecosystem - The ecosystem identifier + * @protected + */ + _setEcosystem(ecosystem) { + this.#ecosystem = ecosystem; + } + /** * Returns the name of the lock file for the specific implementation * @returns {string} The lock file name @@ -117,7 +129,7 @@ export default class Base_javascript { provideStack(manifestPath, opts = {}) { this._setUp(manifestPath, opts); return { - ecosystem, + ecosystem: this.#ecosystem, content: this.#getSBOM(opts), contentType: 'application/vnd.cyclonedx+json' } @@ -132,7 +144,7 @@ export default class Base_javascript { provideComponent(manifestPath, opts = {}) { this._setUp(manifestPath, opts); return { - ecosystem, + ecosystem: this.#ecosystem, content: this.#getDirectDependencySbom(opts), contentType: 'application/vnd.cyclonedx+json' } @@ -163,7 +175,7 @@ export default class Base_javascript { #getSBOM(opts = {}) { const depsObject = this._buildDependencyTree(true); - let mainComponent = toPurl(ecosystem, this.#manifest.name, this.#manifest.version); + let mainComponent = toPurl(purlType, this.#manifest.name, this.#manifest.version); let sbom = new Sbom(); sbom.addRoot(mainComponent); @@ -185,8 +197,8 @@ export default class Base_javascript { Object.entries(dependencies) .forEach(entry => { const [name, artifact] = entry; - const target = toPurl(ecosystem, name, artifact.version); - const rootPurl = toPurl(ecosystem, this.#manifest.name, this.#manifest.version); + const target = toPurl(purlType, name, artifact.version); + const rootPurl = toPurl(purlType, this.#manifest.name, this.#manifest.version); sbom.addDependency(rootPurl, target); this.#addDependenciesOf(sbom, target, artifact); }); @@ -205,7 +217,7 @@ export default class Base_javascript { .forEach(entry => { const [name, depArtifact] = entry; if(depArtifact.version !== undefined) { - const target = toPurl(ecosystem, name, depArtifact.version); + const target = toPurl(purlType, name, depArtifact.version); sbom.addDependency(from, target); this.#addDependenciesOf(sbom, target, depArtifact); } @@ -220,7 +232,7 @@ export default class Base_javascript { */ #getDirectDependencySbom(opts = {}) { const depTree = this._buildDependencyTree(false); - let mainComponent = toPurl(ecosystem, this.#manifest.name, this.#manifest.version); + let mainComponent = toPurl(purlType, this.#manifest.name, this.#manifest.version); let sbom = new Sbom(); sbom.addRoot(mainComponent); @@ -251,7 +263,7 @@ export default class Base_javascript { return new Map( Object.entries(depTree.dependencies).map( - ([key, value]) => [key, toPurl(ecosystem, key, value.version)] + ([key, value]) => [key, toPurl(purlType, key, value.version)] ) ); } diff --git a/src/providers/javascript_yarn.js b/src/providers/javascript_yarn.js index 7756472..9d1c8e1 100644 --- a/src/providers/javascript_yarn.js +++ b/src/providers/javascript_yarn.js @@ -35,6 +35,7 @@ export default class Javascript_yarn extends Base_javascript { } const isClassic = matches[1] === '1'; + this._setEcosystem(isClassic ? 'yarn-classic' : 'yarn-berry'); this.#processor = isClassic ? new Yarn_classic_processor(this._getManifest()) : new Yarn_berry_processor(this._getManifest()); } diff --git a/src/providers/processors/yarn_berry_processor.js b/src/providers/processors/yarn_berry_processor.js index b885407..b5ca032 100644 --- a/src/providers/processors/yarn_berry_processor.js +++ b/src/providers/processors/yarn_berry_processor.js @@ -1,7 +1,7 @@ import { EOL } from 'os'; import { toPurl, toPurlFromString } from "../../tools.js"; -import { ecosystem } from "../base_javascript.js"; +import { purlType } from "../base_javascript.js"; import Yarn_processor from "./yarn_processor.js"; @@ -64,7 +64,7 @@ export default class Yarn_berry_processor extends Yarn_processor { const idx = depName.lastIndexOf('@'); const name = depName.substring(0, idx); const version = dep.children.Version; - return [name, toPurl(ecosystem, name, version)]; + return [name, toPurl(purlType, name, version)]; } ) ); @@ -120,12 +120,12 @@ export default class Yarn_berry_processor extends Yarn_processor { const matches = Yarn_berry_processor.LOCATOR_PATTERN.exec(locator); if (matches) { - return toPurl(ecosystem, matches[1], matches[2]); + return toPurl(purlType, matches[1], matches[2]); } const virtualMatches = Yarn_berry_processor.VIRTUAL_LOCATOR_PATTERN.exec(locator); if (virtualMatches) { - return toPurl(ecosystem, virtualMatches[1], virtualMatches[2]); + return toPurl(purlType, virtualMatches[1], virtualMatches[2]); } return undefined; @@ -145,6 +145,6 @@ export default class Yarn_berry_processor extends Yarn_processor { const name = depName.substring(0, depName.lastIndexOf('@')); const version = node.children.Version; - return toPurl(ecosystem, name, version); + return toPurl(purlType, name, version); } } diff --git a/src/providers/processors/yarn_classic_processor.js b/src/providers/processors/yarn_classic_processor.js index 4f7c910..baa17d4 100644 --- a/src/providers/processors/yarn_classic_processor.js +++ b/src/providers/processors/yarn_classic_processor.js @@ -1,5 +1,5 @@ import { toPurl, toPurlFromString } from "../../tools.js"; -import { ecosystem } from "../base_javascript.js"; +import { purlType } from "../base_javascript.js"; import Yarn_processor from "./yarn_processor.js"; @@ -52,7 +52,7 @@ export default class Yarn_classic_processor extends Yarn_processor { const idx = depName.lastIndexOf('@'); const name = depName.substring(0, idx); const version = idx !== -1 ? depName.substring(idx + 1) : ''; - return [name, toPurl(ecosystem, name, version)]; + return [name, toPurl(purlType, name, version)]; } ) ) @@ -119,7 +119,7 @@ class NodeMetaData { const idx = this.nodeName.lastIndexOf('@'); this.name = this.nodeName.substring(0, idx); this.version = idx !== -1 ? this.nodeName.substring(idx + 1) : ''; - this.purl = toPurl(ecosystem, this.name, this.version); + this.purl = toPurl(purlType, this.name, this.version); const shadowNode = node.shadow; this.shadow = shadowNode ? shadowNode : false; }