3 * Copyright (C) 2009-2022 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.issue.index;
22 import java.util.List;
24 import java.util.OptionalInt;
25 import java.util.stream.Collectors;
26 import org.junit.Test;
27 import org.sonar.api.issue.Issue;
28 import org.sonar.api.rule.Severity;
29 import org.sonar.api.rules.RuleType;
30 import org.sonar.api.server.rule.RulesDefinition;
31 import org.sonar.db.component.ComponentDto;
32 import org.sonar.server.view.index.ViewDoc;
34 import static java.lang.Integer.parseInt;
35 import static java.util.Arrays.asList;
36 import static java.util.Collections.singletonList;
37 import static java.util.Comparator.comparing;
38 import static java.util.stream.Collectors.toList;
39 import static org.assertj.core.api.Assertions.assertThat;
40 import static org.assertj.core.api.Assertions.tuple;
41 import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2017;
42 import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2021;
43 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
44 import static org.sonar.server.issue.IssueDocTesting.newDoc;
45 import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION;
46 import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES;
47 import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE;
48 import static org.sonar.server.security.SecurityStandards.UNKNOWN_STANDARD;
50 public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon {
53 public void getOwaspTop10Report_dont_count_vulnerabilities_from_other_projects() {
54 ComponentDto project = newPrivateProjectDto();
55 ComponentDto another = newPrivateProjectDto();
57 IssueDoc openVulDoc = newDoc("openvul1", project).setOwaspTop10(singletonList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR);
58 openVulDoc.setOwaspTop10For2021(singletonList("a2")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR);
60 IssueDoc otherProjectDoc = newDoc("anotherProject", another).setOwaspTop10(singletonList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL);
61 otherProjectDoc.setOwaspTop10For2021(singletonList("a2")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL);
63 indexIssues(openVulDoc, otherProjectDoc);
65 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
66 assertThat(owaspTop10Report)
67 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
68 SecurityStandardCategoryStatistics::getVulnerabilityRating)
70 tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */));
72 List<SecurityStandardCategoryStatistics> owaspTop10For2021Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2021);
73 assertThat(owaspTop10For2021Report)
74 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
75 SecurityStandardCategoryStatistics::getVulnerabilityRating)
77 tuple("a2", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */));
82 public void getOwaspTop10Report_dont_count_closed_vulnerabilities() {
83 ComponentDto project = newPrivateProjectDto();
85 newDoc("openvul1", project).setOwaspTop10(asList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR),
86 newDoc("openvul12021", project).setOwaspTop10For2021(asList("a2")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR),
87 newDoc("notopenvul", project).setOwaspTop10(asList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_FIXED)
88 .setSeverity(Severity.BLOCKER),
89 newDoc("notopenvul2021", project).setOwaspTop10For2021(asList("a2")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_FIXED)
90 .setSeverity(Severity.BLOCKER));
92 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
93 assertThat(owaspTop10Report)
94 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
95 SecurityStandardCategoryStatistics::getVulnerabilityRating)
97 tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */));
99 List<SecurityStandardCategoryStatistics> owaspTop10For2021Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2021);
100 assertThat(owaspTop10For2021Report)
101 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
102 SecurityStandardCategoryStatistics::getVulnerabilityRating)
104 tuple("a2", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */));
108 public void getOwaspTop10Report_dont_count_old_vulnerabilities() {
109 ComponentDto project = newPrivateProjectDto();
111 // Previous vulnerabilities in projects that are not reanalyzed will have no owasp nor cwe attributes (not even 'unknown')
112 newDoc("openvulNotReindexed", project).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR));
114 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
115 assertThat(owaspTop10Report)
116 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
117 SecurityStandardCategoryStatistics::getVulnerabilityRating)
119 tuple(0L, OptionalInt.empty()));
121 List<SecurityStandardCategoryStatistics> owaspTop10For2021Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2021);
122 assertThat(owaspTop10For2021Report)
123 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
124 SecurityStandardCategoryStatistics::getVulnerabilityRating)
126 tuple(0L, OptionalInt.empty()));
130 public void getOwaspTop10Report_dont_count_hotspots_from_other_projects() {
131 ComponentDto project = newPrivateProjectDto();
132 ComponentDto another = newPrivateProjectDto();
134 newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
135 newDoc("openhotspot2021", project).setOwaspTop10For2021(asList("a2")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
136 newDoc("anotherProject", another).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
137 newDoc("anotherProject2021", another).setOwaspTop10For2021(asList("a2")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
139 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
140 assertThat(owaspTop10Report)
141 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
143 tuple("a1", 1L /* openhotspot1 */));
145 List<SecurityStandardCategoryStatistics> owaspTop10For2021Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2021);
146 assertThat(owaspTop10For2021Report)
147 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
149 tuple("a2", 1L /* openhotspot1 */));
153 public void getOwaspTop10Report_dont_count_closed_hotspots() {
154 ComponentDto project = newPrivateProjectDto();
156 newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
157 newDoc("openhotspot2021", project).setOwaspTop10For2021(asList("a2")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
158 newDoc("closedHotspot", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_CLOSED)
159 .setResolution(Issue.RESOLUTION_FIXED),
160 newDoc("closedHotspot2021", project).setOwaspTop10For2021(asList("a2")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_CLOSED)
161 .setResolution(Issue.RESOLUTION_FIXED));
163 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2017);
164 assertThat(owaspTop10Report)
165 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
167 tuple("a1", 1L /* openhotspot1 */));
169 List<SecurityStandardCategoryStatistics> owaspTop10For2021Report = underTest.getOwaspTop10Report(project.uuid(), false, false, Y2021);
170 assertThat(owaspTop10For2021Report)
171 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
173 tuple("a2", 1L /* openhotspot1 */));
177 public void getOwaspTop10Report_aggregation_no_cwe() {
178 List<SecurityStandardCategoryStatistics> owaspTop10Report = indexIssuesAndAssertOwaspReport(false);
180 assertThat(owaspTop10Report)
182 .allMatch(category -> category.getChildren().isEmpty());
186 public void getPciDss32Report_aggregation() {
187 List<SecurityStandardCategoryStatistics> pciDss32Report = indexIssuesAndAssertPciDss32Report();
189 assertThat(pciDss32Report)
192 assertThat(pciDss32Report.get(0).getChildren()).hasSize(2);
193 assertThat(pciDss32Report.get(1).getChildren()).isEmpty();
194 assertThat(pciDss32Report.get(2).getChildren()).hasSize(4);
195 assertThat(pciDss32Report.get(3).getChildren()).isEmpty();
196 assertThat(pciDss32Report.get(4).getChildren()).isEmpty();
197 assertThat(pciDss32Report.get(5).getChildren()).hasSize(2);
198 assertThat(pciDss32Report.get(6).getChildren()).isEmpty();
199 assertThat(pciDss32Report.get(7).getChildren()).hasSize(1);
200 assertThat(pciDss32Report.get(8).getChildren()).isEmpty();
201 assertThat(pciDss32Report.get(9).getChildren()).hasSize(1);
202 assertThat(pciDss32Report.get(10).getChildren()).isEmpty();
203 assertThat(pciDss32Report.get(11).getChildren()).isEmpty();
207 public void getOwaspTop10Report_aggregation_with_cwe() {
208 List<SecurityStandardCategoryStatistics> owaspTop10Report = indexIssuesAndAssertOwaspReport(true);
210 Map<String, List<SecurityStandardCategoryStatistics>> cweByOwasp = owaspTop10Report.stream()
211 .collect(Collectors.toMap(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getChildren));
213 assertThat(cweByOwasp.get("a1")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
214 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
215 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
216 .containsExactlyInAnyOrder(
217 tuple("123", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
218 tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
219 tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 5));
220 assertThat(cweByOwasp.get("a3")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
221 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
222 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
223 .containsExactlyInAnyOrder(
224 tuple("123", 2L /* openvul1, openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
225 tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
226 tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 5));
230 public void getOwaspTop10For2021Report_aggregation_with_cwe() {
231 List<SecurityStandardCategoryStatistics> owaspTop10Report = indexIssuesAndAssertOwasp2021Report(true);
233 Map<String, List<SecurityStandardCategoryStatistics>> cweByOwasp = owaspTop10Report.stream()
234 .collect(Collectors.toMap(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getChildren));
236 assertThat(cweByOwasp.get("a1")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
237 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
238 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
239 .containsExactlyInAnyOrder(
240 tuple("123", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
241 tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
242 tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 5));
243 assertThat(cweByOwasp.get("a3")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
244 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
245 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
246 .containsExactlyInAnyOrder(
247 tuple("123", 2L /* openvul1, openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
248 tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
249 tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 5));
252 private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertOwaspReport(boolean includeCwe) {
253 ComponentDto project = newPrivateProjectDto();
255 newDoc("openvul1", project).setOwaspTop10(asList("a1", "a3")).setCwe(asList("123", "456")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
256 .setSeverity(Severity.MAJOR),
257 newDoc("openvul2", project).setOwaspTop10(asList("a3", "a6")).setCwe(asList("123")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
258 .setSeverity(Severity.MINOR),
259 newDoc("notowaspvul", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
260 newDoc("toreviewhotspot1", project).setOwaspTop10(asList("a1", "a3")).setCwe(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT)
261 .setStatus(Issue.STATUS_TO_REVIEW),
262 newDoc("toreviewhotspot2", project).setOwaspTop10(asList("a3", "a6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
263 newDoc("reviewedHotspot", project).setOwaspTop10(asList("a3", "a8")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED)
264 .setResolution(Issue.RESOLUTION_FIXED),
265 newDoc("notowasphotspot", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
267 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe, Y2017);
268 assertThat(owaspTop10Report)
269 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
270 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
271 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
272 .containsExactlyInAnyOrder(
273 tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 5),
274 tuple("a2", 0L, OptionalInt.empty(), 0L, 0L, 1),
275 tuple("a3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* reviewedHotspot */, 4),
276 tuple("a4", 0L, OptionalInt.empty(), 0L, 0L, 1),
277 tuple("a5", 0L, OptionalInt.empty(), 0L, 0L, 1),
278 tuple("a6", 1L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 5),
279 tuple("a7", 0L, OptionalInt.empty(), 0L, 0L, 1),
280 tuple("a8", 0L, OptionalInt.empty(), 0L, 1L /* reviewedHotspot */, 1),
281 tuple("a9", 0L, OptionalInt.empty(), 0L, 0L, 1),
282 tuple("a10", 0L, OptionalInt.empty(), 0L, 0L, 1));
283 return owaspTop10Report;
286 private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertPciDss32Report() {
287 ComponentDto project = newPrivateProjectDto();
289 newDoc("openvul1", project).setPciDss32(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
290 .setSeverity(Severity.MAJOR),
291 newDoc("openvul2", project).setPciDss32(asList("3.3.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
292 .setSeverity(Severity.MINOR),
293 newDoc("openvul3", project).setPciDss32(asList("10.1.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
294 .setSeverity(Severity.MINOR),
295 newDoc("notpcidssvul", project).setPciDss32(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
296 newDoc("toreviewhotspot1", project).setPciDss32(asList("1.3.0", "3.3.2")).setType(RuleType.SECURITY_HOTSPOT)
297 .setStatus(Issue.STATUS_TO_REVIEW),
298 newDoc("toreviewhotspot2", project).setPciDss32(asList("3.5.6", "6.4.5")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
299 newDoc("reviewedHotspot", project).setPciDss32(asList("3.1.1", "8.6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED)
300 .setResolution(Issue.RESOLUTION_FIXED),
301 newDoc("notpcidsshotspot", project).setPciDss32(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
303 List<SecurityStandardCategoryStatistics> pciDssReport = underTest.getPciDssReport(project.uuid(), false, RulesDefinition.PciDssVersion.V3_2).stream()
304 .sorted(comparing(s -> parseInt(s.getCategory())))
306 assertThat(pciDssReport)
307 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
308 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
309 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
310 .containsExactlyInAnyOrder(
311 tuple("1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 5),
312 tuple("2", 0L, OptionalInt.empty(), 0L, 0L, 1),
313 tuple("3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* reviewedHotspot */, 4),
314 tuple("4", 0L, OptionalInt.empty(), 0L, 0L, 1),
315 tuple("5", 0L, OptionalInt.empty(), 0L, 0L, 1),
316 tuple("6", 2L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 5),
317 tuple("7", 0L, OptionalInt.empty(), 0L, 0L, 1),
318 tuple("8", 0L, OptionalInt.empty(), 0L, 1L /* reviewedHotspot */, 1),
319 tuple("9", 0L, OptionalInt.empty(), 0L, 0L, 1),
320 tuple("10", 1L, OptionalInt.of(2), 0L, 0L, 1),
321 tuple("11", 0L, OptionalInt.empty(), 0L, 0L, 1),
322 tuple("12", 0L, OptionalInt.empty(), 0L, 0L, 1));
327 private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertOwasp2021Report(boolean includeCwe) {
328 ComponentDto project = newPrivateProjectDto();
330 newDoc("openvul1", project).setOwaspTop10For2021(asList("a1", "a3")).setCwe(asList("123", "456")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
331 .setSeverity(Severity.MAJOR),
332 newDoc("openvul2", project).setOwaspTop10For2021(asList("a3", "a6")).setCwe(asList("123")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
333 .setSeverity(Severity.MINOR),
334 newDoc("notowaspvul", project).setOwaspTop10For2021(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
335 newDoc("toreviewhotspot1", project).setOwaspTop10For2021(asList("a1", "a3")).setCwe(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT)
336 .setStatus(Issue.STATUS_TO_REVIEW),
337 newDoc("toreviewhotspot2", project).setOwaspTop10For2021(asList("a3", "a6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
338 newDoc("reviewedHotspot", project).setOwaspTop10For2021(asList("a3", "a8")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED)
339 .setResolution(Issue.RESOLUTION_FIXED),
340 newDoc("notowasphotspot", project).setOwaspTop10For2021(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
342 List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe, Y2021);
343 assertThat(owaspTop10Report)
344 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
345 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
346 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
347 .containsExactlyInAnyOrder(
348 tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 5),
349 tuple("a2", 0L, OptionalInt.empty(), 0L, 0L, 1),
350 tuple("a3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* reviewedHotspot */, 4),
351 tuple("a4", 0L, OptionalInt.empty(), 0L, 0L, 1),
352 tuple("a5", 0L, OptionalInt.empty(), 0L, 0L, 1),
353 tuple("a6", 1L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 5),
354 tuple("a7", 0L, OptionalInt.empty(), 0L, 0L, 1),
355 tuple("a8", 0L, OptionalInt.empty(), 0L, 1L /* reviewedHotspot */, 1),
356 tuple("a9", 0L, OptionalInt.empty(), 0L, 0L, 1),
357 tuple("a10", 0L, OptionalInt.empty(), 0L, 0L, 1));
358 return owaspTop10Report;
362 public void getSansTop25Report_aggregation() {
363 ComponentDto project = newPrivateProjectDto();
365 newDoc("openvul1", project).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
366 .setSeverity(Severity.MAJOR),
367 newDoc("openvul2", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
368 .setSeverity(Severity.MINOR),
369 newDoc("notopenvul", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
370 .setResolution(Issue.RESOLUTION_FIXED)
371 .setSeverity(Severity.BLOCKER),
372 newDoc("notsansvul", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
373 newDoc("toreviewhotspot1", project).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT)
374 .setStatus(Issue.STATUS_TO_REVIEW),
375 newDoc("toreviewhotspot2", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT)
376 .setStatus(Issue.STATUS_TO_REVIEW),
377 newDoc("inReviewHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
378 newDoc("reviewedHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED)
379 .setResolution(Issue.RESOLUTION_FIXED),
380 newDoc("notowasphotspot", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
382 List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(project.uuid(), false, false);
383 assertThat(sansTop25Report)
384 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
385 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
386 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
387 .containsExactlyInAnyOrder(
388 tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 5),
389 tuple(SANS_TOP_25_RISKY_RESOURCE, 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */,
390 1L /* reviewedHotspot */, 4),
391 tuple(SANS_TOP_25_POROUS_DEFENSES, 1L /* openvul2 */, OptionalInt.of(2)/* MINOR = B */, 1L/* openhotspot2 */, 0L, 5));
393 assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
397 public void getSansTop25Report_aggregation_on_portfolio() {
398 ComponentDto portfolio1 = db.components().insertPrivateApplication();
399 ComponentDto portfolio2 = db.components().insertPrivateApplication();
400 ComponentDto project1 = db.components().insertPrivateProject();
401 ComponentDto project2 = db.components().insertPrivateProject();
404 newDoc("openvul1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
405 .setSeverity(Severity.MAJOR),
406 newDoc("openvul2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
407 .setSeverity(Severity.MINOR),
408 newDoc("notopenvul", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
409 .setResolution(Issue.RESOLUTION_FIXED)
410 .setSeverity(Severity.BLOCKER),
411 newDoc("notsansvul", project2).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
412 newDoc("toreviewhotspot1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT)
413 .setStatus(Issue.STATUS_TO_REVIEW),
414 newDoc("toreviewhotspot2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT)
415 .setStatus(Issue.STATUS_TO_REVIEW),
416 newDoc("reviewedHotspot", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED)
417 .setResolution(Issue.RESOLUTION_FIXED),
418 newDoc("notowasphotspot", project1).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
420 indexView(portfolio1.uuid(), singletonList(project1.uuid()));
421 indexView(portfolio2.uuid(), singletonList(project2.uuid()));
423 List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(portfolio1.uuid(), true, false);
424 assertThat(sansTop25Report)
425 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
426 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
427 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
428 .containsExactlyInAnyOrder(
429 tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 5),
430 tuple(SANS_TOP_25_RISKY_RESOURCE, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* toreviewhotspot1 */, 0L, 5),
431 tuple(SANS_TOP_25_POROUS_DEFENSES, 0L, OptionalInt.empty(), 0L, 0L, 1));
433 assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
437 public void getPciDssReport_aggregation_on_portfolio() {
438 ComponentDto portfolio1 = db.components().insertPrivateApplication();
439 ComponentDto portfolio2 = db.components().insertPrivateApplication();
440 ComponentDto project1 = db.components().insertPrivateProject();
441 ComponentDto project2 = db.components().insertPrivateProject();
444 newDoc("openvul1", project1).setPciDss32(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
445 .setSeverity(Severity.MAJOR),
446 newDoc("openvul2", project2).setPciDss32(asList("3.3.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
447 .setSeverity(Severity.MINOR),
448 newDoc("openvul3", project1).setPciDss32(asList("10.1.2", "6.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
449 .setSeverity(Severity.MINOR),
450 newDoc("notpcidssvul", project1).setPciDss32(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
451 newDoc("toreviewhotspot1", project2).setPciDss32(asList("1.3.0", "3.3.2")).setType(RuleType.SECURITY_HOTSPOT)
452 .setStatus(Issue.STATUS_TO_REVIEW),
453 newDoc("toreviewhotspot2", project1).setPciDss32(asList("3.5.6", "6.4.5")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
454 newDoc("reviewedHotspot", project2).setPciDss32(asList("3.1.1", "8.6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED)
455 .setResolution(Issue.RESOLUTION_FIXED),
456 newDoc("notpcidsshotspot", project1).setPciDss32(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
458 indexView(portfolio1.uuid(), singletonList(project1.uuid()));
459 indexView(portfolio2.uuid(), singletonList(project2.uuid()));
461 List<SecurityStandardCategoryStatistics> pciDssReport = underTest.getPciDssReport(portfolio1.uuid(), true, RulesDefinition.PciDssVersion.V3_2).stream()
462 .sorted(comparing(s -> parseInt(s.getCategory())))
464 assertThat(pciDssReport)
465 .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
466 SecurityStandardCategoryStatistics::getVulnerabilityRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
467 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots, SecurityStandardCategoryStatistics::getSecurityReviewRating)
468 .containsExactlyInAnyOrder(
469 tuple("1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 1),
470 tuple("2", 0L, OptionalInt.empty(), 0L, 0L, 1),
471 tuple("3", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* toreviewhotspot2 */, 0L, 5),
472 tuple("4", 0L, OptionalInt.empty(), 0L, 0L, 1),
473 tuple("5", 0L, OptionalInt.empty(), 0L, 0L, 1),
474 tuple("6", 1L /* openvul3 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 5),
475 tuple("7", 0L, OptionalInt.empty(), 0L, 0L, 1),
476 tuple("8", 0L, OptionalInt.empty(), 0L, 0L /* reviewedHotspot */, 1),
477 tuple("9", 0L, OptionalInt.empty(), 0L, 0L, 1),
478 tuple("10", 1L /* openvul3 */, OptionalInt.of(2), 0L, 0L, 1),
479 tuple("11", 0L, OptionalInt.empty(), 0L, 0L, 1),
480 tuple("12", 0L, OptionalInt.empty(), 0L, 0L, 1));
484 public void getCWETop25Report_aggregation() {
485 ComponentDto project = newPrivateProjectDto();
487 newDoc("openvul", project).setCwe(asList("119")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
488 .setSeverity(Severity.MAJOR),
489 newDoc("notopenvul", project).setCwe(asList("119")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
490 .setResolution(Issue.RESOLUTION_FIXED)
491 .setSeverity(Severity.BLOCKER),
492 newDoc("toreviewhotspot", project).setCwe(asList("89")).setType(RuleType.SECURITY_HOTSPOT)
493 .setStatus(Issue.STATUS_TO_REVIEW),
494 newDoc("only2020", project).setCwe(asList("862")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
495 .setSeverity(Severity.MINOR),
496 newDoc("unknown", project).setCwe(asList("999")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
497 .setSeverity(Severity.MINOR));
499 List<SecurityStandardCategoryStatistics> cweTop25Reports = underTest.getCweTop25Reports(project.uuid(), false);
501 List<String> listOfYears = cweTop25Reports.stream()
502 .map(SecurityStandardCategoryStatistics::getCategory)
505 assertThat(listOfYears).contains("2019", "2020", "2021");
507 SecurityStandardCategoryStatistics cwe2019 = cweTop25Reports.stream()
508 .filter(s -> s.getCategory().equals("2019"))
510 assertThat(cwe2019.getChildren()).hasSize(25);
511 assertThat(findRuleInCweByYear(cwe2019, "119")).isNotNull()
512 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
513 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
514 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
515 .containsExactlyInAnyOrder(1L, 0L, 0L);
516 assertThat(findRuleInCweByYear(cwe2019, "89")).isNotNull()
517 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
518 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
519 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
520 .containsExactlyInAnyOrder(0L, 1L, 0L);
521 assertThat(findRuleInCweByYear(cwe2019, "862")).isNull();
522 assertThat(findRuleInCweByYear(cwe2019, "999")).isNull();
524 SecurityStandardCategoryStatistics cwe2020 = cweTop25Reports.stream()
525 .filter(s -> s.getCategory().equals("2020"))
527 assertThat(cwe2020.getChildren()).hasSize(25);
528 assertThat(findRuleInCweByYear(cwe2020, "119")).isNotNull()
529 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
530 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
531 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
532 .containsExactlyInAnyOrder(1L, 0L, 0L);
533 assertThat(findRuleInCweByYear(cwe2020, "89")).isNotNull()
534 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
535 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
536 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
537 .containsExactlyInAnyOrder(0L, 1L, 0L);
538 assertThat(findRuleInCweByYear(cwe2020, "862")).isNotNull()
539 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
540 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
541 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
542 .containsExactlyInAnyOrder(1L, 0L, 0L);
543 assertThat(findRuleInCweByYear(cwe2020, "999")).isNull();
545 SecurityStandardCategoryStatistics cwe2021 = cweTop25Reports.stream()
546 .filter(s -> s.getCategory().equals("2021"))
548 assertThat(cwe2021.getChildren()).hasSize(25);
549 assertThat(findRuleInCweByYear(cwe2021, "119")).isNotNull()
550 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
551 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
552 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
553 .containsExactlyInAnyOrder(1L, 0L, 0L);
554 assertThat(findRuleInCweByYear(cwe2021, "89")).isNotNull()
555 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
556 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
557 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
558 .containsExactlyInAnyOrder(0L, 1L, 0L);
559 assertThat(findRuleInCweByYear(cwe2021, "295")).isNull();
560 assertThat(findRuleInCweByYear(cwe2021, "999")).isNull();
564 public void getCWETop25Report_aggregation_on_portfolio() {
565 ComponentDto application = db.components().insertPrivateApplication();
566 ComponentDto project1 = db.components().insertPrivateProject();
567 ComponentDto project2 = db.components().insertPrivateProject();
570 newDoc("openvul1", project1).setCwe(asList("119")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
571 .setSeverity(Severity.MAJOR),
572 newDoc("openvul2", project2).setCwe(asList("119")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
573 .setSeverity(Severity.MINOR),
574 newDoc("toreviewhotspot", project1).setCwe(asList("89")).setType(RuleType.SECURITY_HOTSPOT)
575 .setStatus(Issue.STATUS_TO_REVIEW),
576 newDoc("only2020", project2).setCwe(asList("862")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
577 .setSeverity(Severity.MINOR),
578 newDoc("unknown", project2).setCwe(asList("999")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
579 .setSeverity(Severity.MINOR));
581 indexView(application.uuid(), asList(project1.uuid(), project2.uuid()));
583 List<SecurityStandardCategoryStatistics> cweTop25Reports = underTest.getCweTop25Reports(application.uuid(), true);
585 List<String> listOfYears = cweTop25Reports.stream()
586 .map(SecurityStandardCategoryStatistics::getCategory)
589 assertThat(listOfYears).contains("2019", "2020", "2021");
591 SecurityStandardCategoryStatistics cwe2019 = cweTop25Reports.stream()
592 .filter(s -> s.getCategory().equals("2019"))
594 assertThat(cwe2019.getChildren()).hasSize(25);
595 assertThat(findRuleInCweByYear(cwe2019, "119")).isNotNull()
596 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
597 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
598 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
599 .containsExactlyInAnyOrder(2L, 0L, 0L);
600 assertThat(findRuleInCweByYear(cwe2019, "89")).isNotNull()
601 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
602 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
603 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
604 .containsExactlyInAnyOrder(0L, 1L, 0L);
605 assertThat(findRuleInCweByYear(cwe2019, "862")).isNull();
606 assertThat(findRuleInCweByYear(cwe2019, "999")).isNull();
608 SecurityStandardCategoryStatistics cwe2020 = cweTop25Reports.stream()
609 .filter(s -> s.getCategory().equals("2020"))
611 assertThat(cwe2020.getChildren()).hasSize(25);
612 assertThat(findRuleInCweByYear(cwe2020, "119")).isNotNull()
613 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
614 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
615 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
616 .containsExactlyInAnyOrder(2L, 0L, 0L);
617 assertThat(findRuleInCweByYear(cwe2020, "89")).isNotNull()
618 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
619 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
620 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
621 .containsExactlyInAnyOrder(0L, 1L, 0L);
622 assertThat(findRuleInCweByYear(cwe2020, "862")).isNotNull()
623 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
624 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
625 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
626 .containsExactlyInAnyOrder(1L, 0L, 0L);
627 assertThat(findRuleInCweByYear(cwe2020, "999")).isNull();
629 SecurityStandardCategoryStatistics cwe2021 = cweTop25Reports.stream()
630 .filter(s -> s.getCategory().equals("2021"))
632 assertThat(cwe2021.getChildren()).hasSize(25);
633 assertThat(findRuleInCweByYear(cwe2021, "119")).isNotNull()
634 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
635 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
636 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
637 .containsExactlyInAnyOrder(2L, 0L, 0L);
638 assertThat(findRuleInCweByYear(cwe2021, "89")).isNotNull()
639 .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
640 SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
641 SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
642 .containsExactlyInAnyOrder(0L, 1L, 0L);
643 assertThat(findRuleInCweByYear(cwe2021, "295")).isNull();
644 assertThat(findRuleInCweByYear(cwe2021, "999")).isNull();
647 private SecurityStandardCategoryStatistics findRuleInCweByYear(SecurityStandardCategoryStatistics statistics, String cweId) {
648 return statistics.getChildren().stream().filter(stat -> stat.getCategory().equals(cweId)).findAny().orElse(null);
651 private void indexView(String viewUuid, List<String> projects) {
652 viewIndexer.index(new ViewDoc().setUuid(viewUuid).setProjects(projects));