Skip to content

Commit ead57a2

Browse files
authored
Merge pull request #271 from ruromero/multi-pkg
feat: add multi-package support for snyk
2 parents c6246ab + d54be1c commit ead57a2

File tree

22 files changed

+338
-161
lines changed

22 files changed

+338
-161
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@
214214
<groupId>net.sourceforge.htmlunit</groupId>
215215
<artifactId>htmlunit</artifactId>
216216
<version>${htmlunit.version}</version>
217+
<scope>test</scope>
217218
</dependency>
218219
</dependencies>
219220
<build>

src/main/java/com/redhat/exhort/integration/Constants.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,16 @@ private Constants() {}
5858

5959
public static final String HTTP_UNAUTHENTICATED = "Unauthenticated";
6060

61-
public static final String MAVEN_PKG_MANAGER = "maven";
62-
public static final String NPM_PKG_MANAGER = "npm";
63-
public static final String PYPI_PKG_MANAGER = "pypi";
64-
public static final String GOLANG_PKG_MANAGER = "golang";
61+
// PURL Types used in the application. See Snyk Supported PURL Types
62+
public static final String MAVEN_PURL_TYPE = "maven";
63+
public static final String NPM_PURL_TYPE = "npm";
64+
public static final String PYPI_PURL_TYPE = "pypi";
65+
public static final String GOLANG_PURL_TYPE = "golang";
66+
public static final String DEB_PURL_TYPE = "deb";
67+
public static final String NUGET_PURL_TYPE = "nuget";
68+
public static final String GEM_PURL_TYPE = "gem";
69+
public static final String COCOAPODS_PURL_TYPE = "cocoapods";
70+
public static final String RPM_PURL_TYPE = "rpm";
6571

6672
public static final String PKG_MANAGER_PROPERTY = "pkgManager";
6773
public static final String REQUEST_CONTENT_PROPERTY = "requestContent";

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@ protected DependencyTree buildTree(InputStream input) {
7373
rootRef = new PackageRef(rootComponent.get().getPurl());
7474
} else if (componentPurls.containsKey(rootComponent.get().getBomRef())) {
7575
rootRef = componentPurls.get(rootComponent.get().getBomRef());
76-
} else {
77-
throw new IllegalStateException("Cannot retrieve the purl for the root component");
7876
}
7977
}
8078
return treeBuilder.dependencies(buildDependencies(bom, componentPurls, rootRef)).build();

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,33 @@ public abstract class ProviderResponseHandler {
7777
public abstract ProviderResponse responseToIssues(
7878
byte[] response, String privateProviders, DependencyTree tree) throws IOException;
7979

80+
public ProviderResponse aggregateSplit(ProviderResponse oldExchange, ProviderResponse newExchange)
81+
throws IOException {
82+
if (oldExchange == null) {
83+
return newExchange;
84+
}
85+
if (oldExchange.status() != null && !Boolean.TRUE.equals(oldExchange.status().getOk())) {
86+
return oldExchange;
87+
}
88+
oldExchange
89+
.issues()
90+
.entrySet()
91+
.forEach(
92+
e -> {
93+
var issues = newExchange.issues().get(e.getKey());
94+
if (issues != null) {
95+
e.getValue().addAll(issues);
96+
}
97+
});
98+
newExchange.issues().keySet().stream()
99+
.filter(k -> !oldExchange.issues().keySet().contains(k))
100+
.forEach(
101+
k -> {
102+
oldExchange.issues().put(k, newExchange.issues().get(k));
103+
});
104+
return oldExchange;
105+
}
106+
80107
protected ProviderStatus defaultOkStatus(String provider) {
81108
return new ProviderStatus()
82109
.name(provider)
@@ -122,7 +149,7 @@ public void processResponseError(Exchange exchange) {
122149
LOGGER.warn("Unable to process request: {}", message, cause);
123150
} else if (cause instanceof IllegalArgumentException) {
124151
status.message(cause.getMessage()).code(422);
125-
LOGGER.warn("Unable to process request to: {}", getProviderName(), exception);
152+
LOGGER.debug("Unable to process request to: {}", getProviderName(), exception);
126153
} else {
127154
status
128155
.message(cause.getMessage())

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public List<String> getProviderEndpoints(
7676
.map(
7777
p ->
7878
switch (p) {
79-
case Constants.SNYK_PROVIDER -> "direct:snykDepGraph";
79+
case Constants.SNYK_PROVIDER -> "direct:snykScan";
8080
case Constants.OSS_INDEX_PROVIDER -> "direct:ossIndexScan";
8181
case Constants.OSV_NVD_PROVIDER -> "direct:osvNvdScan";
8282
default -> throw new IllegalArgumentException("Unexpected provider: " + p);

src/main/java/com/redhat/exhort/integration/providers/ossindex/OssIndexIntegration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void configure() {
8989
.timeoutEnabled(true)
9090
.timeoutDuration(timeout)
9191
.end()
92-
.setBody(constant(List.of(DependencyTree.getDefaultRoot(Constants.MAVEN_PKG_MANAGER))))
92+
.setBody(constant(List.of(DependencyTree.getDefaultRoot(Constants.MAVEN_PURL_TYPE))))
9393
.transform().method(OssIndexRequestBuilder.class, "buildRequest")
9494
.process(this::processComponentRequest)
9595
.to(vertxHttp("{{api.ossindex.host}}"))

src/main/java/com/redhat/exhort/integration/providers/ossindex/OssIndexRequestBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package com.redhat.exhort.integration.providers.ossindex;
2020

2121
import java.util.ArrayList;
22+
import java.util.Collection;
2223
import java.util.List;
2324

2425
import org.apache.camel.Body;
@@ -59,7 +60,7 @@ public List<List<PackageRef>> split(DependencyTree tree) {
5960
return bulks;
6061
}
6162

62-
public boolean isEmpty(@Body List<List<PackageRef>> body) {
63+
public boolean isEmpty(@Body Collection<List<PackageRef>> body) {
6364
return body == null || body.isEmpty();
6465
}
6566

src/main/java/com/redhat/exhort/integration/providers/ossindex/OssIndexResponseHandler.java

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -57,33 +57,6 @@ public class OssIndexResponseHandler extends ProviderResponseHandler {
5757

5858
@Inject ObjectMapper mapper;
5959

60-
public ProviderResponse aggregateSplit(ProviderResponse oldExchange, ProviderResponse newExchange)
61-
throws IOException {
62-
if (oldExchange == null) {
63-
return newExchange;
64-
}
65-
if (oldExchange.status() != null && !Boolean.TRUE.equals(oldExchange.status().getOk())) {
66-
return oldExchange;
67-
}
68-
oldExchange
69-
.issues()
70-
.entrySet()
71-
.forEach(
72-
e -> {
73-
var issues = newExchange.issues().get(e.getKey());
74-
if (issues != null) {
75-
e.getValue().addAll(issues);
76-
}
77-
});
78-
newExchange.issues().keySet().stream()
79-
.filter(k -> !oldExchange.issues().keySet().contains(k))
80-
.forEach(
81-
k -> {
82-
oldExchange.issues().put(k, newExchange.issues().get(k));
83-
});
84-
return oldExchange;
85-
}
86-
8760
public ProviderResponse responseToIssues(
8861
@Body byte[] response,
8962
@ExchangeProperty(Constants.PROVIDER_PRIVATE_DATA_PROPERTY) String privateProviders,

src/main/java/com/redhat/exhort/integration/providers/osvnvd/OsvNvdResponseHandler.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727

2828
import org.apache.camel.Body;
2929
import org.apache.camel.ExchangeProperty;
30-
import org.slf4j.Logger;
31-
import org.slf4j.LoggerFactory;
3230

3331
import com.fasterxml.jackson.databind.JsonNode;
3432
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -40,7 +38,6 @@
4038
import com.redhat.exhort.api.v4.SeverityUtils;
4139
import com.redhat.exhort.integration.Constants;
4240
import com.redhat.exhort.integration.providers.ProviderResponseHandler;
43-
import com.redhat.exhort.integration.providers.ossindex.OssIndexRequestBuilder;
4441
import com.redhat.exhort.model.CvssParser;
4542
import com.redhat.exhort.model.DependencyTree;
4643
import com.redhat.exhort.model.ProviderResponse;
@@ -54,8 +51,6 @@
5451
@RegisterForReflection
5552
public class OsvNvdResponseHandler extends ProviderResponseHandler {
5653

57-
private static final Logger LOGGER = LoggerFactory.getLogger(OssIndexRequestBuilder.class);
58-
5954
@Inject ObjectMapper mapper;
6055

6156
@Override

src/main/java/com/redhat/exhort/integration/providers/snyk/SnykIntegration.java

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.apache.camel.Exchange;
2222
import org.apache.camel.Message;
23+
import org.apache.camel.builder.AggregationStrategies;
2324
import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
2425
import org.eclipse.microprofile.config.inject.ConfigProperty;
2526

@@ -51,27 +52,40 @@ public class SnykIntegration extends EndpointRouteBuilder {
5152
public void configure() {
5253

5354
// fmt:off
54-
from(direct("snykDepGraph"))
55-
.routeId("snykDepGraph")
55+
onException(IllegalArgumentException.class)
56+
.routeId("snykIllegalArgumentException")
57+
.useOriginalMessage()
58+
.handled(true)
59+
.process(responseHandler::processResponseError);
60+
61+
from(direct("snykScan"))
62+
.routeId("snykScan")
5663
.process(this::setAuthToken)
57-
.circuitBreaker()
58-
.faultToleranceConfiguration()
59-
.timeoutEnabled(true)
60-
.timeoutDuration(timeout)
61-
.end()
62-
.process(SnykRequestBuilder::validate)
63-
.transform().method(SnykRequestBuilder.class, "fromDiGraph")
64-
.process(this::processDepGraphRequest)
65-
.to(direct("snykRequest"))
66-
.onFallback()
67-
.process(responseHandler::processResponseError)
68-
.end()
69-
.transform().method(SnykResponseHandler.class, "buildReport");
64+
.transform(method(SnykRequestBuilder.class, "splitByPkgManager"))
65+
.choice()
66+
.when(method(SnykRequestBuilder.class, "isEmpty"))
67+
.setBody(method(SnykResponseHandler.class, "emptyResponse"))
68+
.setBody(method(SnykResponseHandler.class, "buildReport"))
69+
.otherwise()
70+
.to(direct("snykRequest"))
71+
.transform().method(SnykResponseHandler.class, "buildReport");
7072

7173
from(direct("snykRequest"))
7274
.routeId("snykRequest")
73-
.to(vertxHttp("{{api.snyk.host}}"))
74-
.transform().method(SnykResponseHandler.class, "responseToIssues");
75+
.split(body(), AggregationStrategies.beanAllowNull(SnykResponseHandler.class, "aggregateSplit"))
76+
.parallelProcessing()
77+
.circuitBreaker()
78+
.faultToleranceConfiguration()
79+
.timeoutEnabled(true)
80+
.timeoutDuration(timeout)
81+
.end()
82+
.process(SnykRequestBuilder::validate)
83+
.transform().method(SnykRequestBuilder.class, "buildRequest")
84+
.process(this::processDepGraphRequest)
85+
.to(vertxHttp("{{api.snyk.host}}"))
86+
.transform(method(SnykResponseHandler.class, "responseToIssues"))
87+
.onFallback()
88+
.process(responseHandler::processResponseError);
7589

7690
from(direct("snykValidateToken"))
7791
.routeId("snykValidateToken")

0 commit comments

Comments
 (0)