]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17393 add constants and common code for handling OWASP ASVS
authorMatteo Mara <matteo.mara@sonarsource.com>
Wed, 28 Sep 2022 14:19:43 +0000 (16:19 +0200)
committerPhilippe Perrin <philippe.perrin@sonarsource.com>
Fri, 7 Oct 2022 10:13:56 +0000 (12:13 +0200)
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java
server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java
server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java

index ac194d590ab7ecb2191612750ee4b6aac4e992a6..f00a40a8036e0cebd7e88620e0606a66eead438e 100644 (file)
@@ -295,6 +295,16 @@ public class IssueDoc extends BaseDoc {
     return getNullableField(IssueIndexDefinition.FIELD_ISSUE_PCI_DSS_40);
   }
 
+  public IssueDoc setOwaspAsvs40(@Nullable Collection<String> o) {
+    setField(IssueIndexDefinition.FIELD_ISSUE_OWASP_ASVS_40, o);
+    return this;
+  }
+
+  @CheckForNull
+  public Collection<String> getOwaspAsvs40() {
+    return getNullableField(IssueIndexDefinition.FIELD_ISSUE_OWASP_ASVS_40);
+  }
+
   @CheckForNull
   public Collection<String> getOwaspTop10() {
     return getNullableField(IssueIndexDefinition.FIELD_ISSUE_OWASP_TOP_10);
index a0bf45938158e3324372096454a3b00ca71e0b4e..0eaccdeb01e5d8fb2cd5323329118d1fcf771b7e 100644 (file)
@@ -98,6 +98,7 @@ public class IssueIndexDefinition implements IndexDefinition {
   public static final String FIELD_ISSUE_TYPE = "type";
   public static final String FIELD_ISSUE_PCI_DSS_32 = "pciDss-3.2";
   public static final String FIELD_ISSUE_PCI_DSS_40 = "pciDss-4.0";
+  public static final String FIELD_ISSUE_OWASP_ASVS_40 = "owaspAsvs-4.0";
   public static final String FIELD_ISSUE_OWASP_TOP_10 = "owaspTop10";
   public static final String FIELD_ISSUE_OWASP_TOP_10_2021 = "owaspTop10-2021";
   public static final String FIELD_ISSUE_SANS_TOP_25 = "sansTop25";
@@ -168,6 +169,7 @@ public class IssueIndexDefinition implements IndexDefinition {
     mapping.keywordFieldBuilder(FIELD_ISSUE_TYPE).disableNorms().build();
     mapping.keywordFieldBuilder(FIELD_ISSUE_PCI_DSS_32).disableNorms().build();
     mapping.keywordFieldBuilder(FIELD_ISSUE_PCI_DSS_40).disableNorms().build();
+    mapping.keywordFieldBuilder(FIELD_ISSUE_OWASP_ASVS_40).disableNorms().build();
     mapping.keywordFieldBuilder(FIELD_ISSUE_OWASP_TOP_10).disableNorms().build();
     mapping.keywordFieldBuilder(FIELD_ISSUE_OWASP_TOP_10_2021).disableNorms().build();
     mapping.keywordFieldBuilder(FIELD_ISSUE_SANS_TOP_25).disableNorms().build();
index 9586ff3cb55a21f063f95bb03318c14063547df6..d2b3715304d9d3b6453c88f370935c73e4ab4f57 100644 (file)
@@ -237,6 +237,7 @@ class IssueIteratorForSingleChunk implements IssueIterator {
       doc.setOwaspTop10For2021(securityStandards.getOwaspTop10For2021());
       doc.setPciDss32(securityStandards.getPciDss32());
       doc.setPciDss40(securityStandards.getPciDss40());
+      doc.setOwaspAsvs40(securityStandards.getOwaspAsvs40());
       doc.setCwe(securityStandards.getCwe());
       doc.setSansTop25(securityStandards.getSansTop25());
       doc.setSonarSourceSecurityCategory(sqCategory);
index afb13b4271bc9993784becd1a355ae82e76c1b8e..b06a72461a4e395b10dd53d74d7bb70ed1dff70d 100644 (file)
@@ -32,13 +32,14 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
+import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion;
+import org.sonar.api.server.rule.RulesDefinition.PciDssVersion;
 
 import static java.util.Arrays.asList;
 import static java.util.Arrays.stream;
 import static java.util.Collections.singleton;
 import static java.util.Collections.singletonList;
 import static org.sonar.api.server.rule.RulesDefinition.PciDssVersion.V3_2;
-import static org.sonar.api.server.rule.RulesDefinition.PciDssVersion.V4_0;
 import static org.sonar.core.util.stream.MoreCollectors.toList;
 import static org.sonar.core.util.stream.MoreCollectors.toSet;
 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
@@ -57,7 +58,8 @@ public final class SecurityStandards {
   private static final String OWASP_TOP10_PREFIX = "owaspTop10:";
   private static final String OWASP_TOP10_2021_PREFIX = "owaspTop10-2021:";
   private static final String PCI_DSS_32_PREFIX = V3_2.prefix() + ":";
-  private static final String PCI_DSS_40_PREFIX = V4_0.prefix() + ":";
+  private static final String PCI_DSS_40_PREFIX = PciDssVersion.V4_0.prefix() + ":";
+  private static final String OWASP_ASVS_40_PREFIX = OwaspAsvsVersion.V4_0.prefix() + ":";
   private static final String CWE_PREFIX = "cwe:";
   // See https://www.sans.org/top25-software-errors
   private static final Set<String> INSECURE_CWE = new HashSet<>(asList("89", "78", "79", "434", "352", "601"));
@@ -177,6 +179,20 @@ public final class SecurityStandards {
     }
   }
 
+  public enum OwaspAsvs {
+    C1("1"), C2("2"), C3("3"), C4("4"), C5("5"), C6("6"), C7("7"), C8("8"), C9("9"), C10("10"), C11("11"), C12("12"), C13("13"), C14("14");
+
+    private final String category;
+
+    OwaspAsvs(String category) {
+      this.category = category;
+    }
+
+    public String category() {
+      return category;
+    }
+  }
+
   public static final Map<SQCategory, Set<String>> CWES_BY_SQ_CATEGORY = ImmutableMap.<SQCategory, Set<String>>builder()
     .put(SQCategory.BUFFER_OVERFLOW, Set.of("119", "120", "131", "676", "788"))
     .put(SQCategory.SQL_INJECTION, Set.of("89", "564", "943"))
@@ -226,19 +242,23 @@ public final class SecurityStandards {
   }
 
   public Set<String> getPciDss32() {
-    return toPciDss(standards, PCI_DSS_32_PREFIX);
+    return getMatchingStandards(standards, PCI_DSS_32_PREFIX);
   }
 
   public Set<String> getPciDss40() {
-    return toPciDss(standards, PCI_DSS_40_PREFIX);
+    return getMatchingStandards(standards, PCI_DSS_40_PREFIX);
+  }
+
+  public Set<String> getOwaspAsvs40() {
+    return getMatchingStandards(standards, OWASP_ASVS_40_PREFIX);
   }
 
   public Set<String> getOwaspTop10() {
-    return toOwaspTop10(standards, OWASP_TOP10_PREFIX);
+    return getMatchingStandards(standards, OWASP_TOP10_PREFIX);
   }
 
   public Set<String> getOwaspTop10For2021() {
-    return toOwaspTop10(standards, OWASP_TOP10_2021_PREFIX);
+    return getMatchingStandards(standards, OWASP_TOP10_2021_PREFIX);
   }
 
   /**
@@ -276,14 +296,7 @@ public final class SecurityStandards {
     return new SecurityStandards(standards, cwe, sqCategory, ignoredSQCategories);
   }
 
-  private static Set<String> toPciDss(Set<String> securityStandards, String prefix) {
-    return securityStandards.stream()
-      .filter(s -> s.startsWith(prefix))
-      .map(s -> s.substring(prefix.length()))
-      .collect(toSet());
-  }
-
-  private static Set<String> toOwaspTop10(Set<String> securityStandards, String prefix) {
+  private static Set<String> getMatchingStandards(Set<String> securityStandards, String prefix) {
     return securityStandards.stream()
       .filter(s -> s.startsWith(prefix))
       .map(s -> s.substring(prefix.length()))
index 665d27fa357a95e91aac45d03bf76fc1a0c4de90..c61c4106a3199b0a19899196ea6409c41ebfb242 100644 (file)
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.junit.Test;
+import org.sonar.server.security.SecurityStandards.OwaspAsvs;
 import org.sonar.server.security.SecurityStandards.PciDss;
 import org.sonar.server.security.SecurityStandards.SQCategory;
 
@@ -125,4 +126,11 @@ public class SecurityStandardsTest {
 
     assertThat(pciDssCategories).hasSize(12).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
   }
+
+  @Test
+  public void owaspAsvs_categories_check() {
+    List<String> owaspAsvsCategories = Arrays.stream(OwaspAsvs.values()).map(OwaspAsvs::category).collect(Collectors.toList());
+
+    assertThat(owaspAsvsCategories).hasSize(14).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14");
+  }
 }
index 2ed15da00f5eaae21dfa2d7effeb21a0ddf7f084..aac88c660fc5d1c5f61896454b0fbb527e30268e 100644 (file)
@@ -124,6 +124,7 @@ import static org.sonar.server.issue.index.IssueIndex.Facet.CWE;
 import static org.sonar.server.issue.index.IssueIndex.Facet.DIRECTORIES;
 import static org.sonar.server.issue.index.IssueIndex.Facet.FILES;
 import static org.sonar.server.issue.index.IssueIndex.Facet.LANGUAGES;
+import static org.sonar.server.issue.index.IssueIndex.Facet.OWASP_ASVS_40;
 import static org.sonar.server.issue.index.IssueIndex.Facet.OWASP_TOP_10;
 import static org.sonar.server.issue.index.IssueIndex.Facet.OWASP_TOP_10_2021;
 import static org.sonar.server.issue.index.IssueIndex.Facet.PCI_DSS_32;
@@ -155,6 +156,7 @@ import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_LANG
 import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_LINE;
 import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH;
 import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_NEW_CODE_REFERENCE;
+import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_OWASP_ASVS_40;
 import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_OWASP_TOP_10;
 import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_OWASP_TOP_10_2021;
 import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_PCI_DSS_32;
@@ -187,6 +189,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CWE;
 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_ASVS_40;
 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10;
 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10_2021;
 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PCI_DSS_32;
@@ -255,6 +258,7 @@ public class IssueIndex {
     ASSIGNED_TO_ME(FACET_ASSIGNED_TO_ME, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, 1),
     PCI_DSS_32(PARAM_PCI_DSS_32, FIELD_ISSUE_PCI_DSS_32, STICKY, DEFAULT_FACET_SIZE),
     PCI_DSS_40(PARAM_PCI_DSS_40, FIELD_ISSUE_PCI_DSS_40, STICKY, DEFAULT_FACET_SIZE),
+    OWASP_ASVS_40(PARAM_OWASP_ASVS_40, FIELD_ISSUE_OWASP_ASVS_40, STICKY, DEFAULT_FACET_SIZE),
     OWASP_TOP_10(PARAM_OWASP_TOP_10, FIELD_ISSUE_OWASP_TOP_10, STICKY, DEFAULT_FACET_SIZE),
     OWASP_TOP_10_2021(PARAM_OWASP_TOP_10_2021, FIELD_ISSUE_OWASP_TOP_10_2021, STICKY, DEFAULT_FACET_SIZE),
     SANS_TOP_25(PARAM_SANS_TOP_25, FIELD_ISSUE_SANS_TOP_25, STICKY, DEFAULT_FACET_SIZE),
@@ -764,6 +768,7 @@ public class IssueIndex {
 
     addSecurityCategoryFacetIfNeeded(PARAM_PCI_DSS_32, PCI_DSS_32, options, aggregationHelper, esRequest, query.pciDss32().toArray());
     addSecurityCategoryFacetIfNeeded(PARAM_PCI_DSS_40, PCI_DSS_40, options, aggregationHelper, esRequest, query.pciDss40().toArray());
+    addSecurityCategoryFacetIfNeeded(PARAM_OWASP_ASVS_40, OWASP_ASVS_40, options, aggregationHelper, esRequest, query.owaspAsvs40().toArray());
     addSecurityCategoryFacetIfNeeded(PARAM_OWASP_TOP_10, OWASP_TOP_10, options, aggregationHelper, esRequest, query.owaspTop10().toArray());
     addSecurityCategoryFacetIfNeeded(PARAM_OWASP_TOP_10_2021, OWASP_TOP_10_2021, options, aggregationHelper, esRequest, query.owaspTop10For2021().toArray());
     addSecurityCategoryFacetIfNeeded(PARAM_SANS_TOP_25, SANS_TOP_25, options, aggregationHelper, esRequest, query.sansTop25().toArray());
index 77fe8d8ab72f5244bbf4738a139a96deba165f06..38c3a2299bab3624e5d5632f1456d4f38db4bd29 100644 (file)
@@ -82,6 +82,7 @@ public class IssueQuery {
   private final Collection<String> owaspTop10;
   private final Collection<String> pciDss32;
   private final Collection<String> pciDss40;
+  private final Collection<String> owaspAsvs40;
   private final Collection<String> owaspTop10For2021;
   private final Collection<String> sansTop25;
   private final Collection<String> cwe;
@@ -123,6 +124,7 @@ public class IssueQuery {
     this.types = defaultCollection(builder.types);
     this.pciDss32 = defaultCollection(builder.pciDss32);
     this.pciDss40 = defaultCollection(builder.pciDss40);
+    this.owaspAsvs40 = defaultCollection(builder.owaspAsvs40);
     this.owaspTop10 = defaultCollection(builder.owaspTop10);
     this.owaspTop10For2021 = defaultCollection(builder.owaspTop10For2021);
     this.sansTop25 = defaultCollection(builder.sansTop25);
@@ -225,6 +227,9 @@ public class IssueQuery {
     return pciDss40;
   }
 
+  public Collection<String> owaspAsvs40() {
+    return owaspAsvs40;
+  }
   public Collection<String> owaspTop10() {
     return owaspTop10;
   }
@@ -347,6 +352,7 @@ public class IssueQuery {
     private Collection<String> types;
     private Collection<String> pciDss32;
     private Collection<String> pciDss40;
+    private Collection<String> owaspAsvs40;
     private Collection<String> owaspTop10;
     private Collection<String> owaspTop10For2021;
     private Collection<String> sansTop25;
@@ -472,6 +478,11 @@ public class IssueQuery {
       return this;
     }
 
+    public Builder owaspAsvs40(@Nullable Collection<String> o) {
+      this.owaspAsvs40 = o;
+      return this;
+    }
+
     public Builder owaspTop10(@Nullable Collection<String> o) {
       this.owaspTop10 = o;
       return this;
index 5215a89d36f4cd9fbdf07dc804dffad045c1d18a..24aa3bec6a9cce5037e0e365cd19cf5f4c0f0791 100644 (file)
@@ -101,6 +101,15 @@ public class IssueQueryTest {
     assertThat(query.pciDss40()).containsOnly("3.4.5", "5.6");
   }
 
+  @Test
+  public void build_owasp_asvs_query() {
+    IssueQuery query = IssueQuery.builder()
+      .owaspAsvs40(List.of("1.2.3", "3.2.1"))
+      .build();
+
+    assertThat(query.owaspAsvs40()).containsOnly("1.2.3", "3.2.1");
+  }
+
   @Test
   public void build_owasp_query() {
     IssueQuery query = IssueQuery.builder()
index 9fb03b98b9515580a98da52fb19b0b514c39318c..1ca2b86ce5c28e8b7f4011b2d0c0afc225fa82f8 100644 (file)
@@ -82,6 +82,7 @@ public class IssuesWsParameters {
   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";
+  public static final String PARAM_OWASP_ASVS_40 = "owaspAsvs-4.0";
   public static final String PARAM_OWASP_TOP_10 = "owaspTop10";
   public static final String PARAM_OWASP_TOP_10_2021 = "owaspTop10-2021";
   @Deprecated