diff --git a/sechub-api-java/src/main/resources/reduced-openapi3.json b/sechub-api-java/src/main/resources/reduced-openapi3.json index dd10836526..d58f642882 100644 --- a/sechub-api-java/src/main/resources/reduced-openapi3.json +++ b/sechub-api-java/src/main/resources/reduced-openapi3.json @@ -2919,55 +2919,6 @@ } } }, - "ExecutionProfileFetch": { - "title": "ExecutionProfileFetch", - "type": "object", - "properties": { - "configurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "productIdentifier": { - "type": "string", - "description": "executed product" - }, - "name": { - "type": "string", - "description": "name of configuration" - }, - "executorVersion": { - "type": "number", - "description": "executor version" - }, - "uuid": { - "type": "string", - "description": "uuid of configuration" - }, - "enabled": { - "type": "boolean", - "description": "enabled state of this config" - } - } - } - }, - "description": { - "type": "string", - "description": "A short description for the profile" - }, - "projectIds": { - "type": "array", - "description": "Projects can be linked by their ids here", - "items": { - "type": "string" - } - }, - "enabled": { - "type": "boolean", - "description": "Enabled state of profile, default is false" - } - } - }, "FalsePositives": { "title": "FalsePositives", "type": "object", @@ -3081,6 +3032,55 @@ } } }, + "ExecutionProfileFetch": { + "title": "ExecutionProfileFetch", + "type": "object", + "properties": { + "configurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "productIdentifier": { + "type": "string", + "description": "executed product" + }, + "name": { + "type": "string", + "description": "name of configuration" + }, + "executorVersion": { + "type": "number", + "description": "executor version" + }, + "uuid": { + "type": "string", + "description": "uuid of configuration" + }, + "enabled": { + "type": "boolean", + "description": "enabled state of this config" + } + } + } + }, + "description": { + "type": "string", + "description": "A short description for the profile" + }, + "projectIds": { + "type": "array", + "description": "Projects can be linked by their ids here", + "items": { + "type": "string" + } + }, + "enabled": { + "type": "boolean", + "description": "Enabled state of profile, default is false" + } + } + }, "FullScanDataZIP": { "title": "FullScanDataZIP", "type": "object" @@ -3251,19 +3251,6 @@ "webScan": { "type": "object", "properties": { - "maxScanDuration": { - "type": "object", - "properties": { - "duration": { - "type": "number", - "description": "Duration of the scan as integer" - }, - "unit": { - "type": "string", - "description": "Unit of the duration. Possible values are: millisecond(s), second(s), minute(s), hour(s), day(s)" - } - } - }, "headers": { "type": "array", "description": "List of HTTP headers. Can be used for authentication or anything else.", @@ -3292,6 +3279,19 @@ } } }, + "maxScanDuration": { + "type": "object", + "properties": { + "duration": { + "type": "number", + "description": "Duration of the scan as integer" + }, + "unit": { + "type": "string", + "description": "Unit of the duration. Possible values are: millisecond(s), second(s), minute(s), hour(s), day(s)" + } + } + }, "clientCertificate": { "type": "object", "properties": { diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaData.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaData.java index 12a94ef465..0db161188b 100644 --- a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaData.java +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaData.java @@ -11,7 +11,17 @@ public class SecHubReportMetaData { private Map labels = new LinkedHashMap<>(); + private SecHubReportSummary summary = new SecHubReportSummary(); + public Map getLabels() { return labels; } + + public SecHubReportSummary getSummary() { + return summary; + } + + public void setSummary(SecHubReportSummary summary) { + this.summary = summary; + } } diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummary.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummary.java new file mode 100644 index 0000000000..934fcb14f7 --- /dev/null +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummary.java @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.commons.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecHubReportMetaDataSummary { + + private long total = 0; + private long red = 0; + private long yellow = 0; + private long green = 0; + private SecHubReportMetaDataSummaryDetails details = new SecHubReportMetaDataSummaryDetails(); + + public void reportScanHelper(SecHubFinding finding) { + incrementColors(finding); + details.detailsHelper(finding); + } + + protected void incrementColors(SecHubFinding finding) { + Severity severity = finding.getSeverity(); + switch (severity) { + case HIGH, CRITICAL -> incrementRedCount(); + case MEDIUM -> incrementYellowCount(); + case UNCLASSIFIED, INFO, LOW -> incrementGreenCount(); + } + incrementTotalCount(); + } + + protected void incrementRedCount() { + this.red++; + } + + protected void incrementYellowCount() { + this.yellow++; + } + + protected void incrementGreenCount() { + this.green++; + } + + protected void incrementTotalCount() { + this.total++; + } + + public long getTotal() { + return total; + } + + public long getRed() { + return red; + } + + public long getYellow() { + return yellow; + } + + public long getGreen() { + return green; + } + + public SecHubReportMetaDataSummaryDetails getDetails() { + return details; + } +} diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryDetails.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryDetails.java new file mode 100644 index 0000000000..c157268bc9 --- /dev/null +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryDetails.java @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.commons.model; + +import java.io.IOException; +import java.util.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecHubReportMetaDataSummaryDetails { + + private static final Logger LOG = LoggerFactory.getLogger(SecHubReportMetaDataSummaryDetails.class); + + @JsonDeserialize(using = TreeMapDeserializer.class) + Map high = new TreeMap<>(); + + @JsonDeserialize(using = TreeMapDeserializer.class) + Map medium = new TreeMap<>(); + + @JsonDeserialize(using = TreeMapDeserializer.class) + Map low = new TreeMap<>(); + + public void detailsHelper(SecHubFinding finding) { + switch (finding.getSeverity()) { + case HIGH, CRITICAL -> detailsFiller(high, finding); + case MEDIUM -> detailsFiller(medium, finding); + case UNCLASSIFIED, LOW, INFO -> detailsFiller(low, finding); + } + } + + protected void detailsFiller(Map helperMap, SecHubFinding finding) { + Integer cweId = finding.getCweId(); + String name = finding.getName() != null ? finding.getName() : "no_name"; + SeverityDetails severityDetails = helperMap.get(name); + if (severityDetails != null) { + severityDetails.incrementCount(); + } else { + helperMap.put(name, new SeverityDetails(cweId, name)); + } + } + + public List getHigh() { + return new ArrayList<>(high.values()); + } + + public List getMedium() { + return new ArrayList<>(medium.values()); + } + + public List getLow() { + return new ArrayList<>(low.values()); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public class SeverityDetails { + private Integer cweId; + private String name; + private long count; + + SeverityDetails(Integer cweId, String name) { + this.cweId = cweId; + this.name = name; + this.count = 1; + } + + public void incrementCount() { + this.count++; + } + + public Integer getCweId() { + return cweId; + } + + public String getName() { + return name; + } + + public long getCount() { + return count; + } + } + + private static class TreeMapDeserializer extends StdDeserializer> { + + public TreeMapDeserializer() { + this(null); + } + + protected TreeMapDeserializer(Class vc) { + super(vc); + } + + @Override + public TreeMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException, JsonProcessingException { + TreeMap treeMap = new TreeMap<>(); + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + node.fields().forEachRemaining(entry -> { + try { + String key = entry.getKey(); + SeverityDetails value = entry.getValue().traverse(jsonParser.getCodec()).readValueAs(SeverityDetails.class); + treeMap.put(key, value); + } catch (IOException e) { + LOG.debug("JSON deserialization failed \n" + e); + } + }); + return treeMap; + } + } +} diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportSummary.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportSummary.java new file mode 100644 index 0000000000..f9bec1c5e1 --- /dev/null +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/SecHubReportSummary.java @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.commons.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecHubReportSummary { + + SecHubReportMetaDataSummary codeScan = new SecHubReportMetaDataSummary(); + SecHubReportMetaDataSummary infraScan = new SecHubReportMetaDataSummary(); + SecHubReportMetaDataSummary licenseScan = new SecHubReportMetaDataSummary(); + SecHubReportMetaDataSummary secretScan = new SecHubReportMetaDataSummary(); + SecHubReportMetaDataSummary webScan = new SecHubReportMetaDataSummary(); + + public SecHubReportMetaDataSummary getCodeScan() { + return codeScan; + } + + public void setCodeScan(SecHubReportMetaDataSummary codeScan) { + this.codeScan = codeScan; + } + + public SecHubReportMetaDataSummary getInfraScan() { + return infraScan; + } + + public void setInfraScan(SecHubReportMetaDataSummary infraScan) { + this.infraScan = infraScan; + } + + public SecHubReportMetaDataSummary getWebScan() { + return webScan; + } + + public void setWebScan(SecHubReportMetaDataSummary webScan) { + this.webScan = webScan; + } + + public SecHubReportMetaDataSummary getLicenseScan() { + return licenseScan; + } + + public void setLicenseScan(SecHubReportMetaDataSummary licenseScan) { + this.licenseScan = licenseScan; + } + + public SecHubReportMetaDataSummary getSecretScan() { + return secretScan; + } + + public void setSecretScan(SecHubReportMetaDataSummary secretScan) { + this.secretScan = secretScan; + } + +} diff --git a/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryDetailsTest.java b/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryDetailsTest.java new file mode 100644 index 0000000000..81fd40435d --- /dev/null +++ b/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryDetailsTest.java @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.commons.model; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class SecHubReportMetaDataSummaryDetailsTest { + + static final int CRITICAL_FINDING_CWEID = 1; + static final int HIGH_FINDING_CWEID = 2; + static final int MEDIUM_FINDING_CWEID = 3; + static final int LOW_FINDING_CWEID = 4; + static final int INFO_FINDING_CWEID = 5; + static final int UNCLASSIFIED_FINDING_CWEID = 6; + + static final String CRITICAL_FINDING_NAME = "Critical name"; + static final String HIGH_FINDING_NAME = "Cross Site Scripting (Reflected)"; + static final String MEDIUM_FINDING_NAME = "CSP: Wildcard Directive"; + static final String LOW_FINDING_NAME = "Cookie Without Secure Flag"; + static final String INFO_FINDING_NAME = "Info name"; + static final String UNCLASSIFIED_FINDING_NAME = "Unclassified name"; + + SecHubReportMetaDataSummaryDetails secHubReportMetaDataSummaryDetails; + SecHubFinding criticalFinding; + SecHubFinding highFinding; + SecHubFinding mediumFinding; + SecHubFinding lowFinding; + SecHubFinding infoFinding; + SecHubFinding unclassifiedFinding; + + @BeforeEach + void beforeEach() { + secHubReportMetaDataSummaryDetails = new SecHubReportMetaDataSummaryDetails(); + + criticalFinding = new SecHubFinding(); + criticalFinding.setCweId(CRITICAL_FINDING_CWEID); + criticalFinding.setSeverity(Severity.CRITICAL); + criticalFinding.setName(CRITICAL_FINDING_NAME); + + highFinding = new SecHubFinding(); + highFinding.setCweId(HIGH_FINDING_CWEID); + highFinding.setSeverity(Severity.HIGH); + highFinding.setName(HIGH_FINDING_NAME); + + mediumFinding = new SecHubFinding(); + mediumFinding.setCweId(MEDIUM_FINDING_CWEID); + mediumFinding.setSeverity(Severity.MEDIUM); + mediumFinding.setName(MEDIUM_FINDING_NAME); + + lowFinding = new SecHubFinding(); + lowFinding.setCweId(LOW_FINDING_CWEID); + lowFinding.setSeverity(Severity.LOW); + lowFinding.setName(LOW_FINDING_NAME); + + infoFinding = new SecHubFinding(); + infoFinding.setCweId(INFO_FINDING_CWEID); + infoFinding.setSeverity(Severity.INFO); + infoFinding.setName(INFO_FINDING_NAME); + + unclassifiedFinding = new SecHubFinding(); + unclassifiedFinding.setCweId(UNCLASSIFIED_FINDING_CWEID); + unclassifiedFinding.setSeverity(Severity.UNCLASSIFIED); + unclassifiedFinding.setName(UNCLASSIFIED_FINDING_NAME); + } + + @Test + void new_element_for_critical_finding_in_high_map_must_be_created() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(criticalFinding); + + /* test */ + assertNotNull(secHubReportMetaDataSummaryDetails.high.get(CRITICAL_FINDING_NAME)); + } + + @Test + void new_element_for_high_finding_in_high_map_must_be_created() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(highFinding); + + /* test */ + assertNotNull(secHubReportMetaDataSummaryDetails.high.get(HIGH_FINDING_NAME)); + } + + @Test + void new_element_for_medium_finding_in_medium_map_must_be_created() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(mediumFinding); + + /* test */ + assertNotNull(secHubReportMetaDataSummaryDetails.medium.get(MEDIUM_FINDING_NAME)); + } + + @Test + void new_element_for_low_finding_in_low_map_must_be_created() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(lowFinding); + + /* test */ + assertNotNull(secHubReportMetaDataSummaryDetails.low.get(LOW_FINDING_NAME)); + } + + @Test + void new_element_for_info_finding_in_low_map_must_be_created() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(infoFinding); + + /* test */ + assertNotNull(secHubReportMetaDataSummaryDetails.low.get(INFO_FINDING_NAME)); + } + + @Test + void new_element_for_unclassified_finding_in_low_map_must_be_created() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(unclassifiedFinding); + + /* test */ + assertNotNull(secHubReportMetaDataSummaryDetails.low.get(UNCLASSIFIED_FINDING_NAME)); + } + + @Test + void instance_variables_of_new_element_in_high_map_initialized_correctly() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(highFinding); + SecHubReportMetaDataSummaryDetails.SeverityDetails severityDetails = secHubReportMetaDataSummaryDetails.high.get(HIGH_FINDING_NAME); + + /* test */ + assertEquals(HIGH_FINDING_CWEID, severityDetails.getCweId()); + assertEquals(HIGH_FINDING_NAME, severityDetails.getName()); + assertEquals(1, severityDetails.getCount()); + } + + @Test + void instance_variables_of_new_element_in_medium_map_initialized_correctly() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(mediumFinding); + SecHubReportMetaDataSummaryDetails.SeverityDetails severityDetails = secHubReportMetaDataSummaryDetails.medium.get(MEDIUM_FINDING_NAME); + + /* test */ + assertEquals(MEDIUM_FINDING_CWEID, severityDetails.getCweId()); + assertEquals(MEDIUM_FINDING_NAME, severityDetails.getName()); + assertEquals(1, severityDetails.getCount()); + } + + @Test + void instance_variables_of_new_element_in_low_map_initialized_correctly() { + /* execute */ + secHubReportMetaDataSummaryDetails.detailsHelper(lowFinding); + SecHubReportMetaDataSummaryDetails.SeverityDetails severityDetails = secHubReportMetaDataSummaryDetails.low.get(LOW_FINDING_NAME); + + /* test */ + assertEquals(LOW_FINDING_CWEID, severityDetails.getCweId()); + assertEquals(LOW_FINDING_NAME, severityDetails.getName()); + assertEquals(1, severityDetails.getCount()); + } + + @Test + void if_adding_multiple_similar_findings_into_high_map_counter_contains_correct_value() { + /* execute */ + for (int i = 0; i < 8; i++) { + secHubReportMetaDataSummaryDetails.detailsHelper(highFinding); + } + SecHubReportMetaDataSummaryDetails.SeverityDetails severityDetails = secHubReportMetaDataSummaryDetails.high.get(HIGH_FINDING_NAME); + + /* test */ + assertEquals(8, severityDetails.getCount()); + } + + @Test + void if_adding_multiple_similar_findings_into_medium_map_counter_contains_correct_value() { + /* execute */ + for (int i = 0; i < 4; i++) { + secHubReportMetaDataSummaryDetails.detailsHelper(mediumFinding); + } + SecHubReportMetaDataSummaryDetails.SeverityDetails severityDetails = secHubReportMetaDataSummaryDetails.medium.get(MEDIUM_FINDING_NAME); + + /* test */ + assertEquals(4, severityDetails.getCount()); + } + + @Test + void if_adding_multiple_similar_findings_into_low_map_counter_contains_correct_value() { + /* execute */ + for (int i = 0; i < 11; i++) { + secHubReportMetaDataSummaryDetails.detailsHelper(lowFinding); + } + SecHubReportMetaDataSummaryDetails.SeverityDetails severityDetails = secHubReportMetaDataSummaryDetails.low.get(LOW_FINDING_NAME); + + /* test */ + assertEquals(11, severityDetails.getCount()); + } + + @Test + void must_get_correct_list_must_from_high_map() { + /* prepare */ + secHubReportMetaDataSummaryDetails.detailsHelper(highFinding); + + /* execute */ + List list = secHubReportMetaDataSummaryDetails.getHigh(); + + /* test */ + assertTrue(!list.isEmpty()); + assertEquals(1, list.size()); + assertEquals(highFinding.getCweId(), list.get(0).getCweId()); + assertEquals(highFinding.getName(), list.get(0).getName()); + assertEquals(1, list.get(0).getCount()); + } + + @Test + void must_get_correct_list_from_medium_map() { + /* prepare */ + secHubReportMetaDataSummaryDetails.detailsHelper(mediumFinding); + + /* execute */ + List list = secHubReportMetaDataSummaryDetails.getMedium(); + + /* test */ + assertTrue(!list.isEmpty()); + assertEquals(1, list.size()); + assertEquals(mediumFinding.getCweId(), list.get(0).getCweId()); + assertEquals(mediumFinding.getName(), list.get(0).getName()); + assertEquals(1, list.get(0).getCount()); + } + + @Test + void must_get_correct_list_from_low_map() { + /* prepare */ + secHubReportMetaDataSummaryDetails.detailsHelper(lowFinding); + + /* execute */ + List list = secHubReportMetaDataSummaryDetails.getLow(); + + /* test */ + assertTrue(!list.isEmpty()); + assertEquals(1, list.size()); + assertEquals(lowFinding.getCweId(), list.get(0).getCweId()); + assertEquals(lowFinding.getName(), list.get(0).getName()); + assertEquals(1, list.get(0).getCount()); + } +} diff --git a/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryTest.java b/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryTest.java new file mode 100644 index 0000000000..80cdbdddcf --- /dev/null +++ b/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/SecHubReportMetaDataSummaryTest.java @@ -0,0 +1,206 @@ +package com.mercedesbenz.sechub.commons.model; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class SecHubReportMetaDataSummaryTest { + + SecHubReportMetaDataSummary secHubReportMetaDataSummary; + SecHubFinding highFinding, criticalFinding; + SecHubFinding mediumFinding; + SecHubFinding infoFinding, unclassifiedFinding, lowFinding; + + @BeforeEach + void beforeEach() { + secHubReportMetaDataSummary = new SecHubReportMetaDataSummary(); + + criticalFinding = new SecHubFinding(); + criticalFinding.setSeverity(Severity.CRITICAL); + criticalFinding.setName("Critical name"); + + highFinding = new SecHubFinding(); + highFinding.setSeverity(Severity.HIGH); + highFinding.setName("Cross Site Scripting (Reflected)"); + + mediumFinding = new SecHubFinding(); + mediumFinding.setSeverity(Severity.MEDIUM); + mediumFinding.setName("CSP: Wildcard Directive"); + + lowFinding = new SecHubFinding(); + lowFinding.setSeverity(Severity.LOW); + lowFinding.setName("Cookie Without Secure Flag"); + + infoFinding = new SecHubFinding(); + infoFinding.setSeverity(Severity.INFO); + infoFinding.setName("Info name"); + + unclassifiedFinding = new SecHubFinding(); + unclassifiedFinding.setSeverity(Severity.UNCLASSIFIED); + unclassifiedFinding.setName("Unclassified name"); + } + + @Test + void when_add_new_critical_finding_then_only_red_and_total_counters_must_be_increased() { + /* execute */ + secHubReportMetaDataSummary.reportScanHelper(criticalFinding); + + /* test */ + assertEquals(1, secHubReportMetaDataSummary.getTotal()); + assertEquals(1, secHubReportMetaDataSummary.getRed()); + assertEquals(0, secHubReportMetaDataSummary.getYellow()); + assertEquals(0, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_new_high_finding_then_only_red_and_total_counters_must_be_increased() { + /* execute */ + secHubReportMetaDataSummary.reportScanHelper(highFinding); + + /* test */ + assertEquals(1, secHubReportMetaDataSummary.getTotal()); + assertEquals(1, secHubReportMetaDataSummary.getRed()); + assertEquals(0, secHubReportMetaDataSummary.getYellow()); + assertEquals(0, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_new_medium_finding_then_only_yellow_and_total_counters_must_be_increased() { + /* execute */ + secHubReportMetaDataSummary.reportScanHelper(mediumFinding); + + /* test */ + assertEquals(1, secHubReportMetaDataSummary.getTotal()); + assertEquals(0, secHubReportMetaDataSummary.getRed()); + assertEquals(1, secHubReportMetaDataSummary.getYellow()); + assertEquals(0, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_new_low_finding_then_only_green_and_total_counters_must_be_increased() { + /* execute */ + secHubReportMetaDataSummary.reportScanHelper(lowFinding); + + /* test */ + assertEquals(1, secHubReportMetaDataSummary.getTotal()); + assertEquals(0, secHubReportMetaDataSummary.getRed()); + assertEquals(0, secHubReportMetaDataSummary.getYellow()); + assertEquals(1, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_new_info_finding_then_only_green_and_total_counters_must_be_increased() { + /* execute */ + secHubReportMetaDataSummary.reportScanHelper(infoFinding); + + /* test */ + assertEquals(1, secHubReportMetaDataSummary.getTotal()); + assertEquals(0, secHubReportMetaDataSummary.getRed()); + assertEquals(0, secHubReportMetaDataSummary.getYellow()); + assertEquals(1, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_new_unclassified_finding_then_only_green_and_total_counters_must_be_increased() { + /* execute */ + secHubReportMetaDataSummary.reportScanHelper(unclassifiedFinding); + + /* test */ + assertEquals(1, secHubReportMetaDataSummary.getTotal()); + assertEquals(0, secHubReportMetaDataSummary.getRed()); + assertEquals(0, secHubReportMetaDataSummary.getYellow()); + assertEquals(1, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_multiple_critical_findings_then_red_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 9; i++) { + secHubReportMetaDataSummary.reportScanHelper(criticalFinding); + } + + /* test */ + assertEquals(9, secHubReportMetaDataSummary.getTotal()); + assertEquals(9, secHubReportMetaDataSummary.getRed()); + } + + @Test + void when_add_multiple_high_findings_then_red_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 11; i++) { + secHubReportMetaDataSummary.reportScanHelper(highFinding); + } + + /* test */ + assertEquals(11, secHubReportMetaDataSummary.getTotal()); + assertEquals(11, secHubReportMetaDataSummary.getRed()); + } + + @Test + void when_add_multiple_medium_findings_then_yellow_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 6; i++) { + secHubReportMetaDataSummary.reportScanHelper(mediumFinding); + } + + /* test */ + assertEquals(6, secHubReportMetaDataSummary.getTotal()); + assertEquals(6, secHubReportMetaDataSummary.getYellow()); + } + + @Test + void when_add_multiple_low_findings_then_green_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 4; i++) { + secHubReportMetaDataSummary.reportScanHelper(lowFinding); + } + + /* test */ + assertEquals(4, secHubReportMetaDataSummary.getTotal()); + assertEquals(4, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_multiple_info_findings_then_green_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 3; i++) { + secHubReportMetaDataSummary.reportScanHelper(infoFinding); + } + + /* test */ + assertEquals(3, secHubReportMetaDataSummary.getTotal()); + assertEquals(3, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_multiple_unclassified_findings_then_green_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 5; i++) { + secHubReportMetaDataSummary.reportScanHelper(unclassifiedFinding); + } + + /* test */ + assertEquals(5, secHubReportMetaDataSummary.getTotal()); + assertEquals(5, secHubReportMetaDataSummary.getGreen()); + } + + @Test + void when_add_multiple_critical_high_medium_low_info_unclassified_findings_then_red_yellow_green_and_total_counters_must_be_increased() { + /* execute */ + for (int i = 0; i < 4; i++) { + secHubReportMetaDataSummary.reportScanHelper(criticalFinding); + secHubReportMetaDataSummary.reportScanHelper(highFinding); + secHubReportMetaDataSummary.reportScanHelper(mediumFinding); + secHubReportMetaDataSummary.reportScanHelper(lowFinding); + secHubReportMetaDataSummary.reportScanHelper(infoFinding); + secHubReportMetaDataSummary.reportScanHelper(unclassifiedFinding); + } + + /* test */ + assertEquals(24, secHubReportMetaDataSummary.getTotal()); + assertEquals(8, secHubReportMetaDataSummary.getRed()); + assertEquals(4, secHubReportMetaDataSummary.getYellow()); + assertEquals(12, secHubReportMetaDataSummary.getGreen()); + } +} diff --git a/sechub-developertools/src/main/java/com/mercedesbenz/sechub/developertools/generator/HTMLReportCSSFragementGenerator.java b/sechub-developertools/src/main/java/com/mercedesbenz/sechub/developertools/generator/HTMLReportCSSFragementGenerator.java index 6b18a0c50b..8a05abfa76 100644 --- a/sechub-developertools/src/main/java/com/mercedesbenz/sechub/developertools/generator/HTMLReportCSSFragementGenerator.java +++ b/sechub-developertools/src/main/java/com/mercedesbenz/sechub/developertools/generator/HTMLReportCSSFragementGenerator.java @@ -44,11 +44,18 @@ public void generate() throws IOException { File scanHTMLFolder = new File("./../sechub-scan/src/main/resources/templates/report/html"); File cssFile = new File(scanHTMLFolder, "scanresult.css"); - File fragmentsFile = new File(scanHTMLFolder, "fragments.html"); - CSSFileToFragementMerger merger = new CSSFileToFragementMerger(); - merger.merge(cssFile, fragmentsFile); + File fragmentsFile = new File(scanHTMLFolder, "fragment-cwe-summary-table.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-generic-scan-table.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-generic-scan-table-row.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-summary-table-row.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-web-scan-table.html"); + merger.merge(cssFile, fragmentsFile); } } diff --git a/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/ScanReportRestControllerRestDocTest.java b/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/ScanReportRestControllerRestDocTest.java index fa26528402..ca44eb0139 100644 --- a/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/ScanReportRestControllerRestDocTest.java +++ b/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/ScanReportRestControllerRestDocTest.java @@ -14,11 +14,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import org.junit.Before; import org.junit.Test; @@ -38,6 +34,7 @@ import com.mercedesbenz.sechub.commons.model.TrafficLight; import com.mercedesbenz.sechub.docgen.util.RestDocFactory; import com.mercedesbenz.sechub.domain.scan.HTMLScanResultReportModelBuilder; +import com.mercedesbenz.sechub.domain.scan.ScanTypeCount; import com.mercedesbenz.sechub.domain.scan.report.DownloadScanReportService; import com.mercedesbenz.sechub.domain.scan.report.DownloadSpdxScanReportService; import com.mercedesbenz.sechub.domain.scan.report.ScanReport; @@ -241,7 +238,8 @@ public void before() throws Exception { map.put("yellowList", new ArrayList<>()); map.put("greenList", new ArrayList<>()); map.put("isWebDesignMode", false); - map.put("metaData", Optional.ofNullable(null)); + map.put("metaData", null); + map.put("scanTypeCountSet", new TreeSet()); when(modelBuilder.build(any())).thenReturn(map); } diff --git a/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertHTMLReport.java b/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertHTMLReport.java index 1e48d6e989..fdd9154aea 100644 --- a/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertHTMLReport.java +++ b/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertHTMLReport.java @@ -52,4 +52,10 @@ public AssertHTMLReport hasMetaDataLabel(String key, String value) { return this; } + public AssertHTMLReport hasHTMLString(String value) { + if (!html.contains(value)) { + failWithDump("The report does not contain expected HTML string ':" + value + "'"); + } + return this; + } } diff --git a/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertReport.java b/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertReport.java index dc3e6c43f7..88f41d773d 100644 --- a/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertReport.java +++ b/sechub-integrationtest/src/main/java/com/mercedesbenz/sechub/integrationtest/api/AssertReport.java @@ -12,19 +12,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.mercedesbenz.sechub.commons.model.ScanType; -import com.mercedesbenz.sechub.commons.model.SecHubCodeCallStack; -import com.mercedesbenz.sechub.commons.model.SecHubFinding; -import com.mercedesbenz.sechub.commons.model.SecHubMessage; -import com.mercedesbenz.sechub.commons.model.SecHubMessageType; -import com.mercedesbenz.sechub.commons.model.SecHubReportData; -import com.mercedesbenz.sechub.commons.model.SecHubReportMetaData; -import com.mercedesbenz.sechub.commons.model.SecHubReportModel; -import com.mercedesbenz.sechub.commons.model.SecHubReportVersion; -import com.mercedesbenz.sechub.commons.model.SecHubResult; -import com.mercedesbenz.sechub.commons.model.SecHubStatus; -import com.mercedesbenz.sechub.commons.model.Severity; -import com.mercedesbenz.sechub.commons.model.TrafficLight; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.integrationtest.internal.SecHubJobAutoDumper; public class AssertReport { @@ -328,6 +316,48 @@ public AssertReport hasMetaDataLabel(String key, String value) { return this; } + public SecHubReportMetaDataSummary getMetaDataSummaryCodeScan() { + Optional metaDataOpt = report.getMetaData(); + if (metaDataOpt.isEmpty()) { + fail("Meta data not found inside report!"); + } + SecHubReportMetaData metaData = metaDataOpt.get(); + + return metaData.getSummary().getCodeScan(); + } + + public AssertReport hasMetaDataSummaryCodeScanTotal(long value) { + SecHubReportMetaDataSummary metaDataSummary = getMetaDataSummaryCodeScan(); + + assertEquals(value, metaDataSummary.getTotal()); + + return this; + } + + public AssertReport hasMetaDataSummaryCodeScanRed(long value) { + SecHubReportMetaDataSummary metaDataSummary = getMetaDataSummaryCodeScan(); + + assertEquals(value, metaDataSummary.getRed()); + + return this; + } + + public AssertReport hasMetaDataSummaryCodeScanYellow(long value) { + SecHubReportMetaDataSummary metaDataSummary = getMetaDataSummaryCodeScan(); + + assertEquals(value, metaDataSummary.getYellow()); + + return this; + } + + public AssertReport hasMetaDataSummaryCodeScanGreen(long value) { + SecHubReportMetaDataSummary metaDataSummary = getMetaDataSummaryCodeScan(); + + assertEquals(value, metaDataSummary.getGreen()); + + return this; + } + public AssertReport dump() { LOG.info("-----------------------------------------------------------"); LOG.info("----------------------------DUMP---------------------------"); diff --git a/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario10/PDSCodeScanSarifJobScenario10IntTest.java b/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario10/PDSCodeScanSarifJobScenario10IntTest.java index 2b10314e7c..3fde71e462 100644 --- a/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario10/PDSCodeScanSarifJobScenario10IntTest.java +++ b/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario10/PDSCodeScanSarifJobScenario10IntTest.java @@ -73,11 +73,10 @@ public void a_user_can_start_a_pds_sarif_scan_and_get_the_sarif_results_transfor hasStatus(SecHubStatus.SUCCESS). hasMessages(0). hasJobUUID(jobUUID). - hasMetaDataLabel("quality-level", "high"). - hasMetaDataLabel("test-label1", "Something special"). - hasMetaDataLabel("test-label2", ""). - hasMetaDataLabel("test-label3_with_html", "HTML is allowed, but must always be escaped in reports!"). - hasMetaDataLabel("test-label4_with_special_chars", "Line1\nLine2\tLine3"). + hasMetaDataSummaryCodeScanTotal(32). + hasMetaDataSummaryCodeScanRed(28). + hasMetaDataSummaryCodeScanYellow(2). + hasMetaDataSummaryCodeScanGreen(2). hasTrafficLight(RED). finding(0). hasSeverity(Severity.HIGH). @@ -100,11 +99,17 @@ public void a_user_can_start_a_pds_sarif_scan_and_get_the_sarif_results_transfor assertHTMLReport(htmlReport). containsAtLeastOneOpenDetailsBlock(). - hasMetaDataLabel("quality-level", "high"). - hasMetaDataLabel("test-label1", "Something special"). - hasMetaDataLabel("test-label2", ""). - hasMetaDataLabel("test-label3_with_html", "<html>HTML is allowed, but must always be escaped in reports!</html>"). - hasMetaDataLabel("test-label4_with_special_chars", "Line1\nLine2\tLine3"); + hasHTMLString("28"). + hasHTMLString("2"). + hasHTMLString("2"). + hasHTMLString(" \n" + + " CWE-null\n" + + " BRAKE0000\n" + + " 2\n" + + " "). + hasHTMLString("Red findings (Count: 28)"). + hasHTMLString("Yellow findings (Count: 2)"). + hasHTMLString("Green findings (Count: 2)"); // try to restart SecHub (will reuse existing PDS job because already done ) assertSecHubRestartWillNotStartNewJobButReusesExistingBecausePDSJobWasAlreadyDone(project,jobUUID); diff --git a/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilder.java b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilder.java index 9fb59dfdc2..b7ea1acf38 100644 --- a/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilder.java +++ b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilder.java @@ -1,23 +1,20 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.domain.scan; +import static java.util.stream.Collectors.groupingBy; + import java.io.File; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; -import com.mercedesbenz.sechub.commons.model.SecHubFinding; -import com.mercedesbenz.sechub.commons.model.SecHubResult; -import com.mercedesbenz.sechub.commons.model.SecHubResultTrafficLightFilter; -import com.mercedesbenz.sechub.commons.model.TrafficLight; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.domain.scan.report.ScanSecHubReport; import com.mercedesbenz.sechub.sharedkernel.MustBeDocumented; @@ -111,6 +108,82 @@ public Map build(ScanSecHubReport report) { } else { model.put("jobuuid", "none"); } + + model.put("scanTypeCountSet", prepareScanTypesForModel(result.getFindings())); + + model.put("redHTMLSecHubFindingList", filterFindingsForGeneralScan(result.getFindings(), codeScanEntries, List.of(Severity.HIGH))); + model.put("yellowHTMLSecHubFindingList", filterFindingsForGeneralScan(result.getFindings(), codeScanEntries, List.of(Severity.MEDIUM))); + model.put("greenHTMLSecHubFindingList", filterFindingsForGeneralScan(result.getFindings(), codeScanEntries, List.of(Severity.INFO, Severity.LOW))); + + model.put("redHTMLWebScanMap", filterFindingsForWebScan(result.getFindings(), List.of(Severity.HIGH))); + model.put("yellowHTMLWebScanMap", filterFindingsForWebScan(result.getFindings(), List.of(Severity.MEDIUM))); + model.put("greenHTMLWebScanMap", filterFindingsForWebScan(result.getFindings(), List.of(Severity.INFO, Severity.LOW))); + return model; } + + protected Set prepareScanTypesForModel(List findings) { + Map scanSummaryMap = new HashMap<>(); + for (SecHubFinding finding : findings) { + ScanType scanType = finding.getType(); + ScanTypeCount scanTypeCount; + if (scanSummaryMap.containsKey(scanType)) { + scanTypeCount = scanSummaryMap.get(scanType); + } else { + scanTypeCount = ScanTypeCount.of(scanType); + scanSummaryMap.put(scanType, scanTypeCount); + } + incrementScanCount(finding.getSeverity(), scanTypeCount); + } + Set scanTypeCountSet = new TreeSet<>(); + scanTypeCountSet.addAll(scanSummaryMap.values()); + return scanTypeCountSet; + } + + protected void incrementScanCount(Severity severity, ScanTypeCount scanTypeCount) { + switch (severity) { + case HIGH, CRITICAL -> scanTypeCount.incrementHighSeverityCount(); + case MEDIUM -> scanTypeCount.incrementMediumSeverityCount(); + case UNCLASSIFIED, INFO, LOW -> scanTypeCount.incrementLowSeverityCount(); + } + } + + public Map> filterFindingsForWebScan(List findings, List severities) { + Map> groupedFindingsByName = findings.stream().filter(finding -> severities.contains(finding.getSeverity())) + .filter(finding -> finding.hasScanType(ScanType.WEB_SCAN.getId())).collect(groupingBy(SecHubFinding::getName)); + Map> groupedAndSortedFindingsByName = new TreeMap<>(); + groupedAndSortedFindingsByName.putAll(groupedFindingsByName); + return groupedAndSortedFindingsByName; + } + + public List filterFindingsForGeneralScan(List findings, Map> codeScanEntries, + List severitiesToShow) { + List htmlSecHubFindings = new LinkedList<>(); + Map> groupedFindingsByName = findings.stream().filter(finding -> severitiesToShow.contains(finding.getSeverity())) + .collect(groupingBy(SecHubFinding::getName)); + + Map> groupedAndSortedFindingsByName = new TreeMap<>(); + groupedAndSortedFindingsByName.putAll(groupedFindingsByName); + + groupedAndSortedFindingsByName.entrySet().stream().forEach(entry -> { + List findingList = entry.getValue(); + if (!findingList.isEmpty()) { + SecHubFinding firstFinding = findingList.get(0); + HTMLSecHubFinding htmlSecHubFinding = new HTMLSecHubFinding(); + BeanUtils.copyProperties(firstFinding, htmlSecHubFinding); + htmlSecHubFinding.setId(0); + List entryList = htmlSecHubFinding.getEntryList(); + for (SecHubFinding finding : findingList) { + if (!finding.hasScanType(ScanType.WEB_SCAN.getId())) { + List codeScanEntryList = codeScanEntries.get(finding.getId()); + for (HTMLScanResultCodeScanEntry htmlScanResultCodeScanEntry : codeScanEntryList) { + entryList.add(htmlScanResultCodeScanEntry); + } + } + } + htmlSecHubFindings.add(htmlSecHubFinding); + } + }); + return htmlSecHubFindings; + } } diff --git a/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLSecHubFinding.java b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLSecHubFinding.java new file mode 100644 index 0000000000..b4e1d6cf99 --- /dev/null +++ b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/HTMLSecHubFinding.java @@ -0,0 +1,15 @@ +package com.mercedesbenz.sechub.domain.scan; + +import java.util.ArrayList; +import java.util.List; + +import com.mercedesbenz.sechub.commons.model.SecHubFinding; + +public class HTMLSecHubFinding extends SecHubFinding { + + private List entryList = new ArrayList<>(); + + public List getEntryList() { + return entryList; + } +} diff --git a/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/ScanTypeCount.java b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/ScanTypeCount.java new file mode 100644 index 0000000000..423a44ab5b --- /dev/null +++ b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/ScanTypeCount.java @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.domain.scan; + +import com.mercedesbenz.sechub.commons.model.ScanType; + +public class ScanTypeCount implements Comparable { + + private ScanType scanType; + protected long highSeverityCount; + protected long mediumSeverityCount; + protected long lowSeverityCount; + + private ScanTypeCount(ScanType scanType) { + this.scanType = scanType; + highSeverityCount = 0; + mediumSeverityCount = 0; + lowSeverityCount = 0; + } + + public static ScanTypeCount of(ScanType scanType) { + if (scanType == null) { + throw new IllegalArgumentException("ScanType argument must exist"); + } + return new ScanTypeCount(scanType); + } + + public ScanType getScanType() { + return scanType; + } + + public long getHighSeverityCount() { + return highSeverityCount; + } + + public long getMediumSeverityCount() { + return mediumSeverityCount; + } + + public long getLowSeverityCount() { + return lowSeverityCount; + } + + public void incrementHighSeverityCount() { + this.highSeverityCount++; + } + + public void incrementMediumSeverityCount() { + this.mediumSeverityCount++; + } + + public void incrementLowSeverityCount() { + this.lowSeverityCount++; + } + + @Override + public int compareTo(ScanTypeCount o) { + if (o == null) { + return 1; + } + String descriptionA = this.scanType.getDescription(); + String descriptionB = o.scanType.getDescription(); + return descriptionA.compareTo(descriptionB); + } +} diff --git a/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReport.java b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReport.java index 8f8f5e6d0f..27198712b4 100644 --- a/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReport.java +++ b/sechub-scan/src/main/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReport.java @@ -12,16 +12,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.mercedesbenz.sechub.commons.core.MustBeKeptStable; -import com.mercedesbenz.sechub.commons.model.JSONConverterException; -import com.mercedesbenz.sechub.commons.model.JSONable; -import com.mercedesbenz.sechub.commons.model.SecHubMessage; -import com.mercedesbenz.sechub.commons.model.SecHubMessageType; -import com.mercedesbenz.sechub.commons.model.SecHubReportData; -import com.mercedesbenz.sechub.commons.model.SecHubReportMetaData; -import com.mercedesbenz.sechub.commons.model.SecHubReportModel; -import com.mercedesbenz.sechub.commons.model.SecHubResult; -import com.mercedesbenz.sechub.commons.model.SecHubStatus; -import com.mercedesbenz.sechub.commons.model.TrafficLight; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.sharedkernel.UUIDTraceLogID; @JsonIgnoreProperties(ignoreUnknown = true) @@ -67,7 +58,6 @@ public ScanSecHubReport(ScanReport report) { LOG.warn("Job uuid not found inside report result JSON, will set Job UUID from entity data"); model.setJobUUID(report.getSecHubJobUUID()); } - } catch (JSONConverterException e) { LOG.error("FATAL PROBLEM! Failed to create sechub result by model for job:{}", report.getSecHubJobUUID(), e); @@ -100,14 +90,42 @@ public ScanSecHubReport(ScanReport report) { throw new IllegalStateException("Unsupported report result type:" + resultType); } + SecHubReportMetaData reportMetaData = new SecHubReportMetaData(); + setMetaData(reportMetaData); + + SecHubReportSummary secHubReportSummary = new SecHubReportSummary(); + reportMetaData.setSummary(secHubReportSummary); + /* calculate data */ buildCalculatedData(report); } private void buildCalculatedData(ScanReport report) { - model.setTrafficLight(TrafficLight.fromString(report.getTrafficLightAsString())); model.getResult().setCount(model.getResult().getFindings().size()); + calculateSummary(); + } + + protected void calculateSummary() { + var summary = model.getMetaData().get().getSummary(); + SecHubReportMetaDataSummary codeScan = summary.getCodeScan(); + SecHubReportMetaDataSummary infraScan = summary.getInfraScan(); + SecHubReportMetaDataSummary licenseScan = summary.getLicenseScan(); + SecHubReportMetaDataSummary secretScan = summary.getSecretScan(); + SecHubReportMetaDataSummary webScan = summary.getWebScan(); + + for (SecHubFinding finding : model.getResult().getFindings()) { + ScanType scanType = finding.getType(); + if (scanType != null) { + switch (scanType) { + case CODE_SCAN -> codeScan.reportScanHelper(finding); + case INFRA_SCAN -> infraScan.reportScanHelper(finding); + case WEB_SCAN -> webScan.reportScanHelper(finding); + case LICENSE_SCAN -> licenseScan.reportScanHelper(finding); + case SECRET_SCAN -> secretScan.reportScanHelper(finding); + } + } + } } @Override diff --git a/sechub-scan/src/main/resources/templates/report/html/details_footer.html b/sechub-scan/src/main/resources/templates/report/html/details_footer.html index cd7caab935..69daa8e677 100644 --- a/sechub-scan/src/main/resources/templates/report/html/details_footer.html +++ b/sechub-scan/src/main/resources/templates/report/html/details_footer.html @@ -1,18 +1,18 @@ - -

Description

-
Description1
-
-
A full description of "
-
Finding name
-
" can be found at 
-
-
.
-
- -

Solution

-
Solution
-
-

There is no dedicated solution. Please have a look at the proposed solutions and examples at - and adapt them to your situation.

-
+ +

Description

+
Description1
+
+
A full description of "
+
Finding name
+
" can be found at 
+
+
.
+
+ +

Solution

+
Solution
+
+

There is no dedicated solution. Please have a look at the proposed solutions and examples at + and adapt them to your situation.

+
\ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/fragment-cwe-summary-table.html b/sechub-scan/src/main/resources/templates/report/html/fragment-cwe-summary-table.html new file mode 100644 index 0000000000..091b8a13ce --- /dev/null +++ b/sechub-scan/src/main/resources/templates/report/html/fragment-cwe-summary-table.html @@ -0,0 +1,498 @@ + + + + + + +

+ + + + + + + + + + + + +
CWENameCount
+ + +
+ \ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/fragment-generic-scan-table-row.html b/sechub-scan/src/main/resources/templates/report/html/fragment-generic-scan-table-row.html new file mode 100644 index 0000000000..ab213461b9 --- /dev/null +++ b/sechub-scan/src/main/resources/templates/report/html/fragment-generic-scan-table-row.html @@ -0,0 +1,509 @@ + + + + + + + HIGH + +
Command Injection
+
+ + +
Description1
+
+
+
Location
+
Line
+
Column
+
Source
+
+
+
the location
+
101
+
54
+
result= evalCode.execute()
+
+
+ +
+ +
+
+ + +
\ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/fragment-generic-scan-table.html b/sechub-scan/src/main/resources/templates/report/html/fragment-generic-scan-table.html new file mode 100644 index 0000000000..8ecc248a9e --- /dev/null +++ b/sechub-scan/src/main/resources/templates/report/html/fragment-generic-scan-table.html @@ -0,0 +1,497 @@ + + + + + + +

scan_type

+ + + + + + + + + + +
+ + +
SeverityTypeDescription
+ +
\ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/fragment-summary-table-row.html b/sechub-scan/src/main/resources/templates/report/html/fragment-summary-table-row.html new file mode 100644 index 0000000000..899717dce3 --- /dev/null +++ b/sechub-scan/src/main/resources/templates/report/html/fragment-summary-table-row.html @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/fragments.html b/sechub-scan/src/main/resources/templates/report/html/fragment-web-scan-table.html similarity index 52% rename from sechub-scan/src/main/resources/templates/report/html/fragments.html rename to sechub-scan/src/main/resources/templates/report/html/fragment-web-scan-table.html index ef19b93c55..77f9472c66 100644 --- a/sechub-scan/src/main/resources/templates/report/html/fragments.html +++ b/sechub-scan/src/main/resources/templates/report/html/fragment-web-scan-table.html @@ -395,114 +395,156 @@ display:flex; } +.summaryHeadline { + font-family: monospace; +} + +.summaryTable { + width: 20%; + padding-bottom: 16px; + padding-top: 10px; + border-collapse: separate; + border: solid #cccccc 1px; + border-radius: 16px; + border-spacing: 0px; +} + +.summaryTable th { + padding: 8px; + vertical-align: center; + text-align: center; +} + +.summaryTable td { + padding: 8px; + font-family: monospace; + vertical-align: center; + text-align: center; +} + +.summaryTable td:nth-child(2) { + border-left: 1px solid #cccccc; +} + +.summaryTable td:nth-child(3) { + border-left: 1px solid #cccccc; +} + +.summaryScanType { + font-family: monospace; + font-size: 1.5em; + font-weight: bold; +} + +.summarySeverity { + font-family: monospace; +} + +.summaryScanTypeTable { + width: 40%; + padding-bottom: 16px; + padding-top: 10px; + border-collapse: separate; + border: solid #cccccc 1px; + border-radius: 16px; + border-spacing: 0px; +} + +.summaryScanTypeTable th { + padding: 8px; + vertical-align: center; + text-align: left; +} + +.summaryScanTypeTable td { + padding: 8px; + font-family: monospace; + vertical-align: center; + text-align: left; +} + +.summaryScanTypeTable td:nth-child(2) { + border-left: 1px solid #cccccc; +} + +.summaryScanTypeTable td:nth-child(3) { + border-left: 1px solid #cccccc; +} + +.scanTypeHeadline { + /*color: #cc0000;*/ + font-family: monospace; +} - - -4711 -HIGH - -
Command Injection
-
- - -
Description1
-
-
-
Call
-
Location
-
Line
-
Column
-
Relevant part
-
Source
-
-
-
1
-
the location
-
101
-
54
-
execute
-
result= evalCode.execute()
-
-
-
+ + HIGH + +
Command Injection
+
+ +
-
Location
-
Attack vector
-
Evidence
+
Location
+
Attack vector
+
Evidence
-
-
1
-
the location
-
101
+
+
location
+
attack_vector
+
evidence
-
-
- -
-
-
Call
-
Location
-
Line
-
Column
-
Relevant part
-
Source
-
-
-
1
-
the location
-
101
-
54
-
execute
-
result= evalCode.execute()
-
-
-
-
-
- - - -

Request

-
-
-
-
-
/
-
-

Attack vector

- - -
- -

Body

-
No body content
- - - - -

Response

-
-
/
-
 
-
-

Evidence

- -
-
Found in response body. Start line:
-
- -
-

Body

-
No body content
- - - -
- -
- +
+ + + +

Request

+
+
+ +
+
+
+
/
+
+
+

Attack vector

+ + +
+ +

Body

+
No body content
+ + + + +

Response

+
+
+
/
+
+
 
+
+
+

Evidence

+ +
+
Found in response body. Start line:
+
+
+ +
+

Body

+
No body content
+ + + +
+
+
\ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/links.html b/sechub-scan/src/main/resources/templates/report/html/links.html index b0f36415cb..a0a857309a 100644 --- a/sechub-scan/src/main/resources/templates/report/html/links.html +++ b/sechub-scan/src/main/resources/templates/report/html/links.html @@ -1,3 +1,7 @@ - +
CWE-77 + + + CWE-77 + \ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/scanresult.css b/sechub-scan/src/main/resources/templates/report/html/scanresult.css index d4a463c8df..441763548d 100644 --- a/sechub-scan/src/main/resources/templates/report/html/scanresult.css +++ b/sechub-scan/src/main/resources/templates/report/html/scanresult.css @@ -385,3 +385,83 @@ rTableSourceHead, display:flex; } +.summaryHeadline { + font-family: monospace; +} + +.summaryTable { + width: 20%; + padding-bottom: 16px; + padding-top: 10px; + border-collapse: separate; + border: solid #cccccc 1px; + border-radius: 16px; + border-spacing: 0px; +} + +.summaryTable th { + padding: 8px; + vertical-align: center; + text-align: center; +} + +.summaryTable td { + padding: 8px; + font-family: monospace; + vertical-align: center; + text-align: center; +} + +.summaryTable td:nth-child(2) { + border-left: 1px solid #cccccc; +} + +.summaryTable td:nth-child(3) { + border-left: 1px solid #cccccc; +} + +.summaryScanType { + font-family: monospace; + font-size: 1.5em; + font-weight: bold; +} + +.summarySeverity { + font-family: monospace; +} + +.summaryScanTypeTable { + width: 40%; + padding-bottom: 16px; + padding-top: 10px; + border-collapse: separate; + border: solid #cccccc 1px; + border-radius: 16px; + border-spacing: 0px; +} + +.summaryScanTypeTable th { + padding: 8px; + vertical-align: center; + text-align: left; +} + +.summaryScanTypeTable td { + padding: 8px; + font-family: monospace; + vertical-align: center; + text-align: left; +} + +.summaryScanTypeTable td:nth-child(2) { + border-left: 1px solid #cccccc; +} + +.summaryScanTypeTable td:nth-child(3) { + border-left: 1px solid #cccccc; +} + +.scanTypeHeadline { + /*color: #cc0000;*/ + font-family: monospace; +} \ No newline at end of file diff --git a/sechub-scan/src/main/resources/templates/report/html/scanresult.html b/sechub-scan/src/main/resources/templates/report/html/scanresult.html index b234130e02..a058ee5a8e 100644 --- a/sechub-scan/src/main/resources/templates/report/html/scanresult.html +++ b/sechub-scan/src/main/resources/templates/report/html/scanresult.html @@ -1,207 +1,294 @@ - -SecHub scan result - - - + + SecHub scan result + + + -
-
-
-
-
-
-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - -
-
1UNCLASSIFIEDName 2Description 2
2HIGHName 3Description 3
3CRITICALName 4Description 5
-
-
-

Yellow findings

- - - - - - - - - - - - - -
- - - - - - - - - -
IdSeverityTypeDescription
4MEDIUMName 2Description 2
-
-
-

Green findings

- - - - - - - - - - - +
+

Summary

+
IdSeverityTypeDescription
+ + + + + + + + + + + +
+ + +
TotalRedYellowGreen
+
-
+
+
+ CodeScan +
+
+
+
+
+
+
+
+
+
+
+ InfraScan +
+
+
+
+
+
+
+
+
+
+
+ LicenseScan +
+
+
+
+
+
+
+
+
+
+
+ SecretScan +
+
+
+
+
+
+
+
+
+
+
+ WebScan +
+
+
+
+
+
+
+
+
+
+
- - - 5 - INFO - Name 2 - Description 2 - - - -
-
-
-

Messages

- +
+

+
+ +
+
+
+ +
+
+
+ +
+
+
+ +

Web Scan

+

+ + + + + + + - - - - - - - - - - - - - - - - - - - + +
+
SeverityTypeDescription
🛇This is an error message text
This is a warning message text
🛈This is an info message text
This is a message where message type is null
-
- - + + +
+

+
+ +
+
+
+ +
+
+
+ +
+
+
+ +

Web Scan

+ + + + + + + + + + +
+ + +
SeverityTypeDescription
+
+

+
+

+
+ +
+
+
+ +
+
+
+ +
+
+
+ +

Web Scan

+ + + + + + + + + + +
+ + +
SeverityTypeDescription
+
+

+ + +
+

Messages

+ + + + + + + + + + + + + + + + + + + +
🛇This is an error message text
âš This is a warning message text
🛈This is an info message text
This is a message where message type is null
+
+ \ No newline at end of file diff --git a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilderTest.java b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilderTest.java index 6951a68ab1..f12a2942a1 100644 --- a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilderTest.java +++ b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/HTMLScanResultReportModelBuilderTest.java @@ -6,23 +6,13 @@ import java.io.ByteArrayInputStream; import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.core.io.Resource; -import com.mercedesbenz.sechub.commons.model.SecHubCodeCallStack; -import com.mercedesbenz.sechub.commons.model.SecHubFinding; -import com.mercedesbenz.sechub.commons.model.SecHubReportMetaData; -import com.mercedesbenz.sechub.commons.model.SecHubResult; -import com.mercedesbenz.sechub.commons.model.SecHubResultTrafficLightFilter; -import com.mercedesbenz.sechub.commons.model.TrafficLight; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.domain.scan.report.ScanSecHubReport; class HTMLScanResultReportModelBuilderTest { @@ -41,6 +31,7 @@ class HTMLScanResultReportModelBuilderTest { private List greenList; private List redList; private List yellowList; + private ScanTypeCount scanTypeCount; @BeforeEach void beforeEach() throws Exception { @@ -65,10 +56,11 @@ void beforeEach() throws Exception { when(trafficLightFilter.filterFindingsFor(result, TrafficLight.RED)).thenReturn(redList); when(trafficLightFilter.filterFindingsFor(result, TrafficLight.YELLOW)).thenReturn(yellowList); when(trafficLightFilter.filterFindingsFor(result, TrafficLight.GREEN)).thenReturn(greenList); + + scanTypeCount = ScanTypeCount.of(ScanType.CODE_SCAN); } - @Test - void metaData_set_as_optional_not_present_when_configuration_has_metadata_optional_null() { + @Test void metaData_set_as_optional_not_present_when_configuration_has_metadata_optional_null() { /* prepare */ when(scanSecHubReport.getTrafficLight()).thenReturn(TrafficLight.YELLOW); // traffic light necessary to avoid illegal state exception when(scanSecHubReport.getMetaData()).thenReturn(Optional.ofNullable(null)); @@ -77,14 +69,12 @@ void metaData_set_as_optional_not_present_when_configuration_has_metadata_option Map map = builderToTest.build(scanSecHubReport); /* test */ - @SuppressWarnings("unchecked") - Optional metaData = (Optional) map.get("metaData"); + @SuppressWarnings("unchecked") Optional metaData = (Optional) map.get("metaData"); assertNotNull(metaData); assertFalse(metaData.isPresent()); } - @Test - void metaData_set_as_optional_not_present_when_configuration_has_metadata_optional_defined() { + @Test void metaData_set_as_optional_not_present_when_configuration_has_metadata_optional_defined() { /* prepare */ when(scanSecHubReport.getTrafficLight()).thenReturn(TrafficLight.YELLOW); // traffic light necessary to avoid illegal state exception SecHubReportMetaData reportMetaData = mock(SecHubReportMetaData.class); @@ -94,8 +84,7 @@ void metaData_set_as_optional_not_present_when_configuration_has_metadata_option Map map = builderToTest.build(scanSecHubReport); /* test */ - @SuppressWarnings("unchecked") - Optional metaData = (Optional) map.get("metaData"); + @SuppressWarnings("unchecked") Optional metaData = (Optional) map.get("metaData"); assertNotNull(metaData); assertTrue(metaData.isPresent()); } @@ -168,8 +157,7 @@ void all_parameters_build_webdesignmode_true() throws Exception { assertEquals(HIDE_LIGHT, map.get("styleGreen")); } - @Test - void trafficlight_red_set_display_block__others_are_none() { + @Test void trafficlight_red_set_display_block__others_are_none() { when(scanSecHubReport.getTrafficLight()).thenReturn(TrafficLight.RED); Map map = builderToTest.build(scanSecHubReport); @@ -178,8 +166,7 @@ void trafficlight_red_set_display_block__others_are_none() { assertEquals(HIDE_LIGHT, map.get("styleGreen")); } - @Test - public void trafficlight_yellow_set_display_block__others_are_none() { + @Test public void trafficlight_yellow_set_display_block__others_are_none() { when(scanSecHubReport.getTrafficLight()).thenReturn(TrafficLight.YELLOW); Map map = builderToTest.build(scanSecHubReport); @@ -188,8 +175,7 @@ public void trafficlight_yellow_set_display_block__others_are_none() { assertEquals(HIDE_LIGHT, map.get("styleGreen")); } - @Test - void trafficlight_green_set_display_block__others_are_none() { + @Test void trafficlight_green_set_display_block__others_are_none() { when(scanSecHubReport.getTrafficLight()).thenReturn(TrafficLight.GREEN); Map map = builderToTest.build(scanSecHubReport); @@ -210,6 +196,9 @@ void code_scan_entries_set_and_right_amount_of_call_stacks_populated() { when(scanSecHubReport.getResult()).thenReturn(result); when(result.getFindings()).thenReturn(Arrays.asList(finding)); when(finding.getCode()).thenReturn(code1); + when(finding.getType()).thenReturn(ScanType.CODE_SCAN); + when(finding.getSeverity()).thenReturn(Severity.HIGH); + when(finding.getName()).thenReturn("some_vulnerability_name"); when(code1.getCalls()).thenReturn(subCode); /* execute */ @@ -228,8 +217,7 @@ void code_scan_entries_set_and_right_amount_of_call_stacks_populated() { assertTrue(scanEntriesList.size() == 2); } - @Test - void code_scan_support_set_and_not_null() { + @Test void code_scan_support_set_and_not_null() { /* prepare */ when(scanSecHubReport.getTrafficLight()).thenReturn(TrafficLight.RED); @@ -237,10 +225,256 @@ void code_scan_support_set_and_not_null() { Map map = builderToTest.build(scanSecHubReport); /* test */ - assertNotNull(map.get("codeScanSupport")); assertTrue(map.get("codeScanSupport") instanceof HtmlCodeScanDescriptionSupport); + } + + @Test + void when_severity_is_critical_then_highSeverityCount_should_be_incremented() { + /* execute */ + builderToTest.incrementScanCount(Severity.CRITICAL, scanTypeCount); + + /* test */ + assertEquals(1, scanTypeCount.getHighSeverityCount()); + } + + @Test + void when_severity_is_high_then_highSeverityCount_should_be_incremented() { + /* execute */ + builderToTest.incrementScanCount(Severity.HIGH, scanTypeCount); + + /* test */ + assertEquals(1, scanTypeCount.getHighSeverityCount()); + } + + @Test + void when_severity_is_medium_then_mediumSeverityCount_should_be_incremented() { + /* execute */ + builderToTest.incrementScanCount(Severity.MEDIUM, scanTypeCount); + + /* test */ + assertEquals(1, scanTypeCount.getMediumSeverityCount()); + } + + @Test + void when_severity_is_low_then_lowSeverityCount_should_be_incremented() { + /* execute */ + builderToTest.incrementScanCount(Severity.LOW, scanTypeCount); + + /* test */ + assertEquals(1, scanTypeCount.getLowSeverityCount()); + } + + @Test + void when_severity_is_info_then_lowSeverityCount_should_be_incremented() { + /* execute */ + builderToTest.incrementScanCount(Severity.INFO, scanTypeCount); + + /* test */ + assertEquals(1, scanTypeCount.getLowSeverityCount()); + } + + @Test + void when_severity_is_unclassified_then_lowSeverityCount_should_be_incremented() { + /* execute */ + builderToTest.incrementScanCount(Severity.UNCLASSIFIED, scanTypeCount); + + /* test */ + assertEquals(1, scanTypeCount.getLowSeverityCount()); + } + + @Test + void when_findings_list_is_empty_then_prepareScanTypesForModel_returns_empty_set() { + /* prepare */ + List findings = new ArrayList<>(); + /* execute */ + Set scanTypeCountSet = builderToTest.prepareScanTypesForModel(findings); + + /* test */ + assertTrue(scanTypeCountSet.isEmpty()); + } + + @Test + void when_findings_list_contains_multiple_CODE_SCAN_findings_only_then_prepareScanTypesForModel_returns_set_with_one_appropriate_element_only() { + /* prepare */ + List findings = new ArrayList<>(); + SecHubFinding finding = new SecHubFinding(); + finding.setId(0); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.LOW); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(1); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.MEDIUM); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(2); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.HIGH); + findings.add(finding); + + /* execute */ + Set scanTypeCountSet = builderToTest.prepareScanTypesForModel(findings); + Iterator iterator = scanTypeCountSet.iterator(); + ScanTypeCount scanTypeCount = iterator.next(); + + /* test */ + assertTrue(scanTypeCountSet.size() == 1); + assertEquals(ScanType.CODE_SCAN, scanTypeCount.getScanType()); + assertEquals(1, scanTypeCount.getLowSeverityCount()); + assertEquals(1, scanTypeCount.getMediumSeverityCount()); + assertEquals(1, scanTypeCount.getHighSeverityCount()); + } + + @Test + void when_findings_list_contains_multiple_findings_of_differernt_ScanType_then_prepareScanTypesForModel_returns_appropriate_set() { + /* prepare */ + List findings = new ArrayList<>(); + SecHubFinding finding = new SecHubFinding(); + finding.setId(0); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.LOW); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(1); + finding.setType(ScanType.INFRA_SCAN); + finding.setSeverity(Severity.MEDIUM); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(2); + finding.setType(ScanType.SECRET_SCAN); + finding.setSeverity(Severity.HIGH); + findings.add(finding); + + /* execute */ + Set scanTypeCountSet = builderToTest.prepareScanTypesForModel(findings); + Iterator iterator = scanTypeCountSet.iterator(); + + /* execute + test */ + assertTrue(scanTypeCountSet.size() == 3); + + while (iterator.hasNext()) { + ScanTypeCount scanTypeCount = iterator.next(); + switch (scanTypeCount.getScanType()) { + case CODE_SCAN -> assertEquals(1, scanTypeCount.getLowSeverityCount()); + case INFRA_SCAN -> assertEquals(1, scanTypeCount.getMediumSeverityCount()); + case SECRET_SCAN -> assertEquals(1, scanTypeCount.getHighSeverityCount()); + } + } + } + + @Test + void when_findings_list_is_empty_then_filterFindingsForWebScan_must_return_empty_map() { + /* prepare */ + List findings = new ArrayList<>(); + List severities = List.of(Severity.HIGH); + + /* execute */ + Map> groupedAndSortedFindingsByName = builderToTest.filterFindingsForWebScan(findings, severities); + + /* test */ + assertTrue(groupedAndSortedFindingsByName.isEmpty()); + } + + @Test + void when_findings_list_contains_3_WEB_SCAN_HIGH_findings_then_filterFindingsForWebScan_must_return_appropriate_map() { + /* prepare */ + List findings = new ArrayList<>(); + SecHubFinding finding = new SecHubFinding(); + finding.setId(0); + finding.setType(ScanType.WEB_SCAN); + finding.setSeverity(Severity.HIGH); + finding.setName("Cross Site Scripting (Reflected)"); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(1); + finding.setType(ScanType.WEB_SCAN); + finding.setSeverity(Severity.HIGH); + finding.setName("Cross Site Scripting (Reflected)"); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(2); + finding.setType(ScanType.WEB_SCAN); + finding.setSeverity(Severity.HIGH); + finding.setName("Cross Site Scripting (Reflected)"); + findings.add(finding); + + List severities = List.of(Severity.HIGH); + + /* execute */ + Map> groupedAndSortedFindingsByName = builderToTest.filterFindingsForWebScan(findings, severities); + List findingList = groupedAndSortedFindingsByName.get("Cross Site Scripting (Reflected)"); + + /* test */ + assertEquals(1, groupedAndSortedFindingsByName.size()); + assertTrue(groupedAndSortedFindingsByName.containsKey("Cross Site Scripting (Reflected)")); + assertEquals(3, findingList.size()); + for (SecHubFinding secHubFinding : findingList) { + assertEquals(ScanType.WEB_SCAN, secHubFinding.getType()); + assertEquals(Severity.HIGH, secHubFinding.getSeverity()); + assertEquals("Cross Site Scripting (Reflected)", secHubFinding.getName()); + } + } + + @Test + void when_findings_list_is_empty_then_filterFindingsForGeneralScan_must_return_empty_list() { + /* prepare */ + List findings = new ArrayList<>(); + Map> codeScanEntries = new HashMap<>(); + List severities = List.of(Severity.HIGH); + + /* execute */ + List htmlSecHubFindingList = builderToTest.filterFindingsForGeneralScan(findings, codeScanEntries, severities); + + /* test */ + assertTrue(htmlSecHubFindingList.isEmpty()); + } + + @Test + void when_findings_list_contains_1_CODE_SCAN_HIGH_findings_then_filterFindingsForGeneralScan_must_return_appropriate_list() { + /* prepare */ + List findings = new ArrayList<>(); + SecHubFinding finding = new SecHubFinding(); + finding.setId(0); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.HIGH); + finding.setName("Deferring unsafe method \"Close\" on type \"*os.File\""); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(1); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.HIGH); + finding.setName("Deferring unsafe method \"Close\" on type \"*os.File\""); + findings.add(finding); + finding = new SecHubFinding(); + finding.setId(2); + finding.setType(ScanType.CODE_SCAN); + finding.setSeverity(Severity.HIGH); + finding.setName("Deferring unsafe method \"Close\" on type \"*os.File\""); + findings.add(finding); + + Map> codeScanEntries = new HashMap<>(); + List list = new ArrayList<>(); + list.add(new HTMLScanResultCodeScanEntry()); + codeScanEntries.put(0, list); + list = new ArrayList<>(); + list.add(new HTMLScanResultCodeScanEntry()); + codeScanEntries.put(1, list); + list = new ArrayList<>(); + list.add(new HTMLScanResultCodeScanEntry()); + codeScanEntries.put(2, list); + + List severities = List.of(Severity.HIGH); + + /* execute */ + List htmlSecHubFindingList = builderToTest.filterFindingsForGeneralScan(findings, codeScanEntries, severities); + + /* test */ + assertEquals(1, htmlSecHubFindingList.size()); + assertEquals("Deferring unsafe method \"Close\" on type \"*os.File\"", htmlSecHubFindingList.get(0).getName()); + assertEquals(3, htmlSecHubFindingList.get(0).getEntryList().size()); } } diff --git a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanReportRestControllerMockTest.java b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanReportRestControllerMockTest.java index e33d083fee..63b3709c5c 100644 --- a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanReportRestControllerMockTest.java +++ b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanReportRestControllerMockTest.java @@ -9,12 +9,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,17 +25,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; -import com.mercedesbenz.sechub.commons.model.SecHubFinding; -import com.mercedesbenz.sechub.commons.model.TrafficLight; -import com.mercedesbenz.sechub.commons.model.TrafficLightCalculator; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.domain.scan.product.ReportProductExecutionService; -import com.mercedesbenz.sechub.domain.scan.report.CreateScanReportService; -import com.mercedesbenz.sechub.domain.scan.report.DownloadScanReportService; -import com.mercedesbenz.sechub.domain.scan.report.DownloadSpdxScanReportService; -import com.mercedesbenz.sechub.domain.scan.report.ScanReport; -import com.mercedesbenz.sechub.domain.scan.report.ScanReportRepository; -import com.mercedesbenz.sechub.domain.scan.report.ScanReportRestController; -import com.mercedesbenz.sechub.domain.scan.report.ScanSecHubReport; +import com.mercedesbenz.sechub.domain.scan.report.*; import com.mercedesbenz.sechub.test.TestPortProvider; @ExtendWith(SpringExtension.class) @@ -130,11 +117,14 @@ void get_html_report_with_cwe_id() throws Exception { Integer cweId = Integer.valueOf(77); - SecHubFinding finding = new SecHubFinding(); + HTMLSecHubFinding finding = new HTMLSecHubFinding(); finding.setCweId(cweId); + finding.setSeverity(Severity.HIGH); + finding.setType(ScanType.CODE_SCAN); + finding.setDescription("Potential file inclusion via variable"); - reportModelBuilderResult.put("redList", Arrays.asList(finding)); - reportModelBuilderResult.put("codeScanEntries", new ArrayList<>()); + reportModelBuilderResult.put("reportHelper", HTMLReportHelper.DEFAULT); + reportModelBuilderResult.put("redHTMLSecHubFindingList", Arrays.asList(finding)); when(modelBuilder.build(any())).thenReturn(reportModelBuilderResult); @@ -264,8 +254,9 @@ void beforeEach() throws Exception { reportModelBuilderResult.put("yellowList", new ArrayList<>()); reportModelBuilderResult.put("greenList", new ArrayList<>()); reportModelBuilderResult.put("isWebDesignMode", false); - reportModelBuilderResult.put("metaData", Optional.ofNullable(null)); + reportModelBuilderResult.put("metaData", null); reportModelBuilderResult.put("codeScanSupport", new HtmlCodeScanDescriptionSupport()); + reportModelBuilderResult.put("scanTypeCountSet", new TreeSet()); when(modelBuilder.build(any())).thenReturn(reportModelBuilderResult); } diff --git a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanTypeCountTest.java b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanTypeCountTest.java new file mode 100644 index 0000000000..2048e83959 --- /dev/null +++ b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/ScanTypeCountTest.java @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.domain.scan; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.commons.model.ScanType; + +public class ScanTypeCountTest { + + private ScanTypeCount scanTypeCount; + + @BeforeEach + void beforeEach() { + scanTypeCount = ScanTypeCount.of(ScanType.CODE_SCAN); + } + + @Test + void of_constructor_creates_right_object() { + /* prepare + execute */ + scanTypeCount = ScanTypeCount.of(ScanType.CODE_SCAN); + + /* test */ + assertEquals(scanTypeCount.getScanType(), ScanType.CODE_SCAN); + assertEquals(scanTypeCount.getHighSeverityCount(), 0); + assertEquals(scanTypeCount.getMediumSeverityCount(), 0); + assertEquals(scanTypeCount.getLowSeverityCount(), 0); + } + + @Test + void when_ScanType_is_null_then_of_constructor_throws_IllegalArgumentException() { + /* prepare */ + String expectedMessage = "ScanType argument must exist"; + + /* execute */ + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + ScanTypeCount.of(null); + }); + + /* test */ + String actualMessage = exception.getMessage(); + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + void execute_incrementHighSeverityCount_once_increment_highSeverityCount_value_by_one() { + /* execute */ + scanTypeCount.incrementHighSeverityCount(); + + /* test */ + assertEquals(scanTypeCount.getHighSeverityCount(), 1); + } + + @Test + void executing_incrementHighSeverityCount_4_times_increases_highSeverityCount_value_by_4() { + /* execute */ + for (int i = 0; i < 4; i++) { + scanTypeCount.incrementHighSeverityCount(); + } + + /* test */ + assertEquals(scanTypeCount.getHighSeverityCount(), 4); + } + + @Test + void execute_incrementMediumSeverityCount_once_increment_mediumSeverityCount_value_by_one() { + /* execute */ + scanTypeCount.incrementMediumSeverityCount(); + + /* test */ + assertEquals(scanTypeCount.getMediumSeverityCount(), 1); + } + + @Test + void executing_incrementMediumSeverityCount_5_times_increases_mediumSeverityCount_value_by_5() { + /* execute */ + for (int i = 0; i < 5; i++) { + scanTypeCount.incrementMediumSeverityCount(); + } + + /* test */ + assertEquals(scanTypeCount.getMediumSeverityCount(), 5); + } + + @Test + void execute_incrementLowSeverityCount_once_increment_lowSeverityCount_value_by_one() { + /* execute */ + scanTypeCount.incrementLowSeverityCount(); + + /* test */ + assertEquals(scanTypeCount.getLowSeverityCount(), 1); + } + + @Test + void executing_incrementLowSeverityCount_7_times_increases_lowSeverityCount_value_by_7() { + /* execute */ + for (int i = 0; i < 7; i++) { + scanTypeCount.incrementLowSeverityCount(); + } + + /* test */ + assertEquals(scanTypeCount.getLowSeverityCount(), 7); + } + + @Test + void compareTo_must_return_positive_on_scanTypeCount_is_null() { + /* prepare */ + ScanTypeCount scanTypeCountA = ScanTypeCount.of(ScanType.CODE_SCAN); + ScanTypeCount scanTypeCountB = null; + + /* execute */ + int compareResult = scanTypeCountA.compareTo(scanTypeCountB); + + /* test */ + assertTrue(0 < compareResult); + } + + @Test + void compareTo_must_return_zero_on_equals_scanTypeCounts() { + /* prepare */ + ScanTypeCount scanTypeCountA = ScanTypeCount.of(ScanType.CODE_SCAN); + ScanTypeCount scanTypeCountB = ScanTypeCount.of(ScanType.CODE_SCAN); + + /* execute */ + int compareResult = scanTypeCountA.compareTo(scanTypeCountB); + + /* test */ + assertEquals(0, compareResult); + } + + @Test + void compareTo_must_return_positive_value_because_scanTypeCountA_different_from_scanTypeCountB() { + /* prepare */ + ScanTypeCount scanTypeCountA = ScanTypeCount.of(ScanType.CODE_SCAN); + ScanTypeCount scanTypeCountB = ScanTypeCount.of(ScanType.WEB_SCAN); + + /* execute */ + int compareResult = scanTypeCountA.compareTo(scanTypeCountB); + + /* test */ + assertTrue(0 < compareResult); + } + + @Test + void compareTo_must_return_negative_value_because_scanTypeCountA_different_from_scanTypeCountB() { + /* prepare */ + ScanTypeCount scanTypeCountA = ScanTypeCount.of(ScanType.WEB_SCAN); + ScanTypeCount scanTypeCountB = ScanTypeCount.of(ScanType.CODE_SCAN); + + /* execute */ + int compareResult = scanTypeCountA.compareTo(scanTypeCountB); + + /* test */ + assertTrue(0 > compareResult); + } + + @Test + void when_highSeverityCount_equals_MAX_VALUE_then_after_increasing_it_must_be_less_than_0() { + /* prepare */ + scanTypeCount.highSeverityCount = Long.MAX_VALUE; + + /* execute */ + scanTypeCount.incrementHighSeverityCount(); + + /* test */ + assertTrue(0 > scanTypeCount.getHighSeverityCount()); + } + + @Test + void when_mediumSeverityCount_equals_MAX_VALUE_then_after_increasing_it_must_be_less_than_0() { + /* prepare */ + scanTypeCount.mediumSeverityCount = Long.MAX_VALUE; + + /* execute */ + scanTypeCount.incrementMediumSeverityCount(); + + /* test */ + assertTrue(0 > scanTypeCount.getMediumSeverityCount()); + } + + @Test + void when_lowSeverityCount_equals_MAX_VALUE_then_after_increasing_it_must_be_less_than_0() { + /* prepare */ + scanTypeCount.lowSeverityCount = Long.MAX_VALUE; + + /* execute */ + scanTypeCount.incrementLowSeverityCount(); + + /* test */ + assertTrue(0 > scanTypeCount.getLowSeverityCount()); + } + +} diff --git a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReportTest.java b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReportTest.java index 1772d9c83c..20e8c04f4a 100644 --- a/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReportTest.java +++ b/sechub-scan/src/test/java/com/mercedesbenz/sechub/domain/scan/report/ScanSecHubReportTest.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.domain.scan.report; +import static com.mercedesbenz.sechub.commons.model.ScanType.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -287,4 +288,128 @@ void scanreport_result_with_report_containing_sechub_report_model_init_and_json_ assertEquals(1, reportToTest.getResult().getCount()); } + @Test + void when_finding_is_CODE_SCAN_then_only_relevant_reports_metadata_total_value_should_be_increased() { + /* prepare */ + SecHubReportModel reportModel = new SecHubReportModel(); + SecHubFinding finding = new SecHubFinding(); + finding.setName("finding1"); + finding.setType(CODE_SCAN); + finding.setSeverity(Severity.HIGH); + reportModel.getResult().getFindings().add(finding); + + ScanReport report = new ScanReport(); + report.setResult(reportModel.toJSON()); + report.setResultType(ScanReportResultType.MODEL); + + /* execute */ + ScanSecHubReport scanSecHubReport = new ScanSecHubReport(report); + + /* test */ + assertTrue(1 == scanSecHubReport.getMetaData().get().getSummary().getCodeScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getInfraScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getLicenseScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getSecretScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getWebScan().getTotal()); + } + + @Test + void when_finding_is_INFRA_SCAN_then_only_relevant_reports_metadata_total_value_should_be_increased() { + /* prepare */ + SecHubReportModel reportModel = new SecHubReportModel(); + SecHubFinding finding = new SecHubFinding(); + finding.setName("finding1"); + finding.setType(INFRA_SCAN); + finding.setSeverity(Severity.HIGH); + reportModel.getResult().getFindings().add(finding); + + ScanReport report = new ScanReport(); + report.setResult(reportModel.toJSON()); + report.setResultType(ScanReportResultType.MODEL); + + /* execute */ + ScanSecHubReport scanSecHubReport = new ScanSecHubReport(report); + + /* test */ + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getCodeScan().getTotal()); + assertTrue(1 == scanSecHubReport.getMetaData().get().getSummary().getInfraScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getLicenseScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getSecretScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getWebScan().getTotal()); + } + + @Test + void when_finding_is_LICENSE_SCAN_then_only_relevant_reports_metadata_total_value_should_be_increased() { + /* prepare */ + SecHubReportModel reportModel = new SecHubReportModel(); + SecHubFinding finding = new SecHubFinding(); + finding.setName("finding1"); + finding.setType(LICENSE_SCAN); + finding.setSeverity(Severity.HIGH); + reportModel.getResult().getFindings().add(finding); + + ScanReport report = new ScanReport(); + report.setResult(reportModel.toJSON()); + report.setResultType(ScanReportResultType.MODEL); + + /* execute */ + ScanSecHubReport scanSecHubReport = new ScanSecHubReport(report); + + /* test */ + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getCodeScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getInfraScan().getTotal()); + assertTrue(1 == scanSecHubReport.getMetaData().get().getSummary().getLicenseScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getSecretScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getWebScan().getTotal()); + } + + @Test + void when_finding_is_SECRET_SCAN_then_only_relevant_reports_metadata_total_value_should_be_increased() { + /* prepare */ + SecHubReportModel reportModel = new SecHubReportModel(); + SecHubFinding finding = new SecHubFinding(); + finding.setName("finding1"); + finding.setType(SECRET_SCAN); + finding.setSeverity(Severity.HIGH); + reportModel.getResult().getFindings().add(finding); + + ScanReport report = new ScanReport(); + report.setResult(reportModel.toJSON()); + report.setResultType(ScanReportResultType.MODEL); + + /* execute */ + ScanSecHubReport scanSecHubReport = new ScanSecHubReport(report); + + /* test */ + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getCodeScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getInfraScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getLicenseScan().getTotal()); + assertTrue(1 == scanSecHubReport.getMetaData().get().getSummary().getSecretScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getWebScan().getTotal()); + } + + @Test + void when_finding_is_WEB_SCAN_then_only_relevant_reports_metadata_total_value_should_be_increased() { + /* prepare */ + SecHubReportModel reportModel = new SecHubReportModel(); + SecHubFinding finding = new SecHubFinding(); + finding.setName("finding1"); + finding.setType(WEB_SCAN); + finding.setSeverity(Severity.HIGH); + reportModel.getResult().getFindings().add(finding); + + ScanReport report = new ScanReport(); + report.setResult(reportModel.toJSON()); + report.setResultType(ScanReportResultType.MODEL); + + /* execute */ + ScanSecHubReport scanSecHubReport = new ScanSecHubReport(report); + + /* test */ + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getCodeScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getInfraScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getLicenseScan().getTotal()); + assertTrue(0 == scanSecHubReport.getMetaData().get().getSummary().getSecretScan().getTotal()); + assertTrue(1 == scanSecHubReport.getMetaData().get().getSummary().getWebScan().getTotal()); + } } diff --git a/sechub-systemtest/src/test/resources/additional-resources/expected-output/sechub-result1.json b/sechub-systemtest/src/test/resources/additional-resources/expected-output/sechub-result1.json index 13c6ffdd76..8aa236c453 100644 --- a/sechub-systemtest/src/test/resources/additional-resources/expected-output/sechub-result1.json +++ b/sechub-systemtest/src/test/resources/additional-resources/expected-output/sechub-result1.json @@ -55,6 +55,46 @@ }, "status" : "SUCCESS", "reportVersion" : "1.0", + "metaData" : { + "labels" : { }, + "summary" : { + "codeScan" : { + "total" : 4, + "red" : 0, + "yellow" : 1, + "green" : 3, + "details" : { } + }, + "infraScan" : { + "total" : 0, + "red" : 0, + "yellow" : 0, + "green" : 0, + "details" : { } + }, + "licenseScan" : { + "total" : 0, + "red" : 0, + "yellow" : 0, + "green" : 0, + "details" : { } + }, + "secretScan" : { + "total" : 0, + "red" : 0, + "yellow" : 0, + "green" : 0, + "details" : { } + }, + "webScan" : { + "total" : 0, + "red" : 0, + "yellow" : 0, + "green" : 0, + "details" : { } + } + } + }, "messages" : [ { "type" : "ERROR", "text" : "error for PDS job: {*:36} but with\n a multine ....\n " diff --git a/sechub-test/src/test/java/com/mercedesbenz/sechub/test/report/ThymeLeafHTMLReportingTest.java b/sechub-test/src/test/java/com/mercedesbenz/sechub/test/report/ThymeLeafHTMLReportingTest.java index a5fbe7ce43..119ef8d1d2 100644 --- a/sechub-test/src/test/java/com/mercedesbenz/sechub/test/report/ThymeLeafHTMLReportingTest.java +++ b/sechub-test/src/test/java/com/mercedesbenz/sechub/test/report/ThymeLeafHTMLReportingTest.java @@ -10,6 +10,7 @@ import java.time.LocalDateTime; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.TreeMap; import org.junit.jupiter.api.BeforeAll; @@ -75,13 +76,19 @@ private static void beforAll() throws IOException { thymeleafTemplateEngine.setTemplateResolver(templateResolver); if (TestUtil.isAutoCSSFragementGenerationEnabled()) { - File scanHTMLFolder = new File("./../sechub-scan/src/main/resources/templates/report/html"); - File cssFile = new File(scanHTMLFolder, "scanresult.css"); - File fragmentsFile = new File(scanHTMLFolder, "fragments.html"); - CSSFileToFragementMerger merger = new CSSFileToFragementMerger(); + + File fragmentsFile = new File(scanHTMLFolder, "fragment-cwe-summary-table.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-generic-scan-table.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-generic-scan-table-row.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-summary-table-row.html"); + merger.merge(cssFile, fragmentsFile); + fragmentsFile = new File(scanHTMLFolder, "fragment-web-scan-table.html"); merger.merge(cssFile, fragmentsFile); } else { LOG.info("Skipping CSS auto generation/merging"); @@ -105,6 +112,7 @@ void example1_owasp_zap_sarif_report_is_transformed_to_expected_sechub_report_HT assertTrue(htmlResult.contains(context.sechubJobUUID)); assertTrue(htmlResult.contains("XSS"), "The report must at least contain a cross site scripting vulnerability!"); + assertTrue(htmlResult.contains("CWE-614"), "The report must at least contain the CWE-614 vulnerability!"); assertTrue(htmlResult.contains("Cross Site Scripting (Reflected)"), "The report must at least contain a cross site scripting reflected vulnerability!"); assertTrue(htmlResult.contains("Red findings")); @@ -344,9 +352,9 @@ private Map createThymeLeafReportData() throws IOException, SecH ScanSecHubReport scanReport = new ScanSecHubReport(report); if (getMetaData().isMetaDataNecessaryForReport()) { - SecHubReportMetaData reportMetaData = new SecHubReportMetaData(); - reportMetaData.getLabels().putAll(getMetaData().labels); - scanReport.setMetaData(reportMetaData); + Optional reportMetaData = scanReport.getMetaData(); + reportMetaData.get().getLabels().putAll(getMetaData().labels); + scanReport.setMetaData(reportMetaData.get()); } storeAsJSONFileForDebuggingWhenTempFilesAreKept(JSONConverter.get().toJSON(scanReport, true), this); Map tyhmeleafMap = reportModelBuilder.build(scanReport);