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

Report with results of both SCA and SAST from Jenkins Plugin #117

Open
wants to merge 3 commits into
base: march23-integration
Choose a base branch
from
Open
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
117 changes: 112 additions & 5 deletions src/main/java/com/checkmarx/jenkins/CxScanBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public class CxScanBuilder extends Builder implements SimpleBuildStep {
private boolean failBuildOnNewResults;
private String failBuildOnNewSeverity;
private boolean generatePdfReport;
private boolean generateScaReport;
private boolean enableProjectPolicyEnforcement;
@Nullable
private Integer osaHighThreshold;
Expand Down Expand Up @@ -194,6 +195,7 @@ public class CxScanBuilder extends Builder implements SimpleBuildStep {
CxLoggerAdapter log;

private JobStatusOnError jobStatusOnError;
private ScaReportFormat scaReportFormat;
private String exclusionsSetting;
private String thresholdSettings;
private Result vulnerabilityThresholdResult;
Expand Down Expand Up @@ -223,6 +225,7 @@ public CxScanBuilder(
Boolean sastEnabled,
@Nullable String preset,
JobStatusOnError jobStatusOnError,
ScaReportFormat scaReportFormat,
boolean presetSpecified,
String exclusionsSetting,
@Nullable String excludeFolders,
Expand All @@ -245,6 +248,7 @@ public CxScanBuilder(
@Nullable Integer osaMediumThreshold,
@Nullable Integer osaLowThreshold,
boolean generatePdfReport,
boolean generateScaReport,
boolean enableProjectPolicyEnforcement,
String thresholdSettings,
String vulnerabilityThresholdResult,
Expand All @@ -271,6 +275,7 @@ public CxScanBuilder(
this.sastEnabled = sastEnabled;
this.preset = (preset != null && !preset.startsWith("Provide Checkmarx")) ? preset : null;
this.jobStatusOnError = jobStatusOnError;
this.scaReportFormat = scaReportFormat;
this.presetSpecified = presetSpecified;
this.exclusionsSetting = exclusionsSetting;
this.globalExclusions = "global".equals(exclusionsSetting);
Expand All @@ -294,6 +299,7 @@ public CxScanBuilder(
this.osaMediumThreshold = osaMediumThreshold;
this.osaLowThreshold = osaLowThreshold;
this.generatePdfReport = generatePdfReport;
this.generateScaReport = generateScaReport;
this.enableProjectPolicyEnforcement = enableProjectPolicyEnforcement;
this.thresholdSettings = thresholdSettings;
if (vulnerabilityThresholdResult != null) {
Expand Down Expand Up @@ -590,6 +596,10 @@ public void setOsaInstallBeforeScan(boolean osaInstallBeforeScan) {
public boolean isGeneratePdfReport() {
return generatePdfReport;
}

public boolean isGenerateScaReport() {
return generateScaReport;
}

public boolean isEnableProjectPolicyEnforcement() {
return enableProjectPolicyEnforcement;
Expand Down Expand Up @@ -747,6 +757,11 @@ public void setLowThreshold(@Nullable Integer lowThreshold) {
public void setGeneratePdfReport(boolean generatePdfReport) {
this.generatePdfReport = generatePdfReport;
}

@DataBoundSetter
public void setGenerateScaReport(boolean generateScaReport) {
this.generateScaReport = generateScaReport;
}

@DataBoundSetter
public void setEnableProjectPolicyEnforcement(boolean enableProjectPolicyEnforcement) {
Expand Down Expand Up @@ -911,8 +926,10 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnul
EnvVars env = run.getEnvironment(listener);
setJvmVars(env);
Map<String, String> fsaVars = getAllFsaVars(env);
CxScanConfig config = resolveConfiguration(run, descriptor, env, log);

CxScanConfig config;
try {
config = resolveConfiguration(run, descriptor, env, log);

if (configAsCode) {
try {
overrideConfigAsCode(config, workspace);
Expand Down Expand Up @@ -975,6 +992,30 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnul
scanResults.getSastResults().setSastPDFLink(pdfUrl);
}
}

if (config.isGenerateScaReport()) {
if(config.getScaReportFormat() != null) {
String path = "";
// run.getUrl() returns a URL path similar to job/MyJobName/124/
//getRootUrl() will return the value of "Manage Jenkins->configuration->Jenkins URL"
String baseUrl = Jenkins.getInstance().getRootUrl();
if (StringUtils.isNotEmpty(baseUrl)) {
URL parsedUrl = new URL(baseUrl);
path = parsedUrl.getPath();
}
if (!(path.equals("/"))) {
//to handle this Jenkins root url,EX: http://localhost:8081/jenkins
Path pdfUrlPath = Paths.get(path, run.getUrl(), PDF_URL);
scanResults.getScaResults().setScaPDFLink(pdfUrlPath.toString());
} else {
//to handle this Jenkins root url,EX: http://localhost:8081/
String pdfUrl = String.format(PDF_URL_TEMPLATE, run.getUrl());
scanResults.getScaResults().setScaPDFLink(pdfUrl);
}
}
}



//in case of async mode, do not create reports (only the report of the latest scan)
//and don't assert threshold vulnerabilities
Expand Down Expand Up @@ -1015,7 +1056,11 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnul
cxScanResult.setHtmlReportName(reportName);
}
run.addAction(cxScanResult);
} catch (ConfigurationException e1) {
e1.printStackTrace();
}
}


private void overrideConfigAsCode(CxScanConfig config, FilePath workspace) throws ConfigurationException {
String configFilePath =
Expand Down Expand Up @@ -1246,6 +1291,15 @@ private void createScaReports(AstScaResults scaResults, File checkmarxBuildDir)
writeJsonObjectToFile(scaResults.getSummary(), new File(checkmarxBuildDir, SCA_SUMMERY_JSON), "OSA summary json report");
writeJsonObjectToFile(scaResults.getPackages(), new File(checkmarxBuildDir, SCA_LIBRARIES_JSON), "OSA libraries json report");
writeJsonObjectToFile(scaResults.getFindings(), new File(checkmarxBuildDir, SCA_VULNERABILITIES_JSON), "OSA vulnerabilities json report");

if (scaResults.getPDFReport() != null) {
File pdfReportFile = new File(checkmarxBuildDir, CxScanResult.PDF_REPORT_NAME);
try {
FileUtils.writeByteArrayToFile(pdfReportFile, scaResults.getPDFReport());
} catch (IOException e) {
log.warn("Failed to write SCA PDF report to workspace: " + e.getMessage());
}
}
}

/**
Expand Down Expand Up @@ -1330,7 +1384,7 @@ private Boolean verifyCustomCharacters(String inputString) {
}
return true;
}
private CxScanConfig resolveConfiguration(Run<?, ?> run, DescriptorImpl descriptor, EnvVars env, CxLoggerAdapter log) throws IOException {
private CxScanConfig resolveConfiguration(Run<?, ?> run, DescriptorImpl descriptor, EnvVars env, CxLoggerAdapter log) throws IOException, ConfigurationException {
CxScanConfig ret = new CxScanConfig();

ret.setIsOverrideProjectSetting(overrideProjectSetting);
Expand Down Expand Up @@ -1498,6 +1552,20 @@ private CxScanConfig resolveConfiguration(Run<?, ?> run, DescriptorImpl descript
}
ret.setEnablePolicyViolations(enableProjectPolicyEnforcement);

if (!ret.isAstScaEnabled() || !ret.getSynchronous()) {
generateScaReport = false;
}
if (ret.isAstScaEnabled()) {
ret.setGenerateScaReport(generateScaReport);
ret.setScaReportFormat(scaReportFormat.name());
if (ret.getScaReportFormat() != null && !ret.getScaReportFormat().isEmpty()) {
ret.setGenerateScaReport(true);
} else {
ret.setGenerateScaReport(false);
throw new ConfigurationException("Invalid SCA report format:" + scaReportFormat + ".");
}
}

// Set the Continue build flag to Configuration object if Option from UI is choosen as useContinueBuildOnError
if (useContinueBuildOnError(getDescriptor())) {
ret.setContinueBuild(Boolean.TRUE);
Expand Down Expand Up @@ -1791,6 +1859,7 @@ private void printConfiguration(CxScanConfig config, CxLoggerAdapter log) {
log.info("CxSCA web app URL: " + config.getAstScaConfig().getWebAppUrl());
log.info("Account: " + config.getAstScaConfig().getTenant());
log.info("Team: " + config.getAstScaConfig().getTeamPath());
log.info("is generate SCA report: "+ config.isGenerateScaReport());
}
}

Expand Down Expand Up @@ -2139,8 +2208,19 @@ protected Object readResolve() {
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) super.getDescriptor();
}

public ScaReportFormat getScaReportFormat() {
return scaReportFormat;
}

@DataBoundSetter
public void setScaReportFormat(ScaReportFormat scaReportFormat) {
this.scaReportFormat = scaReportFormat;
}

@Extension


@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {

public static final String DEFAULT_FILTER_PATTERNS = CxConfig.defaultFilterPattern();
Expand Down Expand Up @@ -2642,6 +2722,20 @@ public FormValidation doCheckIncremental(@QueryParameter boolean value, @QueryPa

return FormValidation.ok();
}
@POST
public FormValidation doCheckGenerateScaReport(@QueryParameter boolean value, @QueryParameter boolean dependencyScanConfig, @QueryParameter boolean generateScaReport,@AncestorInPath Item item) {
if (item == null) {
return FormValidation.ok();
}
item.checkPermission(Item.CONFIGURE);
if (!dependencyScanConfig && value) {
generateScaReport=false;
dependencyScanConfig = false;
return FormValidation.error("Enable dependency scanner as SCA");
}

return FormValidation.ok();
}

@POST
public FormValidation doTestScaSASTConnection(@QueryParameter final String scaSastServerUrl, @QueryParameter final String password,
Expand Down Expand Up @@ -3068,6 +3162,19 @@ public ListBoxModel doFillVulnerabilityThresholdResultItems(@AncestorInPath Item

return listBoxModel;
}

@POST
public ListBoxModel doFillScaReportFormat(@AncestorInPath Item item) {
if (item == null) {
return new ListBoxModel();
}
item.checkPermission(Item.CONFIGURE);
ListBoxModel listBoxModel = new ListBoxModel();
for (ScaReportFormat status : ScaReportFormat.values()) {
listBoxModel.add(new ListBoxModel.Option(status.getDisplayName(), status.name()));
}
return listBoxModel;
}


/*
Expand Down Expand Up @@ -3371,4 +3478,4 @@ public void setDependencyScanConfig(DependencyScanConfig dependencyScanConfig) {
this.dependencyScanConfig = dependencyScanConfig;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public class DependencyScanConfig {
@DataBoundSetter
public Integer scaTimeout;

@DataBoundSetter
public boolean generateScaReport;

@DataBoundSetter
public boolean isIncludeSources;

Expand All @@ -98,4 +101,4 @@ public class DependencyScanConfig {
@DataBoundConstructor
public DependencyScanConfig() {
}
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/checkmarx/jenkins/ScaReportFormat.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.checkmarx.jenkins;

public enum ScaReportFormat {
PDF("PDF"), XML("XML"), CSV("CSV"), JSON("JSON"), cyclonedxjson("cyclonedxjson"), cyclonedxxml("cyclonedxxml");

private final String displayName;

ScaReportFormat(String displayName) {
this.displayName = displayName;
}

public String getDisplayName() {
return displayName;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@



<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:c="/lib/credentials" xmlns:l="/lib/layout"
xmlns:t="/lib/hudson" xmlns:f="/lib/form" descriptor="${it.descriptor}">
Expand Down Expand Up @@ -242,7 +239,7 @@
<f:entry title="Project ID" field="scaSASTProjectID">
<f:textbox checkMethod="POST" value="${instance.dependencyScanConfig.scaSASTProjectID}"/>
</f:entry>
</f:optionalBlock>
</f:optionalBlock>
</f:radioBlock>
</f:nested>
</f:radioBlock>
Expand Down Expand Up @@ -310,7 +307,16 @@

<!-- -= Generate PDF report =- -->
<f:optionalBlock title="Generate CxSAST PDF report" inline="true" field="generatePdfReport" />


<!-- -= generateScaReport =- -->
<f:optionalBlock title="Generate SCA report" inline="true" field="generateScaReport" checkMethod="POST"
checked="${instance.dependencyScanConfig.dependencyScannerType == 'SCA'}">

<f:entry name="scaReportFormat" title="Report Format:" field="scaReportFormat">
<f:enum field="scaReportFormat">${it.displayName}</f:enum>
</f:entry>
</f:optionalBlock>

<!-- -= enableProjectPolicyEnforcement =- -->
<f:optionalBlock title="Enable Project's policy enforcement" inline="true" field="enableProjectPolicyEnforcement" />

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Downloads a report with scan results from the Checkmarx server. The report is available via a link on "Checkmarx Scan Results" page.
</div>