Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
],
"rules": {
"curly": "warn",
"eqeqeq": "warn",
"eqeqeq": ["warn", "always", {"null": "never"}],
"no-throw-literal": "warn",
"sort-imports": "warn"
},
"ignorePatterns": [
"integration"
]
}
}
11 changes: 11 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4

- name: Setup syft
uses: jaxxstorm/action-install-gh-release@v1.10.0
with:
repo: anchore/syft
platform: linux
arch: amd64
# tag: the latest one, so we can catch changes

- name: Setup skopeo
run: sudo apt update && sudo apt-get -y install skopeo

- name: Install project modules
run: npm ci

Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/stage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ jobs:
- name: Prepare PNPM
run: corepack prepare pnpm@latest --activate


- name: Setup Java 17
uses: actions/setup-java@v4
with:
Expand All @@ -76,6 +75,17 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v3

- name: Setup syft
uses: jaxxstorm/action-install-gh-release@v1.10.0
with:
repo: anchore/syft
platform: linux
arch: amd64
# tag: the latest one, so we can catch changes

- name: Setup skopeo
run: sudo apt update && sudo apt-get -y install skopeo

- name: Configure git
run: |
git config user.name "${{ github.actor }}"
Expand Down
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 50 additions & 3 deletions src/analysis.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import fs from "node:fs";
import path from "node:path";
import {EOL} from "os";
import {RegexNotToBeLogged, getCustom} from "./tools.js";
import { EOL } from "os";

Check warning on line 3 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically

Check warning on line 3 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically
import { RegexNotToBeLogged, getCustom } from "./tools.js";

Check warning on line 4 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Expected 'multiple' syntax before 'single' syntax

Check warning on line 4 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Expected 'multiple' syntax before 'single' syntax
import { HttpsProxyAgent } from "https-proxy-agent";
import { generateImageSBOM, parseImageRef } from "./oci_image/utils.js";

Check warning on line 6 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Expected 'multiple' syntax before 'single' syntax

Check warning on line 6 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Expected 'multiple' syntax before 'single' syntax

export default { requestComponent, requestStack, validateToken }
export default { requestComponent, requestStack, requestImages, validateToken }

const rhdaTokenHeader = "rhda-token";
const rhdaSourceHeader = "rhda-source"
Expand Down Expand Up @@ -133,6 +134,52 @@
return Promise.resolve(result)
}

/**
*
* @param {Array<string>} imageRefs
* @param {string} url
* @param {{}} [opts={}] - optional various options to pass along the application
* @returns {Promise<string|import('@trustification/exhort-api-spec/model/v4/AnalysisReport').AnalysisReport>}
*/
async function requestImages(imageRefs, url, html = false, opts = {}) {
const imageSboms = {}
for (const image of imageRefs) {
const parsedImageRef = parseImageRef(image)
imageSboms[parsedImageRef.getPackageURL().toString()] = generateImageSBOM(parsedImageRef)
}

const resp = await fetch(`${url}/api/v4/batch-analysis`, {
method: 'POST',
headers: {
'Accept': html ? 'text/html' : 'application/json',
'Content-Type': 'application/vnd.cyclonedx+json',
...getTokenHeaders(opts)
},
body: JSON.stringify(imageSboms),
})

if(resp.status === 200) {
let result;
if (!html) {
result = await resp.json()
} else {
result = await resp.text()
}
if (process.env["EXHORT_DEBUG"] === "true") {
let exRequestId = resp.headers.get("ex-request-id");
if (exRequestId) {
console.log("Unique Identifier associated with this request - ex-request-id=" + exRequestId)
}
console.log("Response body received from exhort server : " + EOL + EOL)
console.log(JSON.stringify(result, null, 4))
console.log("Ending time of sending component analysis request to exhort server= " + new Date())
}
return result
} else {
throw new Error(`Got error response from exhort backend - http return code : ${resp.status}, ex-request-id: ${resp.headers.get("ex-request-id")} error message => ${await resp.text()}`)
}
}

/**
*
* @param url the backend url to send the request to
Expand Down
35 changes: 34 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getCustom } from "./tools.js";
import.meta.dirname
import * as url from 'url';

export default { componentAnalysis, stackAnalysis, validateToken }
export default { componentAnalysis, stackAnalysis, imageAnalysis, validateToken }

export const exhortDevDefaultUrl = 'https://exhort.stage.devshift.net';

Expand Down Expand Up @@ -148,6 +148,39 @@ async function componentAnalysis(manifest, opts = {}) {
return await analysis.requestComponent(provider, manifest, theUrl, opts) // throws error request sending failed
}

/**
* @overload
* @param {Array<string>} imageRefs
* @param {true} html
* @param {object} [opts={}]
* @returns {Promise<string>}
* @throws {Error}
*/

/**
* @overload
* @param {Array<string>} imageRefs
* @param {false} html
* @param {object} [opts={}]
* @returns {Promise<import('@trustification/exhort-api-spec/model/v4/AnalysisReport').AnalysisReport}
* @throws {Error}
*/

/**
* Get image analysis report for a set of OCI image references.
* @overload
* @param {Array<string>} imageRefs - OCI image references
* @param {boolean} [html=false] - true will return a html string, false will return AnalysisReport
* @param {{}} [opts={}] - optional various options to pass along the application
* @returns {Promise<string|import('@trustification/exhort-api-spec/model/v4/AnalysisReport').AnalysisReport}
* @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
* or backend request failed
*/
async function imageAnalysis(imageRefs, html = false, opts = {}) {
theUrl = selectExhortBackend(opts)
return await analysis.requestImages(imageRefs, theUrl, opts)
}

/**
* Validates the Exhort token.
* @param {object} [opts={}] - Optional parameters, potentially including token override.
Expand Down
Loading
Loading