From ba77762bece10654af73a4682f92821cfec87b36 Mon Sep 17 00:00:00 2001 From: attiasas Date: Thu, 4 Apr 2024 16:34:48 +0300 Subject: [PATCH] add get scan event --- README.md | 19 ++++++++++++++++ model/Xsc/Event/ScanEvent.ts | 5 ++++- model/Xsc/Event/ScanEventResponse.ts | 4 ++++ model/Xsc/Event/index.ts | 1 + src/Xray/XrayClient.ts | 2 +- src/Xray/XrayScanClient.ts | 31 +++++++++++++++----------- src/Xsc/XscClient.ts | 2 +- src/Xsc/XscEventClient.ts | 13 +++++++++++ test/tests/Xray/XrayScanClient.spec.ts | 22 ++++++++++++++++-- test/tests/Xsc/XscEventClient.spec.ts | 28 +++++++++++++++++++++-- 10 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 model/Xsc/Event/ScanEventResponse.ts diff --git a/README.md b/README.md index 5e3d594..2a68a64 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Add jfrog-client-js as a dependency to your package.json file: - [Sending Log Message Event](#sending-log-mesage-event) - [Sending Start Scan Event](#sending-start-scan-event) - [Sending End Scan Event](#sending-end-scan-event) + - [Getting Scan Event Details](#getting-scan-event-details) ### Setting up JFrog client @@ -412,3 +413,21 @@ jfrogClient console.error(error); }); ``` + +##### Getting Scan Event Details + +```javascript +const multiScanId = XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX // UUID +jfrogClient + .xsc() + .event() + .getScanEvent(multiScanId) + .then((result) => { + ... + }) + .catch((error) => { + ... + }); +``` + +Please note that you need to replace 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' with the actual multi scan ID that you've generated with `startScan`. diff --git a/model/Xsc/Event/ScanEvent.ts b/model/Xsc/Event/ScanEvent.ts index b1f8064..cfc8045 100644 --- a/model/Xsc/Event/ScanEvent.ts +++ b/model/Xsc/Event/ScanEvent.ts @@ -1,7 +1,10 @@ import { ScanEventStatus } from './index'; -export interface ScanEvent { +export interface ScanEvent extends ScanEventEndData { multi_scan_id: string; +} + +export interface ScanEventEndData { event_status?: ScanEventStatus; total_findings?: number; total_ignored_findings?: number; diff --git a/model/Xsc/Event/ScanEventResponse.ts b/model/Xsc/Event/ScanEventResponse.ts new file mode 100644 index 0000000..6c26ae4 --- /dev/null +++ b/model/Xsc/Event/ScanEventResponse.ts @@ -0,0 +1,4 @@ +import { ScanEventEndData } from './ScanEvent'; +import { StartScanRequest } from './StartScanRequest'; + +export interface ScanEventResponse extends StartScanRequest, ScanEventEndData {} diff --git a/model/Xsc/Event/index.ts b/model/Xsc/Event/index.ts index 9e5c98f..e248865 100644 --- a/model/Xsc/Event/index.ts +++ b/model/Xsc/Event/index.ts @@ -1,5 +1,6 @@ export { ScanEvent } from './ScanEvent'; export { StartScanRequest } from './StartScanRequest'; +export { ScanEventResponse } from './ScanEventResponse'; export { XscLog } from './XscLog'; export enum ScanEventStatus { diff --git a/src/Xray/XrayClient.ts b/src/Xray/XrayClient.ts index 99b5cf4..1897073 100644 --- a/src/Xray/XrayClient.ts +++ b/src/Xray/XrayClient.ts @@ -60,7 +60,7 @@ export class XrayClient { } public scan(): XrayScanClient { - return new XrayScanClient(this.httpClient, this.logger); + return new XrayScanClient(this.httpClient, false, this.logger); } public entitlements(): XrayEntitlementsClient { diff --git a/src/Xray/XrayScanClient.ts b/src/Xray/XrayScanClient.ts index fe7d777..1e50b99 100644 --- a/src/Xray/XrayScanClient.ts +++ b/src/Xray/XrayScanClient.ts @@ -10,7 +10,11 @@ export class XrayScanClient { private static readonly SLEEP_INTERVAL_MILLISECONDS: number = 5000; private static readonly MAX_ATTEMPTS: number = 60; - constructor(private readonly httpClient: HttpClient, private readonly logger: ILogger) {} + constructor( + private readonly httpClient: HttpClient, + private readonly xsc: boolean, + private readonly logger: ILogger + ) {} public async graph( request: IGraphRequestModel, @@ -18,8 +22,8 @@ export class XrayScanClient { checkCanceled: () => void, projectKey: string | undefined, watches: string[] | undefined, - multiScanId: string | undefined, - technologies: string[] | undefined, + multiScanId?: string, + technologies?: string[], sleepIntervalMilliseconds: number = XrayScanClient.SLEEP_INTERVAL_MILLISECONDS ): Promise { try { @@ -39,7 +43,6 @@ export class XrayScanClient { progress, checkCanceled, (!projectKey || projectKey.length === 0) && (!watches || watches.length === 0), - multiScanId !== undefined && multiScanId.length > 0, sleepIntervalMilliseconds ); } finally { @@ -88,13 +91,17 @@ export class XrayScanClient { } /** - * Get URL for "POST api/v1/scan/graph". - * If no project key provided - api/v1/scan/graph - * If project key was provided - api/v1/scan/graph?project= - * If watches provided - api/v1/scan/graph?watch=&watch= + * Get URL for "POST scan/graph" (Xray: api/v1/scan/graph, XSC: api/v1/sca/scan/graph). + * If no project key provided - /scan/graph + * If project key was provided - /scan/graph?project= + * If watches provided - /scan/graph?watch=&watch= + * If multiScanId provided - /scan/graph?multi_scan_id= + * If technologies provided - /scan/graph?tech=&tech= * @param projectKey - Project key or undefined * @param watches - List of Watches or undefined - * @returns URL for "POST api/v1/scan/graph" + * @param multiScanId - Multi scan ID or undefined + * @param technologies - List of technologies or undefined + * @returns URL for "POST /scan/graph" */ private getUrl( projectKey: string | undefined, @@ -102,7 +109,7 @@ export class XrayScanClient { multiScanId?: string, technologies?: string[] ): string { - let url: string = XrayScanClient.scanGraphEndpoint; + let url: string = this.xsc ? XrayScanClient.xscScanGraphEndpoint : XrayScanClient.scanGraphEndpoint; let params: string[] = []; if (projectKey && projectKey.length > 0) { @@ -112,7 +119,6 @@ export class XrayScanClient { } if (multiScanId) { params.push(`multi_scan_id=${multiScanId}`); - url = XrayScanClient.xscScanGraphEndpoint; } if (technologies && technologies.length > 0) { params.push(`tech=${technologies.join('&tech=')}`); @@ -140,10 +146,9 @@ export class XrayScanClient { progress: XrayScanProgress, checkCanceled: () => void, includeVulnerabilities: boolean, - xsc: boolean, sleepIntervalMilliseconds: number ): Promise { - const scanGraphUrl: string = xsc + const scanGraphUrl: string = this.xsc ? XrayScanClient.xscScanGraphEndpoint : XrayScanClient.scanGraphEndpoint + '/' + diff --git a/src/Xsc/XscClient.ts b/src/Xsc/XscClient.ts index 7d59918..fcc68ad 100644 --- a/src/Xsc/XscClient.ts +++ b/src/Xsc/XscClient.ts @@ -47,7 +47,7 @@ export class XscClient { } public scan(): XrayScanClient { - return new XrayScanClient(this.httpClient, this.logger); + return new XrayScanClient(this.httpClient, true, this.logger); } public event(): XscEventClient { diff --git a/src/Xsc/XscEventClient.ts b/src/Xsc/XscEventClient.ts index bd5d590..f40a462 100644 --- a/src/Xsc/XscEventClient.ts +++ b/src/Xsc/XscEventClient.ts @@ -10,6 +10,7 @@ import { StartScanRequest, ScanEvent, } from '../../model/'; +import { ScanEventResponse } from './Event/ScanEventResponse'; export class XscEventClient { static readonly eventEndpoint: string = 'api/v1/event'; @@ -86,4 +87,16 @@ export class XscEventClient { return false; } } + + public async getScanEvent(multiScanId: string): Promise { + this.logger.debug(`Sending GET event/${multiScanId} request...`); + const requestParams: IRequestParams = { + url: XscEventClient.eventEndpoint + '/' + multiScanId, + method: 'GET', + validateStatus: (status: number) => status === 200, + }; + return await ( + await this.httpClient.doAuthRequest(requestParams) + ).data; + } } diff --git a/test/tests/Xray/XrayScanClient.spec.ts b/test/tests/Xray/XrayScanClient.spec.ts index b7b2371..57ac19c 100644 --- a/test/tests/Xray/XrayScanClient.spec.ts +++ b/test/tests/Xray/XrayScanClient.spec.ts @@ -120,7 +120,16 @@ describe('Scan graph tests', () => { await client .xray() .scan() - .graph({ component_id: 'engine' } as IGraphRequestModel, progress, () => undefined, '', [], 10); + .graph( + { component_id: 'engine' } as IGraphRequestModel, + progress, + () => undefined, + '', + [], + undefined, + undefined, + 10 + ); expect(scope.isDone()).toBeTruthy(); expect(progress.lastPercentage).toBe(100); }); @@ -139,7 +148,16 @@ describe('Scan graph tests', () => { await client .xray() .scan() - .graph({ component_id: 'engine' } as IGraphRequestModel, progress, () => undefined, '', [], 10); + .graph( + { component_id: 'engine' } as IGraphRequestModel, + progress, + () => undefined, + '', + [], + undefined, + undefined, + 10 + ); }).rejects.toThrow(`Xray get scan graph exceeded the timeout.`); expect(progress.lastPercentage).toBe(100); }); diff --git a/test/tests/Xsc/XscEventClient.spec.ts b/test/tests/Xsc/XscEventClient.spec.ts index 5f62502..9d16e4b 100644 --- a/test/tests/Xsc/XscEventClient.spec.ts +++ b/test/tests/Xsc/XscEventClient.spec.ts @@ -2,9 +2,17 @@ import nock from 'nock'; import * as os from 'os'; import { JfrogClient } from '../../../src/JfrogClient'; import { TestUtils } from '../../TestUtils'; -import { IJfrogClientConfig, ScanEvent, ScanEventStatus, XscLog } from '../../../model'; +import { + IJfrogClientConfig, + ScanEvent, + ScanEventStatus, + ScanEventType, + StartScanRequest, + ScanEventResponse, + XscLog, +} from '../../../model'; -describe('Xsc Events tests', () => { +describe.only('Xsc Events tests', () => { const clientConfig: IJfrogClientConfig = TestUtils.getJfrogClientConfig(); const jfrogClient: JfrogClient = new JfrogClient(clientConfig); @@ -29,6 +37,13 @@ describe('Xsc Events tests', () => { if (await shouldSkipTest()) { return; } + let testEvent: StartScanRequest = { + product: 'jfrog-client-js tests', + os_platform: os.platform(), + os_architecture: os.arch(), + event_type: ScanEventType.SourceCode, + event_status: ScanEventStatus.Started, + }; // Start scan const res: ScanEvent = await jfrogClient .xsc() @@ -37,9 +52,18 @@ describe('Xsc Events tests', () => { expect(res).toBeTruthy(); expect(isValidUUID(res.multi_scan_id)).toBeTruthy(); + // Get scan information + let response: ScanEventResponse = await jfrogClient.xsc().event().getScanEvent(res.multi_scan_id); + expect(response).toBeTruthy(); + expect(response).toStrictEqual(testEvent); + // End scan res.event_status = ScanEventStatus.Completed; expect(await jfrogClient.xsc().event().endScan(res)).toBeTruthy(); + + response = await jfrogClient.xsc().event().getScanEvent(res.multi_scan_id); + expect(response).toBeTruthy(); + expect(response).toStrictEqual({ ...testEvent, event_status: ScanEventStatus.Completed }); }); async function shouldSkipTest(): Promise {