diff --git a/pom.xml b/pom.xml index 289117c..5011a28 100644 --- a/pom.xml +++ b/pom.xml @@ -163,6 +163,19 @@ + + + atlassian-public + https://m2proxy.atlassian.com/repository/public/ + + true + + + true + + + + atlassian-public @@ -175,5 +188,4 @@ - diff --git a/src/main/java/neuvector/NeuVectorGlobalConfigurator.java b/src/main/java/neuvector/NeuVectorGlobalConfigurator.java index e98d229..4ca590f 100644 --- a/src/main/java/neuvector/NeuVectorGlobalConfigurator.java +++ b/src/main/java/neuvector/NeuVectorGlobalConfigurator.java @@ -4,6 +4,7 @@ import com.atlassian.bamboo.configuration.AdministrationConfigurationPersister; import com.atlassian.bamboo.configuration.GlobalAdminAction; import com.atlassian.spring.container.ContainerManager; +import org.apache.commons.lang3.math.NumberUtils; import java.net.InetAddress; @@ -19,6 +20,11 @@ public class NeuVectorGlobalConfigurator extends GlobalAdminAction { private String scannerImageRepository; private String scannerRegistryUsername; private String scannerRegistryPassword; + + private boolean isCustomThreshold = false; + private String customCriticalThreshold; + private String customHighThreshold; + private String customMediumThreshold; public String execute() throws Exception { final AdministrationConfiguration adminConfig = (AdministrationConfiguration) ContainerManager.getComponent("administrationConfiguration"); @@ -33,11 +39,20 @@ public String execute() throws Exception { this.scannerImageRepository = adminConfig.getSystemProperty("scannerImageRepository"); this.scannerRegistryUsername = adminConfig.getSystemProperty("scannerRegistryUsername"); this.scannerRegistryPassword = adminConfig.getSystemProperty("scannerRegistryPassword"); + + this.customCriticalThreshold = adminConfig.getSystemProperty("customCriticalThreshold"); + this.customHighThreshold = adminConfig.getSystemProperty("customHighThreshold"); + this.customMediumThreshold = adminConfig.getSystemProperty("customMediumThreshold"); + return "input"; } public String save() { final AdministrationConfiguration adminConfig = (AdministrationConfiguration) ContainerManager.getComponent("administrationConfiguration"); + if (!checkCustomThreshold(this.customCriticalThreshold, this.customHighThreshold, this.customMediumThreshold)) { + return "success"; + } + adminConfig.setSystemProperty("controllerIP", this.controllerIP); adminConfig.setSystemProperty("controllerPort", this.controllerPort); adminConfig.setSystemProperty("nvUsername", this.nvUsername); @@ -50,6 +65,12 @@ public String save() { adminConfig.setSystemProperty("scannerRegistryUsername", this.scannerRegistryUsername); adminConfig.setSystemProperty("scannerRegistryPassword", this.scannerRegistryPassword); + adminConfig.setSystemProperty("customCriticalThreshold", this.customCriticalThreshold); + adminConfig.setSystemProperty("customHighThreshold", this.customHighThreshold); + adminConfig.setSystemProperty("customMediumThreshold", this.customMediumThreshold); + adminConfig.setSystemProperty("customMediumThreshold", this.customMediumThreshold); + adminConfig.setSystemProperty("isCustomThreshold", String.valueOf(this.isCustomThreshold)); + ((AdministrationConfigurationPersister) ContainerManager.getComponent("administrationConfigurationPersister")).saveAdministrationConfiguration(adminConfig); this.addActionMessage("NeuVector Global Configuration Successfully Saved"); return "success"; @@ -78,6 +99,41 @@ public boolean checkControllerPort(final String value) { } } + public boolean checkCustomThreshold(final String customCriticalThreshold, final String customHighThreshold, final String customMediumThreshold) { + if (customCriticalThreshold == null && customHighThreshold == null && customMediumThreshold == null) { + return true; + } + + if (!NumberUtils.isParsable(customCriticalThreshold) || !NumberUtils.isParsable(customHighThreshold) || !NumberUtils.isParsable(customMediumThreshold)) { + this.addActionError("One or more thresholds are not valid numbers."); + return false; + } + + try { + double criticalSeverityThreshold = Double.parseDouble(customCriticalThreshold.trim()); + double highSeverityThreshold = Double.parseDouble(customHighThreshold.trim()); + double mediumSeverityThreshold = Double.parseDouble(customMediumThreshold.trim()); + + if (criticalSeverityThreshold < 0.0 || criticalSeverityThreshold > 10.0 || + highSeverityThreshold < 0.0 || highSeverityThreshold > 10.0 || + mediumSeverityThreshold < 0.0 || mediumSeverityThreshold > 10.0) { + this.addActionError("Threshold values must be between 0.0 and 10.0."); + return false; + } + + if (criticalSeverityThreshold <= highSeverityThreshold || criticalSeverityThreshold <= mediumSeverityThreshold || highSeverityThreshold <= mediumSeverityThreshold) { + this.addActionError("Thresholds must satisfy: Critical > High > Medium."); + return false; + } + + } catch (NumberFormatException e) { + this.addActionError("An unexpected error occurred while parsing the numbers."); // Fallback error + return false; + } + isCustomThreshold = true; + return true; + } + public String getControllerIP() { return this.controllerIP; } @@ -165,4 +221,36 @@ public String getScannerRegistryPassword() { public void setScannerRegistryPassword(String scannerRegistryPassword) { this.scannerRegistryPassword = scannerRegistryPassword; } + + public String getCustomCriticalThreshold() { + return customCriticalThreshold; + } + + public void setCustomCriticalThreshold(String customCriticalThreshold) { + this.customCriticalThreshold = customCriticalThreshold; + } + + public String getCustomHighThreshold() { + return customHighThreshold; + } + + public void setCustomHighThreshold(String customHighThreshold) { + this.customHighThreshold = customHighThreshold; + } + + public String getCustomMediumThreshold() { + return customMediumThreshold; + } + + public void setCustomMediumThreshold(String customMediumThreshold) { + this.customMediumThreshold = customMediumThreshold; + } + + // public boolean getIsCustomizeThresholds() { + // return isCustomizeThresholds; + // } + + // public void setCustomizeThresholds(boolean isCustomizeThresholds) { + // this.isCustomizeThresholds = isCustomizeThresholds; + // } } \ No newline at end of file diff --git a/src/main/java/neuvector/NeuVectorScannerTask.java b/src/main/java/neuvector/NeuVectorScannerTask.java index 7a06207..2f1ce01 100644 --- a/src/main/java/neuvector/NeuVectorScannerTask.java +++ b/src/main/java/neuvector/NeuVectorScannerTask.java @@ -1,5 +1,7 @@ package neuvector; +import com.atlassian.spring.container.ContainerManager; +import com.atlassian.bamboo.configuration.AdministrationConfiguration; import com.atlassian.bamboo.build.logger.BuildLogger; import com.atlassian.bamboo.task.TaskContext; import com.atlassian.bamboo.task.TaskException; @@ -26,12 +28,16 @@ import neuvector.report.*; import neuvector.scanner.*; +import org.apache.commons.lang3.math.NumberUtils; + public class NeuVectorScannerTask implements TaskType { private BuildLogger buildLogger; private ScanConfig scanConfig; private StandaloneScanner standaloneScanner; private ControllerScanner controllerScanner; + private NeuVectorGlobalConfigurator nvConfigurator = new NeuVectorGlobalConfigurator(); + final AdministrationConfiguration adminConfig = (AdministrationConfiguration) ContainerManager.getComponent("administrationConfiguration"); @Override public TaskResult execute(final TaskContext taskContext) throws TaskException { @@ -76,11 +82,43 @@ public TaskResult execute(final TaskContext taskContext) throws TaskException { } } + private Double getCustomThresholdScore(String threshold) { + double thresholdScore = 0.0; + String thresholdScoreStr = adminConfig.getSystemProperty("customCriticalThreshold"); + + if (NumberUtils.isParsable(thresholdScoreStr)) { + thresholdScore = Double.parseDouble(thresholdScoreStr); + } + return thresholdScore; + } + + // getSeverity(Double.parseDouble(s_score), criticalSeverityScaleThreshold, highSeverityScaleThreshold, mediumSeverityScaleThreshold); + private String getSeverity(Double score, ScanResult scanResult, String defaultSeverity) { + boolean isCustomThreshold = Boolean.parseBoolean(AdminConfigUtil.getAdminConfig("isCustomThreshold")); + String severity = defaultSeverity; + + if (isCustomThreshold) { + scanResult.setCriticalSeverityThreshold(getCustomThresholdScore("customCriticalThreshold")); + scanResult.setHighSeverityThreshold(getCustomThresholdScore("customHighThreshold")); + scanResult.setMediumSeverityThreshold(getCustomThresholdScore("customMediumThreshold")); + + if (score >= scanResult.getCriticalSeverityThreshold()){ + severity = SeverityRating.Critical.name(); + } else if (score >= scanResult.getHighSeverityThreshold()){ + severity = SeverityRating.High.name(); + } else if(score >= scanResult.getMediumSeverityThreshold()){ + severity = SeverityRating.Medium.name(); + } + } + return severity; + } + private void processScanReport(ProcessResult processResult) throws TaskException { String serverMessageFromScan = processResult.getScanResultString(); ScanResult scanResult = processResult.getScanResult(); int totalVulnerabilityNumber = 0; + int totalCriticalSeverity = 0; int totalHighSeverity = 0; int totalMediumSeverity = 0; @@ -88,6 +126,8 @@ private void processScanReport(ProcessResult processResult) throws TaskException boolean hasWhiteListVuls = false; Set existedBlackListVulSet = new HashSet<>(); Set existedWhiteListVulSet = new HashSet<>(); + + Set criticalVulnerabilitySet = new HashSet<>(); Set highVulnerabilitySet = new HashSet<>(); Set mediumVulnerabilitySet = new HashSet<>(); @@ -109,7 +149,7 @@ private void processScanReport(ProcessResult processResult) throws TaskException for (int i = 0; i < vulnerabilityArray.size(); i++) { JsonObject vulnerabilityObject = vulnerabilityArray.get(i).getAsJsonObject(); String name = vulnerabilityObject.get("name").getAsString().toLowerCase(); - String severity = vulnerabilityObject.get("severity").getAsString(); + String severity = getSeverity(Double.parseDouble(vulnerabilityObject.get("score").getAsString()), scanResult, vulnerabilityObject.get("severity").getAsString()); if (!scanConfig.getVulBlackListSet().isEmpty() && scanConfig.getVulBlackListSet().contains(name)) { hasBlackListVuls = true; existedBlackListVulSet.add(name.toUpperCase()); @@ -130,7 +170,11 @@ private void processScanReport(ProcessResult processResult) throws TaskException vulnerability.setDescription(vulnerabilityObject.get("description").getAsString()); vulnerability.setFeed_rating(vulnerabilityObject.get("feed_rating").getAsString()); - if (severity.equalsIgnoreCase("High")) { + if(severity.equalsIgnoreCase("Critical")) { + totalCriticalSeverity = totalCriticalSeverity + 1; + vulnerability.setSeverity("Critical"); + criticalVulnerabilitySet.add(vulnerability); + } else if (severity.equalsIgnoreCase("High")) { totalHighSeverity = totalHighSeverity + 1; vulnerability.setSeverity("High"); highVulnerabilitySet.add(vulnerability); @@ -154,8 +198,12 @@ private void processScanReport(ProcessResult processResult) throws TaskException scanResult.setExistedBlackListVulSet(existedBlackListVulSet); scanResult.setExistedWhiteListVulSet(existedWhiteListVulSet); scanResult.setTotalVulnerabilityNumber(totalVulnerabilityNumber); + + scanResult.setCriticalSeverityNumber(totalCriticalSeverity); scanResult.setHighSeverityNumber(totalHighSeverity); scanResult.setMediumSeverityNumber(totalMediumSeverity); + + scanResult.setCriticalVulnerabilitySet(criticalVulnerabilitySet); scanResult.setHighVulnerabilitySet(highVulnerabilitySet); scanResult.setMediumVulnerabilitySet(mediumVulnerabilitySet); @@ -202,43 +250,73 @@ private void processScanReport(ProcessResult processResult) throws TaskException } } + // add the critical related thing private void makeIfFailDecision(ProcessResult processResult) { + ScanResult scanResult = processResult.getScanResult(); + + int aboveHighSeverityNumber = scanResult.getAboveHighSeverityNumber(); + int currentCriticalSeverity = scanResult.getCriticalSeverityNumber(); + int currentHighSeverity = scanResult.getHighSeverityNumber(); + int currentMediumSeverity = scanResult.getMediumSeverityNumber(); + + int totalCriticalSeverity = processResult.getScanResult().getCriticalSeverityNumber(); int totalHighSeverity = processResult.getScanResult().getHighSeverityNumber(); int totalMediumSeverity = processResult.getScanResult().getMediumSeverityNumber(); boolean foundNameInBlackList = processResult.getScanResult().isBlackListVulExisted(); Set blackListToPresent = processResult.getScanResult().getExistedBlackListVulSet(); boolean numberExceed = false; + boolean criticalExceed = false; + boolean highExceed = false; + boolean medExceed = false; StringBuilder statementBuilder = new StringBuilder(); - if (scanConfig.getHighVul() != null && !scanConfig.getHighVul().trim().isEmpty()) { - int configNumberOfHigh = Integer.parseInt(scanConfig.getHighVul().trim()); - if (configNumberOfHigh != 0 && configNumberOfHigh <= totalHighSeverity) { - numberExceed = true; - statementBuilder.append(totalHighSeverity).append(" High severity vulnerabilities"); + if (scanConfig.getNumberOfCriticalSeverityToFail() != null) { + if (scanConfig.getNumberOfCriticalSeverityToFail() != 0 && scanConfig.getNumberOfCriticalSeverityToFail() <= currentCriticalSeverity) { + criticalExceed = true; + statementBuilder.append(currentCriticalSeverity).append(" Critical severity vulnerabilities"); + } + } + + if (scanConfig.getNumberOfHighSeverityToFail() != null) { + if (scanConfig.getNumberOfHighSeverityToFail() != 0 && scanConfig.getNumberOfHighSeverityToFail() <= currentCriticalSeverity) { + if (criticalExceed) { + statementBuilder.append(", "); + } + highExceed = true; + statementBuilder.append(currentHighSeverity).append(" High severity vulnerabilities"); } } - if (scanConfig.getMediumVul() != null && !scanConfig.getMediumVul().trim().isEmpty()) { - int configNumberOfMedium = Integer.parseInt(scanConfig.getMediumVul().trim()); - if (configNumberOfMedium != 0 && configNumberOfMedium <= totalMediumSeverity) { - if (numberExceed) { + if (scanConfig.getNumberOfMediumSeverityToFail() != null) { + if (scanConfig.getNumberOfMediumSeverityToFail() != 0 && scanConfig.getNumberOfMediumSeverityToFail() <= currentCriticalSeverity) { + if (criticalExceed || highExceed) { statementBuilder.append(", "); } + medExceed = true; + statementBuilder.append(currentMediumSeverity).append(" Medium severity vulnerabilities"); + } + } + + // Handle the upgrade to include critical severity cases. + if ((!criticalExceed && !highExceed) && scanConfig.getIsUpgradedToIncludeCriticalSeverity()) { + if (aboveHighSeverityNumber != 0 && aboveHighSeverityNumber <= (currentCriticalSeverity + currentHighSeverity)) { numberExceed = true; - statementBuilder.append(totalMediumSeverity).append(" Medium severity vulnerabilities"); + statementBuilder.append(currentCriticalSeverity).append(" Critical severity vulnerabilities, "); + statementBuilder.append(currentHighSeverity).append(" High severity vulnerabilities"); } } + numberExceed = (numberExceed || criticalExceed || highExceed || medExceed); + if (foundNameInBlackList) { if (numberExceed) { statementBuilder.append(", and "); } - numberExceed = true; statementBuilder.append("vulnerabilities: ").append(blackListToPresent.toString()); } - if (numberExceed) { + if (numberExceed || foundNameInBlackList) { statementBuilder.append(" are present."); buildLogger.addErrorLogEntry("Build failed because " + statementBuilder.toString()); processResult.setSuccess(false); @@ -275,6 +353,7 @@ public void writeTxtReport(final TaskContext taskContext, ProcessResult processR } writer.write("Repository: " + scanResult.getRepository() + "\n"); writer.write("Tag: " + scanResult.getTag() + "\n"); + writer.write("Critical severity vulnerabilities: " + scanResult.getCriticalSeverityNumber() + "\n"); writer.write("High severity vulnerabilities: " + scanResult.getHighSeverityNumber() + "\n"); writer.write("Medium severity vulnerabilities: " + scanResult.getMediumSeverityNumber() + "\n"); writer.write("Total vulnerabilities: " + scanResult.getTotalVulnerabilityNumber() + "\n"); @@ -285,6 +364,9 @@ public void writeTxtReport(final TaskContext taskContext, ProcessResult processR writer.write("Scanned. No vulnerabilities found.\n"); } else { // Detailed vulnerabilities + for (Vulnerability vulnerability : scanResult.getCriticalVulnerabilitySet()) { + writeTxtReportVulnerabilityDetails(writer, vulnerability, "Critical"); + } for (Vulnerability vulnerability : scanResult.getHighVulnerabilitySet()) { writeTxtReportVulnerabilityDetails(writer, vulnerability, "High"); } @@ -365,6 +447,8 @@ public void writeHTMLReport(final TaskContext taskContext, ProcessResult process .append("Registry URL\n") .append("Repository\n") .append("Tag\n") + .append("Critical severity VULs\n") + .append("Critical severity threshold\n") .append("High severity VULs\n") .append("High severity threshold\n") .append("Medium severity VULs\n") @@ -376,10 +460,12 @@ public void writeHTMLReport(final TaskContext taskContext, ProcessResult process .append("").append(escapeHtml(scanResult.getRegistry())).append("\n") .append("").append(escapeHtml(scanResult.getRepository())).append("\n") .append("").append(escapeHtml(scanResult.getTag())).append("\n") + .append("").append(Integer.toString(scanResult.getCriticalVulnerabilitySet().size())).append("\n") + .append("").append(scanResult.getCriticalSeverityThreshold() != 0.0 ? Double.toString(scanResult.getCriticalSeverityThreshold()) : "No Limit").append("\n") .append("").append(Integer.toString(scanResult.getHighVulnerabilitySet().size())).append("\n") - .append("").append(scanResult.getHighSeverityThreshold() != 0 ? Integer.toString(scanResult.getHighSeverityThreshold()) : "No Limit").append("\n") + .append("").append(scanResult.getHighSeverityThreshold() != 0.0 ? Double.toString(scanResult.getHighSeverityThreshold()) : "No Limit").append("\n") .append("").append(Integer.toString(scanResult.getMediumVulnerabilitySet().size())).append("\n") - .append("").append(scanResult.getMediumSeverityThreshold() != 0 ? Integer.toString(scanResult.getMediumSeverityThreshold()) : "No Limit").append("\n") + .append("").append(scanResult.getMediumSeverityThreshold() != 0.0 ? Double.toString(scanResult.getMediumSeverityThreshold()) : "No Limit").append("\n") .append("").append(escapeHtml(String.join(", ", scanResult.getExistedBlackListVulSet()))).append("\n") .append("").append(Integer.toString(scanResult.getTotalVulnerabilityNumber())).append("\n") .append("\n") @@ -400,6 +486,11 @@ public void writeHTMLReport(final TaskContext taskContext, ProcessResult process .append("Description\n") .append("Feed_rating\n") .append("\n"); + + // Critical vulnerabilities + for (Vulnerability vulnerability : scanResult.getCriticalVulnerabilitySet()) { + htmlContent.append(getVulnerabilityRowHtml(vulnerability, "Critical")); + } // High vulnerabilities for (Vulnerability vulnerability : scanResult.getHighVulnerabilitySet()) { htmlContent.append(getVulnerabilityRowHtml(vulnerability, "High")); diff --git a/src/main/java/neuvector/NeuVectorTaskConfigurator.java b/src/main/java/neuvector/NeuVectorTaskConfigurator.java index cd3894c..fbc7873 100644 --- a/src/main/java/neuvector/NeuVectorTaskConfigurator.java +++ b/src/main/java/neuvector/NeuVectorTaskConfigurator.java @@ -37,6 +37,7 @@ public Map generateTaskConfigMap(@NotNull final ActionParameters config.put("repository", params.getString("repository")); config.put("tag", params.getString("tag")); config.put("scanLayers", params.getString("scanLayers")); + config.put("criticalVul", params.getString("criticalVul")); config.put("highVul", params.getString("highVul")); config.put("mediumVul", params.getString("mediumVul")); if (registryType != null && registryType.equals("custom")) { @@ -85,6 +86,7 @@ public void populateContextForEdit(@NotNull final Map context, @ context.put("repository", taskDefinition.getConfiguration().get("repository")); context.put("tag", taskDefinition.getConfiguration().get("tag")); context.put("scanLayers", taskDefinition.getConfiguration().get("scanLayers")); + context.put("criticalVul", taskDefinition.getConfiguration().get("criticalVul")); context.put("highVul", taskDefinition.getConfiguration().get("highVul")); context.put("mediumVul", taskDefinition.getConfiguration().get("mediumVul")); if (registryType != null && registryType.equals("custom")) { diff --git a/src/main/java/neuvector/ScanConfig.java b/src/main/java/neuvector/ScanConfig.java index 5c10f81..8649685 100644 --- a/src/main/java/neuvector/ScanConfig.java +++ b/src/main/java/neuvector/ScanConfig.java @@ -16,10 +16,14 @@ public class ScanConfig { private String registryType; private String repository; private String tag; + private boolean scanLayers; private boolean enableStandalone; - private String highVul; - private String mediumVul; + private boolean isUpgradedToIncludeCriticalSeverity; + + // private String criticalVul; + // private String highVul; + // private String mediumVul; private String controllerIP; private String controllerPortString; private int controllerPort; @@ -33,6 +37,14 @@ public class ScanConfig { private String scannerRegistryUsername; private String scannerRegistryPassword; + private Integer numberOfCriticalSeverityToFail = 0; + private Integer numberOfHighSeverityToFail = 0; + private Integer numberOfMediumSeverityToFail = 0; + + private String criticalVulFailureLimit; + private String highVulFailureLimit; + private String mediumVulFailureLimit; + private Set vulBlackListSet; private Set vulWhiteListSet; @@ -40,10 +52,13 @@ public ScanConfig(final TaskContext taskContext, ProcessResult processResult) { enableStandalone = Boolean.valueOf((String)taskContext.getConfigurationMap().get("enableStandalone")); repository = (String)taskContext.getConfigurationMap().get("repository"); scanLayers = Boolean.valueOf((String)taskContext.getConfigurationMap().get("scanLayers")); - highVul = (String)taskContext.getConfigurationMap().get("highVul"); - mediumVul = (String)taskContext.getConfigurationMap().get("mediumVul"); + + taskContext.getBuildLogger().addBuildLogEntry("taskContext.getConfigurationMap(): " + taskContext.getConfigurationMap()); + + criticalVulFailureLimit = (String)taskContext.getConfigurationMap().get("criticalVul"); + highVulFailureLimit = (String)taskContext.getConfigurationMap().get("highVul"); + mediumVulFailureLimit = (String)taskContext.getConfigurationMap().get("mediumVul"); tag = (String)taskContext.getConfigurationMap().get("tag"); - registryType = (String)taskContext.getConfigurationMap().get("registryType"); if (registryType != null && registryType.equals("custom")) { registryURL = (String)taskContext.getConfigurationMap().get("customRegistryURL"); @@ -60,22 +75,60 @@ public ScanConfig(final TaskContext taskContext, ProcessResult processResult) { scanResult.setRepository(repository); scanResult.setTag(tag); - int highSeverityThreshold = 0; - if(!highVul.isEmpty()){ - try { - highSeverityThreshold = Integer.parseInt(highVul); - } finally { - scanResult.setHighSeverityThreshold(highSeverityThreshold); - } - } - - int mediumSeverityThreshold = 0; - if(!mediumVul.isEmpty()){ - try { - mediumSeverityThreshold = Integer.parseInt(mediumVul); - } finally { - scanResult.setMediumSeverityThreshold(mediumSeverityThreshold); - } + // Parsing and setting the medium severity threshold + numberOfMediumSeverityToFail = parseAndSetSeverityThresholdToFail(mediumVulFailureLimit, taskContext, 0); + + // Parsing and setting the high severity threshold + numberOfHighSeverityToFail = parseAndSetSeverityThresholdToFail(highVulFailureLimit, taskContext, 0); + + // int mediumVulFailureLimit = 0; + // // Check if mediumVul is not null + // if (mediumVulFailureLimit != null) { + // // Further check if mediumVul is not empty + // if (!mediumVulFailureLimit.isEmpty()) { + // try { + // mediumVulFailureLimit = Integer.parseInt(mediumVulFailureLimit); + // } catch (NumberFormatException e) { + // taskContext.getBuildLogger().addBuildLogEntry("Invalid number format: " + mediumVul); + // // Handle the error, maybe set a default value or log the error + // } finally { + // numberOfMediumSeverityToFail = mediumVulFailureLimit; + // } + // } else { + // taskContext.getBuildLogger().addBuildLogEntry("mediumVul is empty"); + // // Handle the case where mediumVul is empty, maybe set a default value or log this condition + // } + // } else { + // taskContext.getBuildLogger().addBuildLogEntry("mediumVul is null"); + // // Handle the case where mediumVul is null, maybe set a default value or log this condition + // } + + // int highSeverityThreshold = 0; + // if(!highVul.isEmpty()){ + // try { + // highSeverityThreshold = Integer.parseInt(highVul); + // } finally { + // numberOfHighSeverityToFail = highSeverityThreshold; + // } + // } + + // int criticalSeverityThreshold = 0; + if(criticalVulFailureLimit == null) { + /* + * Support Critical, Medium, and High severity thresholds in new version, add this condition for backward compatibility. + * If critical is not set, we assume that this is a migrate from the version prior to the support of Critical, Medium, and High. + */ + isUpgradedToIncludeCriticalSeverity = true; + scanResult.setAboveHighSeverityNumber(numberOfHighSeverityToFail); + } else { + // if(!criticalVul.isEmpty()){ + // try { + // criticalSeverityThreshold = Integer.parseInt(criticalVul); + // } finally { + // numberOfCriticalSeverityToFail = criticalSeverityThreshold; + // } + // } + numberOfCriticalSeverityToFail = parseAndSetSeverityThresholdToFail(criticalVulFailureLimit, taskContext, 0); } String storedVulnsToFail = (String)taskContext.getConfigurationMap().get("vulnerabilitiesToFail").toLowerCase(); @@ -106,6 +159,26 @@ public ScanConfig(final TaskContext taskContext, ProcessResult processResult) { scannerRegistryPassword = AdminConfigUtil.getAdminConfig("scannerRegistryPassword"); } + /** + * Attempts to parse a string as an integer to set a severity threshold. + * If parsing fails, it logs an error and sets a default value. + * + * @param vulValue the string input representing the severity threshold. + * @param taskContext the task context for logging. + * @param defaultValue the default value to use if parsing fails or the input is empty. + * @return the parsed or default severity threshold. + */ + public static Integer parseAndSetSeverityThresholdToFail(String vulValue, TaskContext taskContext, Integer defaultValue) { + if (vulValue != null && !vulValue.isEmpty()) { + try { + return Integer.parseInt(vulValue); + } catch (NumberFormatException e) { + taskContext.getBuildLogger().addBuildLogEntry("Invalid number format: " + vulValue); + } + } + return defaultValue; // Return default value in case of empty input or parse failure + } + public String getToken() { return token; } @@ -154,21 +227,22 @@ public void setEnableStandalone(boolean enableStandalone) { this.enableStandalone = enableStandalone; } - public String getHighVul() { - return highVul; - } + // how much to fail + // public String getHighVul() { + // return highVul; + // } - public void setHighVul(String highVul) { - this.highVul = highVul; - } + // public void setHighVul(String highVul) { + // this.highVul = highVul; + // } - public String getMediumVul() { - return mediumVul; - } + // public String getMediumVul() { + // return mediumVul; + // } - public void setMediumVul(String mediumVul) { - this.mediumVul = mediumVul; - } + // public void setMediumVul(String mediumVul) { + // this.mediumVul = mediumVul; + // } public String getControllerIP() { return controllerIP; @@ -281,4 +355,36 @@ public Set getVulWhiteListSet() { public void setVulWhiteListSet(Set vulWhiteListSet) { this.vulWhiteListSet = vulWhiteListSet; } + + public boolean getIsUpgradedToIncludeCriticalSeverity() { + return isUpgradedToIncludeCriticalSeverity; + } + + public void setIsUpgradedToIncludeCriticalSeverity(boolean value) { + isUpgradedToIncludeCriticalSeverity = value; + } + + public Integer getNumberOfCriticalSeverityToFail() { + return numberOfCriticalSeverityToFail; + } + + public void setNumberOfCriticalSeverityToFail(Integer numberOfCriticalSeverityToFail) { + this.numberOfCriticalSeverityToFail = numberOfCriticalSeverityToFail; + } + + public Integer getNumberOfHighSeverityToFail() { + return numberOfHighSeverityToFail; + } + + public void setNumberOfHighSeverityToFail(Integer numberOfHighSeverityToFail) { + this.numberOfHighSeverityToFail = numberOfHighSeverityToFail; + } + + public Integer getNumberOfMediumSeverityToFail() { + return numberOfMediumSeverityToFail; + } + + public void setNumberOfMediumSeverityToFail(Integer numberOfMediumSeverityToFail) { + this.numberOfMediumSeverityToFail = numberOfMediumSeverityToFail; + } } diff --git a/src/main/java/neuvector/SeverityRating.java b/src/main/java/neuvector/SeverityRating.java new file mode 100644 index 0000000..80cdceb --- /dev/null +++ b/src/main/java/neuvector/SeverityRating.java @@ -0,0 +1,9 @@ +package neuvector; + +public enum SeverityRating { + None, + Low, + Medium, + High, + Critical +} diff --git a/src/main/java/neuvector/report/ScanResult.java b/src/main/java/neuvector/report/ScanResult.java index 9665ab4..7300c33 100644 --- a/src/main/java/neuvector/report/ScanResult.java +++ b/src/main/java/neuvector/report/ScanResult.java @@ -1,6 +1,5 @@ package neuvector.report; - import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Set; @@ -19,13 +18,18 @@ public class ScanResult { Set existedBlackListVulSet = new HashSet<>(); Set existedWhiteListVulSet = new HashSet<>(); boolean isSeverityScaleCustomized; + double customizedCriticalSeverityScale; double customizedHighSeverityScale; double customizedMediumSeverityScale; - int highSeverityThreshold; - int mediumSeverityThreshold; + Double criticalSeverityThreshold = 0.0; + Double highSeverityThreshold = 0.0; + Double mediumSeverityThreshold = 0.0; + int aboveHighSeverityNumber; + int criticalSeverityNumber; // total found high severity vuls number int highSeverityNumber; // total found high severity vuls number int mediumSeverityNumber; // total found medium severity vuls number int totalVulnerabilityNumber; // total vuls number + Set criticalVulnerabilitySet = new HashSet<>(); Set highVulnerabilitySet = new HashSet<>(); Set mediumVulnerabilitySet = new HashSet<>(); boolean scanLayerConfigured; @@ -50,6 +54,22 @@ public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } + public int getAboveHighSeverityNumber() { + return aboveHighSeverityNumber; + } + + public void setAboveHighSeverityNumber(int aboveHighSeverityNumber) { + this.aboveHighSeverityNumber = aboveHighSeverityNumber; + } + + public int getCriticalSeverityNumber() { + return criticalSeverityNumber; + } + + public void setCriticalSeverityNumber(int criticalSeverityNumber) { + this.criticalSeverityNumber = criticalSeverityNumber; + } + public int getHighSeverityNumber() { return highSeverityNumber; } @@ -154,6 +174,14 @@ public void setSeverityScaleCustomized(boolean severityScaleCustomized) { isSeverityScaleCustomized = severityScaleCustomized; } + public double getCustomizedCriticalSeverityScale() { + return customizedCriticalSeverityScale; + } + + public void setCustomizedCriticalSeverityScale(double customizedCriticalSeverityScale) { + this.customizedCriticalSeverityScale = customizedCriticalSeverityScale; + } + public double getCustomizedHighSeverityScale() { return customizedHighSeverityScale; } @@ -170,19 +198,27 @@ public void setCustomizedMediumSeverityScale(double customizedMediumSeverityScal this.customizedMediumSeverityScale = customizedMediumSeverityScale; } - public int getHighSeverityThreshold() { + public Double getCriticalSeverityThreshold() { + return criticalSeverityThreshold; + } + + public void setCriticalSeverityThreshold(Double criticalSeverityThreshold) { + this.criticalSeverityThreshold = criticalSeverityThreshold; + } + + public Double getHighSeverityThreshold() { return highSeverityThreshold; } - public void setHighSeverityThreshold(int highSeverityThreshold) { + public void setHighSeverityThreshold(Double highSeverityThreshold) { this.highSeverityThreshold = highSeverityThreshold; } - public int getMediumSeverityThreshold() { + public Double getMediumSeverityThreshold() { return mediumSeverityThreshold; } - public void setMediumSeverityThreshold(int mediumSeverityThreshold) { + public void setMediumSeverityThreshold(Double mediumSeverityThreshold) { this.mediumSeverityThreshold = mediumSeverityThreshold; } @@ -194,6 +230,15 @@ public void setTotalVulnerabilityNumber(int totalVulnerabilityNumber) { this.totalVulnerabilityNumber = totalVulnerabilityNumber; } + public Set getCriticalVulnerabilitySet() { + return criticalVulnerabilitySet; + } + + public void setCriticalVulnerabilitySet(Set criticalVulnerabilitySet) { + this.criticalVulnerabilitySet = criticalVulnerabilitySet; + + } + public Set getHighVulnerabilitySet() { return highVulnerabilitySet; } diff --git a/src/main/resources/templates/neuvectorGlobalConfiguration.ftl b/src/main/resources/templates/neuvectorGlobalConfiguration.ftl index e27685d..ab250f0 100644 --- a/src/main/resources/templates/neuvectorGlobalConfiguration.ftl +++ b/src/main/resources/templates/neuvectorGlobalConfiguration.ftl @@ -24,6 +24,12 @@ [@ww.textfield labelKey="NeuVector Scanner Registry User" name="scannerRegistryUsername" description="Enter the NeuVector Scanner Registry username, if applicable." required="false"/] [@ww.password labelKey="NeuVector Scanner Registry Password" name="scannerRegistryPassword" description="Enter the NeuVector Scanner Registry password, if applicable." showPassword="true" required="false"/] [/@ui.bambooSection] + + [@ui.bambooSection titleKey="NeuVector Custom Criteria Configuration"] + [@ww.textfield labelKey="Custom Critical Severity Threshold" name="customCriticalThreshold" description="From the Critical Severity Threshold to 10.0 is the Critical Severity Range. Vulnerabilities that score in the Critical Severity Range has the Critical severity level.." required="false"/] + [@ww.textfield labelKey="Custom High Severity Threshold" name="customHighThreshold" description="From the High Severity Threshold to Critical Severity Threshold is the High Severity Range. Vulnerabilities that score in the High Severity Range has the High severity level." required="false"/] + [@ww.textfield labelKey="Custom Medium Severity Threshold" name="customMediumThreshold" description="From the Medium Severity Threshold to the High Severity Threshold is the Medium Severity Range. Vulnerabilities that score in the Medium Severity Range has the Medium severity level." required="false"/] + [/@ui.bambooSection] [/@ww.form] - + \ No newline at end of file diff --git a/src/main/resources/templates/neuvectorScannerTask.ftl b/src/main/resources/templates/neuvectorScannerTask.ftl index d8da041..14031d4 100644 --- a/src/main/resources/templates/neuvectorScannerTask.ftl +++ b/src/main/resources/templates/neuvectorScannerTask.ftl @@ -8,6 +8,7 @@ [@ww.textfield label="Repository" name="repository" required="true"/] [@ww.textfield label="Tag" name="tag" required="true"/] [@ww.checkbox label="Scan Layers" name="scanLayers" toggle="true" required="false"/] +[@ww.textfield label="Critical vulnerabilities to fail" name="criticalVul" required="false"/] [@ww.textfield label="High vulnerabilities to fail" name="highVul" required="false"/] [@ww.textfield label="Medium vulnerabilities to fail" name="mediumVul" required="false"/>