diff --git a/misp/connector/src/main/scala/org/thp/thehive/connector/misp/controllers/v0/MispCtrl.scala b/misp/connector/src/main/scala/org/thp/thehive/connector/misp/controllers/v0/MispCtrl.scala index a9b06ff214..001a876b52 100644 --- a/misp/connector/src/main/scala/org/thp/thehive/connector/misp/controllers/v0/MispCtrl.scala +++ b/misp/connector/src/main/scala/org/thp/thehive/connector/misp/controllers/v0/MispCtrl.scala @@ -2,12 +2,13 @@ package org.thp.thehive.connector.misp.controllers.v0 import akka.actor.ActorRef import com.google.inject.name.Named + import javax.inject.{Inject, Singleton} import org.thp.scalligraph.EntityIdOrName import org.thp.scalligraph.controllers.Entrypoint import org.thp.scalligraph.models.Database import org.thp.scalligraph.traversal.TraversalOps._ -import org.thp.thehive.connector.misp.services.{MispActor, MispExportSrv} +import org.thp.thehive.connector.misp.services.{MispActor, MispExportSrv, Synchro} import org.thp.thehive.models.Permissions import org.thp.thehive.services.AlertOps._ import org.thp.thehive.services.CaseOps._ @@ -31,7 +32,7 @@ class MispCtrl @Inject() ( def sync: Action[AnyContent] = entrypoint("sync MISP events") .authPermitted(Permissions.manageOrganisation) { _ => - mispActor ! MispActor.Synchro + mispActor ! Synchro Success(Results.NoContent) } diff --git a/misp/connector/src/main/scala/org/thp/thehive/connector/misp/services/MispActor.scala b/misp/connector/src/main/scala/org/thp/thehive/connector/misp/services/MispActor.scala index fd52006516..dfd4d06694 100644 --- a/misp/connector/src/main/scala/org/thp/thehive/connector/misp/services/MispActor.scala +++ b/misp/connector/src/main/scala/org/thp/thehive/connector/misp/services/MispActor.scala @@ -2,24 +2,22 @@ package org.thp.thehive.connector.misp.services import akka.actor.{Actor, ActorRef, ActorSystem, Cancellable} import akka.cluster.singleton.{ClusterSingletonProxy, ClusterSingletonProxySettings} -import javax.inject.{Inject, Named, Provider} import org.thp.scalligraph.auth.UserSrv import play.api.Logger +import javax.inject.{Inject, Named, Provider} import scala.concurrent.Future -import scala.util.{Failure, Success, Try} +import scala.util.{Failure, Success} -object MispActor { - case object Synchro - case class EndOfSynchro(status: Try[Unit]) -} +sealed trait MispMessage +case object Synchro extends MispMessage +case class EndOfSynchro(error: Option[String]) extends MispMessage class MispActor @Inject() ( connector: Connector, mispImportSrv: MispImportSrv, userSrv: UserSrv ) extends Actor { - import MispActor._ import context.dispatcher lazy val logger: Logger = Logger(getClass) @@ -36,11 +34,11 @@ class MispActor @Inject() ( def running: Receive = { case Synchro => logger.info("MISP synchronisation is already in progress") - case EndOfSynchro(Success(_)) => + case EndOfSynchro(None) => logger.info("MISP synchronisation is complete") context.become(waiting(context.system.scheduler.scheduleOnce(connector.syncInterval, self, Synchro))) - case EndOfSynchro(Failure(error)) => - logger.error("MISP synchronisation fails", error) + case EndOfSynchro(Some(error)) => + logger.error(s"MISP synchronisation fails: $error") context.become(waiting(context.system.scheduler.scheduleOnce(connector.syncInterval, self, Synchro))) case other => logger.warn(s"Unknown message $other (${other.getClass})") } @@ -53,7 +51,12 @@ class MispActor @Inject() ( Future .traverse(connector.clients.filter(_.canImport))(mispImportSrv.syncMispEvents(_)(userSrv.getSystemAuthContext)) .map(_ => ()) - .onComplete(status => self ! EndOfSynchro(status)) + .onComplete { + case _: Success[_] => self ! EndOfSynchro(None) + case Failure(error) => + logger.error("MISP synchronisation failure", error) + self ! EndOfSynchro(Some(error.toString)) + } case other => logger.warn(s"Unknown message $other (${other.getClass})") } } diff --git a/misp/connector/src/test/scala/org/thp/thehive/connector/misp/services/MispSerializer.scala b/misp/connector/src/test/scala/org/thp/thehive/connector/misp/services/MispSerializer.scala new file mode 100644 index 0000000000..89b78069d3 --- /dev/null +++ b/misp/connector/src/test/scala/org/thp/thehive/connector/misp/services/MispSerializer.scala @@ -0,0 +1,23 @@ +package org.thp.thehive.connector.misp.services + +import akka.serialization.Serializer + +class MispSerializer extends Serializer { + override def identifier: Int = -222314660 + + override def includeManifest: Boolean = false + + override def toBinary(o: AnyRef): Array[Byte] = + o match { + case Synchro => Array(0) + case EndOfSynchro(None) => Array(1) + case EndOfSynchro(Some(error)) => 2.toByte +: error.getBytes() + } + + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = + bytes(0) match { + case 0 => Synchro + case 1 => EndOfSynchro(None) + case 2 => EndOfSynchro(Some(new String(bytes.tail))) + } +}