Skip to content

Commit cc724b0

Browse files
authored
Merge pull request #199 from ruromero/common-issues
fix: show issues from dependencies
2 parents 31a4fdd + 5822528 commit cc724b0

File tree

9 files changed

+800
-163
lines changed

9 files changed

+800
-163
lines changed

src/main/java/com/redhat/exhort/integration/backend/sbom/cyclonedx/CycloneDxParser.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ private Map<PackageRef, DirectDependency> buildDependencies(
8989
if (bom.getDependencies() == null || bom.getDependencies().isEmpty()) {
9090
return buildUnknownDependencies(componentPurls);
9191
}
92-
Map<PackageRef, DirectDependency.Builder> direct = new HashMap<>();
92+
Map<PackageRef, DirectDependency.Builder> directDepBuilders = new HashMap<>();
9393
if (rootRef == null) {
9494
var transitive =
9595
bom.getDependencies().stream()
@@ -104,36 +104,39 @@ private Map<PackageRef, DirectDependency> buildDependencies(
104104
.forEach(
105105
dref -> {
106106
PackageRef r = componentPurls.get(dref);
107-
direct.put(r, DirectDependency.builder().ref(r).transitive(new HashSet<>()));
107+
directDepBuilders.put(
108+
r, DirectDependency.builder().ref(r).transitive(new HashSet<>()));
108109
});
109110
}
110111
bom.getDependencies().stream()
111112
.forEach(
112-
d -> {
113-
if (d.getRef().equals(rootRef)) {
114-
d.getDependencies()
113+
bomDep -> {
114+
if (bomDep.getRef().equals(rootRef)) {
115+
bomDep
116+
.getDependencies()
115117
.forEach(
116118
rootDep -> {
117119
var ref = componentPurls.get(rootDep.getRef());
118-
direct.put(
120+
directDepBuilders.put(
119121
ref, DirectDependency.builder().ref(ref).transitive(new HashSet<>()));
120122
});
121-
} else if (d.getDependencies() != null) {
122-
var source = componentPurls.get(d.getRef());
123-
var directBuilder = direct.get(source);
123+
} else if (bomDep.getDependencies() != null) {
124+
var source = componentPurls.get(bomDep.getRef());
125+
var directBuilder = directDepBuilders.get(source);
124126
if (directBuilder == null) {
125-
direct.values().stream()
126-
.filter(v -> v.transitive.contains(source))
127+
directDepBuilders.values().stream()
127128
.forEach(
128-
v ->
129-
d.getDependencies()
129+
builder ->
130+
bomDep
131+
.getDependencies()
130132
.forEach(
131133
t -> {
132134
PackageRef target = componentPurls.get(t.getRef());
133-
v.transitive.add(target);
135+
builder.transitive.add(target);
134136
}));
135137
} else {
136-
d.getDependencies()
138+
bomDep
139+
.getDependencies()
137140
.forEach(
138141
t -> {
139142
PackageRef target = componentPurls.get(t.getRef());
@@ -142,7 +145,7 @@ private Map<PackageRef, DirectDependency> buildDependencies(
142145
}
143146
}
144147
});
145-
return direct.entrySet().stream()
148+
return directDepBuilders.entrySet().stream()
146149
.map(e -> Map.entry(e.getKey(), e.getValue().build()))
147150
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));
148151
}

src/main/java/com/redhat/exhort/integration/providers/ProviderResponseHandler.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,10 @@ public Source buildReportForSource(
203203
List<DependencyReport> sourceReport = new ArrayList<>();
204204
tree.dependencies().entrySet().stream()
205205
.forEach(
206-
e -> {
207-
var ref = e.getKey().ref();
206+
depEntry -> {
207+
var ref = depEntry.getKey().ref();
208208
var issues = issuesData.get(ref);
209-
var directReport = new DependencyReport().ref(e.getKey());
209+
var directReport = new DependencyReport().ref(depEntry.getKey());
210210
if (issues == null) {
211211
issues = Collections.emptyList();
212212
}
@@ -216,7 +216,7 @@ public Source buildReportForSource(
216216
.collect(Collectors.toList()));
217217
directReport.setHighestVulnerability(issues.stream().findFirst().orElse(null));
218218
List<TransitiveDependencyReport> transitiveReports =
219-
e.getValue().transitive().stream()
219+
depEntry.getValue().transitive().stream()
220220
.map(
221221
t -> {
222222
List<Issue> transitiveIssues = Collections.emptyList();
@@ -240,7 +240,7 @@ public Source buildReportForSource(
240240
.issues(transitiveIssues)
241241
.highestVulnerability(highestTransitive.orElse(null));
242242
})
243-
.filter(d -> !d.getIssues().isEmpty())
243+
.filter(transitiveReport -> !transitiveReport.getIssues().isEmpty())
244244
.collect(Collectors.toList());
245245
transitiveReports.sort(Collections.reverseOrder(new TransitiveScoreComparator()));
246246
directReport.setTransitive(transitiveReports);

src/test/java/com/redhat/exhort/integration/AbstractAnalysisTest.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,10 @@
4242
import org.cyclonedx.CycloneDxMediaType;
4343
import org.junit.jupiter.api.AfterEach;
4444

45-
import com.fasterxml.jackson.databind.JsonNode;
46-
import com.fasterxml.jackson.databind.ObjectMapper;
4745
import com.github.jknack.handlebars.internal.Files;
4846
import com.github.tomakehurst.wiremock.WireMockServer;
4947
import com.github.tomakehurst.wiremock.client.BasicCredentials;
5048
import com.google.common.base.Charsets;
51-
import com.redhat.exhort.config.ObjectMapperProducer;
5249
import com.redhat.exhort.extensions.InjectWireMock;
5350
import com.redhat.exhort.extensions.WiremockV3Extension;
5451

@@ -89,14 +86,16 @@ void resetMock() {
8986
}
9087

9188
protected void assertJson(String expectedFile, String currentBody) {
92-
ObjectMapper mapper = ObjectMapperProducer.newInstance();
93-
JsonNode current;
9489
try {
95-
current = mapper.readTree(currentBody);
96-
JsonNode expected =
97-
mapper.readTree(
98-
getClass().getClassLoader().getResourceAsStream("__files/" + expectedFile));
99-
assertEquals(expected, current);
90+
var expectedContent =
91+
new String(
92+
getClass()
93+
.getClassLoader()
94+
.getResourceAsStream("__files/" + expectedFile)
95+
.readAllBytes());
96+
assertTrue(
97+
equalToJson(expectedContent, true, false).match(currentBody).isExactMatch(),
98+
String.format("Expecting: %s \nGot: %s", expectedContent, currentBody));
10099
} catch (IOException e) {
101100
fail("Unexpected processing exception");
102101
}
@@ -279,7 +278,8 @@ protected void stubSnykRequests() {
279278
.withHeader(
280279
"Authorization", equalTo("token " + OK_TOKEN).or(equalTo("token " + SNYK_TOKEN)))
281280
.withHeader(Exchange.CONTENT_TYPE, equalTo(MediaType.APPLICATION_JSON))
282-
.withRequestBody(equalToJson(loadFileAsString("__files/snyk/maven_request.json")))
281+
.withRequestBody(
282+
equalToJson(loadFileAsString("__files/snyk/maven_request.json"), true, false))
283283
.willReturn(
284284
aResponse()
285285
.withStatus(200)
@@ -335,7 +335,9 @@ private void stubSnykEmptyRequest(String provider) {
335335
.withRequestBody(
336336
equalToJson(
337337
loadFileAsString("__files/snyk/empty_request.json")
338-
.replaceAll("__PKG_MANAGER__", provider)))
338+
.replaceAll("__PKG_MANAGER__", provider),
339+
true,
340+
false))
339341
.willReturn(
340342
aResponse()
341343
.withStatus(200)
@@ -360,13 +362,15 @@ protected void stubOssToken() {
360362
post(Constants.OSS_INDEX_AUTH_COMPONENT_API_PATH)
361363
.withBasicAuth(OK_USER, OK_TOKEN)
362364
.withHeader(Exchange.CONTENT_TYPE, equalTo(MediaType.APPLICATION_JSON))
363-
.withRequestBody(equalToJson(loadFileAsString("__files/ossindex/empty_request.json")))
365+
.withRequestBody(
366+
equalToJson(loadFileAsString("__files/ossindex/empty_request.json"), true, false))
364367
.willReturn(aResponse().withStatus(200).withBodyFile("ossindex/empty_report.json")));
365368
server.stubFor(
366369
post(Constants.OSS_INDEX_AUTH_COMPONENT_API_PATH)
367370
.withBasicAuth(OK_USER, OK_TOKEN)
368371
.withHeader(Exchange.CONTENT_TYPE, equalTo(MediaType.APPLICATION_JSON))
369-
.withRequestBody(equalToJson(loadFileAsString("__files/ossindex/maven_request.json")))
372+
.withRequestBody(
373+
equalToJson(loadFileAsString("__files/ossindex/maven_request.json"), true, false))
370374
.willReturn(aResponse().withStatus(200).withBodyFile("ossindex/maven_report.json")));
371375
server.stubFor(
372376
post(Constants.OSS_INDEX_AUTH_COMPONENT_API_PATH)

src/test/java/com/redhat/exhort/integration/AnalysisV3Test.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import java.util.Collections;
3434
import java.util.List;
3535
import java.util.Map;
36-
import java.util.Optional;
3736
import java.util.stream.Stream;
3837

3938
import org.cyclonedx.CycloneDxMediaType;
@@ -44,7 +43,6 @@
4443
import org.junit.jupiter.params.provider.ValueSource;
4544

4645
import com.redhat.exhort.api.v3.AnalysisReport;
47-
import com.redhat.exhort.api.v3.ProviderStatus;
4846

4947
import io.quarkus.test.junit.QuarkusTest;
5048

@@ -63,7 +61,7 @@ public void testEmptySbom(
6361
List<String> providers, Map<String, String> authHeaders, String pkgManager) {
6462
stubAllProviders();
6563

66-
AnalysisReport report =
64+
var report =
6765
given()
6866
.header(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
6967
.headers(authHeaders)
@@ -80,7 +78,7 @@ public void testEmptySbom(
8078

8179
providers.forEach(
8280
p -> {
83-
Optional<ProviderStatus> provider =
81+
var provider =
8482
report.getSummary().getProviderStatuses().stream()
8583
.filter(s -> s.getProvider().equals(p))
8684
.findFirst();
@@ -144,7 +142,7 @@ private static Stream<Arguments> emptySbomArguments() {
144142
public void testAllWithToken() {
145143
stubAllProviders();
146144

147-
String body =
145+
var body =
148146
given()
149147
.header(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
150148
.header("Accept", MediaType.APPLICATION_JSON)
@@ -171,7 +169,7 @@ public void testAllWithToken() {
171169
public void testSnykWithNoToken() {
172170
stubAllProviders();
173171

174-
String body =
172+
var body =
175173
given()
176174
.header(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
177175
.header("Accept", MediaType.APPLICATION_JSON)
@@ -195,7 +193,7 @@ public void testSnykWithNoToken() {
195193
public void testUnauthorizedRequest() {
196194
stubAllProviders();
197195

198-
AnalysisReport report =
196+
var report =
199197
given()
200198
.header(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
201199
.body(loadFileAsString(String.format("%s/empty-sbom.json", CYCLONEDX)))
@@ -212,7 +210,7 @@ public void testUnauthorizedRequest() {
212210
.as(AnalysisReport.class);
213211

214212
assertEquals(1, report.getSummary().getProviderStatuses().size());
215-
ProviderStatus status = report.getSummary().getProviderStatuses().get(0);
213+
var status = report.getSummary().getProviderStatuses().get(0);
216214
assertFalse(status.getOk());
217215
assertEquals(Constants.SNYK_PROVIDER, status.getProvider());
218216
assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), status.getStatus());
@@ -224,7 +222,7 @@ public void testUnauthorizedRequest() {
224222
public void testForbiddenRequest() {
225223
stubAllProviders();
226224

227-
AnalysisReport report =
225+
var report =
228226
given()
229227
.header(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
230228
.body(loadFileAsString(String.format("%s/empty-sbom.json", CYCLONEDX)))
@@ -241,7 +239,7 @@ public void testForbiddenRequest() {
241239
.as(AnalysisReport.class);
242240

243241
assertEquals(1, report.getSummary().getProviderStatuses().size());
244-
ProviderStatus status = report.getSummary().getProviderStatuses().get(0);
242+
var status = report.getSummary().getProviderStatuses().get(0);
245243
assertFalse(status.getOk());
246244
assertEquals(Constants.SNYK_PROVIDER, status.getProvider());
247245
assertEquals(Response.Status.FORBIDDEN.getStatusCode(), status.getStatus());
@@ -254,8 +252,8 @@ public void testForbiddenRequest() {
254252
public void testMultipart_HttpVersions(String version) throws IOException, InterruptedException {
255253
stubAllProviders();
256254

257-
HttpClient client = HttpClient.newHttpClient();
258-
HttpRequest request =
255+
var client = HttpClient.newHttpClient();
256+
var request =
259257
HttpRequest.newBuilder(URI.create("http://localhost:8081/api/v3/analysis"))
260258
.setHeader(Constants.RHDA_TOKEN_HEADER, DEFAULT_RHDA_TOKEN)
261259
.setHeader(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
@@ -267,7 +265,7 @@ public void testMultipart_HttpVersions(String version) throws IOException, Inter
267265
.POST(HttpRequest.BodyPublishers.ofFile(loadSBOMFile(CYCLONEDX).toPath()))
268266
.build();
269267

270-
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
268+
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
271269

272270
assertEquals(Response.Status.OK.getStatusCode(), response.statusCode());
273271

src/test/java/com/redhat/exhort/integration/backend/sbom/SbomParserTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ void testComplexGolangCycloneDX() {
163163
var tree = parser.buildTree(file);
164164

165165
assertEquals(40, tree.dependencies().size());
166-
assertEquals(485, tree.transitiveCount());
166+
assertEquals(900, tree.transitiveCount());
167167
}
168168

169169
static Stream<String> getMediaTypes() {

0 commit comments

Comments
 (0)