From aa815274c6c74485fc9c512ae6d541f6414ce22f Mon Sep 17 00:00:00 2001 From: Sahiba Mittal Date: Thu, 8 Aug 2024 15:41:57 +0100 Subject: [PATCH 1/5] Add Notification For BOM_VALIDATION_FAILED Co-Authored-By: Aravind Parappil --- .../event/kafka/KafkaEventConverter.java | 8 ++- .../notification/NotificationConstants.java | 1 + .../notification/NotificationGroup.java | 1 + .../notification/vo/BomValidationFailed.java | 55 +++++++++++++++++++ .../NotificationModelConverter.java | 20 +++++++ .../resources/v1/BomResource.java | 26 ++++++++- .../resources/v1/VexResource.java | 4 +- .../notification/v1/notification.proto | 8 +++ .../notification/publisher/email.peb | 12 ++++ .../notification/publisher/msteams.peb | 27 +++++++++ .../notification/publisher/slack.peb | 45 +++++++++++++++ .../NotificationModelConverterTest.java | 32 +++++++++++ 12 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java diff --git a/src/main/java/org/dependencytrack/event/kafka/KafkaEventConverter.java b/src/main/java/org/dependencytrack/event/kafka/KafkaEventConverter.java index e2cd33e17..cae504507 100644 --- a/src/main/java/org/dependencytrack/event/kafka/KafkaEventConverter.java +++ b/src/main/java/org/dependencytrack/event/kafka/KafkaEventConverter.java @@ -32,6 +32,7 @@ import org.dependencytrack.parser.dependencytrack.NotificationModelConverter; import org.dependencytrack.proto.notification.v1.BomConsumedOrProcessedSubject; import org.dependencytrack.proto.notification.v1.BomProcessingFailedSubject; +import org.dependencytrack.proto.notification.v1.BomValidationFailedSubject; import org.dependencytrack.proto.notification.v1.NewVulnerabilitySubject; import org.dependencytrack.proto.notification.v1.NewVulnerableDependencySubject; import org.dependencytrack.proto.notification.v1.Notification; @@ -170,7 +171,7 @@ static KafkaEvent convert(final EpssMirrorEvent ignored) { private static Topic extractDestinationTopic(final Notification notification) { return switch (notification.getGroup()) { case GROUP_ANALYZER -> KafkaTopics.NOTIFICATION_ANALYZER; - case GROUP_BOM_CONSUMED, GROUP_BOM_PROCESSED, GROUP_BOM_PROCESSING_FAILED -> KafkaTopics.NOTIFICATION_BOM; + case GROUP_BOM_CONSUMED, GROUP_BOM_PROCESSED, GROUP_BOM_PROCESSING_FAILED, GROUP_BOM_VALIDATION_FAILED -> KafkaTopics.NOTIFICATION_BOM; case GROUP_CONFIGURATION -> KafkaTopics.NOTIFICATION_CONFIGURATION; case GROUP_DATASOURCE_MIRRORING -> KafkaTopics.NOTIFICATION_DATASOURCE_MIRRORING; case GROUP_FILE_SYSTEM -> KafkaTopics.NOTIFICATION_FILE_SYSTEM; @@ -204,6 +205,11 @@ private static String extractEventKey(final Notification notification) throws In final var subject = notification.getSubject().unpack(BomProcessingFailedSubject.class); yield requireNonEmpty(subject.getProject().getUuid()); } + case GROUP_BOM_VALIDATION_FAILED -> { + requireSubjectOfTypeAnyOf(notification, List.of(BomValidationFailedSubject.class)); + final var subject = notification.getSubject().unpack(BomValidationFailedSubject.class); + yield requireNonEmpty(subject.getProject().getUuid()); + } case GROUP_NEW_VULNERABILITY -> { requireSubjectOfTypeAnyOf(notification, List.of(NewVulnerabilitySubject.class)); final var subject = notification.getSubject().unpack(NewVulnerabilitySubject.class); diff --git a/src/main/java/org/dependencytrack/notification/NotificationConstants.java b/src/main/java/org/dependencytrack/notification/NotificationConstants.java index 876151210..0a02f5a97 100644 --- a/src/main/java/org/dependencytrack/notification/NotificationConstants.java +++ b/src/main/java/org/dependencytrack/notification/NotificationConstants.java @@ -50,6 +50,7 @@ public static class Title { public static final String BOM_CONSUMED = "Bill of Materials Consumed"; public static final String BOM_PROCESSED = "Bill of Materials Processed"; public static final String BOM_PROCESSING_FAILED = "Bill of Materials Processing Failed"; + public static final String BOM_VALIDATION_FAILED = "Bill of Materials Validation Failed"; public static final String VEX_CONSUMED = "Vulnerability Exploitability Exchange (VEX) Consumed"; public static final String VEX_PROCESSED = "Vulnerability Exploitability Exchange (VEX) Processed"; public static final String PROJECT_CREATED = "Project Added"; diff --git a/src/main/java/org/dependencytrack/notification/NotificationGroup.java b/src/main/java/org/dependencytrack/notification/NotificationGroup.java index 02b6166cb..fcf5ccd25 100644 --- a/src/main/java/org/dependencytrack/notification/NotificationGroup.java +++ b/src/main/java/org/dependencytrack/notification/NotificationGroup.java @@ -39,6 +39,7 @@ public enum NotificationGroup { BOM_CONSUMED, BOM_PROCESSED, BOM_PROCESSING_FAILED, + BOM_VALIDATION_FAILED, VEX_CONSUMED, VEX_PROCESSED, POLICY_VIOLATION, diff --git a/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java b/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java new file mode 100644 index 000000000..b01e4eb5c --- /dev/null +++ b/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java @@ -0,0 +1,55 @@ +/* + * 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) OWASP Foundation. All Rights Reserved. + */ +package org.dependencytrack.notification.vo; + +import org.dependencytrack.model.Bom; +import org.dependencytrack.model.Project; + +import java.util.List; + +public class BomValidationFailed { + + private Project project; + private String bom; + private List errors; + private Bom.Format format; + + public BomValidationFailed(final Project project, final String bom, final List errors, final Bom.Format format) { + this.project = project; + this.bom = bom; + this.errors = errors; + this.format = format; + } + + public Project getProject() { + return project; + } + + public String getBom() { + return bom; + } + + public List getErrors() { + return errors; + } + + public Bom.Format getFormat() { + return format; + } +} \ No newline at end of file diff --git a/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java b/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java index 22c955b01..ac44ac5d3 100644 --- a/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java +++ b/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java @@ -33,6 +33,7 @@ import org.dependencytrack.notification.vo.AnalysisDecisionChange; import org.dependencytrack.notification.vo.BomConsumedOrProcessed; import org.dependencytrack.notification.vo.BomProcessingFailed; +import org.dependencytrack.notification.vo.BomValidationFailed; import org.dependencytrack.notification.vo.NewVulnerabilityIdentified; import org.dependencytrack.notification.vo.NewVulnerableDependency; import org.dependencytrack.notification.vo.PolicyViolationIdentified; @@ -42,6 +43,7 @@ import org.dependencytrack.proto.notification.v1.BackReference; import org.dependencytrack.proto.notification.v1.BomConsumedOrProcessedSubject; import org.dependencytrack.proto.notification.v1.BomProcessingFailedSubject; +import org.dependencytrack.proto.notification.v1.BomValidationFailedSubject; import org.dependencytrack.proto.notification.v1.Component; import org.dependencytrack.proto.notification.v1.Group; import org.dependencytrack.proto.notification.v1.Level; @@ -73,6 +75,7 @@ import static org.dependencytrack.proto.notification.v1.Group.GROUP_BOM_CONSUMED; import static org.dependencytrack.proto.notification.v1.Group.GROUP_BOM_PROCESSED; import static org.dependencytrack.proto.notification.v1.Group.GROUP_BOM_PROCESSING_FAILED; +import static org.dependencytrack.proto.notification.v1.Group.GROUP_BOM_VALIDATION_FAILED; import static org.dependencytrack.proto.notification.v1.Group.GROUP_CONFIGURATION; import static org.dependencytrack.proto.notification.v1.Group.GROUP_DATASOURCE_MIRRORING; import static org.dependencytrack.proto.notification.v1.Group.GROUP_FILE_SYSTEM; @@ -161,6 +164,7 @@ private static Group convertGroup(final String group) { case BOM_CONSUMED -> GROUP_BOM_CONSUMED; case BOM_PROCESSED -> GROUP_BOM_PROCESSED; case BOM_PROCESSING_FAILED -> GROUP_BOM_PROCESSING_FAILED; + case BOM_VALIDATION_FAILED -> GROUP_BOM_VALIDATION_FAILED; case VEX_CONSUMED -> GROUP_VEX_CONSUMED; case VEX_PROCESSED -> GROUP_VEX_PROCESSED; case POLICY_VIOLATION -> GROUP_POLICY_VIOLATION; @@ -184,6 +188,8 @@ private static Optional convert(final Object subject) { return Optional.of(Any.pack(convert(bcop))); } else if (subject instanceof final BomProcessingFailed bpf) { return Optional.of(Any.pack(convert(bpf))); + } else if (subject instanceof final BomValidationFailed bvf) { + return Optional.of(Any.pack(convert(bvf))); } else if (subject instanceof final VexConsumedOrProcessed vcop) { return Optional.of(Any.pack(convert(vcop))); } else if (subject instanceof final PolicyViolationIdentified pvi) { @@ -278,6 +284,20 @@ private static BomProcessingFailedSubject convert(final BomProcessingFailed subj return builder.build(); } + private static BomValidationFailedSubject convert(final BomValidationFailed subject) { + + org.dependencytrack.proto.notification.v1.Bom.Builder bomBuilder = org.dependencytrack.proto.notification.v1.Bom.newBuilder(); + Optional.ofNullable(subject.getBom()).ifPresent(bomBuilder::setContent); + Optional.ofNullable(subject.getFormat()).map(Bom.Format::getFormatShortName).ifPresent(bomBuilder::setFormat); + + final BomValidationFailedSubject.Builder builder = BomValidationFailedSubject.newBuilder() + .setProject(convert(subject.getProject())) + .setBom(bomBuilder.build()); + + Optional.ofNullable(subject.getErrors()).ifPresent(builder::addAllErrors); + return builder.build(); + } + private static VexConsumedOrProcessedSubject convert(final VexConsumedOrProcessed subject) { return VexConsumedOrProcessedSubject.newBuilder() .setProject(convert(subject.getProject())) diff --git a/src/main/java/org/dependencytrack/resources/v1/BomResource.java b/src/main/java/org/dependencytrack/resources/v1/BomResource.java index 3213b58c1..be5d0a23d 100644 --- a/src/main/java/org/dependencytrack/resources/v1/BomResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/BomResource.java @@ -20,6 +20,8 @@ import alpine.common.logging.Logger; import alpine.event.framework.Event; +import alpine.notification.Notification; +import alpine.notification.NotificationLevel; import alpine.server.auth.PermissionRequired; import alpine.server.resources.AlpineResource; import io.swagger.v3.oas.annotations.Operation; @@ -51,11 +53,17 @@ import org.cyclonedx.exception.GeneratorException; import org.dependencytrack.auth.Permissions; import org.dependencytrack.event.BomUploadEvent; +import org.dependencytrack.event.kafka.KafkaEventDispatcher; +import org.dependencytrack.model.Bom; import org.dependencytrack.model.Component; import org.dependencytrack.model.Project; import org.dependencytrack.model.WorkflowState; import org.dependencytrack.model.WorkflowStatus; import org.dependencytrack.model.validation.ValidUuid; +import org.dependencytrack.notification.NotificationConstants; +import org.dependencytrack.notification.NotificationGroup; +import org.dependencytrack.notification.NotificationScope; +import org.dependencytrack.notification.vo.BomValidationFailed; import org.dependencytrack.parser.cyclonedx.CycloneDXExporter; import org.dependencytrack.parser.cyclonedx.CycloneDxValidator; import org.dependencytrack.parser.cyclonedx.InvalidBomException; @@ -100,6 +108,7 @@ public class BomResource extends AlpineResource { private static final Logger LOGGER = Logger.getLogger(BomResource.class); + private static final KafkaEventDispatcher eventDispatcher = new KafkaEventDispatcher(); @GET @Path("/cyclonedx/project/{uuid}") @@ -538,7 +547,7 @@ private Response process(QueryManager qm, Project project, List errors, Bom.Format format) { + eventDispatcher.dispatchNotification(new Notification() + .scope(NotificationScope.PORTFOLIO) + .group(NotificationGroup.BOM_VALIDATION_FAILED) + .level(NotificationLevel.ERROR) + .title(NotificationConstants.Title.BOM_VALIDATION_FAILED) + .content("An error occurred while validating a BOM") + .subject(new BomValidationFailed(project, /* bom */ "(Omitted)", errors, format))); + } } diff --git a/src/main/java/org/dependencytrack/resources/v1/VexResource.java b/src/main/java/org/dependencytrack/resources/v1/VexResource.java index 07efa82dc..1ce36f01b 100644 --- a/src/main/java/org/dependencytrack/resources/v1/VexResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/VexResource.java @@ -260,7 +260,7 @@ private Response process(QueryManager qm, Project project, String encodedVexData return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified project is forbidden").build(); } final byte[] decoded = Base64.getDecoder().decode(encodedVexData); - BomResource.validate(decoded); + BomResource.validate(decoded, project); final VexUploadEvent vexUploadEvent = new VexUploadEvent(project.getUuid(), decoded); Event.dispatch(vexUploadEvent); return Response.ok(Collections.singletonMap("token", vexUploadEvent.getChainIdentifier())).build(); @@ -281,7 +281,7 @@ private Response process(QueryManager qm, Project project, List Date: Fri, 9 Aug 2024 16:32:07 +0100 Subject: [PATCH 2/5] update tests --- .../resources/v1/BomResource.java | 4 +-- .../resources/v1/BomResourceTest.java | 31 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/dependencytrack/resources/v1/BomResource.java b/src/main/java/org/dependencytrack/resources/v1/BomResource.java index be5d0a23d..587b2a985 100644 --- a/src/main/java/org/dependencytrack/resources/v1/BomResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/BomResource.java @@ -598,13 +598,13 @@ static void validate(final byte[] bomBytes, final Project project) { } } - private static void dispatchBomValidationFailedNotification(Project project, String bomEncoded, List errors, Bom.Format format) { + private static void dispatchBomValidationFailedNotification(Project project, String bom, List errors, Bom.Format format) { eventDispatcher.dispatchNotification(new Notification() .scope(NotificationScope.PORTFOLIO) .group(NotificationGroup.BOM_VALIDATION_FAILED) .level(NotificationLevel.ERROR) .title(NotificationConstants.Title.BOM_VALIDATION_FAILED) .content("An error occurred while validating a BOM") - .subject(new BomValidationFailed(project, /* bom */ "(Omitted)", errors, format))); + .subject(new BomValidationFailed(project, bom, errors, format))); } } diff --git a/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java b/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java index 2ff311544..caea07097 100644 --- a/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java +++ b/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java @@ -34,9 +34,11 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.http.HttpStatus; +import org.assertj.core.api.AssertionsForClassTypes; import org.dependencytrack.JerseyTestRule; import org.dependencytrack.ResourceTest; import org.dependencytrack.auth.Permissions; +import org.dependencytrack.event.kafka.KafkaTopics; import org.dependencytrack.model.AnalysisResponse; import org.dependencytrack.model.AnalysisState; import org.dependencytrack.model.AnalyzerIdentity; @@ -53,6 +55,7 @@ import org.dependencytrack.model.Vulnerability; import org.dependencytrack.model.WorkflowState; import org.dependencytrack.model.WorkflowStep; +import org.dependencytrack.notification.NotificationConstants; import org.dependencytrack.parser.cyclonedx.CycloneDxValidator; import org.dependencytrack.resources.v1.exception.JsonMappingExceptionMapper; import org.dependencytrack.resources.v1.vo.BomSubmitRequest; @@ -78,6 +81,7 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.time.Duration; import java.util.ArrayList; import java.util.Base64; import java.util.Date; @@ -91,12 +95,17 @@ import static org.apache.commons.io.IOUtils.resourceToString; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.dependencytrack.assertion.Assertions.assertConditionWithTimeout; import static org.dependencytrack.model.ConfigPropertyConstants.BOM_VALIDATION_ENABLED; import static org.dependencytrack.model.WorkflowStatus.COMPLETED; import static org.dependencytrack.model.WorkflowStatus.FAILED; import static org.dependencytrack.model.WorkflowStatus.PENDING; import static org.dependencytrack.model.WorkflowStep.BOM_CONSUMPTION; import static org.dependencytrack.model.WorkflowStep.BOM_PROCESSING; +import static org.dependencytrack.proto.notification.v1.Group.GROUP_BOM_VALIDATION_FAILED; +import static org.dependencytrack.proto.notification.v1.Level.LEVEL_ERROR; +import static org.dependencytrack.proto.notification.v1.Scope.SCOPE_PORTFOLIO; +import static org.dependencytrack.util.KafkaTestUtil.deserializeValue; import static org.hamcrest.CoreMatchers.equalTo; @RunWith(JUnitParamsRunner.class) @@ -1136,7 +1145,7 @@ public void isTokenBeingProcessedFalseTest() { } @Test - public void uploadBomInvalidJsonTest() { + public void uploadBomInvalidJsonTest() throws InterruptedException { initializeWithPermissions(Permissions.BOM_UPLOAD); final var project = new Project(); @@ -1181,10 +1190,19 @@ public void uploadBomInvalidJsonTest() { ] } """); + + assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 1, Duration.ofSeconds(5)); + final org.dependencytrack.proto.notification.v1.Notification userNotification = deserializeValue(KafkaTopics.NOTIFICATION_USER, kafkaMockProducer.history().get(0)); + AssertionsForClassTypes.assertThat(userNotification).isNotNull(); + AssertionsForClassTypes.assertThat(userNotification.getScope()).isEqualTo(SCOPE_PORTFOLIO); + AssertionsForClassTypes.assertThat(userNotification.getGroup()).isEqualTo(GROUP_BOM_VALIDATION_FAILED); + AssertionsForClassTypes.assertThat(userNotification.getLevel()).isEqualTo(LEVEL_ERROR); + AssertionsForClassTypes.assertThat(userNotification.getTitle()).isEqualTo(NotificationConstants.Title.BOM_VALIDATION_FAILED); + AssertionsForClassTypes.assertThat(userNotification.getContent()).isEqualTo("An error occurred while validating a BOM"); } @Test - public void uploadBomInvalidXmlTest() { + public void uploadBomInvalidXmlTest() throws InterruptedException { initializeWithPermissions(Permissions.BOM_UPLOAD); final var project = new Project(); @@ -1226,6 +1244,15 @@ public void uploadBomInvalidXmlTest() { ] } """); + + assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 1, Duration.ofSeconds(5)); + final org.dependencytrack.proto.notification.v1.Notification userNotification = deserializeValue(KafkaTopics.NOTIFICATION_USER, kafkaMockProducer.history().get(0)); + AssertionsForClassTypes.assertThat(userNotification).isNotNull(); + AssertionsForClassTypes.assertThat(userNotification.getScope()).isEqualTo(SCOPE_PORTFOLIO); + AssertionsForClassTypes.assertThat(userNotification.getGroup()).isEqualTo(GROUP_BOM_VALIDATION_FAILED); + AssertionsForClassTypes.assertThat(userNotification.getLevel()).isEqualTo(LEVEL_ERROR); + AssertionsForClassTypes.assertThat(userNotification.getTitle()).isEqualTo(NotificationConstants.Title.BOM_VALIDATION_FAILED); + AssertionsForClassTypes.assertThat(userNotification.getContent()).isEqualTo("An error occurred while validating a BOM"); } @Test From 9ea2ca3cb181530531fec683f1f26bab57061514 Mon Sep 17 00:00:00 2001 From: Sahiba Mittal Date: Mon, 12 Aug 2024 14:30:46 +0100 Subject: [PATCH 3/5] fix test --- src/main/java/org/dependencytrack/resources/v1/BomResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/dependencytrack/resources/v1/BomResource.java b/src/main/java/org/dependencytrack/resources/v1/BomResource.java index 587b2a985..eaf56bb25 100644 --- a/src/main/java/org/dependencytrack/resources/v1/BomResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/BomResource.java @@ -108,7 +108,6 @@ public class BomResource extends AlpineResource { private static final Logger LOGGER = Logger.getLogger(BomResource.class); - private static final KafkaEventDispatcher eventDispatcher = new KafkaEventDispatcher(); @GET @Path("/cyclonedx/project/{uuid}") @@ -599,6 +598,7 @@ static void validate(final byte[] bomBytes, final Project project) { } private static void dispatchBomValidationFailedNotification(Project project, String bom, List errors, Bom.Format format) { + final KafkaEventDispatcher eventDispatcher = new KafkaEventDispatcher(); eventDispatcher.dispatchNotification(new Notification() .scope(NotificationScope.PORTFOLIO) .group(NotificationGroup.BOM_VALIDATION_FAILED) From 3ec305f2faa1d5c5457824c01259773a33ee721a Mon Sep 17 00:00:00 2001 From: Sahiba Mittal Date: Mon, 12 Aug 2024 16:50:27 +0100 Subject: [PATCH 4/5] refactor BomValidationFailedSubject proto --- .../notification/vo/BomValidationFailed.java | 9 +-------- .../dependencytrack/NotificationModelConverter.java | 1 - .../org/dependencytrack/resources/v1/BomResource.java | 7 +++---- .../dependencytrack/notification/v1/notification.proto | 1 - .../dependencytrack/NotificationModelConverterTest.java | 3 +-- .../dependencytrack/resources/v1/BomResourceTest.java | 6 ++---- 6 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java b/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java index b01e4eb5c..a6e353a4a 100644 --- a/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java +++ b/src/main/java/org/dependencytrack/notification/vo/BomValidationFailed.java @@ -18,7 +18,6 @@ */ package org.dependencytrack.notification.vo; -import org.dependencytrack.model.Bom; import org.dependencytrack.model.Project; import java.util.List; @@ -28,13 +27,11 @@ public class BomValidationFailed { private Project project; private String bom; private List errors; - private Bom.Format format; - public BomValidationFailed(final Project project, final String bom, final List errors, final Bom.Format format) { + public BomValidationFailed(final Project project, final String bom, final List errors) { this.project = project; this.bom = bom; this.errors = errors; - this.format = format; } public Project getProject() { @@ -48,8 +45,4 @@ public String getBom() { public List getErrors() { return errors; } - - public Bom.Format getFormat() { - return format; - } } \ No newline at end of file diff --git a/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java b/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java index ac44ac5d3..e973cb420 100644 --- a/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java +++ b/src/main/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverter.java @@ -288,7 +288,6 @@ private static BomValidationFailedSubject convert(final BomValidationFailed subj org.dependencytrack.proto.notification.v1.Bom.Builder bomBuilder = org.dependencytrack.proto.notification.v1.Bom.newBuilder(); Optional.ofNullable(subject.getBom()).ifPresent(bomBuilder::setContent); - Optional.ofNullable(subject.getFormat()).map(Bom.Format::getFormatShortName).ifPresent(bomBuilder::setFormat); final BomValidationFailedSubject.Builder builder = BomValidationFailedSubject.newBuilder() .setProject(convert(subject.getProject())) diff --git a/src/main/java/org/dependencytrack/resources/v1/BomResource.java b/src/main/java/org/dependencytrack/resources/v1/BomResource.java index eaf56bb25..3ec336100 100644 --- a/src/main/java/org/dependencytrack/resources/v1/BomResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/BomResource.java @@ -54,7 +54,6 @@ import org.dependencytrack.auth.Permissions; import org.dependencytrack.event.BomUploadEvent; import org.dependencytrack.event.kafka.KafkaEventDispatcher; -import org.dependencytrack.model.Bom; import org.dependencytrack.model.Component; import org.dependencytrack.model.Project; import org.dependencytrack.model.WorkflowState; @@ -587,7 +586,7 @@ static void validate(final byte[] bomBytes, final Project project) { final var bomEncoded = Base64.getEncoder() .encodeToString(bomBytes); - dispatchBomValidationFailedNotification(project, bomEncoded, problemDetails.getErrors(), Bom.Format.CYCLONEDX); + dispatchBomValidationFailedNotification(project, bomEncoded, problemDetails.getErrors()); throw new WebApplicationException(response); } catch (RuntimeException e) { @@ -597,7 +596,7 @@ static void validate(final byte[] bomBytes, final Project project) { } } - private static void dispatchBomValidationFailedNotification(Project project, String bom, List errors, Bom.Format format) { + private static void dispatchBomValidationFailedNotification(Project project, String bom, List errors) { final KafkaEventDispatcher eventDispatcher = new KafkaEventDispatcher(); eventDispatcher.dispatchNotification(new Notification() .scope(NotificationScope.PORTFOLIO) @@ -605,6 +604,6 @@ private static void dispatchBomValidationFailedNotification(Project project, Str .level(NotificationLevel.ERROR) .title(NotificationConstants.Title.BOM_VALIDATION_FAILED) .content("An error occurred while validating a BOM") - .subject(new BomValidationFailed(project, bom, errors, format))); + .subject(new BomValidationFailed(project, bom, errors))); } } diff --git a/src/main/proto/org/dependencytrack/notification/v1/notification.proto b/src/main/proto/org/dependencytrack/notification/v1/notification.proto index 5acda059c..117e85211 100644 --- a/src/main/proto/org/dependencytrack/notification/v1/notification.proto +++ b/src/main/proto/org/dependencytrack/notification/v1/notification.proto @@ -85,7 +85,6 @@ message BomValidationFailedSubject { Project project = 1; Bom bom = 2; repeated string errors = 3; - string format = 4; } message Bom { diff --git a/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java b/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java index d4602573d..2d34948ad 100644 --- a/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java +++ b/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java @@ -434,14 +434,13 @@ public void testConvertBomProcessingFailedNotification() throws Exception { @Test public void testConvertBomValidationFailedNotification() throws Exception { final org.dependencytrack.model.Project project = createProject(); - final var token = UUID.randomUUID(); final var alpineNotification = new alpine.notification.Notification(); alpineNotification.setScope(NotificationScope.PORTFOLIO.name()); alpineNotification.setLevel(NotificationLevel.ERROR); alpineNotification.setGroup(NotificationGroup.BOM_VALIDATION_FAILED.name()); alpineNotification.setTitle("Foo"); alpineNotification.setContent("Bar"); - alpineNotification.setSubject(new BomValidationFailed(project, "bom", List.of("just because"), Bom.Format.CYCLONEDX)); + alpineNotification.setSubject(new BomValidationFailed(project, "bom", List.of("just because"))); final Notification notification = NotificationModelConverter.convert(alpineNotification); assertThat(notification.getScope()).isEqualTo(SCOPE_PORTFOLIO); diff --git a/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java b/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java index caea07097..c262ee69f 100644 --- a/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java +++ b/src/test/java/org/dependencytrack/resources/v1/BomResourceTest.java @@ -81,7 +81,6 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; -import java.time.Duration; import java.util.ArrayList; import java.util.Base64; import java.util.Date; @@ -95,7 +94,6 @@ import static org.apache.commons.io.IOUtils.resourceToString; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; -import static org.dependencytrack.assertion.Assertions.assertConditionWithTimeout; import static org.dependencytrack.model.ConfigPropertyConstants.BOM_VALIDATION_ENABLED; import static org.dependencytrack.model.WorkflowStatus.COMPLETED; import static org.dependencytrack.model.WorkflowStatus.FAILED; @@ -1191,7 +1189,7 @@ public void uploadBomInvalidJsonTest() throws InterruptedException { } """); - assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 1, Duration.ofSeconds(5)); + assertThat(kafkaMockProducer.history()).hasSize(1); final org.dependencytrack.proto.notification.v1.Notification userNotification = deserializeValue(KafkaTopics.NOTIFICATION_USER, kafkaMockProducer.history().get(0)); AssertionsForClassTypes.assertThat(userNotification).isNotNull(); AssertionsForClassTypes.assertThat(userNotification.getScope()).isEqualTo(SCOPE_PORTFOLIO); @@ -1245,7 +1243,7 @@ public void uploadBomInvalidXmlTest() throws InterruptedException { } """); - assertConditionWithTimeout(() -> kafkaMockProducer.history().size() == 1, Duration.ofSeconds(5)); + assertThat(kafkaMockProducer.history()).hasSize(1); final org.dependencytrack.proto.notification.v1.Notification userNotification = deserializeValue(KafkaTopics.NOTIFICATION_USER, kafkaMockProducer.history().get(0)); AssertionsForClassTypes.assertThat(userNotification).isNotNull(); AssertionsForClassTypes.assertThat(userNotification.getScope()).isEqualTo(SCOPE_PORTFOLIO); From 8e66ff363450bd65c5e424244306c1eecdebe504 Mon Sep 17 00:00:00 2001 From: Sahiba Mittal Date: Tue, 13 Aug 2024 10:17:02 +0100 Subject: [PATCH 5/5] Update NotificationModelConverterTest.java --- .../parser/dependencytrack/NotificationModelConverterTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java b/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java index 2d34948ad..f469ef32e 100644 --- a/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java +++ b/src/test/java/org/dependencytrack/parser/dependencytrack/NotificationModelConverterTest.java @@ -455,7 +455,6 @@ public void testConvertBomValidationFailedNotification() throws Exception { final var subject = notification.getSubject().unpack(BomValidationFailedSubject.class); assertProject(subject.getProject()); assertThat(subject.getBom().getContent()).isEqualTo("bom"); - assertThat(subject.getBom().getFormat()).isEqualTo("CycloneDX"); assertThat(subject.getErrors(0)).isEqualTo("just because"); }