Skip to content

Commit

Permalink
Handle breaking change in Trivy server API
Browse files Browse the repository at this point in the history
`Application#libraries` has been renamed to `Application#packages` in Trivy 0.51.2. The `Library` type no longer exists.

It's not possible to tell the Trivy version based on its API. To work around this, we now send both the `packages` and `libraries` fields with redundant information.

Fields that the API does not expect are silently ignored.

Fixes #3737

Signed-off-by: nscuro <nscuro@protonmail.com>
  • Loading branch information
nscuro committed May 20, 2024
1 parent e87c5cc commit f3a37b9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,51 @@
package org.dependencytrack.parser.trivy.model;

import java.util.ArrayList;
import java.util.List;

public class Application {

private String type;
private ArrayList<Library> libraries;
private List<Package> packages;

/**
* NB: GSON doesn't support serialization of getters, it can only deal with fields.
* Need to have libraries as redundant field to packages, with Jackson we could just
* use a computed getter with {@link com.fasterxml.jackson.annotation.JsonGetter}.
* Migrate this to Jackson eventually.
*
* @see <a href="https://github.com/DependencyTrack/dependency-track/issues/3737">GitHub issue</a>
* @deprecated Kept for compatibility with Trivy <= 0.51.1
*/
@Deprecated(forRemoval = true)
private List<Package> libraries;

public Application(String type) {
public Application(final String type) {
this.type = type;
this.libraries = new ArrayList<Library>();
this.packages = new ArrayList<>();
this.libraries = new ArrayList<>();
}

public String getType() {
return type;
}

public void setType(String value) {
this.type = value;
}

public String getType() { return type; }
public void setType(String value) { this.type = value; }
public List<Package> getPackages() {
return packages;
}

public void setPackages(List<Package> value) {
this.packages = value;
this.libraries = value;
}

public void addPackage(Package value) {
this.packages.add(value);
this.libraries.add(value);
}

public ArrayList<Library> getLibraries() { return libraries; }
public void setLibraries(ArrayList<Library> value) { this.libraries = value; }
public void addLibrary(Library value) { this.libraries.add(value); }
}
45 changes: 0 additions & 45 deletions src/main/java/org/dependencytrack/parser/trivy/model/Library.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
import org.dependencytrack.parser.trivy.model.Application;
import org.dependencytrack.parser.trivy.model.BlobInfo;
import org.dependencytrack.parser.trivy.model.DeleteRequest;
import org.dependencytrack.parser.trivy.model.Library;
import org.dependencytrack.parser.trivy.model.OS;
import org.dependencytrack.parser.trivy.model.Options;
import org.dependencytrack.parser.trivy.model.Package;
Expand Down Expand Up @@ -224,7 +223,7 @@ public void analyze(final List<Component> components) {
map.put(key, component);

LOGGER.debug("add library %s".formatted(component.toString()));
app.addLibrary(new Library(name, component.getVersion()));
app.addPackage(new Package(name, component.getVersion(), null, null, null, null, null));
} else {
String srcName = null;
String srcVersion = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@
import org.dependencytrack.model.Component;
import org.dependencytrack.model.Project;
import org.dependencytrack.model.Vulnerability;
import org.junit.AfterClass;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.images.PullPolicy;
import org.testcontainers.utility.DockerImageName;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -42,23 +45,38 @@
import static org.dependencytrack.model.ConfigPropertyConstants.SCANNER_TRIVY_ENABLED;
import static org.testcontainers.containers.wait.strategy.Wait.forLogMessage;

@RunWith(Parameterized.class)
public class TrivyAnalysisTaskIntegrationTest extends PersistenceCapableTest {

private static GenericContainer<?> trivyContainer;
@Parameterized.Parameters(name = "[{index}] trivyVersion={0}")
public static Collection<?> testParameters() {
return Arrays.asList(new Object[][]{
{"0.51.1"}, // Pre breaking change of Application#libraries -> Application#packages
{"0.51.2"}, // Post breaking change of Application#libraries -> Application#packages
{"latest"}
});
}

private final String trivyVersion;
private GenericContainer<?> trivyContainer;

public TrivyAnalysisTaskIntegrationTest(String trivyVersion) {
this.trivyVersion = trivyVersion;
}

@BeforeClass
@Before
@Override
@SuppressWarnings("resource")
public static void setUpClass() {
trivyContainer = new GenericContainer<>(DockerImageName.parse("aquasec/trivy:latest"))
public void before() throws Exception {
super.before();

trivyContainer = new GenericContainer<>(DockerImageName.parse("aquasec/trivy:" + trivyVersion))
.withImagePullPolicy(PullPolicy.alwaysPull())
.withCommand("server --listen :8080 --token TrivyToken")
.withExposedPorts(8080)
.waitingFor(forLogMessage(".*Listening :8080.*", 1));
trivyContainer.start();
}

@Before
public void setUp() throws Exception {
qm.createConfigProperty(
SCANNER_TRIVY_ENABLED.getGroupName(),
SCANNER_TRIVY_ENABLED.getPropertyName(),
Expand All @@ -82,11 +100,14 @@ public void setUp() throws Exception {
);
}

@AfterClass
public static void tearDownClass() {
@After
@Override
public void after() {
if (trivyContainer != null) {
trivyContainer.stop();
}

super.after();
}

@Test
Expand Down

0 comments on commit f3a37b9

Please sign in to comment.