diff --git a/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/BlackDuckReader.java b/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/BlackDuckReader.java new file mode 100644 index 00000000..bcb84f03 --- /dev/null +++ b/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/BlackDuckReader.java @@ -0,0 +1,104 @@ +/** + * OWASP Benchmark Project + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Sascha Knoop + * @created 2025 + */ +package org.owasp.benchmarkutils.score.parsers; + +import static java.lang.Integer.parseInt; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.owasp.benchmarkutils.score.BenchmarkScore; +import org.owasp.benchmarkutils.score.ResultFile; +import org.owasp.benchmarkutils.score.TestCaseResult; +import org.owasp.benchmarkutils.score.TestSuiteResults; + +public class BlackDuckReader extends Reader { + + @Override + public boolean canRead(ResultFile resultFile) { + return resultFile.isJson() + && resultFile.json().has("driver") + && resultFile.json().get("driver").equals("polaris_blackduck"); + } + + @Override + public TestSuiteResults parse(ResultFile resultFile) throws Exception { + TestSuiteResults tr = + new TestSuiteResults("BlackDuck", true, TestSuiteResults.ToolType.SAST); + + Report report = jsonMapper.readValue(resultFile.content(), Report.class); + + report.items.stream() + .filter(Item::isRelevant) + .forEach( + item -> { + Map properties = item.mappedProperties(); + + String testfile = + extractFilenameWithoutEnding(properties.get("filename")); + + TestCaseResult tcr = new TestCaseResult(); + + tcr.setCWE(parseInt(properties.get("cwe").substring(4))); + tcr.setNumber(testNumber(testfile)); + + tr.put(tcr); + }); + + return tr; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + private static class Report { + + @JsonProperty("_items") + public List items; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Item { + + @JsonProperty("occurrenceProperties") + public List properties; + + public Map mappedProperties() { + return properties.stream().collect(Collectors.toMap(Property::key, Property::value)); + } + + public boolean isRelevant() { + return properties.stream() + .anyMatch(property -> property.value.contains(BenchmarkScore.TESTCASENAME)); + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Property { + public String key; + public String value; + + public String key() { + return key; + } + + public String value() { + return value; + } + } +} diff --git a/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/Reader.java b/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/Reader.java index 0892eda5..01c08cd6 100644 --- a/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/Reader.java +++ b/plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/Reader.java @@ -56,6 +56,7 @@ public static List allReaders() { new AppScanSourceReader(), new ArachniReader(), new BearerReader(), + new BlackDuckReader(), new BurpJsonReader(), new BurpReader(), new CASTAIPReader(), diff --git a/plugin/src/test/java/org/owasp/benchmarkutils/score/parsers/BlackDuckReaderTest.java b/plugin/src/test/java/org/owasp/benchmarkutils/score/parsers/BlackDuckReaderTest.java new file mode 100644 index 00000000..99bfa0e5 --- /dev/null +++ b/plugin/src/test/java/org/owasp/benchmarkutils/score/parsers/BlackDuckReaderTest.java @@ -0,0 +1,60 @@ +/** + * OWASP Benchmark Project + * + *

This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For + * details, please see https://owasp.org/www-project-benchmark/. + * + *

The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Foundation, version 2. + * + *

The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * @author Sascha Knoop + * @created 2025 + */ +package org.owasp.benchmarkutils.score.parsers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.owasp.benchmarkutils.score.BenchmarkScore; +import org.owasp.benchmarkutils.score.CweNumber; +import org.owasp.benchmarkutils.score.ResultFile; +import org.owasp.benchmarkutils.score.TestHelper; +import org.owasp.benchmarkutils.score.TestSuiteResults; + +public class BlackDuckReaderTest extends ReaderTestBase { + + private ResultFile resultFile; + + @BeforeEach + void setUp() { + resultFile = TestHelper.resultFileOf("testfiles/Benchmark-BlackDuck.json"); + BenchmarkScore.TESTCASENAME = "BenchmarkTest"; + } + + @Test + public void onlyBlackDuckReaderReportsCanReadAsTrue() { + assertOnlyMatcherClassIs(this.resultFile, BlackDuckReader.class); + } + + @Test + void readerHandlesGivenResultFile() throws Exception { + BlackDuckReader reader = new BlackDuckReader(); + TestSuiteResults result = reader.parse(resultFile); + + assertEquals(TestSuiteResults.ToolType.SAST, result.getToolType()); + assertTrue(result.isCommercial()); + assertEquals("BlackDuck", result.getToolName()); + + assertEquals(2, result.getTotalResults()); + + assertEquals(CweNumber.SQL_INJECTION, result.get(1).get(0).getCWE()); + assertEquals(CweNumber.XSS, result.get(2).get(0).getCWE()); + } +} diff --git a/plugin/src/test/resources/testfiles/Benchmark-BlackDuck.json b/plugin/src/test/resources/testfiles/Benchmark-BlackDuck.json new file mode 100644 index 00000000..5f2aa5ed --- /dev/null +++ b/plugin/src/test/resources/testfiles/Benchmark-BlackDuck.json @@ -0,0 +1,43 @@ +{ + "driver": "polaris_blackduck", + "_items": [ + { + "id": "11111111111111111111111111111111", + "weaknessId": "w-1", + "type": { + "id": "11111111-1111-1111-1111-111111111111", + "altName": "sql_injection:nosink|java" + }, + "occurrenceProperties": [ + { + "key": "filename", + "value": "BenchmarkTest00001.java" + }, + { + "key": "cwe", + "value": "CWE-89" + } + ], + "_type": "issues" + }, + { + "id": "22222222222222222222222222222222", + "weaknessId": "w-2", + "type": { + "id": "22222222-2222-2222-2222-222222222222", + "altName": "xss|java" + }, + "occurrenceProperties": [ + { + "key": "filename", + "value": "BenchmarkTest00002.java" + }, + { + "key": "cwe", + "value": "CWE-79" + } + ] + } + ], + "totalCount": 2 +}