aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-es
diff options
context:
space:
mode:
authorLukasz Jarocki <lukasz.jarocki@sonarsource.com>2022-03-17 13:41:53 +0100
committersonartech <sonartech@sonarsource.com>2022-03-17 20:03:09 +0000
commitf2dd2183a8b1bb62df037fe81d328c9382b4dd8e (patch)
tree5ff7d8db4af7e1afe894664c789ab917593a84d1 /server/sonar-webserver-es
parent9101c69bb7feacb3613c52c796268cea69e2dda5 (diff)
downloadsonarqube-f2dd2183a8b1bb62df037fe81d328c9382b4dd8e.tar.gz
sonarqube-f2dd2183a8b1bb62df037fe81d328c9382b4dd8e.zip
SONAR-16128 SONAR-16126 Update Security PDF Report with OWASP Top 10 and CWE 2021 data
Co-authored-by: Belén Pruvost <belen.pruvost@sonarsource.com>
Diffstat (limited to 'server/sonar-webserver-es')
-rw-r--r--server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java22
-rw-r--r--server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java12
-rw-r--r--server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java13
-rw-r--r--server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryTest.java37
4 files changed, 53 insertions, 31 deletions
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 d8f727ac9e2..05565abc278 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
@@ -68,6 +68,7 @@ import org.joda.time.Duration;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
+import org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.core.util.stream.MoreCollectors;
@@ -104,6 +105,7 @@ import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT;
import static org.sonar.api.rules.RuleType.VULNERABILITY;
+import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2021;
import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
import static org.sonar.server.es.BaseDoc.epochMillisToEpochSeconds;
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars;
@@ -122,6 +124,7 @@ 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.MODULE_UUIDS;
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.PROJECT_UUIDS;
import static org.sonar.server.issue.index.IssueIndex.Facet.RESOLUTIONS;
import static org.sonar.server.issue.index.IssueIndex.Facet.RULES;
@@ -151,6 +154,7 @@ import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_MODU
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_NEW_CODE_REFERENCE;
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_PROJECT_UUID;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_RULE_UUID;
@@ -180,6 +184,7 @@ 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_TOP_10;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10_2021;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SANS_TOP_25;
@@ -245,6 +250,7 @@ public class IssueIndex {
ASSIGNEES(PARAM_ASSIGNEES, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, MAX_FACET_SIZE),
ASSIGNED_TO_ME(FACET_ASSIGNED_TO_ME, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, 1),
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),
CWE(PARAM_CWE, FIELD_ISSUE_CWE, STICKY, DEFAULT_FACET_SIZE),
CREATED_AT(PARAM_CREATED_AT, FIELD_ISSUE_FUNC_CREATED_AT, NON_STICKY),
@@ -444,6 +450,7 @@ public class IssueIndex {
// security category
addSecurityCategoryFilter(FIELD_ISSUE_OWASP_TOP_10, OWASP_TOP_10, query.owaspTop10(), filters);
+ addSecurityCategoryFilter(FIELD_ISSUE_OWASP_TOP_10_2021, OWASP_TOP_10_2021, query.owaspTop10For2021(), filters);
addSecurityCategoryFilter(FIELD_ISSUE_SANS_TOP_25, SANS_TOP_25, query.sansTop25(), filters);
addSecurityCategoryFilter(FIELD_ISSUE_CWE, CWE, query.cwe(), filters);
addSecurityCategoryFilter(FIELD_ISSUE_SQ_SECURITY_CATEGORY, SONARSOURCE_SECURITY, query.sonarsourceSecurity(), filters);
@@ -1043,7 +1050,7 @@ public class IssueIndex {
AggregationBuilders.filter(sansCategory, boolQuery().filter(termQuery(FIELD_ISSUE_SANS_TOP_25, sansCategory))),
includeCwe,
SecurityStandards.CWES_BY_SANS_TOP_25.get(sansCategory))));
- return processSecurityReportSearchResults(request, includeCwe);
+ return search(request, includeCwe);
}
public List<SecurityStandardCategoryStatistics> getCweTop25Reports(String projectUuid, boolean isViewOrApp) {
@@ -1054,7 +1061,7 @@ public class IssueIndex {
AggregationBuilders.filter(cweYear, boolQuery().filter(existsQuery(FIELD_ISSUE_CWE))),
true,
CWES_BY_CWE_TOP_25.get(cweYear))));
- List<SecurityStandardCategoryStatistics> result = processSecurityReportSearchResults(request, true);
+ List<SecurityStandardCategoryStatistics> result = search(request, true);
for (SecurityStandardCategoryStatistics cweReport : result) {
Set<String> foundRules = cweReport.getChildren().stream()
.map(SecurityStandardCategoryStatistics::getCategory)
@@ -1078,21 +1085,22 @@ public class IssueIndex {
AggregationBuilders.filter(sonarsourceCategory.getKey(), boolQuery().filter(termQuery(FIELD_ISSUE_SQ_SECURITY_CATEGORY, sonarsourceCategory.getKey()))),
includeCwe,
SecurityStandards.CWES_BY_SQ_CATEGORY.get(sonarsourceCategory))));
- return processSecurityReportSearchResults(request, includeCwe);
+ return search(request, includeCwe);
}
- public List<SecurityStandardCategoryStatistics> getOwaspTop10Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) {
+ public List<SecurityStandardCategoryStatistics> getOwaspTop10Report(String projectUuid, boolean isViewOrApp, boolean includeCwe, OwaspTop10Version version) {
+ String queryKey = version == Y2021 ? FIELD_ISSUE_OWASP_TOP_10_2021 : FIELD_ISSUE_OWASP_TOP_10;
SearchSourceBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp);
IntStream.rangeClosed(1, 10).mapToObj(i -> "a" + i)
.forEach(owaspCategory -> request.aggregation(
newSecurityReportSubAggregations(
- AggregationBuilders.filter(owaspCategory, boolQuery().filter(termQuery(FIELD_ISSUE_OWASP_TOP_10, owaspCategory))),
+ AggregationBuilders.filter(owaspCategory, boolQuery().filter(termQuery(queryKey, owaspCategory))),
includeCwe,
null)));
- return processSecurityReportSearchResults(request, includeCwe);
+ return search(request, includeCwe);
}
- private List<SecurityStandardCategoryStatistics> processSecurityReportSearchResults(SearchSourceBuilder sourceBuilder, boolean includeCwe) {
+ private List<SecurityStandardCategoryStatistics> search(SearchSourceBuilder sourceBuilder, boolean includeCwe) {
SearchRequest request = EsClient.prepareSearch(TYPE_ISSUE.getMainType())
.source(sourceBuilder);
SearchResponse response = client.search(request);
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 4ab90d7e47d..24b1ecb69c1 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
@@ -81,6 +81,7 @@ public class IssueQuery {
private final Collection<String> tags;
private final Collection<String> types;
private final Collection<String> owaspTop10;
+ private final Collection<String> owaspTop10For2021;
private final Collection<String> sansTop25;
private final Collection<String> cwe;
private final Collection<String> sonarsourceSecurity;
@@ -121,6 +122,7 @@ public class IssueQuery {
this.tags = defaultCollection(builder.tags);
this.types = defaultCollection(builder.types);
this.owaspTop10 = defaultCollection(builder.owaspTop10);
+ this.owaspTop10For2021 = defaultCollection(builder.owaspTop10For2021);
this.sansTop25 = defaultCollection(builder.sansTop25);
this.cwe = defaultCollection(builder.cwe);
this.sonarsourceSecurity = defaultCollection(builder.sonarsourceSecurity);
@@ -221,6 +223,10 @@ public class IssueQuery {
return owaspTop10;
}
+ public Collection<String> owaspTop10For2021() {
+ return owaspTop10For2021;
+ }
+
public Collection<String> sansTop25() {
return sansTop25;
}
@@ -334,6 +340,7 @@ public class IssueQuery {
private Collection<String> tags;
private Collection<String> types;
private Collection<String> owaspTop10;
+ private Collection<String> owaspTop10For2021;
private Collection<String> sansTop25;
private Collection<String> cwe;
private Collection<String> sonarsourceSecurity;
@@ -457,6 +464,11 @@ public class IssueQuery {
return this;
}
+ public Builder owaspTop10For2021(@Nullable Collection<String> o) {
+ this.owaspTop10For2021 = o;
+ return this;
+ }
+
public Builder sansTop25(@Nullable Collection<String> s) {
this.sansTop25 = s;
return this;
diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java
index 34ae01c8306..51c0e47ec57 100644
--- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java
+++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java
@@ -48,6 +48,7 @@ import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2017;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.server.issue.IssueDocTesting.newDoc;
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION;
@@ -79,7 +80,7 @@ public class IssueIndexSecurityReportsTest {
newDoc("anotherProject", another).setOwaspTop10(singletonList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
newDoc("openvul1", project).setOwaspTop10(singletonList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating)
@@ -96,7 +97,7 @@ public class IssueIndexSecurityReportsTest {
newDoc("notopenvul", project).setOwaspTop10(asList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_FIXED)
.setSeverity(Severity.BLOCKER));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating)
@@ -111,7 +112,7 @@ public class IssueIndexSecurityReportsTest {
// Previous vulnerabilities in projects that are not reanalyzed will have no owasp nor cwe attributes (not even 'unknown')
newDoc("openvulNotReindexed", project).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating)
@@ -127,7 +128,7 @@ public class IssueIndexSecurityReportsTest {
newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
newDoc("anotherProject", another).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
.contains(
@@ -142,7 +143,7 @@ public class IssueIndexSecurityReportsTest {
newDoc("closedHotspot", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FIXED));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
.contains(
@@ -196,7 +197,7 @@ public class IssueIndexSecurityReportsTest {
.setResolution(Issue.RESOLUTION_FIXED),
newDoc("notowasphotspot", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe, Y2017);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
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 c1e45e44f30..b99c33d67b2 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
@@ -20,8 +20,8 @@
package org.sonar.server.issue.index;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
import java.util.Date;
+import java.util.List;
import org.junit.Test;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.Severity;
@@ -29,7 +29,6 @@ import org.sonar.core.util.Uuids;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.issue.index.IssueQuery.PeriodStart;
-import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
@@ -40,21 +39,22 @@ public class IssueQueryTest {
RuleDefinitionDto rule = new RuleDefinitionDto().setUuid(Uuids.createFast());
PeriodStart filterDate = new IssueQuery.PeriodStart(new Date(10_000_000_000L), false);
IssueQuery query = IssueQuery.builder()
- .issueKeys(newArrayList("ABCDE"))
- .severities(newArrayList(Severity.BLOCKER))
- .statuses(Lists.newArrayList(Issue.STATUS_RESOLVED))
- .resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE))
- .projectUuids(newArrayList("PROJECT"))
- .componentUuids(newArrayList("org/struts/Action.java"))
- .moduleUuids(newArrayList("org.struts:core"))
- .rules(newArrayList(rule))
- .assigneeUuids(newArrayList("gargantua"))
- .languages(newArrayList("xoo"))
- .tags(newArrayList("tag1", "tag2"))
- .types(newArrayList("RELIABILITY", "SECURITY"))
- .owaspTop10(newArrayList("a1", "a2"))
- .sansTop25(newArrayList("insecure-interaction", "porous-defenses"))
- .cwe(newArrayList("12", "125"))
+ .issueKeys(List.of("ABCDE"))
+ .severities(List.of(Severity.BLOCKER))
+ .statuses(List.of(Issue.STATUS_RESOLVED))
+ .resolutions(List.of(Issue.RESOLUTION_FALSE_POSITIVE))
+ .projectUuids(List.of("PROJECT"))
+ .componentUuids(List.of("org/struts/Action.java"))
+ .moduleUuids(List.of("org.struts:core"))
+ .rules(List.of(rule))
+ .assigneeUuids(List.of("gargantua"))
+ .languages(List.of("xoo"))
+ .tags(List.of("tag1", "tag2"))
+ .types(List.of("RELIABILITY", "SECURITY"))
+ .owaspTop10(List.of("a1", "a2"))
+ .owaspTop10For2021(List.of("a3", "a4"))
+ .sansTop25(List.of("insecure-interaction", "porous-defenses"))
+ .cwe(List.of("12", "125"))
.branchUuid("my_branch")
.createdAfterByProjectUuids(ImmutableMap.of("PROJECT", filterDate))
.assigned(true)
@@ -77,6 +77,7 @@ public class IssueQueryTest {
assertThat(query.tags()).containsOnly("tag1", "tag2");
assertThat(query.types()).containsOnly("RELIABILITY", "SECURITY");
assertThat(query.owaspTop10()).containsOnly("a1", "a2");
+ assertThat(query.owaspTop10For2021()).containsOnly("a3", "a4");
assertThat(query.sansTop25()).containsOnly("insecure-interaction", "porous-defenses");
assertThat(query.cwe()).containsOnly("12", "125");
assertThat(query.branchUuid()).isEqualTo("my_branch");
@@ -94,7 +95,7 @@ public class IssueQueryTest {
@Test
public void build_query_without_dates() {
IssueQuery query = IssueQuery.builder()
- .issueKeys(newArrayList("ABCDE"))
+ .issueKeys(List.of("ABCDE"))
.createdAfter(null)
.createdBefore(null)
.createdAt(null)