From d25867c052c9616fa098476a150f6ddc8c37c8a3 Mon Sep 17 00:00:00 2001 From: Robin Riclet Date: Mon, 26 Oct 2020 14:31:30 +0100 Subject: [PATCH] #1557 One CaseUpdate per alert merge --- .../thehive/controllers/v0/Conversion.scala | 1 - .../org/thp/thehive/services/AlertSrv.scala | 30 ++++++++++++------- .../org/thp/thehive/services/AuditSrv.scala | 4 +-- .../notification/notifiers/Webhook.scala | 9 +++++- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/thehive/app/org/thp/thehive/controllers/v0/Conversion.scala b/thehive/app/org/thp/thehive/controllers/v0/Conversion.scala index 145981b6cc..f972afd972 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/Conversion.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/Conversion.scala @@ -28,7 +28,6 @@ object Conversion { def fromObjectType(objectType: String): String = objectType match { - // case "Case" =>"case" case "Task" => "case_task" case "Log" => "case_task_log" case "Observable" => "case_artifact" diff --git a/thehive/app/org/thp/thehive/services/AlertSrv.scala b/thehive/app/org/thp/thehive/services/AlertSrv.scala index 77ee744d32..ddcf2d02e7 100644 --- a/thehive/app/org/thp/thehive/services/AlertSrv.scala +++ b/thehive/app/org/thp/thehive/services/AlertSrv.scala @@ -271,17 +271,25 @@ class AlertSrv @Inject() ( updatedCase <- mergeInCase(alert, case0) } yield updatedCase - def mergeInCase(alert: Alert with Entity, `case`: Case with Entity)(implicit graph: Graph, authContext: AuthContext): Try[Case with Entity] = - for { - _ <- caseSrv.addTags(`case`, get(alert).tags.toSeq.map(_.toString).toSet) - description = `case`.description + s"\n \n#### Merged with alert #${alert.sourceRef} ${alert.title}\n\n${alert.description.trim}" - c <- caseSrv.get(`case`).update(_.description, description).getOrFail("Case") - _ <- importObservables(alert, `case`) - _ <- importCustomFields(alert, `case`) - _ <- alertCaseSrv.create(AlertCase(), alert, `case`) - _ <- markAsRead(alert._id) - _ <- auditSrv.alertToCase.merge(alert, c) - } yield c + def mergeInCase(alert: Alert with Entity, `case`: Case with Entity)(implicit graph: Graph, authContext: AuthContext): Try[Case with Entity] = { + auditSrv.mergeAudits { + // No audit for markAsRead and observables + markAsRead(alert._id) + importObservables(alert, `case`) + importCustomFields(alert, `case`) + + // Audits for customFields, description and tags + val customFields = get(alert).richCustomFields.toSeq.map(_.toOutput.toJson) + val description = `case`.description + s"\n \n#### Merged with alert #${alert.sourceRef} ${alert.title}\n\n${alert.description.trim}" + val tags = get(alert).tags.toSeq.map(_.toString) + + caseSrv.get(`case`).update(_.description, description).getOrFail("Case") + caseSrv.addTags(`case`, tags.toSet) + Success(Json.obj("customFields" -> customFields, "description" -> description, "tags" -> tags)) + } (audits => auditSrv.alertToCase.merge(alert, `case`, Some(audits))) + + caseSrv.get(`case`).getOrFail("Case") + } def importObservables(alert: Alert with Entity, `case`: Case with Entity)(implicit graph: Graph, diff --git a/thehive/app/org/thp/thehive/services/AuditSrv.scala b/thehive/app/org/thp/thehive/services/AuditSrv.scala index f5fe61c8ff..077b177834 100644 --- a/thehive/app/org/thp/thehive/services/AuditSrv.scala +++ b/thehive/app/org/thp/thehive/services/AuditSrv.scala @@ -173,8 +173,8 @@ class AuditSrv @Inject() ( def delete(entity: E with Entity, context: Option[C with Entity])(implicit graph: Graph, authContext: AuthContext): Try[Unit] = auditSrv.create(Audit(Audit.delete, entity, None), context, None) - def merge(entity: E with Entity, destination: C with Entity)(implicit graph: Graph, authContext: AuthContext): Try[Unit] = - auditSrv.create(Audit(Audit.merge, entity), Some(destination), None) + def merge(entity: E with Entity, destination: C with Entity, details: Option[JsObject] = None)(implicit graph: Graph, authContext: AuthContext): Try[Unit] = + auditSrv.create(Audit(Audit.merge, destination, details.map(_.toString())), Some(destination), None) } class SelfContextObjectAudit[E <: Product] { diff --git a/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala b/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala index d7b65a3448..757a9e91a3 100644 --- a/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala +++ b/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala @@ -13,6 +13,7 @@ import org.thp.scalligraph.traversal.{Converter, IdentityConverter, Traversal} import org.thp.scalligraph.{BadConfigurationError, EntityIdOrName} import org.thp.thehive.controllers.v0.AuditRenderer import org.thp.thehive.controllers.v0.Conversion.fromObjectType +import org.thp.thehive.models.Audit._ import org.thp.thehive.models._ import org.thp.thehive.services.AlertOps._ import org.thp.thehive.services.AuditOps._ @@ -197,7 +198,7 @@ class Webhook( case (audit, obj) => val objectType = audit.objectType.getOrElse(audit.context._label) Json.obj( - "operation" -> audit.action, + "operation" -> v0Action(audit.action), "details" -> audit.details.fold[JsValue](JsObject.empty)(fixCustomFieldDetails(objectType, _)), "objectType" -> fromObjectType(objectType), "objectId" -> audit.objectId, @@ -227,6 +228,12 @@ class Webhook( case _ => Failure(BadConfigurationError(s"Message version $version in webhook is not supported")) } + def v0Action(action: String): String = + action match { + case Audit.merge => Audit.update + case action => action + } + override def execute( audit: Audit with Entity, context: Option[Entity],