From a8931182fc88970cc422114de623269111235b50 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Nov 2021 11:38:18 +0000 Subject: [PATCH 01/15] fix typo in attack pattern import --- .../scripts/controllers/admin/attack/AttackPatternListCtrl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/scripts/controllers/admin/attack/AttackPatternListCtrl.js b/frontend/app/scripts/controllers/admin/attack/AttackPatternListCtrl.js index 84eccdb2e7..2ee4731a95 100644 --- a/frontend/app/scripts/controllers/admin/attack/AttackPatternListCtrl.js +++ b/frontend/app/scripts/controllers/admin/attack/AttackPatternListCtrl.js @@ -163,7 +163,7 @@ .catch(function (response) { NotificationSrv.error('AttackPatternImportCtrl', response.data, response.status); }) - .fincally(function () { + .finally(function () { this.loading = false; }); }; From a7437f660d9c3dd80d05307cdf5f574a350fb3e8 Mon Sep 17 00:00:00 2001 From: idolaman Date: Wed, 19 Jan 2022 05:58:07 -0500 Subject: [PATCH 02/15] sort template custom field and case custom field seperate --- thehive/app/org/thp/thehive/services/CaseSrv.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thehive/app/org/thp/thehive/services/CaseSrv.scala b/thehive/app/org/thp/thehive/services/CaseSrv.scala index 665870b313..d69941285b 100644 --- a/thehive/app/org/thp/thehive/services/CaseSrv.scala +++ b/thehive/app/org/thp/thehive/services/CaseSrv.scala @@ -126,8 +126,8 @@ class CaseSrv @Inject() ( val uniqueFields = caseTemplateCf.filter { case InputCustomFieldValue(name, _, _) => !caseCf.exists(_.name == name) } - (caseCf ++ uniqueFields) - .sortBy(cf => (cf.order.isEmpty, cf.order)) + + (caseCf.sortBy(_.order) ++ uniqueFields.sortBy(_.order)) .zipWithIndex .map { case (InputCustomFieldValue(name, value, _), i) => InputCustomFieldValue(name, value, Some(i)) } } From 31367bd0713c4f71c01156f58696bf48866752ad Mon Sep 17 00:00:00 2001 From: To-om Date: Fri, 25 Feb 2022 16:40:07 +0100 Subject: [PATCH 03/15] #2351 Fix deadlock --- ScalliGraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ScalliGraph b/ScalliGraph index ad52dd66ba..045cf68865 160000 --- a/ScalliGraph +++ b/ScalliGraph @@ -1 +1 @@ -Subproject commit ad52dd66bad873f7cff2dd0e763c95099c7822fd +Subproject commit 045cf688652a0e325633dea329f46db3b90092af From c7cd8b3ef16c0388fab893df47f3c5a806b538a5 Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 09:25:00 +0200 Subject: [PATCH 04/15] #2366 Update organisatIds when the share is removed --- thehive/app/org/thp/thehive/controllers/v1/ShareCtrl.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thehive/app/org/thp/thehive/controllers/v1/ShareCtrl.scala b/thehive/app/org/thp/thehive/controllers/v1/ShareCtrl.scala index 80e54c98c1..3e691b4086 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/ShareCtrl.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/ShareCtrl.scala @@ -167,7 +167,7 @@ class ShareCtrl @Inject() ( else if (shareSrv.get(shareId).has(_.owner, true).exists) Failure(AuthorizationError("You can't remove initial shares")) else - shareSrv.get(shareId).getOrFail("Share").flatMap(shareSrv.delete(_)) + shareSrv.unshareCase(shareId) def updateShare(shareId: String): Action[AnyContent] = entrypoint("update share") From bd0185814a7faf3f3fd64fec22093d9a72ec93ae Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 09:27:56 +0200 Subject: [PATCH 05/15] #2367 Prevent custom field creation if it already exists --- .../thp/thehive/services/CustomFieldSrv.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/thehive/app/org/thp/thehive/services/CustomFieldSrv.scala b/thehive/app/org/thp/thehive/services/CustomFieldSrv.scala index b27b7c141a..f1ee397bd0 100644 --- a/thehive/app/org/thp/thehive/services/CustomFieldSrv.scala +++ b/thehive/app/org/thp/thehive/services/CustomFieldSrv.scala @@ -2,14 +2,13 @@ package org.thp.thehive.services import akka.actor.typed.ActorRef import org.apache.tinkerpop.gremlin.structure.Edge -import org.thp.scalligraph.EntityIdOrName import org.thp.scalligraph.auth.AuthContext import org.thp.scalligraph.models.{Database, Entity} import org.thp.scalligraph.query.PropertyUpdater -import org.thp.scalligraph.RichSeq -import org.thp.scalligraph.services.{DedupCheck, IntegrityCheckOps, VertexSrv} +import org.thp.scalligraph.services.{DedupCheck, VertexSrv} import org.thp.scalligraph.traversal.TraversalOps._ import org.thp.scalligraph.traversal._ +import org.thp.scalligraph.{CreateError, EntityIdOrName, RichSeq} import org.thp.thehive.controllers.v1.Conversion._ import org.thp.thehive.models._ import org.thp.thehive.services.CustomFieldOps._ @@ -18,7 +17,7 @@ import play.api.libs.json.{JsObject, JsValue} import java.util.{Map => JMap} import javax.inject.{Inject, Provider, Singleton} -import scala.util.{Success, Try} +import scala.util.{Failure, Try} @Singleton class CustomFieldSrv @Inject() ( @@ -37,10 +36,13 @@ class CustomFieldSrv @Inject() ( } def create(e: CustomField)(implicit graph: Graph, authContext: AuthContext): Try[CustomField with Entity] = - for { - created <- createEntity(e) - _ <- auditSrv.customField.create(created, created.toJson) - } yield created + if (startTraversal.getByName(e.name).exists) + Failure(CreateError(s"CustomField ${e.name} already exists")) + else + for { + created <- createEntity(e) + _ <- auditSrv.customField.create(created, created.toJson) + } yield created override def exists(e: CustomField)(implicit graph: Graph): Boolean = startTraversal.getByName(e.name).exists From 4dff8072eed77fa1c018e34cb3e2861d09da7299 Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 09:41:09 +0200 Subject: [PATCH 06/15] #2368 Add integrity check to remove orphan user --- .../thp/thehive/connector/cortex/controllers/v0/JobCtrl.scala | 2 +- thehive/app/org/thp/thehive/services/UserSrv.scala | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/controllers/v0/JobCtrl.scala b/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/controllers/v0/JobCtrl.scala index dc1a7d6a8b..1aa7df543c 100644 --- a/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/controllers/v0/JobCtrl.scala +++ b/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/controllers/v0/JobCtrl.scala @@ -58,7 +58,7 @@ class JobCtrl @Inject() ( db.roTransaction { implicit graph => val artifactId: String = request.body("artifactId") for { - o <- observableSrv.get(EntityIdOrName(artifactId)).richObservable.getOrFail("Observable") + o <- observableSrv.get(EntityIdOrName(artifactId)).can(Permissions.manageAnalyse).richObservable.getOrFail("Observable") c <- observableSrv.get(EntityIdOrName(artifactId)).`case`.getOrFail("Case") } yield (o, c) }.fold( diff --git a/thehive/app/org/thp/thehive/services/UserSrv.scala b/thehive/app/org/thp/thehive/services/UserSrv.scala index b92e077de9..0e324fa4d4 100644 --- a/thehive/app/org/thp/thehive/services/UserSrv.scala +++ b/thehive/app/org/thp/thehive/services/UserSrv.scala @@ -353,6 +353,7 @@ class UserIntegrityCheck @Inject() ( (_.out("UserRole"), _.in("UserRole")), (_.out("RoleOrganisation"), _.in("RoleOrganisation")) ).flatMap(ElementSelector.firstCreatedElement(_)).map(e => removeVertices(e._2)).size - Map("duplicateRoleLinks" -> duplicateRoleLinks.toLong) + val orphanCount = service.startTraversal.filterNot(_.organisations).sideEffect(_.drop()).getCount + Map("duplicateRoleLinks" -> duplicateRoleLinks.toLong, "orphan" -> orphanCount) } } From e14f3ef41156e51cda5aec028789f0b4c62512a8 Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 09:44:06 +0200 Subject: [PATCH 07/15] #2369 Fix edition of tags --- thehive/app/org/thp/thehive/services/AlertSrv.scala | 2 +- thehive/app/org/thp/thehive/services/CaseTemplateSrv.scala | 2 +- thehive/app/org/thp/thehive/services/ObservableSrv.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/thehive/app/org/thp/thehive/services/AlertSrv.scala b/thehive/app/org/thp/thehive/services/AlertSrv.scala index f5d3775380..ad2e1334cb 100644 --- a/thehive/app/org/thp/thehive/services/AlertSrv.scala +++ b/thehive/app/org/thp/thehive/services/AlertSrv.scala @@ -110,7 +110,7 @@ class AlertSrv @Inject() ( tagsToAdd <- (tags -- alert.tags).toTry(tagSrv.getOrCreate) tagsToRemove = get(alert).tags.toSeq.filterNot(t => tags.contains(t.toString)) _ <- tagsToAdd.toTry(alertTagSrv.create(AlertTag(), alert, _)) - _ = if (tags.nonEmpty) get(alert).outE[AlertTag].filter(_.otherV.hasId(tagsToRemove.map(_._id): _*)).remove() + _ = if (tagsToRemove.nonEmpty) get(alert).outE[AlertTag].filter(_.otherV.hasId(tagsToRemove.map(_._id): _*)).remove() _ <- get(alert) .update(_.tags, tags.toSeq) .update(_._updatedAt, Some(new Date)) diff --git a/thehive/app/org/thp/thehive/services/CaseTemplateSrv.scala b/thehive/app/org/thp/thehive/services/CaseTemplateSrv.scala index c1b8fcf819..41b6efafc8 100644 --- a/thehive/app/org/thp/thehive/services/CaseTemplateSrv.scala +++ b/thehive/app/org/thp/thehive/services/CaseTemplateSrv.scala @@ -97,7 +97,7 @@ class CaseTemplateSrv @Inject() ( tagsToAdd <- (tags -- caseTemplate.tags).toTry(tagSrv.getOrCreate) tagsToRemove = get(caseTemplate).tags.toSeq.filterNot(t => tags.contains(t.toString)) _ <- tagsToAdd.toTry(caseTemplateTagSrv.create(CaseTemplateTag(), caseTemplate, _)) - _ = if (tags.nonEmpty) get(caseTemplate).outE[CaseTemplateTag].filter(_.otherV.hasId(tagsToRemove.map(_._id): _*)).remove() + _ = if (tagsToRemove.nonEmpty) get(caseTemplate).outE[CaseTemplateTag].filter(_.otherV.hasId(tagsToRemove.map(_._id): _*)).remove() _ <- get(caseTemplate) .update(_.tags, tags.toSeq) .update(_._updatedAt, Some(new Date)) diff --git a/thehive/app/org/thp/thehive/services/ObservableSrv.scala b/thehive/app/org/thp/thehive/services/ObservableSrv.scala index 077bd92d34..b096dca2df 100644 --- a/thehive/app/org/thp/thehive/services/ObservableSrv.scala +++ b/thehive/app/org/thp/thehive/services/ObservableSrv.scala @@ -133,7 +133,7 @@ class ObservableSrv @Inject() ( tagsToAdd <- (tags -- observable.tags).toTry(tagSrv.getOrCreate) tagsToRemove = get(observable).tags.toSeq.filterNot(t => tags.contains(t.toString)) _ <- tagsToAdd.toTry(observableTagSrv.create(ObservableTag(), observable, _)) - _ = if (tags.nonEmpty) get(observable).outE[ObservableTag].filter(_.otherV.hasId(tagsToRemove.map(_._id): _*)).remove() + _ = if (tagsToRemove.nonEmpty) get(observable).outE[ObservableTag].filter(_.otherV.hasId(tagsToRemove.map(_._id): _*)).remove() _ <- get(observable) .update(_.tags, tags.toSeq) .update(_._updatedAt, Some(new Date)) From da36476a13fae27472a420306581ed57ae63a4ef Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 09:47:46 +0200 Subject: [PATCH 08/15] #2364 Update documentation link --- conf/application.sample.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/application.sample.conf b/conf/application.sample.conf index 1045ee97b3..a4e866f750 100644 --- a/conf/application.sample.conf +++ b/conf/application.sample.conf @@ -1,5 +1,5 @@ ### -## Documentation is available at https://github.com/TheHive-Project/TheHiveDocs/TheHive4 +## Documentation is available at https://docs.thehive-project.org/thehive/ ### ## Include Play secret key From 48e97d5d740bf517210069484f84fedb81333f65 Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 10:19:59 +0200 Subject: [PATCH 09/15] #2199 Typo error --- frontend/app/views/partials/observables/list/observables.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/views/partials/observables/list/observables.html b/frontend/app/views/partials/observables/list/observables.html index f9275cddb9..52ea57db3a 100644 --- a/frontend/app/views/partials/observables/list/observables.html +++ b/frontend/app/views/partials/observables/list/observables.html @@ -39,7 +39,7 @@

- + Value/Filename From 54cfb5dd743da0af10bd7b6a2fabd81ea8ac2774 Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 10:32:10 +0200 Subject: [PATCH 10/15] #2319 Fix tests --- .../test/org/thp/thehive/controllers/v0/CaseCtrlTest.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/thehive/test/org/thp/thehive/controllers/v0/CaseCtrlTest.scala b/thehive/test/org/thp/thehive/controllers/v0/CaseCtrlTest.scala index 1b2f9f1010..00fe70fa9a 100644 --- a/thehive/test/org/thp/thehive/controllers/v0/CaseCtrlTest.scala +++ b/thehive/test/org/thp/thehive/controllers/v0/CaseCtrlTest.scala @@ -89,9 +89,9 @@ class CaseCtrlTest extends PlaySpecification with TestAppBuilder { summary = None, owner = Some("certuser@thehive.local"), customFields = Json.obj( - "boolean1" -> Json.obj("boolean" -> true, "order" -> 2), - "string1" -> Json.obj("string" -> "string1 custom field", "order" -> 0), - "date1" -> Json.obj("date" -> now.getTime, "order" -> 1) + "boolean1" -> Json.obj("boolean" -> true, "order" -> 1), + "string1" -> Json.obj("string" -> "string1 custom field", "order" -> 2), + "date1" -> Json.obj("date" -> now.getTime, "order" -> 0) ), stats = Json.obj() ) From 8e8a10696a7b9f406f10c4868084e791b3fd373d Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 5 Apr 2022 11:02:28 +0200 Subject: [PATCH 11/15] #2356 #2342 Add more option to connect to ES --- .../thehive/cloner/IntegrityCheckApp.scala | 9 +-- .../thehive/migration/th3/ElasticClient.scala | 73 +++++++++++-------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/migration/src/main/scala/org/thp/thehive/cloner/IntegrityCheckApp.scala b/migration/src/main/scala/org/thp/thehive/cloner/IntegrityCheckApp.scala index e23cd224b1..a4e09d7ada 100644 --- a/migration/src/main/scala/org/thp/thehive/cloner/IntegrityCheckApp.scala +++ b/migration/src/main/scala/org/thp/thehive/cloner/IntegrityCheckApp.scala @@ -5,7 +5,7 @@ import akka.actor.typed.ActorRef import akka.stream.Materializer import com.google.inject.{Guice, Injector => GInjector} import net.codingwell.scalaguice.{ScalaModule, ScalaMultibinder} -import org.thp.scalligraph.auth.{AuthContext, UserSrv => UserDB} +import org.thp.scalligraph.auth.{UserSrv => UserDB} import org.thp.scalligraph.models.Database import org.thp.scalligraph.services._ import org.thp.thehive.migration.th4.DummyActor @@ -21,7 +21,6 @@ import scala.collection.JavaConverters._ import scala.collection.immutable import scala.concurrent.ExecutionContext import scala.concurrent.duration.DurationInt -import scala.util.Success trait IntegrityCheckApp { private def buildApp(configuration: Configuration, db: Database)(implicit actorSystem: ActorSystem): GInjector = @@ -78,9 +77,8 @@ trait IntegrityCheckApp { buildApp(configuration, db).getInstance(classOf[IntegrityChecks]).runChecks() } -class IntegrityChecks @Inject() (db: Database, checks: immutable.Set[IntegrityCheck], userSrv: UserDB) extends MapMerger { - def runChecks(): Unit = { - implicit val authContext: AuthContext = userSrv.getSystemAuthContext +class IntegrityChecks @Inject() (checks: immutable.Set[IntegrityCheck]) extends MapMerger { + def runChecks(): Unit = checks.foreach { c => println(s"Running check on ${c.name} ...") val desupStats = c match { @@ -102,5 +100,4 @@ class IntegrityChecks @Inject() (db: Database, checks: immutable.Set[IntegrityCh println(s" $statsStr") } - } } diff --git a/migration/src/main/scala/org/thp/thehive/migration/th3/ElasticClient.scala b/migration/src/main/scala/org/thp/thehive/migration/th3/ElasticClient.scala index 31fbbd4ec2..3fda736894 100644 --- a/migration/src/main/scala/org/thp/thehive/migration/th3/ElasticClient.scala +++ b/migration/src/main/scala/org/thp/thehive/migration/th3/ElasticClient.scala @@ -5,31 +5,35 @@ import akka.actor.{ActorSystem, Scheduler} import akka.stream.Materializer import akka.stream.scaladsl.{Sink, Source} import akka.util.ByteString -import com.typesafe.sslconfig.ssl.{KeyManagerConfig, KeyStoreConfig, SSLConfigSettings, TrustManagerConfig, TrustStoreConfig} -import org.thp.client.{Authentication, NoAuthentication, PasswordAuthentication} +import com.typesafe.config.ConfigRenderOptions +import com.typesafe.sslconfig.ssl.{KeyManagerConfig, KeyStoreConfig, TrustManagerConfig, TrustStoreConfig} +import org.thp.client._ +import org.thp.scalligraph.utils.FunctionalCondition.When import org.thp.scalligraph.utils.Retry import org.thp.scalligraph.{InternalError, NotFoundError} import play.api.http.HeaderNames import play.api.libs.json.{JsNumber, JsObject, JsValue, Json} -import play.api.libs.ws.ahc.{AhcWSClient, AhcWSClientConfig} -import play.api.libs.ws.{WSClient, WSClientConfig, WSResponse} +import play.api.libs.ws.ahc.AhcWSClientConfig +import play.api.libs.ws.{WSClient, WSResponse} import play.api.{Configuration, Logger} import java.net.{URI, URLEncoder} import javax.inject.{Inject, Provider, Singleton} -import scala.concurrent.duration.{Duration, DurationInt, DurationLong, FiniteDuration} +import scala.concurrent.duration.{DurationInt, DurationLong, FiniteDuration} import scala.concurrent.{Await, ExecutionContext, Future} import scala.util.Try @Singleton class ElasticClientProvider @Inject() ( config: Configuration, + mat: Materializer, implicit val actorSystem: ActorSystem ) extends Provider[ElasticClient] { override def get(): ElasticClient = { lazy val logger = Logger(getClass) val ws: WSClient = { + val trustManager = config.getOptional[String]("search.trustStore.path").map { trustStore => val trustStoreConfig = TrustStoreConfig(None, Some(trustStore)) config.getOptional[String]("search.trustStore.type").foreach(trustStoreConfig.withStoreType) @@ -46,33 +50,40 @@ class ElasticClientProvider @Inject() ( keyManager.withKeyStoreConfigs(List(keyStoreConfig)) keyManager } - val sslConfig = SSLConfigSettings() - trustManager.foreach(sslConfig.withTrustManagerConfig) - keyManager.foreach(sslConfig.withKeyManagerConfig) + val connectionTimeout = config.getOptional[Int]("search.connectTimeout").map(_.millis) + val idleTimeout = config.getOptional[Int]("search.socketTimeout").map(_.millis) + val requestTimeout = config.getOptional[Int]("search.connectionRequestTimeout").map(_.millis) + val followRedirects = config.getOptional[Boolean]("search.redirectsEnabled") + val maxNumberOfRedirects = config.getOptional[Int]("search.maxRedirects") - val wsConfig = AhcWSClientConfig( - wsClientConfig = WSClientConfig( - connectionTimeout = config.getOptional[Int]("search.connectTimeout").fold(2.minutes)(_.millis), - idleTimeout = config.getOptional[Int]("search.socketTimeout").fold(2.minutes)(_.millis), - requestTimeout = config.getOptional[Int]("search.connectionRequestTimeout").fold(2.minutes)(_.millis), - followRedirects = config.getOptional[Boolean]("search.redirectsEnabled").getOrElse(false), - useProxyProperties = true, - userAgent = None, - compressionEnabled = false, - ssl = sslConfig - ), - maxConnectionsPerHost = -1, - maxConnectionsTotal = -1, - maxConnectionLifetime = Duration.Inf, - idleConnectionInPoolTimeout = 1.minute, - maxNumberOfRedirects = config.getOptional[Int]("search.maxRedirects").getOrElse(5), - maxRequestRetry = 5, - disableUrlEncoding = false, - keepAlive = true, - useLaxCookieEncoder = false, - useCookieStore = false - ) - AhcWSClient(wsConfig) + val wsConfig = Try(Json.parse(config.underlying.getValue("search.trustStore.wsConfig").render(ConfigRenderOptions.concise())).as[ProxyWSConfig]) + .getOrElse(ProxyWSConfig(AhcWSClientConfig(), None)) + .merge(trustManager) { (cfg, tm) => + cfg.copy(wsConfig = + cfg.wsConfig.copy(wsClientConfig = cfg.wsConfig.wsClientConfig.copy(ssl = cfg.wsConfig.wsClientConfig.ssl.withTrustManagerConfig(tm))) + ) + } + .merge(keyManager) { (cfg, km) => + cfg.copy(wsConfig = + cfg.wsConfig.copy(wsClientConfig = cfg.wsConfig.wsClientConfig.copy(ssl = cfg.wsConfig.wsClientConfig.ssl.withKeyManagerConfig(km))) + ) + } + .merge(connectionTimeout) { (cfg, ct) => + cfg.copy(wsConfig = cfg.wsConfig.copy(wsClientConfig = cfg.wsConfig.wsClientConfig.copy(connectionTimeout = ct))) + } + .merge(idleTimeout) { (cfg, it) => + cfg.copy(wsConfig = cfg.wsConfig.copy(wsClientConfig = cfg.wsConfig.wsClientConfig.copy(idleTimeout = it))) + } + .merge(requestTimeout) { (cfg, rt) => + cfg.copy(wsConfig = cfg.wsConfig.copy(wsClientConfig = cfg.wsConfig.wsClientConfig.copy(requestTimeout = rt))) + } + .merge(followRedirects) { (cfg, fr) => + cfg.copy(wsConfig = cfg.wsConfig.copy(wsClientConfig = cfg.wsConfig.wsClientConfig.copy(followRedirects = fr))) + } + .merge(maxNumberOfRedirects) { (cfg, mr) => + cfg.copy(wsConfig = cfg.wsConfig.copy(maxNumberOfRedirects = mr)) + } + new ProxyWS(wsConfig, mat) } val authentication: Authentication = From 2bd756700d4ecb8059daac23f8a7e9a2508238f1 Mon Sep 17 00:00:00 2001 From: To-om Date: Wed, 6 Apr 2022 11:12:56 +0200 Subject: [PATCH 12/15] #2370 Fix round in time aggregation --- ScalliGraph | 2 +- .../thehive/services/th3/Aggregation.scala | 41 +++++++------------ 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/ScalliGraph b/ScalliGraph index 045cf68865..4d439fcd2d 160000 --- a/ScalliGraph +++ b/ScalliGraph @@ -1 +1 @@ -Subproject commit 045cf688652a0e325633dea329f46db3b90092af +Subproject commit 4d439fcd2d1294c998f1a0d8d559e533500e18c7 diff --git a/thehive/app/org/thp/thehive/services/th3/Aggregation.scala b/thehive/app/org/thp/thehive/services/th3/Aggregation.scala index a560d1aefa..a464538c2d 100644 --- a/thehive/app/org/thp/thehive/services/th3/Aggregation.scala +++ b/thehive/app/org/thp/thehive/services/th3/Aggregation.scala @@ -1,6 +1,7 @@ package org.thp.thehive.services.th3 import org.apache.tinkerpop.gremlin.process.traversal.Order +import org.joda.time.DateTime import org.scalactic.Accumulation._ import org.scalactic._ import org.thp.scalligraph.auth.AuthContext @@ -368,38 +369,26 @@ case class TimeAggregation( subAggs: Seq[Aggregation], filter: Option[InputQuery[Traversal.Unk, Traversal.Unk]] ) extends Aggregation(aggName.getOrElse(fieldName)) { - val calendar: Calendar = Calendar.getInstance() - def dateToKey(date: Date): Long = - unit match { - case ChronoUnit.WEEKS => - calendar.setTime(date) - val year = calendar.get(Calendar.YEAR) - val week = (calendar.get(Calendar.WEEK_OF_YEAR) / interval) * interval - calendar.setTimeInMillis(0) - calendar.set(Calendar.YEAR, year) - calendar.set(Calendar.WEEK_OF_YEAR, week.toInt) - calendar.getTimeInMillis + private val threeDaysInMillis = 259200000L + private val oneWeekInMillis = 604800000L + private def roundToWeek(date: Date, nWeek: Long): Long = { + val shiftedDate = date.getTime + threeDaysInMillis // Jan 1st is a thursday + shiftedDate - (shiftedDate % (oneWeekInMillis * nWeek)) - threeDaysInMillis + } + private def dateToKey(date: Date): Long = + unit match { + case ChronoUnit.WEEKS => roundToWeek(date, interval) case ChronoUnit.MONTHS => - calendar.setTime(date) - val year = calendar.get(Calendar.YEAR) - val month = (calendar.get(Calendar.MONTH) / interval) * interval - calendar.setTimeInMillis(0) - calendar.set(Calendar.YEAR, year) - calendar.set(Calendar.MONTH, month.toInt) - calendar.getTimeInMillis - + val d = new DateTime(date) + new DateTime(d.getYear, d.getMonthOfYear, 1, 0, 0).getMillis case ChronoUnit.YEARS => - calendar.setTime(date) - val year = (calendar.get(Calendar.YEAR) / interval) * interval - calendar.setTimeInMillis(0) - calendar.set(Calendar.YEAR, year.toInt) - calendar.getTimeInMillis - + val d = new DateTime(date) + new DateTime(d.getYear, 1, 1, 0, 0).getMillis case other => val duration = other.getDuration.toMillis * interval - (date.getTime / duration) * duration + date.getTime - (date.getTime % duration) } def keyToDate(key: Long): Date = new Date(key) From a6352a4ed9fea1d5c59191beb27a15eb26def070 Mon Sep 17 00:00:00 2001 From: To-om Date: Wed, 6 Apr 2022 11:29:06 +0200 Subject: [PATCH 13/15] #2362 Update libraries --- ScalliGraph | 2 +- build.sbt | 8 ++++++-- project/Dependencies.scala | 2 +- project/plugins.sbt | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ScalliGraph b/ScalliGraph index 4d439fcd2d..561c5c1f27 160000 --- a/ScalliGraph +++ b/ScalliGraph @@ -1 +1 @@ -Subproject commit 4d439fcd2d1294c998f1a0d8d559e533500e18c7 +Subproject commit 561c5c1f2755b3df94ece18ec951869b1ee0a660 diff --git a/build.sbt b/build.sbt index 5bfefd2092..6c80c3f996 100644 --- a/build.sbt +++ b/build.sbt @@ -62,11 +62,15 @@ libraryDependencies in ThisBuild ++= { } } dependencyOverrides in ThisBuild ++= Seq( -// "org.locationtech.spatial4j" % "spatial4j" % "0.6", -// "org.elasticsearch.client" % "elasticsearch-rest-client" % "6.7.2 akkaActor, logbackClassic ) +val securityUpdates = Seq( + "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.12.6", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.12.6.1", + "org.yaml" % "snakeyaml" % "1.30" +) +dependencyOverrides in ThisBuild ++= securityUpdates PlayKeys.includeDocumentationInBinary := false milestoneFilter := ((milestone: Milestone) => milestone.title.startsWith("4")) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index f541c56dc1..23ffb177b5 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -32,7 +32,7 @@ object Dependencies { lazy val macroParadise = "org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full lazy val chimney = "io.scalaland" %% "chimney" % "0.6.1" lazy val reflections = "org.reflections" % "reflections" % "0.9.12" - lazy val hadoopClient = "org.apache.hadoop" % "hadoop-client" % "3.3.0" exclude ("log4j", "log4j") + lazy val hadoopClient = "org.apache.hadoop" % "hadoop-client" % "3.3.2" exclude ("log4j", "log4j") lazy val zip4j = "net.lingala.zip4j" % "zip4j" % "2.6.4" lazy val alpakka = "com.lightbend.akka" %% "akka-stream-alpakka-json-streaming" % "2.0.2" lazy val handlebars = "com.github.jknack" % "handlebars" % "4.2.0" diff --git a/project/plugins.sbt b/project/plugins.sbt index 3cc2c244d7..a21a80dc51 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.7") +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.13") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.0") addSbtPlugin("org.thehive-project" % "sbt-github-changelog" % "0.3.0") From 4300556432cb492d1ef2fc8d44ab8b963381fed0 Mon Sep 17 00:00:00 2001 From: To-om Date: Wed, 6 Apr 2022 17:50:54 +0200 Subject: [PATCH 14/15] #2371 Improve logging --- ScalliGraph | 2 +- conf/logback.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ScalliGraph b/ScalliGraph index 561c5c1f27..6a590119ff 160000 --- a/ScalliGraph +++ b/ScalliGraph @@ -1 +1 @@ -Subproject commit 561c5c1f2755b3df94ece18ec951869b1ee0a660 +Subproject commit 6a590119ff69a3684e5f9dcc49a3f6e6e848c37f diff --git a/conf/logback.xml b/conf/logback.xml index 81ebc5d266..be6f11e3e2 100644 --- a/conf/logback.xml +++ b/conf/logback.xml @@ -15,13 +15,13 @@ 10MB - %date [%level] from %logger in %thread [%X{request}|%X{tx}] %message%n%xException + %date [%level] from %logger in %thread %replace(\(%X{userId}@%X{organisation}\) ){'\(@\) ',''}[%X{request}|%X{tx}] %message%n%xException - %coloredLevel %logger{15} [%X{request}|%X{tx}] %message%n%xException{10} + %coloredLevel %logger{15} %replace(\(%X{userId}@%X{organisation}\) ){'\(@\) ',''}[%X{request}|%X{tx}] %message%n%xException{10} From d8f25683e1850095420043f60f40954872835374 Mon Sep 17 00:00:00 2001 From: To-om Date: Thu, 7 Apr 2022 12:28:08 +0200 Subject: [PATCH 15/15] Release 4.1.19 --- CHANGELOG.md | 19 +++++++++++++++++++ build.sbt | 2 +- frontend/bower.json | 2 +- frontend/package.json | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebc4e46455..b8857f7681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Change Log +## [4.1.19](https://github.com/TheHive-Project/TheHive/milestone/89) (2022-04-07) + +**Implemented enhancements:** + +- Migrate hive3 to 4, migrate SSL error. Requesting SSL bypass option [\#2356](https://github.com/TheHive-Project/TheHive/issues/2356) +- [Enhancement] Improve logging [\#2371](https://github.com/TheHive-Project/TheHive/issues/2371) + +**Fixed bugs:** + +- [Bug] Regression starting with 4.1.17 in the migration tool with certificate validation [\#2342](https://github.com/TheHive-Project/TheHive/issues/2342) +- [Bug] Deadlock when the index backend changed [\#2351](https://github.com/TheHive-Project/TheHive/issues/2351) +- [Bug][Security] TheHive4 libraries vulnerabilities [\#2362](https://github.com/TheHive-Project/TheHive/issues/2362) +- [Bug] The Link given in /etc/thehive/application.conf says error. [\#2364](https://github.com/TheHive-Project/TheHive/issues/2364) +- [Bug] An unshared case is still visible [\#2366](https://github.com/TheHive-Project/TheHive/issues/2366) +- [Bug] Prevent custom field creation if it already exists [\#2367](https://github.com/TheHive-Project/TheHive/issues/2367) +- [Bug] An user may exist without being member of any organisation [\#2368](https://github.com/TheHive-Project/TheHive/issues/2368) +- [Bug] Tags can't be updated [\#2369](https://github.com/TheHive-Project/TheHive/issues/2369) +- [Bug] Dashboarding on weeks provide incorrect results on specific dates [\#2370](https://github.com/TheHive-Project/TheHive/issues/2370) + ## [4.1.18](https://github.com/TheHive-Project/TheHive/milestone/88) (2022-02-07) **Implemented enhancements:** diff --git a/build.sbt b/build.sbt index 6c80c3f996..ec7354e37d 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ import Dependencies._ import com.typesafe.sbt.packager.Keys.bashScriptDefines import org.thp.ghcl.Milestone -val thehiveVersion = "4.1.18-1" +val thehiveVersion = "4.1.19-1" val scala212 = "2.12.13" val scala213 = "2.13.1" val supportedScalaVersions = List(scala212, scala213) diff --git a/frontend/bower.json b/frontend/bower.json index 0ec1ce3680..6dcd9df3c8 100644 --- a/frontend/bower.json +++ b/frontend/bower.json @@ -1,6 +1,6 @@ { "name": "thehive", - "version": "4.1.18-1", + "version": "4.1.19-1", "license": "AGPL-3.0", "dependencies": { "jquery": "^3.4.1", diff --git a/frontend/package.json b/frontend/package.json index e145d1f50d..9b26aef3f8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "thehive", - "version": "4.1.18-1", + "version": "4.1.19-1", "license": "AGPL-3.0", "repository": { "type": "git",