aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/issue/index/SecurityStandardCategoryStatistics.java13
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/issue/index/SecurityStandardCategoryStatisticsTest.java14
-rw-r--r--server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java48
3 files changed, 51 insertions, 24 deletions
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 484b03f1918..903fe411831 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
@@ -20,6 +20,7 @@
package org.sonar.server.issue.index;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import javax.annotation.Nullable;
@@ -38,9 +39,11 @@ public class SecurityStandardCategoryStatistics {
private boolean hasMoreRules;
private final Optional<String> version;
private Optional<String> level = Optional.empty();
+ private final Map<String, Long> severityDistribution;
public SecurityStandardCategoryStatistics(String category, long vulnerabilities, OptionalInt vulnerabiliyRating, long toReviewSecurityHotspots,
- long reviewedSecurityHotspots, Integer securityReviewRating, @Nullable List<SecurityStandardCategoryStatistics> children, @Nullable String version) {
+ long reviewedSecurityHotspots, Integer securityReviewRating, @Nullable List<SecurityStandardCategoryStatistics> children, @Nullable String version,
+ Map<String, Long> severityDistribution) {
this.category = category;
this.vulnerabilities = vulnerabilities;
this.vulnerabilityRating = vulnerabiliyRating;
@@ -50,6 +53,7 @@ public class SecurityStandardCategoryStatistics {
this.children = children;
this.version = Optional.ofNullable(version);
this.hasMoreRules = false;
+ this.severityDistribution = severityDistribution;
}
public SecurityStandardCategoryStatistics withModifiedVulnerabilities(
@@ -71,7 +75,8 @@ public class SecurityStandardCategoryStatistics {
this.getReviewedSecurityHotspots(),
this.getSecurityReviewRating(),
this.getChildren(),
- this.getVersion().orElse(null));
+ this.getVersion().orElse(null),
+ this.getSeverityDistribution());
}
public String getCategory() {
@@ -140,4 +145,8 @@ public class SecurityStandardCategoryStatistics {
public void setHasMoreRules(boolean hasMoreRules) {
this.hasMoreRules = hasMoreRules;
}
+
+ public Map<String, Long> getSeverityDistribution() {
+ return severityDistribution;
+ }
}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/SecurityStandardCategoryStatisticsTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/SecurityStandardCategoryStatisticsTest.java
index 36638caf954..a23c45cd248 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/SecurityStandardCategoryStatisticsTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/SecurityStandardCategoryStatisticsTest.java
@@ -20,6 +20,7 @@
package org.sonar.server.issue.index;
import java.util.ArrayList;
+import java.util.Map;
import java.util.OptionalInt;
import org.junit.Test;
@@ -33,7 +34,7 @@ public class SecurityStandardCategoryStatisticsTest {
public void hasMoreRules_default_false() {
SecurityStandardCategoryStatistics standardCategoryStatistics = new SecurityStandardCategoryStatistics(
"cat", 0, empty(), 0,
- 0, 5, null, null
+ 0, 5, null, null, Map.of()
);
assertThat(standardCategoryStatistics.hasMoreRules()).isFalse();
}
@@ -42,7 +43,7 @@ public class SecurityStandardCategoryStatisticsTest {
public void hasMoreRules_is_updatable() {
SecurityStandardCategoryStatistics standardCategoryStatistics = new SecurityStandardCategoryStatistics(
"cat", 0, empty(), 0,
- 0, 5, null, null
+ 0, 5, null, null, Map.of()
);
standardCategoryStatistics.setHasMoreRules(true);
assertThat(standardCategoryStatistics.hasMoreRules()).isTrue();
@@ -52,7 +53,7 @@ public class SecurityStandardCategoryStatisticsTest {
public void test_getters() {
SecurityStandardCategoryStatistics standardCategoryStatistics = new SecurityStandardCategoryStatistics(
"cat", 1, empty(), 0,
- 0, 5, new ArrayList<>(), "version"
+ 0, 5, new ArrayList<>(), "version", Map.of()
).setLevel("1");
standardCategoryStatistics.setActiveRules(3);
@@ -71,13 +72,14 @@ public class SecurityStandardCategoryStatisticsTest {
assertThat(standardCategoryStatistics.getVersion().get()).contains("version");
assertThat(standardCategoryStatistics.getLevel().get()).contains("1");
assertThat(standardCategoryStatistics.hasMoreRules()).isFalse();
+ assertThat(standardCategoryStatistics.getSeverityDistribution()).isEmpty();
}
@Test
public void withModifiedVulnerabilities() {
SecurityStandardCategoryStatistics standardCategoryStatistics = new SecurityStandardCategoryStatistics(
"cat", 1, empty(), 0,
- 0, 5, null, null
+ 0, 5, null, null, Map.of()
);
SecurityStandardCategoryStatistics modified = standardCategoryStatistics.withModifiedVulnerabilities(2, 3);
@@ -91,7 +93,7 @@ public class SecurityStandardCategoryStatisticsTest {
public void withModifiedVulnerabilities_noNewRating() {
SecurityStandardCategoryStatistics standardCategoryStatistics = new SecurityStandardCategoryStatistics(
"cat", 1, OptionalInt.of(1), 0,
- 0, 5, null, null
+ 0, 5, null, null, Map.of()
);
SecurityStandardCategoryStatistics modified = standardCategoryStatistics.withModifiedVulnerabilities(2, null);
@@ -105,7 +107,7 @@ public class SecurityStandardCategoryStatisticsTest {
public void withModifiedVulnerabilities_usesLowestRating() {
SecurityStandardCategoryStatistics standardCategoryStatistics = new SecurityStandardCategoryStatistics(
"cat", 1, OptionalInt.of(5), 0,
- 0, 5, null, null
+ 0, 5, null, null, Map.of()
);
SecurityStandardCategoryStatistics modified = standardCategoryStatistics.withModifiedVulnerabilities(2, 3);
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 fd408c6c26a..9235bc57b1a 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
@@ -26,6 +26,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -54,6 +55,7 @@ import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.HasAggregations;
+import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.filter.FiltersAggregator;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
@@ -1292,7 +1294,7 @@ public class IssueIndex {
}
private static SecurityStandardCategoryStatistics emptyCweStatistics(String rule) {
- return new SecurityStandardCategoryStatistics(rule, 0, OptionalInt.of(1), 0, 0, 1, null, null);
+ return new SecurityStandardCategoryStatistics(rule, 0, OptionalInt.of(1), 0, 0, 1, null, null, Map.of());
}
public List<SecurityStandardCategoryStatistics> getSonarSourceReport(String projectUuid, boolean isViewOrApp, boolean includeCwe) {
@@ -1448,10 +1450,11 @@ public class IssueIndex {
Aggregation severitiesAggregations =
((ParsedFilter) categoryBucket.getAggregations().get(AGG_VULNERABILITIES)).getAggregations().get(AGG_SEVERITIES);
- CountAndRating countAndRating = getCountAndRating(severitiesAggregations);
- long vulnerabilities = countAndRating.getCount();
+ SeverityAggregationDetails severityAggregationDetails = getSeverityDetails(severitiesAggregations);
+ long vulnerabilities = severityAggregationDetails.getCount();
// Worst severity having at least one issue
- OptionalInt severityRating = countAndRating.getRating();
+ OptionalInt severityRating = severityAggregationDetails.getRating();
+ Map<String, Long> severityDistribution = severityAggregationDetails.getDistribution();
long toReviewSecurityHotspots = ((ParsedValueCount) ((ParsedFilter) categoryBucket.getAggregations().get(AGG_TO_REVIEW_SECURITY_HOTSPOTS)).getAggregations().get(AGG_COUNT))
.getValue();
@@ -1462,32 +1465,39 @@ public class IssueIndex {
Integer securityReviewRating = computeRating(percent.orElse(null)).getIndex();
return new SecurityStandardCategoryStatistics(categoryName, vulnerabilities, severityRating, toReviewSecurityHotspots,
- reviewedSecurityHotspots, securityReviewRating, children, version);
+ reviewedSecurityHotspots, securityReviewRating, children, version, severityDistribution);
}
- private CountAndRating getCountAndRating(Aggregation severitiesAggregations) {
+ private SeverityAggregationDetails getSeverityDetails(Aggregation severitiesAggregations) {
+ List<? extends Terms.Bucket> severityBuckets;
+ long vulnerabilities;
+ OptionalInt severityRating;
if (isMQRMode()) {
- List<? extends Terms.Bucket> severityBuckets =
+ severityBuckets =
((ParsedStringTerms) ((ParsedFilter) ((ParsedNested) severitiesAggregations).getAggregations().get(ISSUES_WITH_SECURITY_IMPACT)).getAggregations().get(AGG_IMPACT_SEVERITIES)).getBuckets();
- long vulnerabilities =
+ vulnerabilities =
severityBuckets.stream().mapToLong(b -> ((ParsedValueCount) b.getAggregations().get(AGG_COUNT)).getValue()).sum();
// Worst severity having at least one issue
- OptionalInt severityRating = severityBuckets.stream()
+ severityRating = severityBuckets.stream()
.filter(b -> ((ParsedValueCount) b.getAggregations().get(AGG_COUNT)).getValue() != 0)
.mapToInt(b -> org.sonar.api.issue.impact.Severity.valueOf(b.getKeyAsString()).ordinal() + 1)
.max();
- return new CountAndRating(vulnerabilities, severityRating);
} else {
- List<? extends Terms.Bucket> severityBuckets = ((ParsedStringTerms) severitiesAggregations).getBuckets();
- long vulnerabilities =
+ severityBuckets = ((ParsedStringTerms) severitiesAggregations).getBuckets();
+ vulnerabilities =
severityBuckets.stream().mapToLong(b -> ((ParsedValueCount) b.getAggregations().get(AGG_COUNT)).getValue()).sum();
// Worst severity having at least one issue
- OptionalInt severityRating = severityBuckets.stream()
+ severityRating = severityBuckets.stream()
.filter(b -> ((ParsedValueCount) b.getAggregations().get(AGG_COUNT)).getValue() != 0)
.mapToInt(b -> Severity.ALL.indexOf(b.getKeyAsString()) + 1)
.max();
- return new CountAndRating(vulnerabilities, severityRating);
}
+ Map<String, Long> severityDistribution = severityBuckets.stream()
+ .collect(Collectors.toMap(
+ e -> e.getKeyAsString().toLowerCase(Locale.US),
+ MultiBucketsAggregation.Bucket::getDocCount
+ ));
+ return new SeverityAggregationDetails(vulnerabilities, severityRating, severityDistribution);
}
private AggregationBuilder newSecurityReportSubAggregations(AggregationBuilder categoriesAggs, String securityStandardVersionPrefix) {
@@ -1578,13 +1588,15 @@ public class IssueIndex {
}
- private static class CountAndRating {
+ private static class SeverityAggregationDetails {
private long count;
private OptionalInt rating;
+ private Map<String, Long> distribution;
- public CountAndRating(long count, OptionalInt rating) {
+ public SeverityAggregationDetails(long count, OptionalInt rating, Map<String, Long> distribution) {
this.count = count;
this.rating = rating;
+ this.distribution = distribution;
}
public long getCount() {
@@ -1594,5 +1606,9 @@ public class IssueIndex {
public OptionalInt getRating() {
return rating;
}
+
+ public Map<String, Long> getDistribution() {
+ return distribution;
+ }
}
}