Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.dependencytrack.notification.vo.NewVulnerableDependency;
import org.dependencytrack.notification.vo.PolicyViolationIdentified;
import org.dependencytrack.notification.vo.VexConsumedOrProcessed;
import org.dependencytrack.notification.vo.ViolationAnalysisDecisionChange;
import org.dependencytrack.persistence.QueryManager;

import javax.jdo.PersistenceManager;
Expand Down Expand Up @@ -105,16 +106,10 @@ public Notification restrictNotificationToRuleProjects(Notification initialNotif
restrictedNotification.setContent(initialNotification.getContent());
restrictedNotification.setTitle(initialNotification.getTitle());
restrictedNotification.setTimestamp(initialNotification.getTimestamp());
if(initialNotification.getSubject() instanceof NewVulnerabilityIdentified) {
NewVulnerabilityIdentified subject = (NewVulnerabilityIdentified) initialNotification.getSubject();
if(initialNotification.getSubject() instanceof final NewVulnerabilityIdentified subject) {
Set<Project> restrictedProjects = subject.getAffectedProjects().stream().filter(project -> ruleProjectsUuids.contains(project.getUuid().toString())).collect(Collectors.toSet());
NewVulnerabilityIdentified restrictedSubject = new NewVulnerabilityIdentified(subject.getVulnerability(), subject.getComponent(), restrictedProjects, null);
restrictedNotification.setSubject(restrictedSubject);
} else if(initialNotification.getSubject() instanceof AnalysisDecisionChange) {
AnalysisDecisionChange subject = (AnalysisDecisionChange) initialNotification.getSubject();
Set<Project> restrictedProjects = subject.getAffectedProjects().stream().filter(project -> ruleProjectsUuids.contains(project.getUuid().toString())).collect(Collectors.toSet());
AnalysisDecisionChange restrictedSubject = new AnalysisDecisionChange(subject.getVulnerability(), subject.getComponent(), restrictedProjects, subject.getAnalysis());
restrictedNotification.setSubject(restrictedSubject);
}
}
return restrictedNotification;
Expand All @@ -126,7 +121,6 @@ private boolean canRestrictNotificationToRuleProjects(Notification initialNotifi
&& rule.getProjects().size() > 0;
}

@SuppressWarnings("unchecked")
List<NotificationRule> resolveRules(final Notification notification) {
// The notification rules to process for this specific notification
final List<NotificationRule> rules = new ArrayList<>();
Expand All @@ -151,18 +145,16 @@ List<NotificationRule> resolveRules(final Notification notification) {

sb.append("enabled == true && scope == :scope"); //todo: improve this - this only works for testing
query.setFilter(sb.toString());
final List<NotificationRule> result = (List<NotificationRule>)query.execute(NotificationScope.valueOf(notification.getScope()));
query.setParameters(NotificationScope.valueOf(notification.getScope()));
final List<NotificationRule> result = query.executeList();
pm.detachCopyAll(result);

if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() != null && notification.getSubject() instanceof NewVulnerabilityIdentified) {
final NewVulnerabilityIdentified subject = (NewVulnerabilityIdentified) notification.getSubject();
/*
if the rule specified one or more projects as targets, reduce the execution
of the notification down to those projects that the rule matches and which
also match project the component is included in.
NOTE: This logic is slightly different from what is implemented in limitToProject()
*/
&& notification.getSubject() instanceof final NewVulnerabilityIdentified subject) {
// If the rule specified one or more projects as targets, reduce the execution
// of the notification down to those projects that the rule matches and which
// also match project the component is included in.
// NOTE: This logic is slightly different from what is implemented in limitToProject()
for (final NotificationRule rule: result) {
if (rule.getNotifyOn().contains(NotificationGroup.valueOf(notification.getGroup()))) {
if (rule.getProjects() != null && rule.getProjects().size() > 0
Expand All @@ -178,21 +170,23 @@ List<NotificationRule> resolveRules(final Notification notification) {
}
}
} else if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() != null && notification.getSubject() instanceof NewVulnerableDependency) {
final NewVulnerableDependency subject = (NewVulnerableDependency) notification.getSubject();
&& notification.getSubject() instanceof final NewVulnerableDependency subject) {
limitToProject(rules, result, notification, subject.getComponent().getProject());
} else if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() != null && notification.getSubject() instanceof BomConsumedOrProcessed) {
final BomConsumedOrProcessed subject = (BomConsumedOrProcessed) notification.getSubject();
&& notification.getSubject() instanceof final BomConsumedOrProcessed subject) {
limitToProject(rules, result, notification, subject.getProject());
} else if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() instanceof final VexConsumedOrProcessed subject) {
limitToProject(rules, result, notification, subject.getProject());
} else if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() != null && notification.getSubject() instanceof VexConsumedOrProcessed) {
final VexConsumedOrProcessed subject = (VexConsumedOrProcessed) notification.getSubject();
&& notification.getSubject() instanceof final PolicyViolationIdentified subject) {
limitToProject(rules, result, notification, subject.getProject());
} else if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() != null && notification.getSubject() instanceof PolicyViolationIdentified) {
final PolicyViolationIdentified subject = (PolicyViolationIdentified) notification.getSubject();
&& notification.getSubject() instanceof final AnalysisDecisionChange subject) {
limitToProject(rules, result, notification, subject.getProject());
} else if (NotificationScope.PORTFOLIO.name().equals(notification.getScope())
&& notification.getSubject() instanceof final ViolationAnalysisDecisionChange subject) {
limitToProject(rules, result, notification, subject.getComponent().getProject());
} else {
for (final NotificationRule rule: result) {
if (rule.getNotifyOn().contains(NotificationGroup.valueOf(notification.getGroup()))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,18 @@
import org.dependencytrack.model.Project;
import org.dependencytrack.model.Vulnerability;

import java.util.Set;

public class AnalysisDecisionChange {

private final Vulnerability vulnerability;
private final Component component;
private final Set<Project> affectedProjects;
private final Project affectedProject;
private final Analysis analysis;

public AnalysisDecisionChange(final Vulnerability vulnerability, final Component component,
final Set<Project> affectedProjects, final Analysis analysis) {
final Project affectedProject, final Analysis analysis) {
this.vulnerability = vulnerability;
this.component = component;
this.affectedProjects = affectedProjects;
this.affectedProject = affectedProject;
this.analysis = analysis;
}

Expand All @@ -48,18 +46,11 @@ public Component getComponent() {
return component;
}

public Set<Project> getAffectedProjects() {
return affectedProjects;
}

public Analysis getAnalysis() {
return analysis;
}

public Project getProject() {
if (affectedProjects != null && affectedProjects.size() == 1) {
return affectedProjects.iterator().next();
}
return null;
return affectedProject;
}
}
14 changes: 4 additions & 10 deletions src/main/java/org/dependencytrack/util/NotificationUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.nio.charset.StandardCharsets.UTF_8;

Expand Down Expand Up @@ -130,9 +129,7 @@ public static void analyzeNotificationCriteria(final QueryManager qm, Analysis a
final boolean analysisStateChange, final boolean suppressionChange) {
if (analysisStateChange || suppressionChange) {
final NotificationGroup notificationGroup;
final Set<Project> affectedProjects = new HashSet<>();
notificationGroup = NotificationGroup.PROJECT_AUDIT_CHANGE;
affectedProjects.add(analysis.getProject());

String title = null;
if (analysisStateChange) {
Expand Down Expand Up @@ -176,7 +173,7 @@ public static void analyzeNotificationCriteria(final QueryManager qm, Analysis a
.level(NotificationLevel.INFORMATIONAL)
.content(generateNotificationContent(analysis))
.subject(new AnalysisDecisionChange(analysis.getVulnerability(),
analysis.getComponent(), affectedProjects, analysis))
analysis.getComponent(), analysis.getProject(), analysis))
);
}
}
Expand Down Expand Up @@ -382,12 +379,9 @@ public static JsonObject toJson(final AnalysisDecisionChange vo) {
if (vo.getAnalysis() != null) {
builder.add("analysis", toJson(vo.getAnalysis()));
}
if (vo.getAffectedProjects() != null && vo.getAffectedProjects().size() > 0) {
final JsonArrayBuilder projectsBuilder = Json.createArrayBuilder();
for (final Project project: vo.getAffectedProjects()) {
projectsBuilder.add(toJson(project));
}
builder.add("affectedProjects", projectsBuilder.build());
if (vo.getProject() != null) {
// Provide the affected project in the form of an array for backwards-compatibility
builder.add("affectedProjects", Json.createArrayBuilder().add(toJson(vo.getProject())));
}
return builder.build();
}
Expand Down
Loading