Skip to content
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

Q2 2024 integration branch #67

Closed
wants to merge 18 commits into from
Closed
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 CxScan/CxScanV20/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cxsast",
"version": "2023.3.3",
"version": "2024.2.1",
"description": "Add Secure Static Source Code Analysis inside your build process",
"main": "index.js",
"repository": "https://github.com/checkmarx-ltd/VSTS-Plugin",
Expand All @@ -10,7 +10,7 @@
"author": "MajdM",
"license": "SEE LICENSE IN checkmarx-license-terms.md",
"dependencies": {
"@checkmarx/cx-common-js-client": "0.1.83",
"@checkmarx/cx-common-js-client": "0.1.86",
"degenerator": "3.0.4",
"azure-pipelines-task-lib": "^3.1.7",
"cookiejar": "2.1.4",
Expand Down
2 changes: 2 additions & 0 deletions CxScan/CxScanV20/services/configReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ var ConfigReader = /** @class */ (function () {
comment: taskLib.getInput('comment', false) || '',
enablePolicyViolations: taskLib.getBoolInput('enablePolicyViolations', false),
vulnerabilityThreshold: taskLib.getBoolInput('vulnerabilityThreshold', false),
criticalThreshold: ConfigReader.getNumericInput('critical'),
highThreshold: ConfigReader.getNumericInput('high'),
mediumThreshold: ConfigReader.getNumericInput('medium'),
lowThreshold: ConfigReader.getNumericInput('low'),
Expand Down Expand Up @@ -94,6 +95,7 @@ var ConfigReader = /** @class */ (function () {
var formatOptionalNumber = function (input) { return (typeof input === 'undefined' ? 'none' : input); };
this.log.info("\n-------------------------------CxSAST Configurations:--------------------------------\nURL: " + config.serverUrl + "\nProject name: " + config.projectName + "\nSource location: " + config.sourceLocation + "\nFull team path: " + config.teamName + "\nPreset name: " + config.presetName + "\nScan timeout in minutes: " + config.scanTimeoutInMinutes + "\nDeny project creation: " + config.denyProject + "\n\nIs incremental scan: " + config.isIncremental + "\nFolder exclusions: " + formatOptionalString(config.folderExclusion) + "\nFile exclusions: " + formatOptionalString(config.fileExtension) + "\nIs synchronous scan: " + config.isSyncMode + "\n\nCxSAST thresholds enabled: " + config.vulnerabilityThreshold);
if (config.vulnerabilityThreshold) {
this.log.info("CxSAST critical threshold: " + formatOptionalNumber(config.criticalThreshold));
this.log.info("CxSAST high threshold: " + formatOptionalNumber(config.highThreshold));
this.log.info("CxSAST medium threshold: " + formatOptionalNumber(config.mediumThreshold));
this.log.info("CxSAST low threshold: " + formatOptionalNumber(config.lowThreshold));
Expand Down
91 changes: 80 additions & 11 deletions CxScan/CxScanV20/services/configReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export class ConfigReader {
private readonly devAzure = 'dev.azure.com';
private readonly MAX_SIZE_CXORIGINURL = 128;
private readonly SIZE_CXORIGIN = 50;
private readonly SCARESOLVER_FILENAME = "\\ScaResolver.exe";
private readonly SCARESOLVER_FILENAME_WINDOWS = "\\ScaResolver.exe";
private readonly SCARESOLVER_FILENAME_OTHER_OS = "ScaResolver";

constructor(private readonly log: Logger) {
}
Expand Down Expand Up @@ -91,6 +92,8 @@ export class ConfigReader {
let vulnerabilityThresholdEnabled = false;
let failBuildForNewVulnerabilitiesEnabled = false;
let failBuildForNewVulnerabilitiesSeverity = '';
let enableBranching = false;
let parentBranchProjectName = '';

let buildId = taskLib.getVariable('Build.BuildId') || '';

Expand All @@ -107,6 +110,9 @@ export class ConfigReader {
presetSASTServiceCon = taskLib.getEndpointAuthorizationParameter(endpointId, 'preset', true) || '';
sastPassword = taskLib.getEndpointAuthorizationParameter(endpointId, 'password', false) || '';
isIncremental = taskLib.getBoolInput('incScan', false) || false;
enableBranching = taskLib.getBoolInput('enableSastBranching', false) || false;
if(enableBranching)
parentBranchProjectName = taskLib.getInput('masterBranchProjectName', false) || '';
// adding
if(isIncremental) {
isScheduledScan = taskLib.getBoolInput('fullScansScheduled', false) || false;
Expand Down Expand Up @@ -331,6 +337,12 @@ export class ConfigReader {

const postScanAction = taskLib.getInput('postScanAction', false) || '';
const avoidDuplicateProjectScans = taskLib.getBoolInput('avoidDuplicateScans', false);

let rawWaitTime = taskLib.getInput('waitingTimeBeforeRetryScan', false) as any;
let retryWaitTime = +rawWaitTime;

let rawSCAWaitTime = taskLib.getInput('waitingTimeBeforeRetrySCAScan', false) as any;
let retrySCAWaitTime = +rawSCAWaitTime;

let rawTimeout = taskLib.getInput('scanTimeout', false) as any;

Expand Down Expand Up @@ -373,7 +385,8 @@ export class ConfigReader {
isEnableScaResolver:taskLib.getBoolInput('isEnableScaResolver', false) || false,
pathToScaResolver:taskLib.getInput('pathToScaResolver', false) || '',
scaResolverAddParameters:taskLib.getInput('scaResolverAddParameters', false) || '',
scaScanTimeoutInMinutes: scaScanTimeoutInMinutes || undefined
scaScanTimeoutInMinutes: scaScanTimeoutInMinutes || undefined,
scaWaitTimeForRetryScan: retrySCAWaitTime || undefined
};

var isSyncMode = taskLib.getBoolInput('syncMode', false);
Expand All @@ -399,6 +412,7 @@ export class ConfigReader {

generatePDFReport: generatePDFReport,
vulnerabilityThreshold: vulnerabilityThresholdEnabled,
criticalThreshold: ConfigReader.getNumericInput('critical'),
highThreshold: ConfigReader.getNumericInput('high'),
mediumThreshold: ConfigReader.getNumericInput('medium'),
lowThreshold: ConfigReader.getNumericInput('low'),
Expand All @@ -412,6 +426,9 @@ export class ConfigReader {
engineConfigurationId: ConfigReader.getNumericInput('engineConfigId'),
postScanActionName: postScanAction,
avoidDuplicateProjectScans: avoidDuplicateProjectScans,
enableSastBranching : enableBranching,
masterBranchProjectName : parentBranchProjectName,
waitTimeForRetryScan : retryWaitTime || undefined
};

const result: ScanConfig = {
Expand Down Expand Up @@ -472,7 +489,9 @@ Preset name: ${config.sastConfig.presetName}
Deny project creation: ${config.sastConfig.denyProject}
Force scan : ${config.sastConfig.forceScan}
Is Override Project Settings: ${config.sastConfig.overrideProjectSettings}
Is incremental scan: ${config.sastConfig.isIncremental}`);
Is incremental scan: ${config.sastConfig.isIncremental}
Enable SAST Branching : ${config.sastConfig.enableSastBranching}
Master Branch Project Name : ${config.sastConfig.masterBranchProjectName}`);
if (config.sastConfig.isIncremental) {
let isScheduledScan = taskLib.getBoolInput('fullScansScheduled', false) || false;
let scheduleCycle = taskLib.getInput('fullScanCycle', false) || '';
Expand All @@ -482,6 +501,9 @@ if (config.sastConfig.isIncremental) {
if(config.sastConfig.scanTimeoutInMinutes != undefined){
this.log.info(`Scan timeout in minutes: ${config.sastConfig.scanTimeoutInMinutes}`);
}
if(config.sastConfig.waitTimeForRetryScan != undefined){
this.log.info(`Waiting Time Before Retry Scan In Seconds: ${config.sastConfig.waitTimeForRetryScan}`);
}
this.log.info(`Folder exclusions: ${formatOptionalString(config.sastConfig.folderExclusion)}
Include/Exclude Wildcard Patterns: ${formatOptionalString(config.sastConfig.fileExtension)}
Is synchronous scan: ${config.isSyncMode}
Expand All @@ -500,6 +522,7 @@ CxSAST thresholds enabled: ${config.sastConfig.vulnerabilityThreshold}`);
if (config.sastConfig.vulnerabilityThreshold) {
this.log.info(`CxSAST fail build for new vulnerabilities enabled: ${config.sastConfig.failBuildForNewVulnerabilitiesEnabled}`);
this.log.info(`CxSAST fail build for the following severity or greater: ${config.sastConfig.failBuildForNewVulnerabilitiesSeverity}`);
this.log.info(`CxSAST critical threshold: ${formatOptionalNumber(config.sastConfig.criticalThreshold)}`);
this.log.info(`CxSAST high threshold: ${formatOptionalNumber(config.sastConfig.highThreshold)}`);
this.log.info(`CxSAST medium threshold: ${formatOptionalNumber(config.sastConfig.mediumThreshold)}`);
this.log.info(`CxSAST low threshold: ${formatOptionalNumber(config.sastConfig.lowThreshold)}`);
Expand Down Expand Up @@ -534,22 +557,35 @@ Vulnerability Threshold: ${config.scaConfig.vulnerabilityThreshold}
Enable SCA Resolver:${config.scaConfig.isEnableScaResolver}
`);
if(config.scaConfig.isEnableScaResolver) {

var isScaResolverFileExists= fs.existsSync(config.scaConfig.pathToScaResolver.concat(this.SCARESOLVER_FILENAME) );

let isScaResolverFileExists= false;
let osTypeDetails = os.type();

if(osTypeDetails == 'Windows_NT')
{
isScaResolverFileExists = fs.existsSync(config.scaConfig.pathToScaResolver.concat(this.SCARESOLVER_FILENAME_WINDOWS));
}
else if(osTypeDetails == 'Darwin' || osTypeDetails == 'Linux')
{
isScaResolverFileExists = fs.existsSync(path.join(config.scaConfig.pathToScaResolver, this.SCARESOLVER_FILENAME_OTHER_OS));
}

if (!isScaResolverFileExists && config.scaConfig.pathToScaResolver != '' )
{
this.log.warning(`SCA Resolver tool doesn't exists on given SCA Resolver path. Latest SCA Resolver would be auto downloaded for usage in user directory.`);
}

if (config.scaConfig.pathToScaResolver == '' || !isScaResolverFileExists){
config.scaConfig.pathToScaResolver = this.getPathToScaResolver(config.scaConfig.pathToScaResolver);
config.scaConfig.pathToScaResolver = this.getPathToScaResolver(config.scaConfig.pathToScaResolver,config.enableProxy,config.proxyConfig?.scaProxyUrl);
}
this.log.info(`Path To SCA Resolver:${config.scaConfig.pathToScaResolver}`);
}
if(config.scaConfig.scaScanTimeoutInMinutes != undefined) {
this.log.info(`Scan timeout in minutes: ${config.scaConfig.scaScanTimeoutInMinutes}`);
}
if(config.scaConfig.scaWaitTimeForRetryScan != undefined) {
this.log.info(`Waiting time before retry SCA scan in seconds: ${config.scaConfig.scaWaitTimeForRetryScan}`);
}
if (config.scaConfig.vulnerabilityThreshold) {
this.log.info(`CxSCA High Threshold: ${config.scaConfig.highThreshold}
CxSCA Medium Threshold: ${config.scaConfig.mediumThreshold}
Expand Down Expand Up @@ -624,30 +660,63 @@ Proxy Pass: ******`);
}

//To get path of SCA Resolver
public getPathToScaResolver(config : string){
public getPathToScaResolver(config : string,enableProxy :boolean,proxyUrl :string = ''){
let pathToScaResolver;
try {
let SCAResDowonloadCommand = '';
const child_process = require('child_process');
const userHomeDir = os.homedir();
pathToScaResolver = userHomeDir;

this.log.debug("Downloading SCA Resolver and extracting it to user home directory.");

if (enableProxy) {
this.log.info(`scanConfig.enableProxy is TRUE`);
}

if (proxyUrl != undefined && proxyUrl != '') {

this.log.info(`proxyConfig.proxyUrl is TRUE`);
this.log.info(`SCA proxy URL: ` + proxyUrl);
}

let osType = os.type();
switch(osType) {
case 'Darwin':
this.log.debug("Downloading and extracting SCA Resolver for Mac operating system");
SCAResDowonloadCommand = "curl -L https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-macos64.tar.gz -o ScaResolver.tar.gz && tar -vxzf ScaResolver.tar.gz && sudo mv ScaResolver " + userHomeDir + " && rm ScaResolver.tar.gz";
if (enableProxy && proxyUrl !=undefined && proxyUrl != '')
{
SCAResDowonloadCommand = `curl -L -x ${proxyUrl} https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-macos64.tar.gz -o ScaResolver.tar.gz && tar -vxzf ScaResolver.tar.gz && sudo mv ScaResolver ` + userHomeDir + ` && rm ScaResolver.tar.gz`;
}
else
{
SCAResDowonloadCommand = "curl -L https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-macos64.tar.gz -o ScaResolver.tar.gz && tar -vxzf ScaResolver.tar.gz && sudo mv ScaResolver " + userHomeDir + " && rm ScaResolver.tar.gz";
}
this.log.debug("Sca Resolver gets downloaded at location: "+userHomeDir);
break;
case 'Linux':
this.log.debug("Downloading and extracting SCA Resolver for linux operating system");
SCAResDowonloadCommand = "curl -L https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-linux64.tar.gz -o ScaResolver.tar.gz && tar -vxzf ScaResolver.tar.gz && sudo mv ScaResolver " + userHomeDir + " && rm ScaResolver.tar.gz";
if (enableProxy && proxyUrl !=undefined && proxyUrl != '')
{
SCAResDowonloadCommand = `curl -L -x ${proxyUrl} https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-linux64.tar.gz -o ScaResolver.tar.gz && tar -vxzf ScaResolver.tar.gz && sudo mv ScaResolver ` + userHomeDir + ` && rm ScaResolver.tar.gz`;
}
else
{
SCAResDowonloadCommand = "curl -L https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-linux64.tar.gz -o ScaResolver.tar.gz && tar -vxzf ScaResolver.tar.gz && sudo mv ScaResolver " + userHomeDir + " && rm ScaResolver.tar.gz";
}
this.log.debug("Sca Resolver gets downloaded at location: "+userHomeDir);
break;
case 'Windows_NT':
this.log.debug("Downloading and extracting SCA Resolver for windows operating system");
SCAResDowonloadCommand = "curl -L https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-win64.zip -o ScaResolver.zip && tar -xf ScaResolver.zip && move ScaResolver.exe " + userHomeDir + " && del ScaResolver.zip";

if (enableProxy && proxyUrl !=undefined && proxyUrl != '')
{
SCAResDowonloadCommand = `curl -L -x ${proxyUrl} https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-win64.zip -o ScaResolver.zip && tar -xf ScaResolver.zip && move ScaResolver.exe ` + userHomeDir + ` && del ScaResolver.zip`;
}
else
{
SCAResDowonloadCommand = "curl -L https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-win64.zip -o ScaResolver.zip && tar -xf ScaResolver.zip && move ScaResolver.exe " + userHomeDir + " && del ScaResolver.zip";
}
this.log.debug("Sca Resolver gets downloaded at location: "+userHomeDir);
break;
}
Expand Down
56 changes: 46 additions & 10 deletions CxScan/CxScanV20/services/taskRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import {ConsoleLogger} from "./consoleLogger";
import {ConfigReader} from "./configReader";
import * as fs from "fs";
import {tmpNameSync} from "tmp";
import {CxClient} from "@checkmarx/cx-common-js-client";
import {ScanResults} from "@checkmarx/cx-common-js-client";
import {TaskSkippedError} from "@checkmarx/cx-common-js-client";
import {Logger} from "@checkmarx/cx-common-js-client";
import {CxClient, ScanConfig,Logger,TaskSkippedError,ScanResults} from "@checkmarx/cx-common-js-client";
import * as path from "path";

export class TaskRunner {
Expand All @@ -17,6 +14,8 @@ export class TaskRunner {
private static readonly REPORT_SCA_SUMMARY = 'cxSCASummary';
private static readonly CxSAST = 'SAST';
private static readonly CxDependency = 'SCA';
private readonly MinValue = 1;
private readonly MaxValue = 60;

private readonly log: Logger = new ConsoleLogger();

Expand All @@ -43,12 +42,15 @@ export class TaskRunner {
const reader = new ConfigReader(this.log);
const config = reader.readConfig();

const cxClient = new CxClient(this.log);
const scanResults: ScanResults = await cxClient.scan(config);
await this.attachJsonReport(scanResults);

if (scanResults.buildFailed) {
taskLib.setResult(taskLib.TaskResult.Failed, 'Build failed');
if(this.validateConfigParameter(config))
{
this.log.info('Inside validateConfigParameter');
const cxClient = new CxClient(this.log);
const scanResults: ScanResults = await cxClient.scan(config);
await this.attachJsonReport(scanResults);
if (scanResults.buildFailed) {
taskLib.setResult(taskLib.TaskResult.Failed, 'Build failed');
}
}
} catch (err) {
if (err instanceof TaskSkippedError) {
Expand Down Expand Up @@ -203,4 +205,38 @@ export class TaskRunner {

Starting Checkmarx scan`);
}

private validateConfigParameter(config :ScanConfig) : boolean
{
let sastWaitTime = taskLib.getInput('waitingTimeBeforeRetryScan', false) as any;
let scaWaitTime = taskLib.getInput('waitingTimeBeforeRetrySCAScan', false) as any;
if(config.enableSastScan && sastWaitTime!=undefined && sastWaitTime.trim() != '')
{
if(isNaN(sastWaitTime))
{
taskLib.setResult(taskLib.TaskResult.Failed, 'Waiting time before retry scan input is invalid value.');
return false;
}
else if (sastWaitTime <= this.MinValue || sastWaitTime >= this.MaxValue) {
taskLib.setResult(taskLib.TaskResult.Failed, `Waiting time before retry scan value must be a between ${this.MinValue} and ${this.MaxValue}.`);
return false;
}
}

if(config.enableDependencyScan && scaWaitTime!= undefined && scaWaitTime.trim() != '')
{
this.log.info('inside function');
if(isNaN(scaWaitTime))
{
taskLib.setResult(taskLib.TaskResult.Failed, 'Waiting time before retry sca scan input is invalid value.');
return false;
}
else if (scaWaitTime <= this.MinValue || scaWaitTime >= this.MaxValue) {
taskLib.setResult(taskLib.TaskResult.Failed, `Waiting time before retry sca scan value must be a between ${this.MinValue} and ${this.MaxValue}.`);
return false;
}
}
return true;
}

}
Loading