diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2019-04-30 14:51:54 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2019-05-07 09:54:29 +0200 |
commit | 78ac82da528beca83055beba26e9d96aec79d80e (patch) | |
tree | 84a7b2661ed5f91d4f33f0a6fa86fa79e2cbcd84 | |
parent | 86fa76012f7a9a566c581d9fbd712b9aead5a4a2 (diff) | |
download | sonarqube-78ac82da528beca83055beba26e9d96aec79d80e.tar.gz sonarqube-78ac82da528beca83055beba26e9d96aec79d80e.zip |
SONAR-11825 Don't return activeRules and rules for applications and portfolios
3 files changed, 251 insertions, 30 deletions
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 344a8d4d170..03bc4d8b856 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 @@ -38,9 +38,9 @@ import org.sonar.db.rule.RuleDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.SecurityStandardCategoryStatistics; -import org.sonar.server.security.SecurityStandardHelper; import org.sonar.server.qualityprofile.QPMeasureData; import org.sonar.server.qualityprofile.QualityProfile; +import org.sonar.server.security.SecurityStandardHelper; import org.sonar.server.user.UserSession; import org.sonarqube.ws.SecurityReports; @@ -132,31 +132,31 @@ public class ShowAction implements SecurityReportsWsAction { } String standard = request.mandatoryParam(PARAM_STANDARD); boolean includeCwe = request.mandatoryParamAsBoolean(PARAM_INCLUDE_DISTRIBUTION); + List<SecurityStandardCategoryStatistics> statistics; switch (standard) { case PARAM_OWASP_TOP_10: - List<SecurityStandardCategoryStatistics> owaspCategories = issueIndex.getOwaspTop10Report(projectDto.uuid(), isViewOrApp, includeCwe) + statistics = issueIndex.getOwaspTop10Report(projectDto.uuid(), isViewOrApp, includeCwe) .stream() .sorted(comparing(ShowAction::index)) .collect(toList()); - completeStatistics(owaspCategories, projectDto, standard, includeCwe); - writeResponse(request, response, owaspCategories); break; case PARAM_SANS_TOP_25: - List<SecurityStandardCategoryStatistics> sansTop25Report = issueIndex.getSansTop25Report(projectDto.uuid(), isViewOrApp, includeCwe); - completeStatistics(sansTop25Report, projectDto, standard, includeCwe); - writeResponse(request, response, sansTop25Report); + statistics = issueIndex.getSansTop25Report(projectDto.uuid(), isViewOrApp, includeCwe); break; case PARAM_SONARSOURCE_SECURITY: - List<SecurityStandardCategoryStatistics> sonarSourceReport = issueIndex.getSonarSourceReport(projectDto.uuid(), isViewOrApp, includeCwe); - completeStatistics(sonarSourceReport, projectDto, standard, includeCwe); - writeResponse(request, response, sonarSourceReport); + statistics = issueIndex.getSonarSourceReport(projectDto.uuid(), isViewOrApp, includeCwe); break; default: throw new IllegalArgumentException(String.format(UNSUPPORTED_STANDARD_MSG, standard)); } + if (!isViewOrApp) { + // App and Portfolios don't have a quality profile + completeRulesStatistics(statistics, projectDto, standard, includeCwe); + } + writeResponse(request, response, statistics, isViewOrApp); } - private void completeStatistics(List<SecurityStandardCategoryStatistics> input, ComponentDto project, String standard, boolean includeCwe) { + private void completeRulesStatistics(List<SecurityStandardCategoryStatistics> input, ComponentDto project, String standard, boolean includeCwe) { try (DbSession dbSession = dbClient.openSession(false)) { Set<QualityProfile> qualityProfiles = dbClient.liveMeasureDao().selectMeasure(dbSession, project.projectUuid(), QUALITY_PROFILES_KEY) .map(LiveMeasureDto::getDataAsString) @@ -239,7 +239,7 @@ public class ShowAction implements SecurityReportsWsAction { return 11; } - private static void writeResponse(Request request, Response response, List<SecurityStandardCategoryStatistics> categories) { + private static void writeResponse(Request request, Response response, List<SecurityStandardCategoryStatistics> categories, boolean isViewOrApp) { SecurityReports.ShowWsResponse.Builder builder = SecurityReports.ShowWsResponse.newBuilder(); categories.forEach(cat -> { SecurityReports.SecurityStandardCategoryStatistics.Builder catBuilder = SecurityReports.SecurityStandardCategoryStatistics.newBuilder(); @@ -250,9 +250,11 @@ public class ShowAction implements SecurityReportsWsAction { catBuilder .setOpenSecurityHotspots(cat.getOpenSecurityHotspots()) .setToReviewSecurityHotspots(cat.getToReviewSecurityHotspots()) - .setWontFixSecurityHotspots(cat.getWontFixSecurityHotspots()) - .setTotalRules(cat.getTotalRules()) - .setActiveRules(cat.getActiveRules()); + .setWontFixSecurityHotspots(cat.getWontFixSecurityHotspots()); + if (!isViewOrApp) { + catBuilder.setTotalRules(cat.getTotalRules()) + .setActiveRules(cat.getActiveRules()); + } if (cat.getChildren() != null) { cat.getChildren().stream() .sorted(comparing(cweIndex())) @@ -265,9 +267,11 @@ public class ShowAction implements SecurityReportsWsAction { cweBuilder .setOpenSecurityHotspots(cwe.getOpenSecurityHotspots()) .setToReviewSecurityHotspots(cwe.getToReviewSecurityHotspots()) - .setWontFixSecurityHotspots(cwe.getWontFixSecurityHotspots()) - .setActiveRules(cwe.getActiveRules()) - .setTotalRules(cwe.getTotalRules()); + .setWontFixSecurityHotspots(cwe.getWontFixSecurityHotspots()); + if (!isViewOrApp) { + cweBuilder.setActiveRules(cwe.getActiveRules()) + .setTotalRules(cwe.getTotalRules()); + } catBuilder.addDistribution(cweBuilder); }); } 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 11aa64b9274..247bc07e307 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 @@ -20,6 +20,7 @@ package org.sonar.server.securityreport.ws; import java.util.Date; +import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.Rule; @@ -33,6 +34,7 @@ import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.issue.IssueDto; @@ -52,6 +54,8 @@ import org.sonar.server.permission.index.WebAuthorizationTypeSupport; import org.sonar.server.qualityprofile.QPMeasureData; import org.sonar.server.qualityprofile.QualityProfile; import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.view.index.ViewDoc; +import org.sonar.server.view.index.ViewIndexer; import org.sonar.server.ws.WsActionTester; import static com.google.common.collect.Sets.newHashSet; @@ -77,9 +81,11 @@ public class ShowActionTest { public ExpectedException expectedException = none(); private DbClient dbClient = db.getDbClient(); + private ComponentDbTester componentDbTester = db.components(); private DbSession session = db.getSession(); private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient)); + private ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client()); private WsActionTester ws = new WsActionTester(new ShowAction(userSessionRule, TestComponentFinder.from(db), issueIndex, dbClient)); private StartupIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client(), issueIndexer); @@ -97,7 +103,7 @@ public class ShowActionTest { public void setUp() { user = db.users().insertUser("john"); userSessionRule.logIn(user); - project = insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "PROJECT_ID").setDbKey("PROJECT_KEY")); + project = componentDbTester.insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "PROJECT_ID").setDbKey("PROJECT_KEY")); qualityProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), qp -> qp.setLanguage("java")); // owasp : a2 and TopSans25 insecure rule1 = newRule(newHashSet("owaspTop10:a2", "cwe:123", "cwe:89"), RuleType.SECURITY_HOTSPOT); @@ -132,7 +138,7 @@ public class ShowActionTest { public void owasp_empty() { userSessionRule.addProjectPermission(UserRole.USER, project); indexPermissions(); - ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); IssueDto issue1 = newIssue(rule1, project, file) .setStatus("OPEN") .setSeverity("MAJOR") @@ -161,7 +167,7 @@ public class ShowActionTest { public void owasp_without_cwe() { userSessionRule.addProjectPermission(UserRole.USER, project); indexPermissions(); - ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); IssueDto issue1 = newIssue(rule1, project, file) .setStatus("OPEN") .setSeverity("MAJOR") @@ -196,7 +202,7 @@ public class ShowActionTest { public void owasp_with_cwe__matching_json_example() { userSessionRule.addProjectPermission(UserRole.USER, project); indexPermissions(); - ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); IssueDto issue1 = newIssue(rule1, project, file) .setStatus("OPEN") .setSeverity("MAJOR") @@ -232,7 +238,7 @@ public class ShowActionTest { public void sans_with_cwe() { userSessionRule.addProjectPermission(UserRole.USER, project); indexPermissions(); - ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); IssueDto issue1 = newIssue(rule1, project, file) .setStatus("OPEN") .setSeverity("MAJOR") @@ -314,7 +320,7 @@ public class ShowActionTest { public void sonarsource_security_without_cwe() { userSessionRule.addProjectPermission(UserRole.USER, project); indexPermissions(); - ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); IssueDto issue1 = newIssue(rule1, project, file) .setStatus("OPEN") .setSeverity("MAJOR") @@ -350,7 +356,7 @@ public class ShowActionTest { public void sonarsource_security_with_cwe() { userSessionRule.addProjectPermission(UserRole.USER, project); indexPermissions(); - ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); IssueDto issue1 = newIssue(rule1, project, file) .setStatus("OPEN") .setSeverity("MAJOR") @@ -382,6 +388,44 @@ public class ShowActionTest { .isSimilarTo(this.getClass().getResource("ShowActionTest/sonarsourceSecurityWithCwe.json")); } + @Test + public void dont_return_rules_on_application() { + ComponentDto application = db.components().insertPrivateApplication(db.getDefaultOrganization()); + indexView(application.uuid(), singletonList(project.uuid())); + userSessionRule.addProjectPermission(UserRole.USER, application); + indexPermissions(); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); + IssueDto issue1 = newIssue(rule1, project, file) + .setStatus("OPEN") + .setSeverity("MAJOR") + .setType(RuleType.VULNERABILITY); + IssueDto issue2 = newIssue(rule1, project, file) + .setStatus("OPEN") + .setSeverity("MAJOR") + .setType(RuleType.SECURITY_HOTSPOT); + IssueDto issue3 = newIssue(rule1, project, file) + .setStatus(Issue.STATUS_RESOLVED) + .setResolution(Issue.RESOLUTION_FIXED) + .setSeverity("MAJOR") + .setType(RuleType.SECURITY_HOTSPOT); + IssueDto issue4 = newIssue(rule1, project, file) + .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", "sonarsourceSecurity") + .setParam("project", application.getKey()) + .setParam("includeDistribution", "true") + .execute().getInput()) + .withStrictArrayOrder() + .isSimilarTo(this.getClass().getResource("ShowActionTest/sonarsourceSecurityOnApplication.json")); + } + private RuleDefinitionDto newRule(Set<String> standards, RuleType type) { RuleDefinitionDto rule = RuleTesting.newRule() .setType(type) @@ -399,14 +443,13 @@ public class ShowActionTest { issueIndexer.indexOnStartup(issueIndexer.getIndexTypes()); } + private void indexView(String viewUuid, List<String> projects) { + viewIndexer.index(new ViewDoc().setUuid(viewUuid).setProjects(projects)); + } + private void insertQPLiveMeasure(ComponentDto project) { QualityProfile qp = new QualityProfile(qualityProfile.getKee(), qualityProfile.getName(), qualityProfile.getLanguage(), new Date()); db.measures().insertLiveMeasure(project, qpMetric, lm -> lm.setData(QPMeasureData.toJson(new QPMeasureData(singletonList(qp))))); } - private ComponentDto insertComponent(ComponentDto component) { - dbClient.componentDao().insert(session, component); - session.commit(); - return component; - } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/sonarsourceSecurityOnApplication.json b/server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/sonarsourceSecurityOnApplication.json new file mode 100644 index 00000000000..b565b5d309d --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/sonarsourceSecurityOnApplication.json @@ -0,0 +1,174 @@ +{ + "categories": [ + { + "category": "ldap-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "object-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "ssrf", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "insecure-conf", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "xxe", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "auth", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "xpath-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "weak-cryptography", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "dos", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "open-redirect", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "log-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "csrf", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "sql-injection", + "vulnerabilities": 1, + "vulnerabilityRating": 3, + "toReviewSecurityHotspots": 1, + "openSecurityHotspots": 1, + "wontFixSecurityHotspots": 1, + "distribution": [ + { + "cwe": "89", + "vulnerabilities": 1, + "vulnerabilityRating": 3, + "toReviewSecurityHotspots": 1, + "openSecurityHotspots": 1, + "wontFixSecurityHotspots": 1 + } + ] + }, + { + "category": "file-manipulation", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "expression-lang-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "rce", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "xss", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "path-traversal-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "command-injection", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + }, + { + "category": "http-response-splitting", + "vulnerabilities": 0, + "toReviewSecurityHotspots": 0, + "openSecurityHotspots": 0, + "wontFixSecurityHotspots": 0, + "distribution": [] + } + ] +} |