]> source.dussan.org Git - sonarqube.git/blob
68833a8312dc04973e0cfdf64420a42180d95e70
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2020 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.issue.index;
21
22 import java.util.List;
23 import java.util.Map;
24 import java.util.OptionalInt;
25 import java.util.stream.Collectors;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.rules.ExpectedException;
29 import org.sonar.api.issue.Issue;
30 import org.sonar.api.rule.Severity;
31 import org.sonar.api.rules.RuleType;
32 import org.sonar.api.utils.System2;
33 import org.sonar.api.impl.utils.TestSystem2;
34 import org.sonar.db.DbTester;
35 import org.sonar.db.component.ComponentDto;
36 import org.sonar.db.organization.OrganizationDto;
37 import org.sonar.server.es.EsTester;
38 import org.sonar.server.permission.index.IndexPermissions;
39 import org.sonar.server.permission.index.PermissionIndexerTester;
40 import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
41 import org.sonar.server.tester.UserSessionRule;
42 import org.sonar.server.view.index.ViewDoc;
43 import org.sonar.server.view.index.ViewIndexer;
44
45 import static java.util.Arrays.asList;
46 import static java.util.Arrays.stream;
47 import static java.util.Collections.singletonList;
48 import static java.util.TimeZone.getTimeZone;
49 import static java.util.stream.Collectors.toList;
50 import static org.assertj.core.api.Assertions.assertThat;
51 import static org.assertj.core.api.Assertions.tuple;
52 import static org.junit.rules.ExpectedException.none;
53 import static org.sonar.api.resources.Qualifiers.PROJECT;
54 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
55 import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
56 import static org.sonar.server.issue.IssueDocTesting.newDoc;
57 import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION;
58 import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES;
59 import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE;
60 import static org.sonar.server.security.SecurityStandardHelper.UNKNOWN_STANDARD;
61
62 public class IssueIndexSecurityReportsTest {
63
64   @Rule
65   public EsTester es = EsTester.create();
66   @Rule
67   public UserSessionRule userSessionRule = UserSessionRule.standalone();
68   @Rule
69   public ExpectedException expectedException = none();
70   private System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00"));
71   @Rule
72   public DbTester db = DbTester.create(system2);
73
74   private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()));
75   private ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client());
76   private PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer);
77
78   private IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule));
79
80   @Test
81   public void getOwaspTop10Report_dont_count_vulnerabilities_from_other_projects() {
82     OrganizationDto org = newOrganizationDto();
83     ComponentDto project = newPrivateProjectDto(org);
84     ComponentDto another = newPrivateProjectDto(org);
85     indexIssues(
86       newDoc("anotherProject", another).setOwaspTop10(singletonList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
87       newDoc("openvul1", project).setOwaspTop10(singletonList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR));
88
89     List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
90     assertThat(owaspTop10Report)
91       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
92         SecurityStandardCategoryStatistics::getVulnerabiliyRating)
93       .contains(
94         tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */));
95
96   }
97
98   @Test
99   public void getOwaspTop10Report_dont_count_closed_vulnerabilities() {
100     OrganizationDto org = newOrganizationDto();
101     ComponentDto project = newPrivateProjectDto(org);
102     indexIssues(
103       newDoc("openvul1", project).setOwaspTop10(asList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR),
104       newDoc("notopenvul", project).setOwaspTop10(asList("a1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_FIXED)
105         .setSeverity(Severity.BLOCKER));
106
107     List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
108     assertThat(owaspTop10Report)
109       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
110         SecurityStandardCategoryStatistics::getVulnerabiliyRating)
111       .contains(
112         tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */));
113   }
114
115   @Test
116   public void getOwaspTop10Report_dont_count_old_vulnerabilities() {
117     OrganizationDto org = newOrganizationDto();
118     ComponentDto project = newPrivateProjectDto(org);
119     indexIssues(
120       // Previous vulnerabilities in projects that are not reanalyzed will have no owasp nor cwe attributes (not even 'unknown')
121       newDoc("openvulNotReindexed", project).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR));
122
123     List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
124     assertThat(owaspTop10Report)
125       .extracting(SecurityStandardCategoryStatistics::getVulnerabilities,
126         SecurityStandardCategoryStatistics::getVulnerabiliyRating)
127       .containsOnly(
128         tuple(0L, OptionalInt.empty()));
129   }
130
131   @Test
132   public void getOwaspTop10Report_dont_count_hotspots_from_other_projects() {
133     OrganizationDto org = newOrganizationDto();
134     ComponentDto project = newPrivateProjectDto(org);
135     ComponentDto another = newPrivateProjectDto(org);
136     indexIssues(
137       newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
138       newDoc("anotherProject", another).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
139
140     List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
141     assertThat(owaspTop10Report)
142       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
143       .contains(
144         tuple("a1", 1L /* openhotspot1 */));
145   }
146
147   @Test
148   public void getOwaspTop10Report_dont_count_closed_hotspots() {
149     OrganizationDto org = newOrganizationDto();
150     ComponentDto project = newPrivateProjectDto(org);
151     indexIssues(
152       newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
153       newDoc("closedHotspot", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_CLOSED)
154         .setResolution(Issue.RESOLUTION_FIXED));
155
156     List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
157     assertThat(owaspTop10Report)
158       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
159       .contains(
160         tuple("a1", 1L /* openhotspot1 */));
161   }
162
163   @Test
164   public void getOwaspTop10Report_aggregation_no_cwe() {
165     List<SecurityStandardCategoryStatistics> owaspTop10Report = indexIssuesAndAssertOwaspReport(false);
166
167     assertThat(owaspTop10Report).allMatch(category -> category.getChildren().isEmpty());
168   }
169
170   @Test
171   public void getOwaspTop10Report_aggregation_with_cwe() {
172     List<SecurityStandardCategoryStatistics> owaspTop10Report = indexIssuesAndAssertOwaspReport(true);
173
174     Map<String, List<SecurityStandardCategoryStatistics>> cweByOwasp = owaspTop10Report.stream()
175       .collect(Collectors.toMap(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getChildren));
176
177     assertThat(cweByOwasp.get("a1")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
178       SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
179       SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
180       .containsExactlyInAnyOrder(
181         tuple("123", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 0L),
182         tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 0L),
183         tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 0L));
184     assertThat(cweByOwasp.get("a3")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
185       SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
186       SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
187       .containsExactlyInAnyOrder(
188         tuple("123", 2L /* openvul1, openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 0L),
189         tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 1L /* toReviewHotspot */, 0L),
190         tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 0L));
191   }
192
193   private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertOwaspReport(boolean includeCwe) {
194     OrganizationDto org = newOrganizationDto();
195     ComponentDto project = newPrivateProjectDto(org);
196     indexIssues(
197       newDoc("openvul1", project).setOwaspTop10(asList("a1", "a3")).setCwe(asList("123", "456")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR),
198       newDoc("openvul2", project).setOwaspTop10(asList("a3", "a6")).setCwe(asList("123")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED).setSeverity(Severity.MINOR),
199       newDoc("notowaspvul", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
200       newDoc("toreviewhotspot1", project).setOwaspTop10(asList("a1", "a3")).setCwe(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
201       newDoc("toreviewhotspot2", project).setOwaspTop10(asList("a3", "a6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
202       newDoc("inreviewhotspot", project).setOwaspTop10(asList("a5", "a3")).setCwe(asList("456")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
203       newDoc("reviewedHotspot", project).setOwaspTop10(asList("a3", "a8")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setResolution(Issue.RESOLUTION_FIXED),
204       newDoc("notowasphotspot", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
205
206     List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe);
207     assertThat(owaspTop10Report)
208       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
209         SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
210         SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
211       .containsExactlyInAnyOrder(
212         tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 0L),
213         tuple("a2", 0L, OptionalInt.empty(), 0L, 0L, 0L),
214         tuple("a3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* inReviewHotspot */, 1L /* reviewedHotspot */),
215         tuple("a4", 0L, OptionalInt.empty(), 0L, 0L, 0L),
216         tuple("a5", 0L, OptionalInt.empty(), 0L, 1L/* inReviewHotspot */, 0L),
217         tuple("a6", 1L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 0L),
218         tuple("a7", 0L, OptionalInt.empty(), 0L, 0L, 0L),
219         tuple("a8", 0L, OptionalInt.empty(), 0L, 0L, 1L /* reviewedHotspot */),
220         tuple("a9", 0L, OptionalInt.empty(), 0L, 0L, 0L),
221         tuple("a10", 0L, OptionalInt.empty(), 0L, 0L, 0L));
222     return owaspTop10Report;
223   }
224
225   @Test
226   public void getSansTop25Report_aggregation() {
227     OrganizationDto org = newOrganizationDto();
228     ComponentDto project = newPrivateProjectDto(org);
229     indexIssues(
230       newDoc("openvul1", project).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
231         .setSeverity(Severity.MAJOR),
232       newDoc("openvul2", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
233         .setSeverity(Severity.MINOR),
234       newDoc("notopenvul", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
235         .setResolution(Issue.RESOLUTION_FIXED)
236         .setSeverity(Severity.BLOCKER),
237       newDoc("notsansvul", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
238       newDoc("toreviewhotspot1", project).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
239       newDoc("toreviewhotspot2", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
240       newDoc("inReviewHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
241       newDoc("reviewedHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setResolution(Issue.RESOLUTION_FIXED),
242       newDoc("notowasphotspot", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
243
244     List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(project.uuid(), false, false);
245     assertThat(sansTop25Report)
246       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
247         SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
248         SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
249       .containsExactlyInAnyOrder(
250         tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 0L),
251         tuple(SANS_TOP_25_RISKY_RESOURCE, 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* inReviewHotspot */,1L /* reviewedHotspot */),
252         tuple(SANS_TOP_25_POROUS_DEFENSES, 1L /* openvul2 */, OptionalInt.of(2)/* MINOR = B */, 1L/* openhotspot2 */, 0L, 0L));
253
254     assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
255   }
256
257   @Test
258   public void getSansTop25Report_aggregation_on_portfolio() {
259     ComponentDto portfolio1 = db.components().insertPrivateApplication(db.getDefaultOrganization());
260     ComponentDto portfolio2 = db.components().insertPrivateApplication(db.getDefaultOrganization());
261     ComponentDto project1 = db.components().insertPrivateProject();
262     ComponentDto project2 = db.components().insertPrivateProject();
263
264     indexIssues(
265       newDoc("openvul1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
266         .setSeverity(Severity.MAJOR),
267       newDoc("openvul2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
268         .setSeverity(Severity.MINOR),
269       newDoc("notopenvul", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
270         .setResolution(Issue.RESOLUTION_FIXED)
271         .setSeverity(Severity.BLOCKER),
272       newDoc("notsansvul", project2).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
273       newDoc("toreviewhotspot1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
274       newDoc("toreviewhotspot2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
275       newDoc("inReviewHotspot", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
276       newDoc("reviewedHotspot", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setResolution(Issue.RESOLUTION_FIXED),
277       newDoc("notowasphotspot", project1).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
278
279     indexView(portfolio1.uuid(), singletonList(project1.uuid()));
280     indexView(portfolio2.uuid(), singletonList(project2.uuid()));
281
282     List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(portfolio1.uuid(), true, false);
283     assertThat(sansTop25Report)
284       .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
285         SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
286         SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getReviewedSecurityHotspots)
287       .containsExactlyInAnyOrder(
288         tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 0L),
289         tuple(SANS_TOP_25_RISKY_RESOURCE, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* toreviewhotspot1 */, 1L /* inReviewHotspot */, 0L),
290         tuple(SANS_TOP_25_POROUS_DEFENSES, 0L, OptionalInt.empty(), 0L, 0L, 0L));
291
292     assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
293   }
294
295   private void indexIssues(IssueDoc... issues) {
296     issueIndexer.index(asList(issues).iterator());
297     authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList()));
298   }
299
300   private void indexView(String viewUuid, List<String> projects) {
301     viewIndexer.index(new ViewDoc().setUuid(viewUuid).setProjects(projects));
302   }
303
304 }