From 68c9e5eeae38b0e43fef99ad6187aaf4eda2f76c Mon Sep 17 00:00:00 2001 From: Matteo Mara Date: Wed, 28 Sep 2022 16:19:43 +0200 Subject: [PATCH] SONAR-17393 add constants and common code for handling OWASP ASVS --- .../sonar/server/issue/index/IssueDoc.java | 10 +++++ .../issue/index/IssueIndexDefinition.java | 2 + .../index/IssueIteratorForSingleChunk.java | 1 + .../server/security/SecurityStandards.java | 41 ++++++++++++------- .../security/SecurityStandardsTest.java | 8 ++++ .../sonar/server/issue/index/IssueIndex.java | 5 +++ .../sonar/server/issue/index/IssueQuery.java | 11 +++++ .../server/issue/index/IssueQueryTest.java | 9 ++++ .../ws/client/issue/IssuesWsParameters.java | 1 + 9 files changed, 74 insertions(+), 14 deletions(-) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java index ac194d590ab..f00a40a8036 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java @@ -295,6 +295,16 @@ public class IssueDoc extends BaseDoc { return getNullableField(IssueIndexDefinition.FIELD_ISSUE_PCI_DSS_40); } + public IssueDoc setOwaspAsvs40(@Nullable Collection o) { + setField(IssueIndexDefinition.FIELD_ISSUE_OWASP_ASVS_40, o); + return this; + } + + @CheckForNull + public Collection getOwaspAsvs40() { + return getNullableField(IssueIndexDefinition.FIELD_ISSUE_OWASP_ASVS_40); + } + @CheckForNull public Collection getOwaspTop10() { return getNullableField(IssueIndexDefinition.FIELD_ISSUE_OWASP_TOP_10); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java index a0bf4593815..0eaccdeb01e 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java @@ -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(); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java index 9586ff3cb55..d2b3715304d 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java @@ -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); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java index afb13b4271b..b06a72461a4 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java @@ -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 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> CWES_BY_SQ_CATEGORY = ImmutableMap.>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 getPciDss32() { - return toPciDss(standards, PCI_DSS_32_PREFIX); + return getMatchingStandards(standards, PCI_DSS_32_PREFIX); } public Set getPciDss40() { - return toPciDss(standards, PCI_DSS_40_PREFIX); + return getMatchingStandards(standards, PCI_DSS_40_PREFIX); + } + + public Set getOwaspAsvs40() { + return getMatchingStandards(standards, OWASP_ASVS_40_PREFIX); } public Set getOwaspTop10() { - return toOwaspTop10(standards, OWASP_TOP10_PREFIX); + return getMatchingStandards(standards, OWASP_TOP10_PREFIX); } public Set 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 toPciDss(Set securityStandards, String prefix) { - return securityStandards.stream() - .filter(s -> s.startsWith(prefix)) - .map(s -> s.substring(prefix.length())) - .collect(toSet()); - } - - private static Set toOwaspTop10(Set securityStandards, String prefix) { + private static Set getMatchingStandards(Set securityStandards, String prefix) { return securityStandards.stream() .filter(s -> s.startsWith(prefix)) .map(s -> s.substring(prefix.length())) diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java index 665d27fa357..c61c4106a31 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java @@ -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 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"); + } } diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 2ed15da00f5..aac88c660fc 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -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()); diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java index 77fe8d8ab72..38c3a2299ba 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java @@ -82,6 +82,7 @@ public class IssueQuery { private final Collection owaspTop10; private final Collection pciDss32; private final Collection pciDss40; + private final Collection owaspAsvs40; private final Collection owaspTop10For2021; private final Collection sansTop25; private final Collection 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 owaspAsvs40() { + return owaspAsvs40; + } public Collection owaspTop10() { return owaspTop10; } @@ -347,6 +352,7 @@ public class IssueQuery { private Collection types; private Collection pciDss32; private Collection pciDss40; + private Collection owaspAsvs40; private Collection owaspTop10; private Collection owaspTop10For2021; private Collection sansTop25; @@ -472,6 +478,11 @@ public class IssueQuery { return this; } + public Builder owaspAsvs40(@Nullable Collection o) { + this.owaspAsvs40 = o; + return this; + } + public Builder owaspTop10(@Nullable Collection o) { this.owaspTop10 = o; return this; diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryTest.java index 5215a89d36f..24aa3bec6a9 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryTest.java @@ -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() 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 9fb03b98b95..1ca2b86ce5c 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 @@ -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 -- 2.39.5