From: Eric Hartmann Date: Fri, 19 Oct 2018 08:49:04 +0000 (+0200) Subject: SONAR-11370 Extract Owasp, SansTop25 constant to a dedicated helper X-Git-Tag: 7.5~242 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=069f74065ca3f4449dc2685fc73c000958d9cc75;p=sonarqube.git SONAR-11370 Extract Owasp, SansTop25 constant to a dedicated helper --- 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 d6e49f49a51..dd13a01395a 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 @@ -19,17 +19,12 @@ */ package org.sonar.server.issue.index; -import com.google.common.collect.ImmutableMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; import org.sonar.api.config.Configuration; import org.sonar.api.config.internal.MapSettings; import org.sonar.server.es.IndexDefinition; import org.sonar.server.es.IndexType; import org.sonar.server.es.NewIndex; -import static java.util.Arrays.asList; import static org.sonar.server.es.DefaultIndexSettingsElement.SORTABLE_ANALYZER; import static org.sonar.server.es.NewIndex.SettingsConfiguration.MANUAL_REFRESH_INTERVAL; import static org.sonar.server.es.NewIndex.SettingsConfiguration.newBuilder; @@ -100,18 +95,6 @@ public class IssueIndexDefinition implements IndexDefinition { public static final String FIELD_ISSUE_OWASP_TOP_10 = "owaspTop10"; public static final String FIELD_ISSUE_SANS_TOP_25 = "sansTop25"; public static final String FIELD_ISSUE_CWE = "cwe"; - public static final String UNKNOWN_STANDARD = "unknown"; - public static final String SANS_TOP_25_INSECURE_INTERACTION = "insecure-interaction"; - public static final String SANS_TOP_25_RISKY_RESOURCE = "risky-resource"; - public static final String SANS_TOP_25_POROUS_DEFENSES = "porous-defenses"; - // See https://www.sans.org/top25-software-errors - private static final Set INSECURE_CWE = new HashSet<>(asList("89", "78", "79", "434", "352", "601")); - private static final Set RISKY_CWE = new HashSet<>(asList("120", "22", "494", "829", "676", "131", "134", "190")); - private static final Set POROUS_CWE = new HashSet<>(asList("306", "862", "798", "311", "807", "250", "863", "732", "327", "307", "759")); - static final Map> SANS_TOP_25_CWE_MAPPING = ImmutableMap.of( - SANS_TOP_25_INSECURE_INTERACTION, INSECURE_CWE, - SANS_TOP_25_RISKY_RESOURCE, RISKY_CWE, - SANS_TOP_25_POROUS_DEFENSES, POROUS_CWE); private final Configuration config; private final boolean enableSource; 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 eafd2aed3b0..d62bf23e609 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 @@ -27,7 +27,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -42,11 +41,12 @@ import org.sonar.db.DbSession; import org.sonar.db.ResultSetIterator; import static com.google.common.base.Preconditions.checkArgument; -import static java.util.stream.Collectors.toList; import static org.sonar.api.utils.DateUtils.longToDate; import static org.sonar.db.DatabaseUtils.getLong; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_CWE_MAPPING; -import static org.sonar.server.issue.index.IssueIndexDefinition.UNKNOWN_STANDARD; +import static org.sonar.server.issue.index.SecurityStandardHelper.getCwe; +import static org.sonar.server.issue.index.SecurityStandardHelper.getOwaspTop10; +import static org.sonar.server.issue.index.SecurityStandardHelper.getSansTop25; +import static org.sonar.server.issue.index.SecurityStandardHelper.getSecurityStandards; /** * Scrolls over table ISSUES and reads documents to populate @@ -94,10 +94,7 @@ class IssueIteratorForSingleChunk implements IssueIterator { private static final String ISSUE_KEY_FILTER_SUFFIX = ")"; static final Splitter TAGS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); - static final Splitter SECURITY_STANDARDS_SPLITTER = TAGS_SPLITTER; static final Splitter MODULE_PATH_SPLITTER = Splitter.on('.').trimResults().omitEmptyStrings(); - private static final String OWASP_TOP10_PREFIX = "owaspTop10:"; - private static final String CWE_PREFIX = "cwe:"; private final DbSession session; @@ -235,23 +232,14 @@ class IssueIteratorForSingleChunk implements IssueIterator { doc.setType(RuleType.valueOf(rs.getInt(22))); String securityStandards = rs.getString(23); - List standards = IssueIteratorForSingleChunk.SECURITY_STANDARDS_SPLITTER.splitToList(securityStandards == null ? "" : securityStandards); - List owaspTop10 = standards.stream().filter(s -> s.startsWith(OWASP_TOP10_PREFIX)).map(s -> s.substring(OWASP_TOP10_PREFIX.length())).collect(toList()); - doc.setOwaspTop10(owaspTop10.isEmpty() ? Collections.singletonList(UNKNOWN_STANDARD) : owaspTop10); - List cwe = standards.stream().filter(s -> s.startsWith(CWE_PREFIX)).map(s -> s.substring(CWE_PREFIX.length())).collect(toList()); - doc.setCwe(cwe.isEmpty() ? Collections.singletonList(UNKNOWN_STANDARD) : cwe); + List standards = getSecurityStandards(securityStandards); + doc.setOwaspTop10(getOwaspTop10(standards)); + List cwe = getCwe(standards); + doc.setCwe(cwe); doc.setSansTop25(getSansTop25(cwe)); return doc; } - private static List getSansTop25(List cwe) { - return SANS_TOP_25_CWE_MAPPING - .keySet() - .stream() - .filter(k -> cwe.stream().anyMatch(SANS_TOP_25_CWE_MAPPING.get(k)::contains)) - .collect(toList()); - } - @CheckForNull private static String extractDirPath(@Nullable String filePath, String scope) { if (filePath != null) { diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardCategoryStatistics.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardCategoryStatistics.java index 291c394bd7d..de2bdd983be 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardCategoryStatistics.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardCategoryStatistics.java @@ -32,6 +32,8 @@ public class SecurityStandardCategoryStatistics { private final long openSecurityHotspots; private final long wontFixSecurityHotspots; private final List children; + private long activeRules; + private long totalRules; public SecurityStandardCategoryStatistics(String category, long vulnerabilities, OptionalInt vulnerabiliyRating, long toReviewSecurityHotspots, long openSecurityHotspots, long wontFixSecurityHotspots, @Nullable List children) { @@ -71,4 +73,22 @@ public class SecurityStandardCategoryStatistics { public List getChildren() { return children; } + + public long getActiveRules() { + return activeRules; + } + + public long getTotalRules() { + return totalRules; + } + + public SecurityStandardCategoryStatistics setActiveRules(long activeRules) { + this.activeRules = activeRules; + return this; + } + + public SecurityStandardCategoryStatistics setTotalRules(long totalRules) { + this.totalRules = totalRules; + return this; + } } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardHelper.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardHelper.java new file mode 100644 index 00000000000..cdae44ca233 --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardHelper.java @@ -0,0 +1,101 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.issue.index; + +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.toList; + +public class SecurityStandardHelper { + + public static final String UNKNOWN_STANDARD = "unknown"; + public static final String SANS_TOP_25_INSECURE_INTERACTION = "insecure-interaction"; + public static final String SANS_TOP_25_RISKY_RESOURCE = "risky-resource"; + public static final String SANS_TOP_25_POROUS_DEFENSES = "porous-defenses"; + + private static final String OWASP_TOP10_PREFIX = "owaspTop10:"; + 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")); + private static final Set RISKY_CWE = new HashSet<>(asList("120", "22", "494", "829", "676", "131", "134", "190")); + private static final Set POROUS_CWE = new HashSet<>(asList("306", "862", "798", "311", "807", "250", "863", "732", "327", "307", "759")); + + public static final Map> SANS_TOP_25_CWE_MAPPING = ImmutableMap.of( + SANS_TOP_25_INSECURE_INTERACTION, INSECURE_CWE, + SANS_TOP_25_RISKY_RESOURCE, RISKY_CWE, + SANS_TOP_25_POROUS_DEFENSES, POROUS_CWE); + + private static final Splitter SECURITY_STANDARDS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); + + private SecurityStandardHelper() { + // Utility class + } + + public static List getSecurityStandards(@Nullable String securityStandards) { + return securityStandards == null ? emptyList() : SECURITY_STANDARDS_SPLITTER.splitToList(securityStandards); + } + + public static List getSansTop25(Collection cwe) { + return SANS_TOP_25_CWE_MAPPING + .keySet() + .stream() + .filter(k -> cwe.stream().anyMatch(SANS_TOP_25_CWE_MAPPING.get(k)::contains)) + .collect(toList()); + } + + public static List getOwaspTop10(Collection securityStandards) { + List result = securityStandards.stream() + .filter(s -> s.startsWith(OWASP_TOP10_PREFIX)) + .map(s -> s.substring(OWASP_TOP10_PREFIX.length())) + .collect(toList()); + return result.isEmpty() ? singletonList(UNKNOWN_STANDARD) : result; + } + + public static List getCwe(Collection securityStandards) { + List result = securityStandards.stream() + .filter(s -> s.startsWith(CWE_PREFIX)) + .map(s -> s.substring(CWE_PREFIX.length())) + .collect(toList()); + return result.isEmpty() ? singletonList(UNKNOWN_STANDARD) : result; + } + + public static List getSansTop25(String securityStandards) { + return getSansTop25(getCwe(getSecurityStandards(securityStandards))); + } + + public static List getOwaspTop10(String securityStandards) { + return getOwaspTop10(getSecurityStandards(securityStandards)); + } + + public static List getCwe(String securityStandards) { + return getCwe(getSecurityStandards(securityStandards)); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java index 3c793a28e6e..7f370f15c16 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java @@ -57,8 +57,8 @@ import static org.junit.rules.ExpectedException.none; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.server.issue.IssueDocTesting.newDoc; import static org.sonar.server.issue.index.IssueIndexDefinition.INDEX_TYPE_ISSUE; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_POROUS_DEFENSES; -import static org.sonar.server.issue.index.IssueIndexDefinition.UNKNOWN_STANDARD; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; +import static org.sonar.server.issue.index.SecurityStandardHelper.UNKNOWN_STANDARD; import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION; public class IssueIndexerTest { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 7370d306fba..e2aee03ac57 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -143,10 +143,10 @@ import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_STAT import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_TAGS; import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_TYPE; import static org.sonar.server.issue.index.IssueIndexDefinition.INDEX_TYPE_ISSUE; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_INSECURE_INTERACTION; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_POROUS_DEFENSES; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_RISKY_RESOURCE; -import static org.sonar.server.issue.index.IssueIndexDefinition.UNKNOWN_STANDARD; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; +import static org.sonar.server.issue.index.SecurityStandardHelper.UNKNOWN_STANDARD; import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS; diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java index cdac6357f14..147b9aab680 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -73,10 +73,10 @@ import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED; import static org.sonar.server.es.SearchOptions.MAX_LIMIT; import static org.sonar.server.issue.index.IssueIndex.FACET_ASSIGNED_TO_ME; import static org.sonar.server.issue.index.IssueIndex.FACET_PROJECTS; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_INSECURE_INTERACTION; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_POROUS_DEFENSES; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_RISKY_RESOURCE; -import static org.sonar.server.issue.index.IssueIndexDefinition.UNKNOWN_STANDARD; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; +import static org.sonar.server.issue.index.SecurityStandardHelper.UNKNOWN_STANDARD; import static org.sonar.server.issue.index.IssueQuery.SORT_BY_ASSIGNEE; import static org.sonar.server.issue.index.IssueQueryFactory.UNKNOWN; import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java index 1aa86d13e5a..8dcd90ce6b8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java @@ -54,10 +54,10 @@ import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; import static org.sonar.server.issue.IssueDocTesting.newDoc; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_INSECURE_INTERACTION; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_POROUS_DEFENSES; -import static org.sonar.server.issue.index.IssueIndexDefinition.SANS_TOP_25_RISKY_RESOURCE; -import static org.sonar.server.issue.index.IssueIndexDefinition.UNKNOWN_STANDARD; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; +import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; +import static org.sonar.server.issue.index.SecurityStandardHelper.UNKNOWN_STANDARD; public class IssueIndexSecurityReportsTest {