diff --git a/build.gradle b/build.gradle index 82fb6f0b..e7a6a64d 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ dependencies { compileOnly 'com.intellij:annotations:12.0', 'org.slf4j:slf4j-api:1.6.1' - compile 'com.checkmarx:cx-client-common:2020.3.82', + compile 'com.checkmarx:cx-client-common:2020.4.96', 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.5', 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.5' @@ -52,15 +52,15 @@ dependencies { 'org.jenkins-ci.plugins:credentials:2.1.19@jar' - testCompile 'junit:junit:4.12', + testCompile 'junit:junit:4.13.1', 'org.eclipse.sisu:org.eclipse.sisu.plexus:0.0.0.M5', 'org.jmockit:jmockit:1.16' // Fails with Gradle 2.12 and up without it. Related to https://issues.jenkins-ci.org/browse/JENKINS-17129 jenkinsTest 'org.jenkins-ci.plugins:ant:1.2@jar', - 'org.jenkins-ci.plugins:mailer:1.1@jar', - 'org.jenkins-ci.plugins:matrix-project:1.14@jar' + 'org.jenkins-ci.plugins:mailer:1.32.1@jar', + 'org.jenkins-ci.plugins:matrix-project:1.18@jar' testImplementation('org.junit.jupiter:junit-jupiter-api:5.4.2', 'org.mockito:mockito-junit-jupiter:2.23.0') diff --git a/gradle.properties b/gradle.properties index ec2248a7..2ae6c5e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ description = Provides automatic scan of code by Checkmarx server and shows results summary and trend in Jenkins interface. group = com.checkmarx.jenkins -version = 2020.3.6 +version = 2020.4.3 repositoryVersion= diff --git a/src/main/java/com/checkmarx/jenkins/CxScanBuilder.java b/src/main/java/com/checkmarx/jenkins/CxScanBuilder.java index e142d4b9..a36b6a28 100644 --- a/src/main/java/com/checkmarx/jenkins/CxScanBuilder.java +++ b/src/main/java/com/checkmarx/jenkins/CxScanBuilder.java @@ -56,9 +56,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -435,6 +433,11 @@ public boolean isOsaEnabled() { return osaEnabled; } + @DataBoundSetter + public void setOsaEnabled(boolean osaEnabled) { + this.osaEnabled = osaEnabled; + } + @Nullable public Integer getOsaHighThreshold() { return osaHighThreshold; @@ -470,21 +473,41 @@ public String getExcludeOpenSourceFolders() { return excludeOpenSourceFolders; } + @DataBoundSetter + public void setExcludeOpenSourceFolders(@Nullable String excludeOpenSourceFolders) { + this.excludeOpenSourceFolders = excludeOpenSourceFolders; + } + @Nullable public String getIncludeOpenSourceFolders() { return includeOpenSourceFolders; } + @DataBoundSetter + public void setIncludeOpenSourceFolders(@Nullable String includeOpenSourceFolders) { + this.includeOpenSourceFolders = includeOpenSourceFolders; + } + @Nullable public String getOsaArchiveIncludePatterns() { return osaArchiveIncludePatterns; } + @DataBoundSetter + public void setOsaArchiveIncludePatterns(@Nullable String osaArchiveIncludePatterns) { + this.osaArchiveIncludePatterns = osaArchiveIncludePatterns; + } + @Nullable public boolean isOsaInstallBeforeScan() { return osaInstallBeforeScan; } + @DataBoundSetter + public void setOsaInstallBeforeScan(boolean osaInstallBeforeScan) { + this.osaInstallBeforeScan = osaInstallBeforeScan; + } + public boolean isGeneratePdfReport() { return generatePdfReport; } @@ -857,6 +880,17 @@ private CxScanConfig resolveConfiguration(Run run, DescriptorImpl descript } } + if (isOsaEnabled() && getDependencyScanConfig() == null) { + DependencyScanConfig config = new DependencyScanConfig(); + config.overrideGlobalConfig = true; + config.dependencyScannerType = DependencyScannerType.OSA; + config.dependencyScanPatterns = getIncludeOpenSourceFolders(); + config.dependencyScanExcludeFolders = getExcludeOpenSourceFolders(); + config.osaArchiveIncludePatterns = getOsaArchiveIncludePatterns(); + config.osaInstallBeforeScan = isOsaInstallBeforeScan(); + setDependencyScanConfig(config); + } + configureDependencyScan(run, descriptor, env, ret); if (!ret.getSynchronous()) { @@ -886,7 +920,16 @@ private void configureDependencyScan(Run run, DescriptorImpl descriptor, E return; } - config.addScannerType(effectiveConfig.dependencyScannerType); + ScannerType scannerType = null; + if (effectiveConfig.dependencyScannerType == DependencyScannerType.OSA) { + scannerType = ScannerType.OSA; + } else if (effectiveConfig.dependencyScannerType == DependencyScannerType.SCA) { + scannerType = ScannerType.AST_SCA; + } + + if (scannerType != null) { + config.addScannerType(scannerType); + } config.setOsaFilterPattern(env.expand(effectiveConfig.dependencyScanPatterns)); config.setOsaFolderExclusions(env.expand(effectiveConfig.dependencyScanExcludeFolders)); @@ -1063,9 +1106,9 @@ private void failTheBuild(Run run, CxScanConfig config, ScanResults ret) { //assert if expected exception is thrown OR when vulnerabilities under threshold OR when policy violated ScanSummary scanSummary = new ScanSummary(config, ret.getSastResults(), ret.getOsaResults(), ret.getScaResults()); if (scanSummary.hasErrors() || ret.getGeneralException() != null || - (ret.getSastResults() != null && (ret.getSastResults().getCreateException() != null || ret.getSastResults().getWaitException() != null)) || - (ret.getOsaResults() != null && (ret.getOsaResults().getCreateException() != null || ret.getOsaResults().getWaitException() != null)) || - (ret.getScaResults() != null && (ret.getScaResults().getCreateException() != null || ret.getScaResults().getWaitException() != null))) { + (ret.getSastResults() != null && ret.getSastResults().getException() != null) || + (ret.getOsaResults() != null && ret.getOsaResults().getException() != null) || + (ret.getScaResults() != null && ret.getScaResults().getException() != null)) { printBuildFailure(scanSummary.toString(), ret, log); if (resolvedVulnerabilityThresholdResult != null) { run.setResult(resolvedVulnerabilityThresholdResult); @@ -1085,17 +1128,12 @@ private void printBuildFailure(String thDescription, ScanResults ret, CxLoggerAd log.error("********************************************"); logError(ret.getGeneralException()); - if (ret.getSastResults() != null) { - logError(ret.getSastResults().getCreateException()); - logError(ret.getSastResults().getWaitException()); - } - if (ret.getOsaResults() != null) { - logError(ret.getOsaResults().getCreateException()); - logError(ret.getOsaResults().getWaitException()); - } - if (ret.getScaResults() != null) { - logError(ret.getScaResults().getCreateException()); - logError(ret.getScaResults().getWaitException()); + + Map resultsMap = ret.getResults(); + for (Results results : resultsMap.values()) { + if (results != null && results.getException() != null) { + logError(results.getException()); + } } if (thDescription != null) { diff --git a/src/main/java/com/checkmarx/jenkins/CxScanCallable.java b/src/main/java/com/checkmarx/jenkins/CxScanCallable.java index a73618f2..55aef425 100644 --- a/src/main/java/com/checkmarx/jenkins/CxScanCallable.java +++ b/src/main/java/com/checkmarx/jenkins/CxScanCallable.java @@ -2,7 +2,9 @@ import com.cx.restclient.CxClientDelegator; import com.cx.restclient.configuration.CxScanConfig; +import com.cx.restclient.dto.Results; import com.cx.restclient.dto.ScanResults; +import com.cx.restclient.dto.ScannerType; import com.cx.restclient.exception.CxClientException; import hudson.FilePath; import hudson.ProxyConfiguration; @@ -13,6 +15,9 @@ import java.io.File; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.StreamHandler; @@ -25,10 +30,6 @@ public class CxScanCallable implements FilePath.FileCallable, Se private final TaskListener listener; private ProxyConfiguration jenkinsProxy = null; - private Exception sastCreateEx; - private Exception osaCreateEx; - private Exception scaCreateEx; - public CxScanCallable(CxScanConfig config, TaskListener listener) { this.config = config; this.listener = listener; @@ -47,21 +48,22 @@ public RemoteScanInfo invoke(File file, VirtualChannel channel) throws IOExcepti config.setReportsDir(file); RemoteScanInfo result = new RemoteScanInfo(); - ScanResults scanResults = new ScanResults(); - result.setScanResults(scanResults); - CxClientDelegator delegator = null; + List results = new ArrayList<>(); + try { - //todo: add proxy support in new common delegator = CommonClientFactory.getClientDelegatorInstance(config, log); - delegator.init(); + ScanResults initResults = delegator.init(); + results.add(initResults); // Make sure CxARMUrl is passed in the result. // Cannot pass CxARMUrl in the config object, because this callable can be executed on a Jenkins agent. // On a Jenkins agent we'll get a cloned config instead of the original object reference. result.setCxARMUrl(config.getCxARMUrl()); } catch (Exception ex) { + ScanResults scanResults = new ScanResults(); scanResults.setGeneralException(ex); + result.setScanResults(scanResults); String message = ex.getMessage(); // Can actually be null e.g. for NullPointerException. @@ -102,17 +104,18 @@ public RemoteScanInfo invoke(File file, VirtualChannel channel) throws IOExcepti } ScanResults createScanResults = delegator.initiateScan(); - updateCreateExceptions(createScanResults, false); + results.add(createScanResults); if (rootLog != null) { handler.flush(); rootLog.removeHandler(handler); } - scanResults = config.getSynchronous() ? delegator.waitForScanResults() : delegator.getLatestScanResults(); - updateCreateExceptions(scanResults, true); + ScanResults scanResults = config.getSynchronous() ? delegator.waitForScanResults() : delegator.getLatestScanResults(); + results.add(scanResults); - if (config.getSynchronous() && config.isSastEnabled() && scanResults.getSastResults().getWaitException() != null) { + if (config.getSynchronous() && config.isSastEnabled() && + ((createScanResults.getSastResults() != null && createScanResults.getSastResults().getException() != null && createScanResults.getSastResults().getScanId() > 0) || (scanResults.getSastResults() != null && scanResults.getSastResults().getException() != null))) { cancelScan(delegator); } @@ -120,7 +123,8 @@ public RemoteScanInfo invoke(File file, VirtualChannel channel) throws IOExcepti delegator.printIsProjectViolated(scanResults); } - result.setScanResults(scanResults); + ScanResults finalScanResults = getFinalScanResults(results); + result.setScanResults(finalScanResults); return result; } @@ -136,22 +140,21 @@ public void checkRoles(RoleChecker checker) throws SecurityException { } - private void updateCreateExceptions(ScanResults results, boolean shouldAddException) { - boolean sastResults = results.getSastResults() != null; - boolean osaResults = results.getOsaResults() != null; - boolean scaResults = results.getScaResults() != null; - - if (!shouldAddException) { - sastCreateEx = sastResults ? results.getSastResults().getCreateException() : null; - osaCreateEx = osaResults ? results.getOsaResults().getCreateException() : null; - scaCreateEx = scaResults ? results.getScaResults().getCreateException() : null; - } else { - if (sastResults) - results.getSastResults().setCreateException(sastCreateEx); - if (osaResults) - results.getOsaResults().setCreateException(osaCreateEx); - if (scaResults) - results.getScaResults().setCreateException(scaCreateEx); + private ScanResults getFinalScanResults(List results) { + ScanResults scanResults = new ScanResults(); + + for (int i = 0; i < results.size(); i++) { + Map resultsMap = results.get(i).getResults(); + for (Map.Entry entry : resultsMap.entrySet()) { + if (entry != null && entry.getValue() != null && entry.getValue().getException() != null && scanResults.get(entry.getKey()) == null) { + scanResults.put(entry.getKey(), entry.getValue()); + } + if (i == results.size() - 1 && entry != null && entry.getValue() != null && entry.getValue().getException() == null) { + scanResults.put(entry.getKey(), entry.getValue()); + } + } } + + return scanResults; } } \ No newline at end of file diff --git a/src/main/java/com/checkmarx/jenkins/DependencyScanConfig.java b/src/main/java/com/checkmarx/jenkins/DependencyScanConfig.java index af207833..fdad6d56 100644 --- a/src/main/java/com/checkmarx/jenkins/DependencyScanConfig.java +++ b/src/main/java/com/checkmarx/jenkins/DependencyScanConfig.java @@ -1,6 +1,5 @@ package com.checkmarx.jenkins; -import com.cx.restclient.dto.ScannerType; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -22,7 +21,7 @@ public class DependencyScanConfig { public String dependencyScanExcludeFolders; @DataBoundSetter - public ScannerType dependencyScannerType; + public DependencyScannerType dependencyScannerType; @DataBoundSetter public String osaArchiveIncludePatterns; diff --git a/src/main/java/com/checkmarx/jenkins/DependencyScannerType.java b/src/main/java/com/checkmarx/jenkins/DependencyScannerType.java new file mode 100644 index 00000000..5bd9ca7a --- /dev/null +++ b/src/main/java/com/checkmarx/jenkins/DependencyScannerType.java @@ -0,0 +1,6 @@ +package com.checkmarx.jenkins; + +public enum DependencyScannerType { + OSA, + SCA +} diff --git a/src/main/java/com/checkmarx/jenkins/PluginDataMigration.java b/src/main/java/com/checkmarx/jenkins/PluginDataMigration.java index adcee836..774eb8c4 100644 --- a/src/main/java/com/checkmarx/jenkins/PluginDataMigration.java +++ b/src/main/java/com/checkmarx/jenkins/PluginDataMigration.java @@ -1,6 +1,5 @@ package com.checkmarx.jenkins; -import com.cx.restclient.dto.ScannerType; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.jetbrains.annotations.NotNull; @@ -43,7 +42,7 @@ private boolean needToMigrate(CxScanBuilder builder) { private DependencyScanConfig extractDependencyScanConfig(CxScanBuilder builder) { DependencyScanConfig config = new DependencyScanConfig(); config.overrideGlobalConfig = true; - config.dependencyScannerType = ScannerType.OSA; + config.dependencyScannerType = DependencyScannerType.OSA; config.dependencyScanPatterns = builder.getIncludeOpenSourceFolders(); config.dependencyScanExcludeFolders = builder.getExcludeOpenSourceFolders(); config.osaArchiveIncludePatterns = builder.getOsaArchiveIncludePatterns(); diff --git a/src/main/resources/com/checkmarx/jenkins/CxScanBuilder/config.jelly b/src/main/resources/com/checkmarx/jenkins/CxScanBuilder/config.jelly index 14c16ca4..cc3949b0 100644 --- a/src/main/resources/com/checkmarx/jenkins/CxScanBuilder/config.jelly +++ b/src/main/resources/com/checkmarx/jenkins/CxScanBuilder/config.jelly @@ -131,8 +131,8 @@ - + - +