Skip to content

Commit

Permalink
Merge pull request #381 from DependencyTrack/port-pr3067
Browse files Browse the repository at this point in the history
Vex resource test
  • Loading branch information
nscuro authored Oct 23, 2023
2 parents 2ab3c63 + ba3f191 commit 006b5d2
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/test/java/org/dependencytrack/ResourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public abstract class ResourceTest extends JerseyTest {
protected final String V1_SEARCH = "/v1/search";
protected final String V1_TEAM = "/v1/team";
protected final String V1_USER = "/v1/user";
protected final String V1_VEX = "/v1/vex";
protected final String V1_VIOLATION_ANALYSIS = "/v1/violation/analysis";
protected final String V1_VULNERABILITY = "/v1/vulnerability";
protected final String V1_WORKFLOW = "/v1/workflow";
Expand Down
207 changes: 207 additions & 0 deletions src/test/java/org/dependencytrack/resources/v1/VexResourceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* This file is part of Dependency-Track.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) Steve Springett. All Rights Reserved.
*/
package org.dependencytrack.resources.v1;

import alpine.server.filters.ApiFilter;
import alpine.server.filters.AuthenticationFilter;
import org.dependencytrack.ResourceTest;
import org.dependencytrack.model.AnalysisResponse;
import org.dependencytrack.model.AnalysisState;
import org.dependencytrack.model.AnalyzerIdentity;
import org.dependencytrack.model.Classifier;
import org.dependencytrack.model.Component;
import org.dependencytrack.model.Project;
import org.dependencytrack.model.Severity;
import org.dependencytrack.model.Vulnerability;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.junit.Test;

import javax.ws.rs.core.Response;

import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;

public class VexResourceTest extends ResourceTest {

@Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forServlet(new ServletContainer(
new ResourceConfig(VexResource.class)
.register(ApiFilter.class)
.register(AuthenticationFilter.class)
.register(MultiPartFeature.class)))
.build();
}

@Test
public void exportProjectAsCycloneDxTest() {
var vulnA = new Vulnerability();
vulnA.setVulnId("INT-001");
vulnA.setSource(Vulnerability.Source.INTERNAL);
vulnA.setSeverity(Severity.HIGH);
vulnA = qm.createVulnerability(vulnA, false);

var vulnB = new Vulnerability();
vulnB.setVulnId("INT-002");
vulnB.setSource(Vulnerability.Source.INTERNAL);
vulnB.setSeverity(Severity.LOW);
vulnB = qm.createVulnerability(vulnB, false);

final var project = new Project();
project.setName("acme-app");
project.setVersion("1.0.0");
project.setClassifier(Classifier.APPLICATION);
qm.persist(project);

var componentWithoutVuln = new Component();
componentWithoutVuln.setProject(project);
componentWithoutVuln.setName("acme-lib-a");
componentWithoutVuln.setVersion("1.0.0");
componentWithoutVuln.setDirectDependencies("[]");
componentWithoutVuln = qm.createComponent(componentWithoutVuln, false);

var componentWithVuln = new Component();
componentWithVuln.setProject(project);
componentWithVuln.setName("acme-lib-b");
componentWithVuln.setVersion("1.0.0");
componentWithVuln.setDirectDependencies("[]");
componentWithVuln = qm.createComponent(componentWithVuln, false);
qm.addVulnerability(vulnA, componentWithVuln, AnalyzerIdentity.INTERNAL_ANALYZER);

var componentWithVulnAndAnalysis = new Component();
componentWithVulnAndAnalysis.setProject(project);
componentWithVulnAndAnalysis.setName("acme-lib-c");
componentWithVulnAndAnalysis.setVersion("1.0.0");
componentWithVulnAndAnalysis.setDirectDependencies("[]");
componentWithVulnAndAnalysis = qm.createComponent(componentWithVulnAndAnalysis, false);
qm.addVulnerability(vulnB, componentWithVulnAndAnalysis, AnalyzerIdentity.INTERNAL_ANALYZER);
qm.makeAnalysis(componentWithVulnAndAnalysis, vulnB, AnalysisState.RESOLVED, null, AnalysisResponse.UPDATE, null, true);

// Make componentWithoutVuln (acme-lib-a) depend on componentWithVuln (acme-lib-b)
componentWithoutVuln.setDirectDependencies("""
[
{"uuid": "%s"}
]
""".formatted(componentWithVuln.getUuid()));

// Make project depend on componentWithoutVuln (acme-lib-a)
// and componentWithVulnAndAnalysis (acme-lib-c)
project.setDirectDependencies("""
[
{"uuid": "%s"},
{"uuid": "%s"}
]
"""
.formatted(
componentWithoutVuln.getUuid(),
componentWithVulnAndAnalysis.getUuid()
));
qm.persist(project);

final Response response = target("%s/cyclonedx/project/%s".formatted(V1_VEX, project.getUuid()))
.request()
.header(X_API_KEY, apiKey)
.get(Response.class);
assertThat(response.getStatus()).isEqualTo(200);
assertThatJson(getPlainTextBody(response))
.withMatcher("vulnAUuid", equalTo(vulnA.getUuid().toString()))
.withMatcher("vulnBUuid", equalTo(vulnB.getUuid().toString()))
.withMatcher("projectUuid", equalTo(project.getUuid().toString()))
.isEqualTo("""
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"serialNumber": "${json-unit.any-string}",
"version": 1,
"metadata": {
"timestamp": "${json-unit.any-string}",
"component": {
"type": "application",
"bom-ref": "${json-unit.matches:projectUuid}",
"name": "acme-app",
"version": "1.0.0"
},
"tools": [
{
"vendor": "OWASP",
"name": "Dependency-Track",
"version": "${json-unit.any-string}"
}
]
},
"vulnerabilities": [
{
"bom-ref": "${json-unit.matches:vulnAUuid}",
"id": "INT-001",
"source": {
"name": "INTERNAL"
},
"ratings": [
{
"source": {
"name": "INTERNAL"
},
"severity": "high",
"method": "other"
}
],
"affects": [
{
"ref": "${json-unit.matches:projectUuid}"
}
]
},
{
"bom-ref": "${json-unit.matches:vulnBUuid}",
"id": "INT-002",
"source": {
"name": "INTERNAL"
},
"ratings": [
{
"source": {
"name": "INTERNAL"
},
"severity": "low",
"method": "other"
}
],
"analysis":{
"state": "resolved",
"response": [
"update"
]
},
"affects": [
{
"ref": "${json-unit.matches:projectUuid}"
}
]
}
]
}
""");
}

}

0 comments on commit 006b5d2

Please sign in to comment.