|
|
@@ -27,7 +27,6 @@ import org.junit.Test; |
|
|
|
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; |
|
|
|
import org.sonar.db.component.ComponentDto; |
|
|
|
import org.sonar.server.view.index.ViewDoc; |
|
|
|
|
|
|
@@ -38,6 +37,8 @@ import static java.util.Comparator.comparing; |
|
|
|
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.server.rule.RulesDefinition.OwaspAsvsVersion; |
|
|
|
import static org.sonar.api.server.rule.RulesDefinition.PciDssVersion; |
|
|
|
import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2017; |
|
|
|
import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2021; |
|
|
|
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; |
|
|
@@ -203,6 +204,29 @@ public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon { |
|
|
|
assertThat(pciDss32Report.get(11).getChildren()).isEmpty(); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void getOwaspAsvs40Report_aggregation() { |
|
|
|
List<SecurityStandardCategoryStatistics> owaspAsvsReport = indexIssuesAndAssertOwaspAsvsReport(); |
|
|
|
|
|
|
|
assertThat(owaspAsvsReport) |
|
|
|
.isNotEmpty(); |
|
|
|
|
|
|
|
assertThat(owaspAsvsReport.get(0).getChildren()).hasSize(2); |
|
|
|
assertThat(owaspAsvsReport.get(1).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(2).getChildren()).hasSize(4); |
|
|
|
assertThat(owaspAsvsReport.get(3).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(4).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(5).getChildren()).hasSize(2); |
|
|
|
assertThat(owaspAsvsReport.get(6).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(7).getChildren()).hasSize(1); |
|
|
|
assertThat(owaspAsvsReport.get(8).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(9).getChildren()).hasSize(1); |
|
|
|
assertThat(owaspAsvsReport.get(10).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(11).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(12).getChildren()).isEmpty(); |
|
|
|
assertThat(owaspAsvsReport.get(13).getChildren()).isEmpty(); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void getOwaspTop10Report_aggregation_with_cwe() { |
|
|
|
List<SecurityStandardCategoryStatistics> owaspTop10Report = indexIssuesAndAssertOwaspReport(true); |
|
|
@@ -300,7 +324,7 @@ public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon { |
|
|
|
.setResolution(Issue.RESOLUTION_FIXED), |
|
|
|
newDoc("notpcidsshotspot", project).setPciDss32(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW)); |
|
|
|
|
|
|
|
List<SecurityStandardCategoryStatistics> pciDssReport = underTest.getPciDssReport(project.uuid(), false, RulesDefinition.PciDssVersion.V3_2).stream() |
|
|
|
List<SecurityStandardCategoryStatistics> pciDssReport = underTest.getPciDssReport(project.uuid(), false, PciDssVersion.V3_2).stream() |
|
|
|
.sorted(comparing(s -> parseInt(s.getCategory()))) |
|
|
|
.collect(toList()); |
|
|
|
assertThat(pciDssReport) |
|
|
@@ -324,6 +348,49 @@ public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon { |
|
|
|
return pciDssReport; |
|
|
|
} |
|
|
|
|
|
|
|
private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertOwaspAsvsReport() { |
|
|
|
ComponentDto project = newPrivateProjectDto(); |
|
|
|
indexIssues( |
|
|
|
newDoc("openvul1", project).setOwaspAsvs40(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) |
|
|
|
.setSeverity(Severity.MAJOR), |
|
|
|
newDoc("openvul2", project).setOwaspAsvs40(asList("3.3.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) |
|
|
|
.setSeverity(Severity.MINOR), |
|
|
|
newDoc("openvul3", project).setOwaspAsvs40(asList("10.1.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) |
|
|
|
.setSeverity(Severity.MINOR), |
|
|
|
newDoc("notowaspasvsvul", project).setOwaspAsvs40(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL), |
|
|
|
newDoc("toreviewhotspot1", project).setOwaspAsvs40(asList("1.3.0", "3.3.2")).setType(RuleType.SECURITY_HOTSPOT) |
|
|
|
.setStatus(Issue.STATUS_TO_REVIEW), |
|
|
|
newDoc("toreviewhotspot2", project).setOwaspAsvs40(asList("3.5.6", "6.4.5")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW), |
|
|
|
newDoc("reviewedHotspot", project).setOwaspAsvs40(asList("3.1.1", "8.6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED) |
|
|
|
.setResolution(Issue.RESOLUTION_FIXED), |
|
|
|
newDoc("notowaspasvshotspot", project).setOwaspAsvs40(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW)); |
|
|
|
|
|
|
|
List<SecurityStandardCategoryStatistics> owaspAsvsReport = underTest.getOwaspAsvsReport(project.uuid(), false, OwaspAsvsVersion.V4_0).stream() |
|
|
|
.sorted(comparing(s -> parseInt(s.getCategory()))) |
|
|
|
.collect(toList()); |
|
|
|
assertThat(owaspAsvsReport) |
|
|
|
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities, |
|
|
|
SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, |
|
|
|
SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating) |
|
|
|
.containsExactlyInAnyOrder( |
|
|
|
tuple("1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 5), |
|
|
|
tuple("2", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* reviewedHotspot */, 4), |
|
|
|
tuple("4", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("5", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("6", 2L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 5), |
|
|
|
tuple("7", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("8", 0L, OptionalInt.empty(), 0L, 1L /* reviewedHotspot */, 1), |
|
|
|
tuple("9", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("10", 1L, OptionalInt.of(2), 0L, 0L, 1), |
|
|
|
tuple("11", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("12", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("13", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("14", 0L, OptionalInt.empty(), 0L, 0L, 1)); |
|
|
|
|
|
|
|
return owaspAsvsReport; |
|
|
|
} |
|
|
|
|
|
|
|
private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertOwasp2021Report(boolean includeCwe) { |
|
|
|
ComponentDto project = newPrivateProjectDto(); |
|
|
|
indexIssues( |
|
|
@@ -458,7 +525,7 @@ public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon { |
|
|
|
indexView(portfolio1.uuid(), singletonList(project1.uuid())); |
|
|
|
indexView(portfolio2.uuid(), singletonList(project2.uuid())); |
|
|
|
|
|
|
|
List<SecurityStandardCategoryStatistics> pciDssReport = underTest.getPciDssReport(portfolio1.uuid(), true, RulesDefinition.PciDssVersion.V3_2).stream() |
|
|
|
List<SecurityStandardCategoryStatistics> pciDssReport = underTest.getPciDssReport(portfolio1.uuid(), true, PciDssVersion.V3_2).stream() |
|
|
|
.sorted(comparing(s -> parseInt(s.getCategory()))) |
|
|
|
.collect(toList()); |
|
|
|
assertThat(pciDssReport) |
|
|
@@ -480,6 +547,55 @@ public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon { |
|
|
|
tuple("12", 0L, OptionalInt.empty(), 0L, 0L, 1)); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void getOwaspAsvsReport_aggregation_on_portfolio() { |
|
|
|
ComponentDto portfolio1 = db.components().insertPrivateApplication(); |
|
|
|
ComponentDto portfolio2 = db.components().insertPrivateApplication(); |
|
|
|
ComponentDto project1 = db.components().insertPrivateProject(); |
|
|
|
ComponentDto project2 = db.components().insertPrivateProject(); |
|
|
|
|
|
|
|
indexIssues( |
|
|
|
newDoc("openvul1", project1).setOwaspAsvs40(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) |
|
|
|
.setSeverity(Severity.MAJOR), |
|
|
|
newDoc("openvul2", project2).setOwaspAsvs40(asList("3.3.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) |
|
|
|
.setSeverity(Severity.MINOR), |
|
|
|
newDoc("openvul3", project1).setOwaspAsvs40(asList("10.1.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) |
|
|
|
.setSeverity(Severity.MINOR), |
|
|
|
newDoc("notowaspvul", project1).setOwaspAsvs40(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL), |
|
|
|
newDoc("toreviewhotspot1", project2).setOwaspAsvs40(asList("1.3.0", "3.3.2")).setType(RuleType.SECURITY_HOTSPOT) |
|
|
|
.setStatus(Issue.STATUS_TO_REVIEW), |
|
|
|
newDoc("toreviewhotspot2", project1).setOwaspAsvs40(asList("3.5.6", "6.4.5")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW), |
|
|
|
newDoc("reviewedHotspot", project2).setOwaspAsvs40(asList("3.1.1", "8.6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED) |
|
|
|
.setResolution(Issue.RESOLUTION_FIXED), |
|
|
|
newDoc("notowasphotspot", project1).setOwaspAsvs40(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW)); |
|
|
|
|
|
|
|
indexView(portfolio1.uuid(), singletonList(project1.uuid())); |
|
|
|
indexView(portfolio2.uuid(), singletonList(project2.uuid())); |
|
|
|
|
|
|
|
List<SecurityStandardCategoryStatistics> owaspAsvsReport = underTest.getOwaspAsvsReport(portfolio1.uuid(), true, OwaspAsvsVersion.V4_0).stream() |
|
|
|
.sorted(comparing(s -> parseInt(s.getCategory()))) |
|
|
|
.collect(toList()); |
|
|
|
assertThat(owaspAsvsReport) |
|
|
|
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities, |
|
|
|
SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, |
|
|
|
SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating) |
|
|
|
.containsExactlyInAnyOrder( |
|
|
|
tuple("1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1), |
|
|
|
tuple("2", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("3", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* toreviewhotspot2 */, 0L, 5), |
|
|
|
tuple("4", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("5", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("6", 1L /* openvul3 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 5), |
|
|
|
tuple("7", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("8", 0L, OptionalInt.empty(), 0L, 0L /* reviewedHotspot */, 1), |
|
|
|
tuple("9", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("10", 1L /* openvul3 */, OptionalInt.of(2), 0L, 0L, 1), |
|
|
|
tuple("11", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("12", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("13", 0L, OptionalInt.empty(), 0L, 0L, 1), |
|
|
|
tuple("14", 0L, OptionalInt.empty(), 0L, 0L, 1)); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void getCWETop25Report_aggregation() { |
|
|
|
ComponentDto project = newPrivateProjectDto(); |