-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support JFrog Apps Config file #405
Changes from all commits
98fe291
818df44
a21a02a
eb968d6
0f91072
9706616
db359b8
0ab640b
8f4e35a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
} | ||
|
@@ -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) {} | ||
|
||
|
@@ -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' }); | ||
|
@@ -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 []; | ||
} | ||
|
@@ -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[] { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'Resource' is a vague name that refers to any artifact that is downloaded from Artifactory. The 'Resource' in 'scanManager' talks about a specific resource which is the JasRunners. I suggest we use the most descriptive name we can and replace 'Resource' with 'JasRunners' |
||
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'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we identify if we are not entitled before calling |
||
} | ||
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 | ||
*/ | ||
|
@@ -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> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest that we change it to be private, and each support check will be response to update it own property
--->
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the suggestion is not related to Apps Config and not to the changes I did in this PR. |
||
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)) | ||
|
@@ -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; | ||
} | ||
|
||
|
@@ -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); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a couple of quistions regarding the param:
Given that its name suggests that
ScanManager
is responsible for managing all scans, why is it necessary to pass in the supported scan as a parameter? As a manager, one would expect it to handle all aspects of the scan without revealing internal implementation details to other functions. A manager should inherently know what is supported or not.The only reference I could find, calling this func is at 'IssuesTreeDataProvider'. Why data providers should care about scan manager updates? again, no one can tell a manager what to do regarding internal details that are being used for scans operations.