]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17399 Add OWASP ASVS filtering for issues search based on the level
authorZipeng WU <zipeng.wu@sonarsource.com>
Thu, 6 Oct 2022 15:21:12 +0000 (17:21 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 10 Oct 2022 20:03:09 +0000 (20:03 +0000)
server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java
server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java

index 8852d1f2e418cf269792dde0e018a5380106234a..bd86e88b4b63e3d8d9d0c9dd160845abb8fa7f7f 100644 (file)
@@ -71,6 +71,8 @@ public class SearchRequest {
   private List<String> 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;
+  }
 }
index adaeb8a4fcb707e07637a88c7b9816de769bb0f0..c8c0ce282111fda5f3de9c3bf17468cb3b5ab9fe 100644 (file)
@@ -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");
   }
index ed9e96a6a7776100224ac3fbe2bac7292a8122ca..7c8e6d0743ead5a0d1f748f905a1746ce057931a 100644 (file)
@@ -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())
index e2f508b8bb8d6218db176c8c0118d151acd0c6b5..bc313bada1a1ccf92d20585258bb4e2e66c52acb 100644 (file)
@@ -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))
index 5f8f3e082bdf4e1e0b1c3519518affccc9cbe9b0..9d195878e38dd52bcb95e85f0e3f948ee924ea37 100644 (file)
@@ -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<IssueDto> 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);
index 63459ace05056de7dc764036b215b08eb08afb15..4c98ddabf193044a0f8d85a003c356bfd8aec63c 100644 (file)
@@ -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";