Skip to content

Commit

Permalink
Populate audit trail when auto-suppressing withdrawn Snyk findings
Browse files Browse the repository at this point in the history
Signed-off-by: nscuro <[email protected]>
  • Loading branch information
nscuro committed Feb 19, 2025
1 parent 562b29a commit 4d44163
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import com.google.protobuf.Any;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;
import jakarta.ws.rs.core.MultivaluedHashMap;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.dependencytrack.event.PortfolioVulnerabilityAnalysisEvent;
import org.dependencytrack.event.kafka.KafkaEvent;
Expand Down Expand Up @@ -76,6 +75,7 @@
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.slf4j.MDC;

import jakarta.ws.rs.core.MultivaluedHashMap;
import javax.jdo.Query;
import javax.jdo.Transaction;
import java.util.ArrayList;
Expand All @@ -92,6 +92,7 @@
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.datanucleus.PropertyNames.PROPERTY_PERSISTENCE_BY_REACHABILITY_AT_COMMIT;
Expand All @@ -102,7 +103,6 @@
import static org.dependencytrack.parser.dependencytrack.ModelConverterCdxToVuln.convert;
import static org.dependencytrack.persistence.jdbi.JdbiFactory.inJdbiTransaction;
import static org.dependencytrack.persistence.jdbi.JdbiFactory.useJdbiHandle;
import static org.dependencytrack.persistence.jdbi.JdbiFactory.useJdbiTransaction;
import static org.dependencytrack.persistence.jdbi.JdbiFactory.withJdbiHandle;
import static org.dependencytrack.proto.notification.v1.Group.GROUP_NEW_VULNERABILITY;
import static org.dependencytrack.proto.notification.v1.Group.GROUP_NEW_VULNERABLE_DEPENDENCY;
Expand Down Expand Up @@ -294,14 +294,29 @@ private Set<Vulnerability> syncVulnerabilities(final QueryManager qm, final Comp
}

private void compareAndSuppressVulnBySnyk(QueryManager qm, Component component, List<org.cyclonedx.proto.v1_6.Vulnerability> vulnList) {
final var analysisIds = new ArrayList<Long>();
useJdbiTransaction(handle -> {
final List<Long> analysisIds = inJdbiTransaction(handle -> {
final var dao = handle.attach(Dao.class);
analysisIds.addAll(dao.suppressSnykAnalyses(component.id,
vulnList.isEmpty() ? null : vulnList.stream().map(vuln -> vuln.getId()).toList(),
component.projectId));

final List<Long> modifiedAnalysisIds = dao.suppressSnykAnalyses(
component.id,
!vulnList.isEmpty()
? vulnList.stream().map(org.cyclonedx.proto.v1_6.Vulnerability::getId).toList()
: null,
component.projectId);

final List<AnalysisComment> analysisComments = modifiedAnalysisIds.stream()
.flatMap(analysisId -> Stream.of(
new AnalysisComment(analysisId, formatComment(AnalysisCommentField.SUPPRESSED, null, true), /* commenter */ null),
new AnalysisComment(analysisId, "The vulnerability is no longer reported by any analyzer.", /* commenter */ null)))
.toList();
if (!analysisComments.isEmpty()) {
dao.createAnalysisComments(analysisComments);
}

return modifiedAnalysisIds;
});
for (var analysisId : analysisIds) {
// TODO: Use this#maybeQueueProjectAuditChangeNotification instead.
var analysis = qm.getObjectById(org.dependencytrack.model.Analysis.class, analysisId);
var notification = NotificationUtil.generateAnalysisNotification(qm, analysis, true, true);
final var event = KafkaEventConverter.convert(notification);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1566,15 +1566,47 @@ public void processSuccessfulScanResultWithSnykVulnerabilityTest() {
assertThat(qm.getAllVulnerabilities(component, true)).satisfiesExactlyInAnyOrder(
vuln -> {
assertThat(vuln.getVulnId()).isEqualTo("SNYK-001");
assertThat(qm.getAnalysis(component, vuln).isSuppressed()).isFalse();

final Analysis vulnAnalysis = qm.getAnalysis(component, vuln);
assertThat(vulnAnalysis).isNotNull();
assertThat(vulnAnalysis.isSuppressed()).isFalse();
assertThat(vulnAnalysis.getAnalysisComments()).isEmpty();
},
vuln -> {
assertThat(vuln.getVulnId()).isEqualTo("SNYK-002");
assertThat(qm.getAnalysis(component, vuln).isSuppressed()).isTrue();

final Analysis vulnAnalysis = qm.getAnalysis(component, vuln);
assertThat(vulnAnalysis).isNotNull();
assertThat(vulnAnalysis.isSuppressed()).isTrue();
assertThat(vulnAnalysis.getAnalysisComments()).satisfiesExactly(
comment -> {
assertThat(comment.getComment()).isEqualTo("Suppressed");
assertThat(comment.getCommenter()).isNull();
assertThat(comment.getTimestamp()).isNotNull();
},
comment -> {
assertThat(comment.getComment()).isEqualTo("The vulnerability is no longer reported by any analyzer.");
assertThat(comment.getCommenter()).isNull();
assertThat(comment.getTimestamp()).isNotNull();
});
},
vuln -> {
assertThat(vuln.getVulnId()).isEqualTo("SNYK-003");
assertThat(qm.getAnalysis(component, vuln).isSuppressed()).isTrue();

final Analysis vulnAnalysis = qm.getAnalysis(component, vuln);
assertThat(vulnAnalysis).isNotNull();
assertThat(vulnAnalysis.isSuppressed()).isTrue();
assertThat(vulnAnalysis.getAnalysisComments()).satisfiesExactly(
comment -> {
assertThat(comment.getComment()).isEqualTo("Suppressed");
assertThat(comment.getCommenter()).isNull();
assertThat(comment.getTimestamp()).isNotNull();
},
comment -> {
assertThat(comment.getComment()).isEqualTo("The vulnerability is no longer reported by any analyzer.");
assertThat(comment.getCommenter()).isNull();
assertThat(comment.getTimestamp()).isNotNull();
});
},
vuln -> {
assertThat(vuln.getVulnId()).isEqualTo("SNYK-004");
Expand Down

0 comments on commit 4d44163

Please sign in to comment.