Skip to content

Commit

Permalink
Migrate Trivy integration to use Protobuf instead of JSON
Browse files Browse the repository at this point in the history
Closes #4065

Signed-off-by: nscuro <nscuro@protonmail.com>
  • Loading branch information
nscuro committed Sep 2, 2024
1 parent e672e6b commit 2a72c60
Show file tree
Hide file tree
Showing 21 changed files with 590 additions and 937 deletions.
41 changes: 41 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
<lib.open-vulnerability-clients.version>6.2.0</lib.open-vulnerability-clients.version>
<lib.packageurl.version>1.5.0</lib.packageurl.version>
<lib.pebble.version>3.2.2</lib.pebble.version>
<lib.protobuf-java.version>4.28.0</lib.protobuf-java.version>
<lib.resilience4j.version>2.2.0</lib.resilience4j.version>
<lib.swagger-parser.version>2.1.22</lib.swagger-parser.version>
<lib.system-rules.version>1.19.0</lib.system-rules.version>
Expand All @@ -139,8 +140,11 @@
<plugin.cyclonedx.outputFormat>json</plugin.cyclonedx.outputFormat>
<plugin.retirejs.breakOnFailure>false</plugin.retirejs.breakOnFailure>
<plugin.jetty.version>12.0.12</plugin.jetty.version>
<plugin.protoc-jar.version>3.11.4</plugin.protoc-jar.version>
<!-- SonarCloud properties -->
<sonar.exclusions>src/main/webapp/**</sonar.exclusions>
<!-- Tool Versions -->
<tool.protoc.version>com.google.protobuf:protoc:${lib.protobuf-java.version}</tool.protoc.version>
<!-- CycloneDX CLI -->
<cyclonedx-cli.path>cyclonedx</cyclonedx-cli.path>
<services.bom.merge.skip>true</services.bom.merge.skip>
Expand Down Expand Up @@ -203,6 +207,7 @@
<artifactId>cyclonedx-core-java</artifactId>
<version>${lib.cyclonedx-java.version}</version>
</dependency>

<!-- org.json
This was previously transitively included with Unirest. However, Unirest v3.x removed reliance on org.json
in favor of their own API compatible replacement. Therefore, it was necessary to directly include org.json.
Expand Down Expand Up @@ -263,6 +268,17 @@
<version>${lib.pebble.version}</version>
</dependency>

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${lib.protobuf-java.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>${lib.protobuf-java.version}</version>
</dependency>

<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-jakarta</artifactId>
Expand Down Expand Up @@ -561,6 +577,30 @@
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>com.github.os72</groupId>
<artifactId>protoc-jar-maven-plugin</artifactId>
<version>${plugin.protoc-jar.version}</version>
<executions>
<execution>
<id>protobuf</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<includeMavenTypes>direct</includeMavenTypes>
<inputDirectories>
<inputDirectory>src/main/proto</inputDirectory>
</inputDirectories>
<includeDirectories>
<includeDirectory>src/main/proto</includeDirectory>
</includeDirectories>
<protocArtifact>${tool.protoc.version}</protocArtifact>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand All @@ -586,6 +626,7 @@
<configuration>
<excludes>
<exclude>org/dependencytrack/upgrade/**/*</exclude>
<exclude>trivy/proto/**/*</exclude>
</excludes>
</configuration>
</plugin>
Expand Down
69 changes: 22 additions & 47 deletions src/main/java/org/dependencytrack/parser/trivy/TrivyParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,89 +18,64 @@
*/
package org.dependencytrack.parser.trivy;

import alpine.common.logging.Logger;
import com.google.protobuf.util.Timestamps;
import org.dependencytrack.model.Cwe;
import org.dependencytrack.model.Severity;
import org.dependencytrack.model.Vulnerability;
import org.dependencytrack.parser.common.resolver.CweResolver;
import org.dependencytrack.parser.trivy.model.CVSS;
import trivy.proto.common.CVSS;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.List;

import static org.apache.commons.lang3.StringUtils.trimToNull;

public class TrivyParser {

private static final Logger LOGGER = Logger.getLogger(TrivyParser.class);

public Vulnerability parse(org.dependencytrack.parser.trivy.model.Vulnerability data) {
public Vulnerability parse(trivy.proto.common.Vulnerability data) {
var vulnerability = new Vulnerability();
vulnerability.setSource(Vulnerability.Source.resolve(data.getVulnerabilityID()));
vulnerability.setSource(Vulnerability.Source.resolve(data.getVulnerabilityId()));
vulnerability.setPatchedVersions(data.getFixedVersion());

// get the id of the data record (vulnerability)
vulnerability.setVulnId(data.getVulnerabilityID());
vulnerability.setVulnId(data.getVulnerabilityId());
vulnerability.setTitle(data.getTitle());
vulnerability.setDescription(data.getDescription());
vulnerability.setSeverity(parseSeverity(data.getSeverity()));

try {
vulnerability.setPublished(parseDate(data.getPublishedDate()));
if (data.hasPublishedDate()) {
vulnerability.setPublished(new Date(Timestamps.toMillis(data.getPublishedDate())));
vulnerability.setCreated(vulnerability.getPublished());
} catch (ParseException ex) {
LOGGER.warn("Unable to parse published date %s".formatted(data.getPublishedDate()), ex);
}

try {
vulnerability.setUpdated(parseDate(data.getLastModifiedDate()));
} catch (ParseException ex) {
LOGGER.warn("Unable to parse last modified date %s".formatted(data.getLastModifiedDate()), ex);
if (data.hasLastModifiedDate()) {
vulnerability.setUpdated(new Date(Timestamps.toMillis(data.getLastModifiedDate())));
}

vulnerability.setReferences(addReferences(data.getReferences()));
vulnerability.setReferences(addReferences(data.getReferencesList()));

// CWE
for (String id : data.getCweIDS()) {
for (String id : data.getCweIdsList()) {
final Cwe cwe = CweResolver.getInstance().lookup(id);
if (cwe != null) {
vulnerability.addCwe(cwe);
}
}

vulnerability = setCvssScore(data.getCvss().get(data.getSeveritySource()), vulnerability);
vulnerability = setCvssScore(data.getCvssMap().get(data.getSeveritySource()), vulnerability);

return vulnerability;
}

public Date parseDate(String input) throws ParseException {
if (input != null) {
String format = input.length() == 20 ? "yyyy-MM-dd'T'HH:mm:ss'Z'" : "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.ENGLISH);
return formatter.parse(input);
}
return null;
}

public Severity parseSeverity(String severity) {

if (severity != null) {
if (severity.equalsIgnoreCase("CRITICAL")) {
return Severity.CRITICAL;
} else if (severity.equalsIgnoreCase("HIGH")) {
return Severity.HIGH;
} else if (severity.equalsIgnoreCase("MEDIUM")) {
return Severity.MEDIUM;
} else if (severity.equalsIgnoreCase("LOW")) {
return Severity.LOW;
} else {
return Severity.UNASSIGNED;
}
}
return Severity.UNASSIGNED;
public Severity parseSeverity(trivy.proto.common.Severity severity) {
return switch (severity) {
case CRITICAL -> Severity.CRITICAL;
case HIGH -> Severity.HIGH;
case MEDIUM -> Severity.MEDIUM;
case LOW -> Severity.LOW;
default -> Severity.UNASSIGNED;
};
}

public Vulnerability setCvssScore(CVSS cvss, Vulnerability vulnerability) {
Expand All @@ -118,7 +93,7 @@ public Vulnerability setCvssScore(CVSS cvss, Vulnerability vulnerability) {
return vulnerability;
}

public String addReferences(String[] references) {
public String addReferences(List<String> references) {
final StringBuilder sb = new StringBuilder();
for (String reference : references) {
if (reference != null) {
Expand Down

This file was deleted.

47 changes: 0 additions & 47 deletions src/main/java/org/dependencytrack/parser/trivy/model/BlobInfo.java

This file was deleted.

44 changes: 0 additions & 44 deletions src/main/java/org/dependencytrack/parser/trivy/model/CVSS.java

This file was deleted.

Loading

0 comments on commit 2a72c60

Please sign in to comment.