From: Zipeng WU Date: Thu, 6 Oct 2022 15:21:12 +0000 (+0200) Subject: SONAR-17399 Add OWASP ASVS filtering for issues search based on the level X-Git-Tag: 9.7.0.61563~101 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ff7f96d059543d0b92002f26fdde3e2bf6096bdb;p=sonarqube.git SONAR-17399 Add OWASP ASVS filtering for issues search based on the level --- diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java index 8852d1f2e41..bd86e88b4b6 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java @@ -71,6 +71,8 @@ public class SearchRequest { private List cwe; private String timeZone; + private Integer owaspAsvsLevel; + public SearchRequest() { // nothing to do here } @@ -510,4 +512,13 @@ public class SearchRequest { this.inNewCodePeriod = inNewCodePeriod; return this; } + + public Integer getOwaspAsvsLevel() { + return owaspAsvsLevel; + } + + public SearchRequest setOwaspAsvsLevel(@Nullable Integer owaspAsvsLevel) { + this.owaspAsvsLevel = owaspAsvsLevel; + return this; + } } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java index adaeb8a4fcb..c8c0ce28211 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java @@ -51,6 +51,7 @@ public class SearchRequestTest { .setInNewCodePeriod(true) .setOwaspTop10For2021(asList("a2", "a3")) .setOwaspAsvs40(asList("1.1.1", "4.2.2")) + .setOwaspAsvsLevel(2) .setPciDss32(asList("1", "4")) .setPciDss40(asList("3", "5")); @@ -75,6 +76,7 @@ public class SearchRequestTest { assertThat(underTest.getInNewCodePeriod()).isTrue(); assertThat(underTest.getOwaspTop10For2021()).containsExactly("a2", "a3"); assertThat(underTest.getOwaspAsvs40()).containsExactly("1.1.1", "4.2.2"); + assertThat(underTest.getOwaspAsvsLevel()).isEqualTo(2); assertThat(underTest.getPciDss32()).containsExactly("1", "4"); assertThat(underTest.getPciDss40()).containsExactly("3", "5"); } diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java index ed9e96a6a77..7c8e6d0743e 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java @@ -140,6 +140,7 @@ public class IssueQueryFactory { .pciDss32(request.getPciDss32()) .pciDss40(request.getPciDss40()) .owaspAsvs40(request.getOwaspAsvs40()) + .owaspAsvsLevel(request.getOwaspAsvsLevel()) .owaspTop10(request.getOwaspTop10()) .owaspTop10For2021(request.getOwaspTop10For2021()) .sansTop25(request.getSansTop25()) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java index e2f508b8bb8..bc313bada1a 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -109,6 +109,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_IN_NEW_CODE_PERIOD; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES; +import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_ASVS_LEVEL; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ON_COMPONENT_ONLY; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_ASVS_40; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10; @@ -271,6 +272,10 @@ public class SearchAction implements IssuesWsAction { .setSince("5.5") .setPossibleValues(ALL_RULE_TYPES_EXCEPT_SECURITY_HOTSPOTS) .setExampleValue(format("%s,%s", RuleType.CODE_SMELL, RuleType.BUG)); + action.createParam(PARAM_OWASP_ASVS_LEVEL) + .setDescription("Level of OWASP ASVS categories.") + .setSince("9.7") + .setPossibleValues(1,2,3); action.createParam(PARAM_PCI_DSS_32) .setDescription("Comma-separated list of PCI DSS v3.2 categories.") .setSince("9.6") @@ -567,6 +572,7 @@ public class SearchAction implements IssuesWsAction { .setTypes(allRuleTypesExceptHotspotsIfEmpty(request.paramAsStrings(PARAM_TYPES))) .setPciDss32(request.paramAsStrings(PARAM_PCI_DSS_32)) .setPciDss40(request.paramAsStrings(PARAM_PCI_DSS_40)) + .setOwaspAsvsLevel(request.paramAsInt(PARAM_OWASP_ASVS_LEVEL)) .setOwaspAsvs40(request.paramAsStrings(PARAM_OWASP_ASVS_40)) .setOwaspTop10(request.paramAsStrings(PARAM_OWASP_TOP_10)) .setOwaspTop10For2021(request.paramAsStrings(PARAM_OWASP_TOP_10_2021)) diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java index 5f8f3e082bd..9d195878e38 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java @@ -27,6 +27,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; +import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -1088,6 +1089,55 @@ public class SearchActionTest { .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey()); } + @Test + public void only_vulnerabilities_are_returned_by_owaspAsvs40_with_level() { + ComponentDto project = db.components().insertPublicProject(); + ComponentDto file = db.components().insertComponent(newFileDto(project)); + Consumer issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql")); + RuleDto issueRule1 = db.rules().insertIssueRule(r -> r.setSecurityStandards(Set.of("owaspAsvs-4.0:1.7.2", "owaspAsvs-4.0:12.3.1"))); + RuleDto issueRule2 = db.rules().insertIssueRule(r -> r.setSecurityStandards(Set.of("owaspAsvs-4.0:2.2.5"))); + RuleDto issueRule3 = db.rules().insertIssueRule(r -> r.setSecurityStandards(Set.of("owaspAsvs-4.0:2.2.5", "owaspAsvs-4.0:12.1.3"))); + IssueDto issueDto1 = db.issues().insertIssue(issueRule1, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY)); + IssueDto issueDto2 = db.issues().insertIssue(issueRule2, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY)); + IssueDto issueDto3 = db.issues().insertIssue(issueRule3, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY)); + indexPermissionsAndIssues(); + + SearchWsResponse result = ws.newRequest() + .setParam("owaspAsvs-4.0", "1") + .setParam("owaspAsvsLevel", "1") + .executeProtobuf(SearchWsResponse.class); + + assertThat(result.getIssuesList()).isEmpty(); + + result = ws.newRequest() + .setParam("owaspAsvs-4.0", "1") + .setParam("owaspAsvsLevel", "2") + .executeProtobuf(SearchWsResponse.class); + + assertThat(result.getIssuesList()) + .extracting(Issue::getKey) + .containsExactlyInAnyOrder(issueDto1.getKey()); + + result = ws.newRequest() + .setParam("owaspAsvs-4.0", "12") + .setParam("owaspAsvsLevel", "1") + .executeProtobuf(SearchWsResponse.class); + + assertThat(result.getIssuesList()) + .extracting(Issue::getKey) + .containsExactlyInAnyOrder(issueDto1.getKey()); + + result = ws.newRequest() + .setParam("owaspAsvs-4.0", "12") + .setParam("owaspAsvsLevel", "2") + .executeProtobuf(SearchWsResponse.class); + + assertThat(result.getIssuesList()) + .extracting(Issue::getKey) + .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto3.getKey()); + + } + @Test public void only_vulnerabilities_are_returned_by_pciDss32() { ComponentDto project = db.components().insertPublicProject(); @@ -1725,7 +1775,7 @@ public class SearchActionTest { assertThat(def.params()).extracting("key").containsExactlyInAnyOrder( "additionalFields", "asc", "assigned", "assignees", "author", "componentKeys", "branch", "pullRequest", "createdAfter", "createdAt", "createdBefore", "createdInLast", "directories", "facets", "files", "issues", "scopes", "languages", "onComponentOnly", - "p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod", "statuses", "tags", "types", "pciDss-3.2", "pciDss-4.0", "owaspAsvs-4.0", "owaspTop10", + "p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod", "statuses", "tags", "types", "pciDss-3.2", "pciDss-4.0", "owaspAsvs-4.0", "owaspAsvsLevel", "owaspTop10", "owaspTop10-2021", "sansTop25", "cwe", "sonarsourceSecurity", "timeZone", "inNewCodePeriod"); WebService.Param branch = def.param(PARAM_BRANCH); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java index 63459ace050..4c98ddabf19 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java @@ -79,6 +79,7 @@ public class IssuesWsParameters { public static final String PARAM_LANGUAGES = "languages"; public static final String PARAM_TAGS = "tags"; public static final String PARAM_TYPES = "types"; + public static final String PARAM_OWASP_ASVS_LEVEL = "owaspAsvsLevel"; public static final String PARAM_PCI_DSS = "pciDss"; public static final String PARAM_PCI_DSS_32 = "pciDss-3.2"; public static final String PARAM_PCI_DSS_40 = "pciDss-4.0";