aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2018-07-11 13:14:07 +0200
committerSonarTech <sonartech@sonarsource.com>2018-07-17 20:21:25 +0200
commitc5840ddb4b2138e02aa18275a81c2c16679520eb (patch)
tree69e2ff5d35f1267940dcaed1e3917fbe537061bd /server
parentd4b8f895197f7044a68377d47a7bf559c8116a05 (diff)
downloadsonarqube-c5840ddb4b2138e02aa18275a81c2c16679520eb.tar.gz
sonarqube-c5840ddb4b2138e02aa18275a81c2c16679520eb.zip
SONAR-10978 Fix support of branches and applications for security reports
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndex.java24
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java57
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/securityreport/ws/ShowAction.java21
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/securityreport/ws/ShowActionTest.java44
4 files changed, 128 insertions, 18 deletions
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndex.java
index a9794254c77..48bbecfb3c3 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndex.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndex.java
@@ -798,8 +798,8 @@ public class IssueIndex {
.collect(MoreCollectors.toList(branchUuids.size()));
}
- public List<SecurityStandardCategoryStatistics> getSansTop25Report(String projectUuid, boolean includeCwe) {
- SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid);
+ public List<SecurityStandardCategoryStatistics> getSansTop25Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) {
+ SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp);
Stream.of(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES).forEach(sansCategory -> {
AggregationBuilder sansCategoryAggs = AggregationBuilders
.filter(sansCategory, boolQuery()
@@ -809,8 +809,8 @@ public class IssueIndex {
return processSecurityReportSearchResults(request, includeCwe);
}
- public List<SecurityStandardCategoryStatistics> getOwaspTop10Report(String projectUuid, boolean includeCwe) {
- SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid);
+ public List<SecurityStandardCategoryStatistics> getOwaspTop10Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) {
+ SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp);
Stream.concat(IntStream.rangeClosed(1, 10).mapToObj(i -> "a" + i), Stream.of(UNKNOWN_STANDARD)).forEach(owaspCategory -> {
AggregationBuilder owaspCategoryAggs = AggregationBuilders
.filter(owaspCategory, boolQuery()
@@ -898,11 +898,21 @@ public class IssueIndex {
AggregationBuilders.count("count").field(IssueIndexDefinition.FIELD_ISSUE_KEY)));
}
- private SearchRequestBuilder prepareNonClosedVulnerabilitiesAndHotspotSearch(String projectUuid) {
+ private SearchRequestBuilder prepareNonClosedVulnerabilitiesAndHotspotSearch(String projectUuid, boolean isViewOrApp) {
+ BoolQueryBuilder componentFilter = boolQuery();
+ if (isViewOrApp) {
+ componentFilter.filter(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_BRANCH_UUID,
+ new TermsLookup(
+ ViewIndexDefinition.INDEX_TYPE_VIEW.getIndex(),
+ ViewIndexDefinition.INDEX_TYPE_VIEW.getType(),
+ projectUuid,
+ ViewIndexDefinition.FIELD_PROJECTS)));
+ } else {
+ componentFilter.filter(termQuery(IssueIndexDefinition.FIELD_ISSUE_BRANCH_UUID, projectUuid));
+ }
return client.prepareSearch(IssueIndexDefinition.INDEX_TYPE_ISSUE)
.setQuery(
- boolQuery()
- .filter(termQuery(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectUuid))
+ componentFilter
.filter(termsQuery(IssueIndexDefinition.FIELD_ISSUE_TYPE, RuleType.SECURITY_HOTSPOT.name(), RuleType.VULNERABILITY.name()))
.mustNot(termQuery(IssueIndexDefinition.FIELD_ISSUE_STATUS, Issue.STATUS_CLOSED)))
.setSize(0);
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java
index ea07a6587bf..eddde5f4622 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java
@@ -1459,7 +1459,7 @@ public class IssueIndexTest {
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);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating)
@@ -1477,7 +1477,7 @@ public class IssueIndexTest {
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);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating)
@@ -1493,7 +1493,7 @@ public class IssueIndexTest {
// 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);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating)
@@ -1510,7 +1510,7 @@ public class IssueIndexTest {
newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN),
newDoc("anotherProject", another).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getOpenSecurityHotspots)
.contains(
@@ -1526,7 +1526,7 @@ public class IssueIndexTest {
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);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getOpenSecurityHotspots)
.contains(
@@ -1583,7 +1583,7 @@ public class IssueIndexTest {
.setResolution(Issue.RESOLUTION_WONT_FIX),
newDoc("notowasphotspot", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
- List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), includeCwe);
+ List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
@@ -1627,7 +1627,7 @@ public class IssueIndexTest {
.setResolution(Issue.RESOLUTION_WONT_FIX),
newDoc("notowasphotspot", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
- List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(project.uuid(), false);
+ List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(project.uuid(), false, false);
assertThat(sansTop25Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
@@ -1641,6 +1641,49 @@ public class IssueIndexTest {
assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
}
+ @Test
+ public void test_getSansTop25Report_aggregation_on_portfolio() {
+ ComponentDto portfolio1 = db.components().insertPrivateApplication(db.getDefaultOrganization());
+ ComponentDto portfolio2 = db.components().insertPrivateApplication(db.getDefaultOrganization());
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+
+ indexIssues(
+ newDoc("openvul1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
+ .setSeverity(Severity.MAJOR),
+ newDoc("openvul2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
+ .setSeverity(Severity.MINOR),
+ newDoc("notopenvul", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
+ .setResolution(Issue.RESOLUTION_FIXED)
+ .setSeverity(Severity.BLOCKER),
+ newDoc("notsansvul", project2).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
+ .setSeverity(Severity.CRITICAL),
+ newDoc("openhotspot1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT)
+ .setStatus(Issue.STATUS_OPEN),
+ newDoc("openhotspot2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT)
+ .setStatus(Issue.STATUS_REOPENED),
+ newDoc("toReviewHotspot", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
+ .setResolution(Issue.RESOLUTION_FIXED),
+ newDoc("WFHotspot", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
+ .setResolution(Issue.RESOLUTION_WONT_FIX),
+ newDoc("notowasphotspot", project1).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
+
+ indexView(portfolio1.uuid(), singletonList(project1.uuid()));
+ indexView(portfolio2.uuid(), singletonList(project2.uuid()));
+
+ List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(portfolio1.uuid(), true, false);
+ assertThat(sansTop25Report)
+ .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
+ SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
+ SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
+ .containsExactlyInAnyOrder(
+ tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* openhotspot1 */, 0L, 0L),
+ tuple(SANS_TOP_25_RISKY_RESOURCE, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* openhotspot1 */, 1L /* toReviewHotspot */, 0L),
+ tuple(SANS_TOP_25_POROUS_DEFENSES, 0L, OptionalInt.empty(), 0L, 0L, 0L));
+
+ assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
+ }
+
private void addIssues(ComponentDto component, int bugs, int vulnerabilities, int codeSmelles) {
List<IssueDoc> issues = new ArrayList<>();
IntStream.range(0, bugs).forEach(b -> issues.add(newDoc(component).setType(BUG).setResolution(null)));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/securityreport/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/securityreport/ws/ShowAction.java
index 5f5ea130375..280e9100227 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/securityreport/ws/ShowAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/securityreport/ws/ShowAction.java
@@ -21,6 +21,7 @@ package org.sonar.server.securityreport.ws;
import java.util.List;
import java.util.function.Function;
+import org.sonar.api.resources.Qualifiers;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
@@ -72,7 +73,7 @@ public class ShowAction implements SecurityReportsWsAction {
.setInternal(true);
action.createParam(PARAM_PROJECT)
- .setDescription("Project key")
+ .setDescription("Project, view or application key")
.setRequired(true);
action.createParam(PARAM_BRANCH)
.setDescription("Branch name")
@@ -95,18 +96,32 @@ public class ShowAction implements SecurityReportsWsAction {
projectDto = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, request.param(PARAM_BRANCH), null);
}
userSession.checkComponentPermission(USER, projectDto);
+ String qualifier = projectDto.qualifier();
+ boolean isViewOrApp;
+ switch (qualifier) {
+ case Qualifiers.VIEW:
+ case Qualifiers.SUBVIEW:
+ case Qualifiers.APP:
+ isViewOrApp = true;
+ break;
+ case Qualifiers.PROJECT:
+ isViewOrApp = false;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported component type " + qualifier);
+ }
String standard = request.mandatoryParam(PARAM_STANDARD);
boolean includeCwe = request.mandatoryParamAsBoolean(PARAM_INCLUDE_DISTRIBUTION);
switch (standard) {
case PARAM_OWASP_TOP_10:
- List<SecurityStandardCategoryStatistics> owaspCategories = issueIndex.getOwaspTop10Report(projectDto.uuid(), includeCwe)
+ List<SecurityStandardCategoryStatistics> owaspCategories = issueIndex.getOwaspTop10Report(projectDto.uuid(), isViewOrApp, includeCwe)
.stream()
.sorted(comparing(ShowAction::index))
.collect(toList());
writeResponse(request, response, owaspCategories);
break;
case PARAM_SANS_TOP_25:
- writeResponse(request, response, issueIndex.getSansTop25Report(projectDto.uuid(), includeCwe));
+ writeResponse(request, response, issueIndex.getSansTop25Report(projectDto.uuid(), isViewOrApp, includeCwe));
break;
default:
throw new IllegalArgumentException("Unsupported standard: '" + standard + "'");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/securityreport/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/securityreport/ws/ShowActionTest.java
index 9cd3054a64f..d87519555ee 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/securityreport/ws/ShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/securityreport/ws/ShowActionTest.java
@@ -207,7 +207,6 @@ public class ShowActionTest {
@Test
public void sans_with_cwe() {
-
ComponentDto project = insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "PROJECT_ID").setDbKey("PROJECT_KEY"));
userSessionRule.addProjectPermission(UserRole.USER, project);
indexPermissions();
@@ -244,6 +243,49 @@ public class ShowActionTest {
.isSimilarTo(this.getClass().getResource("ShowActionTest/sansWithCwe.json"));
}
+ @Test
+ public void sans_with_cwe_for_branches() {
+ ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1"));
+ ComponentDto project1Branch1 = db.components().insertProjectBranch(project1);
+ ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1));
+ ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2"));
+
+ userSessionRule.addProjectPermission(UserRole.USER, project1);
+ userSessionRule.addProjectPermission(UserRole.USER, project2);
+ indexPermissions();
+ RuleDefinitionDto rule = newRule();
+ IssueDto issue1 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
+ .setStatus("OPEN")
+ .setSeverity("MAJOR")
+ .setType(RuleType.VULNERABILITY);
+ IssueDto issue2 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
+ .setStatus("OPEN")
+ .setSeverity("MAJOR")
+ .setType(RuleType.SECURITY_HOTSPOT);
+ IssueDto issue3 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
+ .setStatus(Issue.STATUS_RESOLVED)
+ .setResolution(Issue.RESOLUTION_FIXED)
+ .setSeverity("MAJOR")
+ .setType(RuleType.SECURITY_HOTSPOT);
+ IssueDto issue4 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
+ .setStatus(Issue.STATUS_RESOLVED)
+ .setResolution(Issue.RESOLUTION_WONT_FIX)
+ .setSeverity("MAJOR")
+ .setType(RuleType.SECURITY_HOTSPOT);
+ dbClient.issueDao().insert(session, issue1, issue2, issue3, issue4);
+ session.commit();
+ indexIssues();
+
+ assertJson(ws.newRequest()
+ .setParam("standard", "sansTop25")
+ .setParam("project", project1Branch1.getKey())
+ .setParam("branch", project1Branch1.getBranch())
+ .setParam("includeDistribution", "true")
+ .execute().getInput())
+ .withStrictArrayOrder()
+ .isSimilarTo(this.getClass().getResource("ShowActionTest/sansWithCwe.json"));
+ }
+
private RuleDefinitionDto newRule() {
RuleDefinitionDto rule = RuleTesting.newRule()