aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server-common/src
diff options
context:
space:
mode:
authorBelen Pruvost <belen.pruvost@sonarsource.com>2022-03-21 09:47:47 +0100
committersonartech <sonartech@sonarsource.com>2022-03-21 20:02:53 +0000
commitcd54028b99d846f7d9a0d3494dd8bcbbd998b088 (patch)
tree74626dc410cdd0472d2c6de68363bd23d7db0547 /server/sonar-server-common/src
parentc361760aa2c86f0beac22d50f4d8ec836a5142ae (diff)
downloadsonarqube-cd54028b99d846f7d9a0d3494dd8bcbbd998b088.tar.gz
sonarqube-cd54028b99d846f7d9a0d3494dd8bcbbd998b088.zip
SONAR-16130 - 'OWASP Top 10 - 2021' Facet and Filter for rules/search
Diffstat (limited to 'server/sonar-server-common/src')
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java11
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java116
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java5
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java11
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java16
5 files changed, 95 insertions, 64 deletions
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java
index a016b98be16..5ce56bdec82 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java
@@ -168,6 +168,16 @@ public class RuleDoc extends BaseDoc {
}
@CheckForNull
+ public Collection<String> getOwaspTop10For2021() {
+ return getNullableField(RuleIndexDefinition.FIELD_RULE_OWASP_TOP_10_2021);
+ }
+
+ public RuleDoc setOwaspTop10For2021(@Nullable Collection<String> o) {
+ setField(RuleIndexDefinition.FIELD_RULE_OWASP_TOP_10_2021, o);
+ return this;
+ }
+
+ @CheckForNull
public Collection<String> getSansTop25() {
return getNullableField(RuleIndexDefinition.FIELD_RULE_SANS_TOP_25);
}
@@ -290,6 +300,7 @@ public class RuleDoc extends BaseDoc {
.setLanguage(dto.getLanguage())
.setCwe(securityStandards.getCwe())
.setOwaspTop10(securityStandards.getOwaspTop10())
+ .setOwaspTop10For2021(securityStandards.getOwaspTop10For2021())
.setSansTop25(securityStandards.getSansTop25())
.setSonarSourceSecurityCategory(securityStandards.getSqCategory())
.setName(dto.getName())
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java
index 2933b7eacdc..0c2e260eeae 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndex.java
@@ -98,6 +98,7 @@ import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_KEY;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_LANGUAGE;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_NAME;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_OWASP_TOP_10;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_OWASP_TOP_10_2021;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_REPOSITORY;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_RULE_KEY;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_SANS_TOP_25;
@@ -128,6 +129,7 @@ public class RuleIndex {
public static final String FACET_CWE = "cwe";
public static final String FACET_SANS_TOP_25 = "sansTop25";
public static final String FACET_OWASP_TOP_10 = "owaspTop10";
+ public static final String FACET_OWASP_TOP_10_2021 = "owaspTop10-2021";
public static final String FACET_SONARSOURCE_SECURITY = "sonarsourceSecurity";
private static final int MAX_FACET_SIZE = 100;
@@ -215,13 +217,13 @@ public class RuleIndex {
BoolQueryBuilder textQuery = boolQuery();
JavaTokenizer.split(queryText)
.stream().map(token -> boolQuery().should(
- matchQuery(
- SEARCH_GRAMS_ANALYZER.subField(FIELD_RULE_NAME),
- StringUtils.left(token, DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH)).boost(20F))
- .should(
- matchPhraseQuery(
- ENGLISH_HTML_ANALYZER.subField(FIELD_RULE_HTML_DESCRIPTION),
- token).boost(3F)))
+ matchQuery(
+ SEARCH_GRAMS_ANALYZER.subField(FIELD_RULE_NAME),
+ StringUtils.left(token, DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH)).boost(20F))
+ .should(
+ matchPhraseQuery(
+ ENGLISH_HTML_ANALYZER.subField(FIELD_RULE_HTML_DESCRIPTION),
+ token).boost(3F)))
.forEach(textQuery::must);
qb.should(textQuery.boost(20F));
@@ -235,7 +237,7 @@ public class RuleIndex {
private static QueryBuilder termQuery(String field, String query, float boost) {
return QueryBuilders.multiMatchQuery(query,
- field, SEARCH_WORDS_ANALYZER.subField(field))
+ field, SEARCH_WORDS_ANALYZER.subField(field))
.operator(Operator.AND)
.boost(boost);
}
@@ -255,63 +257,27 @@ public class RuleIndex {
QueryBuilders.termQuery(FIELD_RULE_STATUS,
RuleStatus.REMOVED.toString())));
- if (StringUtils.isNotEmpty(query.getInternalKey())) {
- filters.put(FIELD_RULE_INTERNAL_KEY,
- QueryBuilders.termQuery(FIELD_RULE_INTERNAL_KEY, query.getInternalKey()));
- }
+ addFilter(filters, FIELD_RULE_INTERNAL_KEY, query.getInternalKey());
- if (StringUtils.isNotEmpty(query.getRuleKey())) {
- filters.put(FIELD_RULE_RULE_KEY,
- QueryBuilders.termQuery(FIELD_RULE_RULE_KEY, query.getRuleKey()));
- }
+ addFilter(filters, FIELD_RULE_RULE_KEY, query.getRuleKey());
- if (isNotEmpty(query.getLanguages())) {
- filters.put(FIELD_RULE_LANGUAGE,
- QueryBuilders.termsQuery(FIELD_RULE_LANGUAGE, query.getLanguages()));
- }
+ addFilter(filters, query.getLanguages(), FIELD_RULE_LANGUAGE);
- if (isNotEmpty(query.getRepositories())) {
- filters.put(FIELD_RULE_REPOSITORY,
- QueryBuilders.termsQuery(FIELD_RULE_REPOSITORY, query.getRepositories()));
- }
+ addFilter(filters, query.getRepositories(), FIELD_RULE_REPOSITORY);
- if (isNotEmpty(query.getSeverities())) {
- filters.put(FIELD_RULE_SEVERITY,
- QueryBuilders.termsQuery(FIELD_RULE_SEVERITY, query.getSeverities()));
- }
+ addFilter(filters, query.getSeverities(), FIELD_RULE_SEVERITY);
- if (isNotEmpty(query.getCwe())) {
- filters.put(FIELD_RULE_CWE,
- boolQuery()
- .must(QueryBuilders.termsQuery(FIELD_RULE_CWE, query.getCwe()))
- .must(QueryBuilders.termsQuery(FIELD_RULE_TYPE, VULNERABILITY.name(), SECURITY_HOTSPOT.name())));
- }
+ addSecurityStandardFilter(filters, FIELD_RULE_CWE, query.getCwe());
- if (isNotEmpty(query.getOwaspTop10())) {
- filters.put(FIELD_RULE_OWASP_TOP_10,
- boolQuery()
- .must(QueryBuilders.termsQuery(FIELD_RULE_OWASP_TOP_10, query.getOwaspTop10()))
- .must(QueryBuilders.termsQuery(FIELD_RULE_TYPE, VULNERABILITY.name(), SECURITY_HOTSPOT.name())));
- }
+ addSecurityStandardFilter(filters, FIELD_RULE_OWASP_TOP_10, query.getOwaspTop10());
- if (isNotEmpty(query.getSansTop25())) {
- filters.put(FIELD_RULE_SANS_TOP_25,
- boolQuery()
- .must(QueryBuilders.termsQuery(FIELD_RULE_SANS_TOP_25, query.getSansTop25()))
- .must(QueryBuilders.termsQuery(FIELD_RULE_TYPE, VULNERABILITY.name(), SECURITY_HOTSPOT.name())));
- }
+ addSecurityStandardFilter(filters, FIELD_RULE_OWASP_TOP_10_2021, query.getOwaspTop10For2021());
- if (isNotEmpty(query.getSonarsourceSecurity())) {
- filters.put(FIELD_RULE_SONARSOURCE_SECURITY,
- boolQuery()
- .must(QueryBuilders.termsQuery(FIELD_RULE_SONARSOURCE_SECURITY, query.getSonarsourceSecurity()))
- .must(QueryBuilders.termsQuery(FIELD_RULE_TYPE, VULNERABILITY.name(), SECURITY_HOTSPOT.name())));
- }
+ addSecurityStandardFilter(filters, FIELD_RULE_SANS_TOP_25, query.getSansTop25());
- if (StringUtils.isNotEmpty(query.getKey())) {
- filters.put(FIELD_RULE_KEY,
- QueryBuilders.termQuery(FIELD_RULE_KEY, query.getKey()));
- }
+ addSecurityStandardFilter(filters, FIELD_RULE_SONARSOURCE_SECURITY, query.getSonarsourceSecurity());
+
+ addFilter(filters, FIELD_RULE_KEY, query.getKey());
if (isNotEmpty(query.getTags())) {
filters.put(FIELD_RULE_TAGS, buildTagsFilter(query.getTags()));
@@ -384,6 +350,29 @@ public class RuleIndex {
return filters;
}
+ private static void addSecurityStandardFilter(Map<String, QueryBuilder> filters, String key, Collection<String> values) {
+ if (isNotEmpty(values)) {
+ filters.put(key,
+ boolQuery()
+ .must(QueryBuilders.termsQuery(key, values))
+ .must(QueryBuilders.termsQuery(FIELD_RULE_TYPE, VULNERABILITY.name(), SECURITY_HOTSPOT.name())));
+ }
+ }
+
+ private static void addFilter(Map<String, QueryBuilder> filters, Collection<String> key, String value) {
+ if (isNotEmpty(key)) {
+ filters.put(value,
+ QueryBuilders.termsQuery(value, key));
+ }
+ }
+
+ private static void addFilter(Map<String, QueryBuilder> filters, String key, String value) {
+ if (StringUtils.isNotEmpty(value)) {
+ filters.put(key,
+ QueryBuilders.termQuery(key, value));
+ }
+ }
+
private static BoolQueryBuilder buildTagsFilter(Collection<String> tags) {
BoolQueryBuilder q = boolQuery();
for (String tag : tags) {
@@ -476,10 +465,10 @@ public class RuleIndex {
private static Function<TermsAggregationBuilder, AggregationBuilder> filterSecurityCategories() {
return termsAggregation -> AggregationBuilders.filter(
- "filter_by_rule_types_" + termsAggregation.getName(),
- termsQuery(FIELD_RULE_TYPE,
- VULNERABILITY.name(),
- SECURITY_HOTSPOT.name()))
+ "filter_by_rule_types_" + termsAggregation.getName(),
+ termsQuery(FIELD_RULE_TYPE,
+ VULNERABILITY.name(),
+ SECURITY_HOTSPOT.name()))
.subAggregation(termsAggregation);
}
@@ -499,6 +488,13 @@ public class RuleIndex {
FACET_DEFAULT_SIZE, filterSecurityCategories(),
(categories == null) ? (new String[0]) : categories.toArray()));
}
+ if (options.getFacets().contains(FACET_OWASP_TOP_10_2021)) {
+ Collection<String> categories = query.getOwaspTop10For2021();
+ aggregations.put(FACET_OWASP_TOP_10_2021,
+ stickyFacetBuilder.buildStickyFacet(FIELD_RULE_OWASP_TOP_10_2021, FACET_OWASP_TOP_10_2021,
+ FACET_DEFAULT_SIZE, filterSecurityCategories(),
+ (categories == null) ? (new String[0]) : categories.toArray()));
+ }
if (options.getFacets().contains(FACET_SANS_TOP_25)) {
Collection<String> categories = query.getSansTop25();
aggregations.put(FACET_SANS_TOP_25,
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
index 23b0b2a2693..63b5330cbc6 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
@@ -21,6 +21,7 @@ package org.sonar.server.rule.index;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
+import javax.inject.Inject;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.server.es.Index;
@@ -37,8 +38,6 @@ import static org.sonar.server.es.newindex.DefaultIndexSettingsElement.SORTABLE_
import static org.sonar.server.es.newindex.SettingsConfiguration.MANUAL_REFRESH_INTERVAL;
import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
-import javax.inject.Inject;
-
/**
* Definition of ES index "rules", including settings and fields.
*/
@@ -64,6 +63,7 @@ public class RuleIndexDefinition implements IndexDefinition {
public static final String FIELD_RULE_UPDATED_AT = "updatedAt";
public static final String FIELD_RULE_CWE = "cwe";
public static final String FIELD_RULE_OWASP_TOP_10 = "owaspTop10";
+ public static final String FIELD_RULE_OWASP_TOP_10_2021 = "owaspTop10-2021";
public static final String FIELD_RULE_SANS_TOP_25 = "sansTop25";
public static final String FIELD_RULE_SONARSOURCE_SECURITY = "sonarsourceSecurity";
public static final String FIELD_RULE_TAGS = "tags";
@@ -146,6 +146,7 @@ public class RuleIndexDefinition implements IndexDefinition {
ruleMapping.keywordFieldBuilder(FIELD_RULE_CWE).disableNorms().build();
ruleMapping.keywordFieldBuilder(FIELD_RULE_OWASP_TOP_10).disableNorms().build();
+ ruleMapping.keywordFieldBuilder(FIELD_RULE_OWASP_TOP_10_2021).disableNorms().build();
ruleMapping.keywordFieldBuilder(FIELD_RULE_SANS_TOP_25).disableNorms().build();
ruleMapping.keywordFieldBuilder(FIELD_RULE_SONARSOURCE_SECURITY).disableNorms().build();
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java
index 57867a732eb..54c9116d62d 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleQuery.java
@@ -54,6 +54,7 @@ public class RuleQuery {
private String ruleKey;
private boolean includeExternal;
private Collection<String> owaspTop10;
+ private Collection<String> owaspTop10For2021;
private Collection<String> sansTop25;
private Collection<String> cwe;
private Collection<String> sonarsourceSecurity;
@@ -308,6 +309,16 @@ public class RuleQuery {
}
@CheckForNull
+ public Collection<String> getOwaspTop10For2021() {
+ return owaspTop10For2021;
+ }
+
+ public RuleQuery setOwaspTop10For2021(@Nullable Collection<String> owaspTop10For2021) {
+ this.owaspTop10For2021 = owaspTop10For2021;
+ return this;
+ }
+
+ @CheckForNull
public Collection<String> getSansTop25() {
return sansTop25;
}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
index 511ec5c6b54..8f367c1069d 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
@@ -458,7 +458,7 @@ public class RuleIndexTest {
}
@Test
- public void search_by_security_owaspTop10_return_vulnerabilities_and_hotspots_only() {
+ public void search_by_security_owaspTop10_2017_return_vulnerabilities_and_hotspots_only() {
RuleDefinitionDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10:a10", "cwe:543")), r -> r.setType(VULNERABILITY));
RuleDefinitionDto rule2 = createRule(setSecurityStandards(of("owaspTop10:a10", "cwe:543")), r -> r.setType(SECURITY_HOTSPOT));
createRule(setSecurityStandards(of("cwe:543")), r -> r.setType(CODE_SMELL));
@@ -470,6 +470,18 @@ public class RuleIndexTest {
}
@Test
+ public void search_by_security_owaspTop10_2021_return_vulnerabilities_and_hotspots_only() {
+ RuleDefinitionDto rule1 = createRule(setSecurityStandards(of("owaspTop10-2021:a1", "owaspTop10-2021:a10", "cwe:543")), r -> r.setType(VULNERABILITY));
+ RuleDefinitionDto rule2 = createRule(setSecurityStandards(of("owaspTop10-2021:a10", "cwe:543")), r -> r.setType(SECURITY_HOTSPOT));
+ createRule(setSecurityStandards(of("cwe:543")), r -> r.setType(CODE_SMELL));
+ index();
+
+ RuleQuery query = new RuleQuery().setOwaspTop10For2021(of("a5", "a10"));
+ SearchIdResult<String> results = underTest.search(query, new SearchOptions().addFacets("owaspTop10-2021"));
+ assertThat(results.getUuids()).containsOnly(rule1.getUuid(), rule2.getUuid());
+ }
+
+ @Test
public void search_by_security_sansTop25_return_vulnerabilities_and_hotspots_only() {
RuleDefinitionDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10:a10", "cwe:89")), r -> r.setType(VULNERABILITY));
RuleDefinitionDto rule2 = createRule(setSecurityStandards(of("owaspTop10:a10", "cwe:829")), r -> r.setType(SECURITY_HOTSPOT));
@@ -483,7 +495,7 @@ public class RuleIndexTest {
@Test
public void search_by_security_sonarsource_return_vulnerabilities_and_hotspots_only() {
- RuleDefinitionDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10:a10", "cwe:89")), r -> r.setType(VULNERABILITY));
+ RuleDefinitionDto rule1 = createRule(setSecurityStandards(of("owaspTop10:a1", "owaspTop10-2021:a10", "cwe:89")), r -> r.setType(VULNERABILITY));
createRule(setSecurityStandards(of("owaspTop10:a10", "cwe:829")), r -> r.setType(CODE_SMELL));
RuleDefinitionDto rule3 = createRule(setSecurityStandards(of("cwe:601")), r -> r.setType(SECURITY_HOTSPOT));
index();