Skip to content

Commit

Permalink
Support JFrog Apps Config file (#405)
Browse files Browse the repository at this point in the history
  • Loading branch information
yahavi authored Oct 12, 2023
1 parent 0c5e245 commit 065c8b1
Show file tree
Hide file tree
Showing 44 changed files with 11,441 additions and 1,402 deletions.
9 changes: 0 additions & 9 deletions src/main/connect/connectionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,6 @@ export class ConnectionUtils {
return Promise.resolve('Successfully connected to Xray version: ' + xrayVersion);
}

public static async testXrayVersionForScanGraph(jfrogClient: JfrogClient, logger: LogManager): Promise<boolean> {
let xrayVersion: string = await this.getXrayVersion(jfrogClient);
if (!(await this.isXrayVersionCompatible(xrayVersion, ConnectionUtils.MINIMAL_XRAY_VERSION_SUPPORTED))) {
logger.logError(new Error('Dependencies scan is supported only on Xray >= 3.29.0'), true);
return false;
}
return true;
}

public static async testXrayEntitlementForFeature(jfrogClient: JfrogClient, feature: EntitlementScanFeature): Promise<boolean> {
return await jfrogClient
.xray()
Expand Down
148 changes: 23 additions & 125 deletions src/main/scanLogic/scanManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,23 @@ import * as vscode from 'vscode';

import { ExtensionComponent } from '../extensionComponent';

import { LogManager } from '../log/logManager';
import { ConnectionManager } from '../connect/connectionManager';
import { ConnectionUtils, EntitlementScanFeature } from '../connect/connectionUtils';
import { LogManager } from '../log/logManager';

import { RootNode } from '../treeDataProviders/dependenciesTree/dependenciesRoot/rootTree';
import { IGraphResponse, XrayScanProgress } from 'jfrog-client-js';
import { GraphScanLogic } from './scanGraphLogic';
import { ApplicabilityRunner, ApplicabilityScanResponse } from './scanRunners/applicabilityScan';
import { EosRunner, EosScanRequest, EosScanResponse } from './scanRunners/eosScan';
import { AnalyzerUtils } from '../treeDataProviders/utils/analyzerUtils';
import { Configuration } from '../utils/configuration';
import { RootNode } from '../treeDataProviders/dependenciesTree/dependenciesRoot/rootTree';
import { StepProgress } from '../treeDataProviders/utils/stepProgress';
import { Resource } from '../utils/resource';
import { BinaryRunner } from './scanRunners/binaryRunner';
import { ScanUtils } from '../utils/scanUtils';
import { StepProgress } from '../treeDataProviders/utils/stepProgress';
import { Utils } from '../utils/utils';
import { IacRunner, IacScanResponse } from './scanRunners/iacScan';
import { SecretsRunner, SecretsScanResponse } from './scanRunners/secretsScan';
import { GraphScanLogic } from './scanGraphLogic';
import { JasRunner } from './scanRunners/jasRunner';

export interface SupportedScans {
export interface EntitledScans {
dependencies: boolean;
applicability: boolean;
eos: boolean;
sast: boolean;
iac: boolean;
secrets: boolean;
}
Expand All @@ -37,7 +31,7 @@ export class ScanManager implements ExtensionComponent {
private static readonly RESOURCE_CHECK_UPDATE_INTERVAL_MILLISECS: number = 1000 * 60 * 60 * 24;

private static lastOutdatedCheck: number;
private _supportedScans: SupportedScans = {} as SupportedScans;
private _entitledScans: EntitledScans = {} as EntitledScans;

constructor(private _connectionManager: ConnectionManager, protected _logManager: LogManager) {}

Expand All @@ -54,16 +48,16 @@ export class ScanManager implements ExtensionComponent {
return this._connectionManager;
}

public get supportedScans(): SupportedScans {
return this._supportedScans;
public get entitledScans(): EntitledScans {
return this._entitledScans;
}

/**
* Updates all the resources that are outdated.
* @param supportedScans - the supported scan to get the needed resources. if default, should call getSupportedScans before calling this method.
* @returns true if all the outdated resources updated successfully, false otherwise
*/
public async updateResources(supportedScans: SupportedScans = this._supportedScans): Promise<boolean> {
public async updateResources(supportedScans: EntitledScans = this._entitledScans): Promise<boolean> {
let result: boolean = true;
await ScanUtils.backgroundTask(async (progress: vscode.Progress<{ message?: string; increment?: number }>) => {
progress.report({ message: 'Checking for updates' });
Expand Down Expand Up @@ -96,7 +90,7 @@ export class ScanManager implements ExtensionComponent {
return result;
}

private async getOutdatedResources(supportedScans: SupportedScans): Promise<Resource[]> {
private async getOutdatedResources(supportedScans: EntitledScans): Promise<Resource[]> {
if (!this.shouldCheckOutdated()) {
return [];
}
Expand Down Expand Up @@ -128,23 +122,16 @@ export class ScanManager implements ExtensionComponent {
return !ScanManager.lastOutdatedCheck || Date.now() - ScanManager.lastOutdatedCheck > ScanManager.RESOURCE_CHECK_UPDATE_INTERVAL_MILLISECS;
}

private getResources(supportedScans: SupportedScans): Resource[] {
private getResources(supportedScans: EntitledScans): Resource[] {
let resources: Resource[] = [];
if (supportedScans.applicability || supportedScans.iac || supportedScans.secrets) {
resources.push(BinaryRunner.getAnalyzerManagerResource(this._logManager));
resources.push(JasRunner.getAnalyzerManagerResource(this._logManager));
} else {
this.logManager.logMessage('You are not entitled to run Advanced Security scans', 'DEBUG');
}
return resources;
}

/**
* Validate if the graph-scan is supported in the Xray version
*/
public async validateGraphSupported(): Promise<boolean> {
return await ConnectionUtils.testXrayVersionForScanGraph(this._connectionManager.createJfrogClient(), this._logManager);
}

/**
* Check if Contextual Analysis (Applicability) is supported for the user
*/
Expand All @@ -167,23 +154,19 @@ export class ScanManager implements ExtensionComponent {
}

/**
* Check if Eos scan is supported for the user
* Check if SAST scan is supported for the user
*/
public async isEosSupported(): Promise<boolean> {
return true;
public async isSastSupported(): Promise<boolean> {
// TODO: change to SAST feature when Xray entitlement service support it.
return await ConnectionUtils.testXrayEntitlementForFeature(this._connectionManager.createJfrogClient(), EntitlementScanFeature.Applicability);
}

/**
* Get all the entitlement status for each type of scan the manager offers
*/
public async getSupportedScans(): Promise<SupportedScans> {
let supportedScans: SupportedScans = {} as SupportedScans;
public async getSupportedScans(): Promise<EntitledScans> {
let supportedScans: EntitledScans = {} as EntitledScans;
let requests: Promise<any>[] = [];
requests.push(
this.validateGraphSupported()
.then(res => (supportedScans.dependencies = res))
.catch(err => ScanUtils.onScanError(err, this._logManager, true))
);
requests.push(
this.isApplicabilitySupported()
.then(res => (supportedScans.applicability = res))
Expand All @@ -200,12 +183,12 @@ export class ScanManager implements ExtensionComponent {
.catch(err => ScanUtils.onScanError(err, this._logManager, true))
);
requests.push(
this.isEosSupported()
.then(res => (supportedScans.eos = res))
this.isSastSupported()
.then(res => (supportedScans.sast = res))
.catch(err => ScanUtils.onScanError(err, this._logManager, true))
);
await Promise.all(requests);
this._supportedScans = supportedScans;
this._entitledScans = supportedScans;
return supportedScans;
}

Expand All @@ -222,89 +205,4 @@ export class ScanManager implements ExtensionComponent {
let scanLogic: GraphScanLogic = new GraphScanLogic(this._connectionManager);
return await scanLogic.scan(graphRoot, progress, checkCanceled);
}

/**
* Scan CVE in files for applicability issues.
* @param directory - the directory that will be scan
* @param checkCancel - check if should cancel
* @param cveToRun - the CVE list we want to run applicability scan on
* @returns the applicability scan response
*/
public async scanApplicability(
directory: string,
checkCancel: () => void,
cveToRun: Set<string> = new Set<string>()
): Promise<ApplicabilityScanResponse> {
let applicableRunner: ApplicabilityRunner = new ApplicabilityRunner(this._connectionManager, this._logManager);
if (!applicableRunner.validateSupported()) {
this._logManager.logMessage('Applicability runner could not find binary to run', 'WARN');
return {} as ApplicabilityScanResponse;
}
let skipFiles: string[] = AnalyzerUtils.getAnalyzerManagerExcludePattern(Configuration.getScanExcludePattern());
this._logManager.logMessage(
"Scanning directory '" + directory + "' for CVE issues: " + Array.from(cveToRun.values()) + '. Skipping files: ' + skipFiles,
'DEBUG'
);
return await applicableRunner.scan(directory, checkCancel, cveToRun, skipFiles);
}

/**
* Scan directory for 'Infrastructure As Code' (Iac) issues.
* @param directory - the directory that will be scan
* @param checkCancel - check if should cancel
* @returns the Iac scan response
*/
public async scanIac(directory: string, checkCancel: () => void): Promise<IacScanResponse> {
let iacRunner: IacRunner = new IacRunner(this._connectionManager, this.logManager);
if (!iacRunner.validateSupported()) {
this._logManager.logMessage('Iac runner could not find binary to run', 'WARN');
return {} as IacScanResponse;
}
let skipFiles: string[] = AnalyzerUtils.getAnalyzerManagerExcludePattern(Configuration.getScanExcludePattern());
this._logManager.logMessage("Scanning directory '" + directory + "', for Iac issues. Skipping files: " + skipFiles, 'DEBUG');
return await iacRunner.scan(directory, checkCancel, skipFiles);
}
/**
* Scan directory for secrets issues.
* @param directory - the directory that will be scan
* @param checkCancel - check if should cancel
* @returns the Secrets scan response
*/
public async scanSecrets(directory: string, checkCancel: () => void): Promise<SecretsScanResponse> {
let secretsRunner: SecretsRunner = new SecretsRunner(this._connectionManager, this.logManager);
if (!secretsRunner.validateSupported()) {
this._logManager.logMessage('Secrets runner could not find binary to run', 'WARN');
return {} as SecretsScanResponse;
}
let skipFiles: string[] = AnalyzerUtils.getAnalyzerManagerExcludePattern(Configuration.getScanExcludePattern());
this._logManager.logMessage("Scanning directory '" + directory + "', for Secrets issues. Skipping files: " + skipFiles, 'DEBUG');
return await secretsRunner.scan(directory, checkCancel, skipFiles);
}

/**
* Scan for Eos issues.
* @param checkCancel - check if should cancel
* @param requests - the Eos requests to run
* @returns the scan response
*/
public async scanEos(checkCancel: () => void, runDirectory?: string, ...requests: EosScanRequest[]): Promise<EosScanResponse> {
let eosRunner: EosRunner = new EosRunner(this._connectionManager, this._logManager, undefined, undefined, runDirectory);
if (!eosRunner.validateSupported()) {
this._logManager.logMessage('Eos runner could not find binary to run', 'WARN');
return {} as EosScanResponse;
}
if (requests.length === 0) {
this._logManager.logMessage('Eos runner must receive at least one request to run', 'ERR');
return {} as EosScanResponse;
}
let skipFiles: string[] = AnalyzerUtils.getAnalyzerManagerExcludePattern(Configuration.getScanExcludePattern());
this._logManager.logMessage(
'Scanning for Eos issues in ' +
requests.map(request => `(Language '${request.language}', roots: [${request.roots.join()}])`) +
'. Skipping files: ' +
skipFiles,
'DEBUG'
);
return eosRunner.scan(checkCancel, skipFiles, ...requests);
}
}
4 changes: 2 additions & 2 deletions src/main/scanLogic/scanRunners/analyzerModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ export interface AnalyzerRequest {
}

export enum ScanType {
ContextualAnalysis = 'analyze-applicability',
AnalyzeApplicability = 'analyze-applicability',
Iac = 'iac-scan-modules',
Eos = 'analyze-codebase',
Sast = 'sast',
Secrets = 'secrets-scan'
}

Expand Down
Loading

0 comments on commit 065c8b1

Please sign in to comment.