Browse Source

SONAR-11370 Add number of rules and active rules on Security Report

tags/7.5
Eric Hartmann 5 years ago
parent
commit
e14f55a7bb

+ 1
- 1
server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml View File

@@ -303,7 +303,7 @@
rules r
<include refid="outerJoinRulesMetadata"/>
where
r.status != 'REMOVED'
r.status != 'REMOVED' and r.is_external is false and r.is_template is false
and r.rule_type in <foreach collection="types" item="type" separator="," open="(" close=")">#{type, jdbcType=INTEGER}</foreach>
and r.language in <foreach collection="languages" item="language" separator="," open="(" close=")">#{language, jdbcType=VARCHAR}</foreach>
</select>

+ 35
- 0
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.db.rule;

import com.hazelcast.map.impl.querycache.accumulator.Accumulator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -525,6 +526,40 @@ public class RuleDaoTest {
.isEmpty();
}

@Test
public void selectByTypeAndLanguages_ignores_external_rules() {
OrganizationDto organization = db.organizations().insert();

RuleDefinitionDto rule1 = db.rules().insert(
r -> r.setKey(RuleKey.of("java", "S001"))
.setConfigKey("S1")
.setType(RuleType.VULNERABILITY)
.setIsExternal(true)
.setLanguage("java"));
db.rules().insertOrUpdateMetadata(rule1, organization);

assertThat(underTest.selectByTypeAndLanguages(db.getSession(), organization.getUuid(), singletonList(RuleType.VULNERABILITY.getDbConstant()), singletonList("java")))
.extracting(RuleDto::getOrganizationUuid, RuleDto::getId, RuleDto::getLanguage, RuleDto::getType)
.isEmpty();
}

@Test
public void selectByTypeAndLanguages_ignores_template_rules() {
OrganizationDto organization = db.organizations().insert();

RuleDefinitionDto rule1 = db.rules().insert(
r -> r.setKey(RuleKey.of("java", "S001"))
.setConfigKey("S1")
.setType(RuleType.VULNERABILITY)
.setIsTemplate(true)
.setLanguage("java"));
db.rules().insertOrUpdateMetadata(rule1, organization);

assertThat(underTest.selectByTypeAndLanguages(db.getSession(), organization.getUuid(), singletonList(RuleType.VULNERABILITY.getDbConstant()), singletonList("java")))
.extracting(RuleDto::getOrganizationUuid, RuleDto::getId, RuleDto::getLanguage, RuleDto::getType)
.isEmpty();
}

@Test
public void select_by_query() {
OrganizationDto organization = db.organizations().insert();

+ 95
- 4
server/sonar-server/src/main/java/org/sonar/server/securityreport/ws/ShowAction.java View File

@@ -19,26 +19,41 @@
*/
package org.sonar.server.securityreport.ws;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rules.RuleType;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.qualityprofile.OrgActiveRuleDto;
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.qualityprofile.QPMeasureData;
import org.sonar.server.qualityprofile.QualityProfile;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.SecurityReports;

import static java.lang.Integer.parseInt;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySortedSet;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.server.issue.index.IssueIndexDefinition.UNKNOWN_STANDARD;
import static org.sonar.server.issue.index.SecurityStandardHelper.UNKNOWN_STANDARD;
import static org.sonar.server.issue.index.SecurityStandardHelper.getCwe;
import static org.sonar.server.issue.index.SecurityStandardHelper.getOwaspTop10;
import static org.sonar.server.issue.index.SecurityStandardHelper.getSansTop25;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SANS_TOP_25;
@@ -118,16 +133,88 @@ public class ShowAction implements SecurityReportsWsAction {
.stream()
.sorted(comparing(ShowAction::index))
.collect(toList());
completeStatistics(owaspCategories, projectDto, standard, includeCwe);
writeResponse(request, response, owaspCategories);
break;
case PARAM_SANS_TOP_25:
writeResponse(request, response, issueIndex.getSansTop25Report(projectDto.uuid(), isViewOrApp, includeCwe));
List<SecurityStandardCategoryStatistics> sansTop25Report = issueIndex.getSansTop25Report(projectDto.uuid(), isViewOrApp, includeCwe);
completeStatistics(sansTop25Report, projectDto, standard, includeCwe);
writeResponse(request, response, sansTop25Report);
break;
default:
throw new IllegalArgumentException("Unsupported standard: '" + standard + "'");
}
}

private void completeStatistics(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)
.map(data -> QPMeasureData.fromJson(data).getProfiles())
.orElse(emptySortedSet());

List<OrgActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByTypeAndProfileUuids(dbSession,
asList(RuleType.SECURITY_HOTSPOT.getDbConstant(), RuleType.VULNERABILITY.getDbConstant()),
qualityProfiles.stream()
.map(QualityProfile::getQpKey)
.collect(toList()));

Multimap<String, OrgActiveRuleDto> activeRulesByCategory = ArrayListMultimap.create();
activeRuleDtos
.forEach(r -> {
List<String> cwe = getCwe(r.getSecurityStandards());
if (includeCwe) {
cwe.forEach(s -> activeRulesByCategory.put(s, r));
}
switch (standard) {
case PARAM_OWASP_TOP_10:
getOwaspTop10(r.getSecurityStandards()).forEach(s -> activeRulesByCategory.put(s, r));
break;
case PARAM_SANS_TOP_25:
getSansTop25(cwe).forEach(s -> activeRulesByCategory.put(s, r));
break;
default:
throw new IllegalArgumentException("Unsupported standard: '" + standard + "'");
}
});

List<RuleDto> ruleDtos = dbClient.ruleDao().selectByTypeAndLanguages(dbSession,
project.getOrganizationUuid(),
asList(RuleType.SECURITY_HOTSPOT.getDbConstant(), RuleType.VULNERABILITY.getDbConstant()),
qualityProfiles.stream()
.map(QualityProfile::getLanguageKey)
.collect(toList()));

Multimap<String, RuleDto> rulesByCategory = ArrayListMultimap.create();
ruleDtos
.forEach(r -> {
List<String> cwe = getCwe(r.getSecurityStandards());
if (includeCwe) {
cwe.forEach(s -> rulesByCategory.put(s, r));
}
switch (standard) {
case PARAM_OWASP_TOP_10:
getOwaspTop10(r.getSecurityStandards()).forEach(s -> rulesByCategory.put(s, r));
break;
case PARAM_SANS_TOP_25:
getSansTop25(cwe).forEach(s -> rulesByCategory.put(s, r));
break;
default:
throw new IllegalArgumentException("Unsupported standard: '" + standard + "'");
}
});

input.forEach(c -> {
c.setTotalRules(rulesByCategory.get(c.getCategory()).size());
c.setActiveRules(activeRulesByCategory.get(c.getCategory()).size());
c.getChildren().forEach(child -> {
child.setTotalRules(rulesByCategory.get(child.getCategory()).size());
child.setActiveRules(activeRulesByCategory.get(child.getCategory()).size());
});
});
}
}

private static Integer index(SecurityStandardCategoryStatistics owaspCat) {
if (owaspCat.getCategory().startsWith(OWASP_CAT_PREFIX)) {
return parseInt(owaspCat.getCategory().substring(OWASP_CAT_PREFIX.length()));
@@ -147,7 +234,9 @@ public class ShowAction implements SecurityReportsWsAction {
catBuilder
.setOpenSecurityHotspots(cat.getOpenSecurityHotspots())
.setToReviewSecurityHotspots(cat.getToReviewSecurityHotspots())
.setWontFixSecurityHotspots(cat.getWontFixSecurityHotspots());
.setWontFixSecurityHotspots(cat.getWontFixSecurityHotspots())
.setTotalRules(cat.getTotalRules())
.setActiveRules(cat.getActiveRules());
if (cat.getChildren() != null) {
cat.getChildren().stream()
.sorted(comparing(cweIndex()))
@@ -160,7 +249,9 @@ public class ShowAction implements SecurityReportsWsAction {
cweBuilder
.setOpenSecurityHotspots(cwe.getOpenSecurityHotspots())
.setToReviewSecurityHotspots(cwe.getToReviewSecurityHotspots())
.setWontFixSecurityHotspots(cwe.getWontFixSecurityHotspots());
.setWontFixSecurityHotspots(cwe.getWontFixSecurityHotspots())
.setActiveRules(cwe.getActiveRules())
.setTotalRules(cwe.getTotalRules());
catBuilder.addDistribution(cweBuilder);
});
}

+ 64
- 37
server/sonar-server/src/test/java/org/sonar/server/securityreport/ws/ShowActionTest.java View File

@@ -19,8 +19,8 @@
*/
package org.sonar.server.securityreport.ws;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Date;
import java.util.Set;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -36,7 +36,9 @@ import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.permission.GroupPermissionDto;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.db.user.UserDto;
@@ -48,11 +50,17 @@ import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.issue.index.IssueIteratorFactory;
import org.sonar.server.permission.index.PermissionIndexer;
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.ws.WsActionTester;

import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.rules.ExpectedException.none;
import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
import static org.sonar.api.measures.Metric.ValueType.STRING;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.issue.IssueTesting.newIssue;
import static org.sonar.server.tester.UserSessionRule.standalone;
@@ -77,11 +85,33 @@ public class ShowActionTest {
private StartupIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client(), issueIndexer);

private UserDto user;
private ComponentDto project;
private QProfileDto qualityProfile;
private RuleDefinitionDto rule1;
private RuleDefinitionDto rule2;
private RuleDefinitionDto rule3;
private RuleDefinitionDto rule4;
private MetricDto qpMetric;

@Before
public void setUp() {
user = db.users().insertUser("john");
userSessionRule.logIn(user);
project = 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"));
// owasp : a1 and TopSans25 risky
rule2 = newRule(newHashSet("owaspTop10:a1", "cwe:22", "cwe:190"));
// owasp : a4 and TopSans25 porous, not activated
rule3 = newRule(newHashSet("owaspTop10:a3", "cwe:759", "cwe:000"));
// cwe with unknown
rule4 = newRule(newHashSet("cwe:999"));
db.qualityProfiles().activateRule(qualityProfile, rule1);
db.qualityProfiles().activateRule(qualityProfile, rule2);
qpMetric = db.measures().insertMetric(m -> m.setValueType(STRING.name()).setKey(QUALITY_PROFILES_KEY));

insertQPLiveMeasure(project);
}

@Test
@@ -95,24 +125,20 @@ public class ShowActionTest {
assertThat(def.params()).extracting("key").containsExactlyInAnyOrder("standard", "project", "branch", "includeDistribution");
}


@Test
public void owasp_empty() {

ComponentDto project = insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "PROJECT_ID").setDbKey("PROJECT_KEY"));
userSessionRule.addProjectPermission(UserRole.USER, project);
indexPermissions();
ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
RuleDefinitionDto rule = newRule();
IssueDto issue1 = newIssue(rule, project, file)
IssueDto issue1 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.CODE_SMELL);
IssueDto issue2 = newIssue(rule, project, file)
IssueDto issue2 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.BUG);
IssueDto issue3 = newIssue(rule, project, file)
IssueDto issue3 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.CODE_SMELL);
@@ -130,26 +156,23 @@ public class ShowActionTest {

@Test
public void owasp_without_cwe() {

ComponentDto project = insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "PROJECT_ID").setDbKey("PROJECT_KEY"));
userSessionRule.addProjectPermission(UserRole.USER, project);
indexPermissions();
ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
RuleDefinitionDto rule = newRule();
IssueDto issue1 = newIssue(rule, project, file)
IssueDto issue1 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.VULNERABILITY);
IssueDto issue2 = newIssue(rule, project, file)
IssueDto issue2 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue3 = newIssue(rule, project, file)
IssueDto issue3 = newIssue(rule1, project, file)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_FIXED)
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue4 = newIssue(rule, project, file)
IssueDto issue4 = newIssue(rule1, project, file)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_WONT_FIX)
.setSeverity("MAJOR")
@@ -168,26 +191,23 @@ public class ShowActionTest {

@Test
public void owasp_with_cwe() {

ComponentDto project = insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "PROJECT_ID").setDbKey("PROJECT_KEY"));
userSessionRule.addProjectPermission(UserRole.USER, project);
indexPermissions();
ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
RuleDefinitionDto rule = newRule();
IssueDto issue1 = newIssue(rule, project, file)
IssueDto issue1 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.VULNERABILITY);
IssueDto issue2 = newIssue(rule, project, file)
IssueDto issue2 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue3 = newIssue(rule, project, file)
IssueDto issue3 = newIssue(rule1, project, file)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_FIXED)
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue4 = newIssue(rule, project, file)
IssueDto issue4 = newIssue(rule1, project, file)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_WONT_FIX)
.setSeverity("MAJOR")
@@ -207,25 +227,23 @@ 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();
ComponentDto file = insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
RuleDefinitionDto rule = newRule();
IssueDto issue1 = newIssue(rule, project, file)
IssueDto issue1 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.VULNERABILITY);
IssueDto issue2 = newIssue(rule, project, file)
IssueDto issue2 = newIssue(rule1, project, file)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue3 = newIssue(rule, project, file)
IssueDto issue3 = newIssue(rule1, project, file)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_FIXED)
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue4 = newIssue(rule, project, file)
IssueDto issue4 = newIssue(rule1, project, file)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_WONT_FIX)
.setSeverity("MAJOR")
@@ -250,24 +268,27 @@ public class ShowActionTest {
ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1));
ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2"));

insertQPLiveMeasure(project1);
insertQPLiveMeasure(project1Branch1);
insertQPLiveMeasure(project2);

userSessionRule.addProjectPermission(UserRole.USER, project1);
userSessionRule.addProjectPermission(UserRole.USER, project2);
indexPermissions();
RuleDefinitionDto rule = newRule();
IssueDto issue1 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
IssueDto issue1 = newIssue(rule1, project1Branch1, fileOnProject1Branch1)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.VULNERABILITY);
IssueDto issue2 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
IssueDto issue2 = newIssue(rule1, project1Branch1, fileOnProject1Branch1)
.setStatus("OPEN")
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue3 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
IssueDto issue3 = newIssue(rule1, project1Branch1, fileOnProject1Branch1)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_FIXED)
.setSeverity("MAJOR")
.setType(RuleType.SECURITY_HOTSPOT);
IssueDto issue4 = newIssue(rule, project1Branch1, fileOnProject1Branch1)
IssueDto issue4 = newIssue(rule1, project1Branch1, fileOnProject1Branch1)
.setStatus(Issue.STATUS_RESOLVED)
.setResolution(Issue.RESOLUTION_WONT_FIX)
.setSeverity("MAJOR")
@@ -286,10 +307,11 @@ public class ShowActionTest {
.isSimilarTo(this.getClass().getResource("ShowActionTest/sansWithCwe.json"));
}


private RuleDefinitionDto newRule() {
private RuleDefinitionDto newRule(Set tags) {
RuleDefinitionDto rule = RuleTesting.newRule()
.setSecurityStandards(new HashSet<>(Arrays.asList("owaspTop10:a2", "cwe:123", "cwe:89")));
.setType(RuleType.SECURITY_HOTSPOT)
.setLanguage("java")
.setSecurityStandards(tags);
db.rules().insert(rule);
return rule;
}
@@ -302,6 +324,11 @@ public class ShowActionTest {
issueIndexer.indexOnStartup(issueIndexer.getIndexTypes());
}

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 void grantPermissionToAnyone(ComponentDto project, String permission) {
dbClient.groupPermissionDao().insert(session,
new GroupPermissionDto()

+ 34
- 12
server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/empty.json View File

@@ -6,7 +6,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 1,
"totalRules": 1
},
{
"category": "a2",
@@ -14,7 +16,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 1,
"totalRules": 1
},
{
"category": "a3",
@@ -22,7 +26,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
},
{
"category": "a4",
@@ -30,7 +36,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a5",
@@ -38,7 +46,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a6",
@@ -46,7 +56,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a7",
@@ -54,7 +66,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a8",
@@ -62,7 +76,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a9",
@@ -70,7 +86,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a10",
@@ -78,7 +96,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "unknown",
@@ -86,7 +106,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
}
]
}
}

+ 34
- 12
server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/owaspNoCwe.json View File

@@ -6,7 +6,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 1,
"totalRules": 1
},
{
"category": "a2",
@@ -15,7 +17,9 @@
"toReviewSecurityHotspots": 1,
"openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1,
"distribution": []
"distribution": [],
"activeRules": 1,
"totalRules": 1
},
{
"category": "a3",
@@ -23,7 +27,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
},
{
"category": "a4",
@@ -31,7 +37,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a5",
@@ -39,7 +47,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a6",
@@ -47,7 +57,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a7",
@@ -55,7 +67,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a8",
@@ -63,7 +77,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a9",
@@ -71,7 +87,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a10",
@@ -79,7 +97,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "unknown",
@@ -87,7 +107,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
}
]
}
}

+ 40
- 14
server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/owaspWithCwe.json View File

@@ -6,7 +6,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 1,
"totalRules": 1
},
{
"category": "a2",
@@ -22,7 +24,9 @@
"vulnerabilityRating": 3,
"toReviewSecurityHotspots": 1,
"openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1
"wontFixSecurityHotspots": 1,
"activeRules": 1,
"totalRules": 1
},
{
"cwe": "123",
@@ -30,9 +34,13 @@
"vulnerabilityRating": 3,
"toReviewSecurityHotspots": 1,
"openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1
"wontFixSecurityHotspots": 1,
"activeRules": 1,
"totalRules": 1
}
]
],
"activeRules": 1,
"totalRules": 1
},
{
"category": "a3",
@@ -40,7 +48,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
},
{
"category": "a4",
@@ -48,7 +58,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a5",
@@ -56,7 +68,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a6",
@@ -64,7 +78,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a7",
@@ -72,7 +88,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a8",
@@ -80,7 +98,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a9",
@@ -88,7 +108,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "a10",
@@ -96,7 +118,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 0
},
{
"category": "unknown",
@@ -104,7 +128,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
}
]
}
}

+ 16
- 6
server/sonar-server/src/test/resources/org/sonar/server/securityreport/ws/ShowActionTest/sansWithCwe.json View File

@@ -6,7 +6,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 0,
"totalRules": 1
},
{
"category": "risky-resource",
@@ -14,7 +16,9 @@
"toReviewSecurityHotspots": 0,
"openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
"distribution": [],
"activeRules": 1,
"totalRules": 1
},
{
"category": "insecure-interaction",
@@ -30,7 +34,9 @@
"vulnerabilityRating": 3,
"toReviewSecurityHotspots": 1,
"openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1
"wontFixSecurityHotspots": 1,
"activeRules": 1,
"totalRules": 1
},
{
"cwe": "123",
@@ -38,9 +44,13 @@
"vulnerabilityRating": 3,
"toReviewSecurityHotspots": 1,
"openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1
"wontFixSecurityHotspots": 1,
"activeRules": 1,
"totalRules": 1
}
]
],
"activeRules": 1,
"totalRules": 1
}
]
}
}

+ 4
- 0
sonar-ws/src/main/protobuf/ws-security.proto View File

@@ -39,6 +39,8 @@ message SecurityStandardCategoryStatistics {
optional int64 openSecurityHotspots = 5;
optional int64 wontFixSecurityHotspots = 6;
repeated CweStatistics distribution = 7;
optional int64 activeRules = 8;
optional int64 totalRules = 9;
}

message CweStatistics {
@@ -48,6 +50,8 @@ message CweStatistics {
optional int64 toReviewSecurityHotspots = 4;
optional int64 openSecurityHotspots = 5;
optional int64 wontFixSecurityHotspots = 6;
optional int64 activeRules = 7;
optional int64 totalRules = 8;
}



Loading…
Cancel
Save