Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit 906d8bc

Browse files
committed
Merge branch 'hotfix/4.1.20'
2 parents 8e97aa3 + 2b82726 commit 906d8bc

File tree

18 files changed

+179
-81
lines changed

18 files changed

+179
-81
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Change Log
22

3+
## [4.1.20](https://github.com/TheHive-Project/TheHive/milestone/90) (2022-05-16)
4+
5+
**Implemented enhancements:**
6+
7+
- [Enhancement] Improve artifact creation from responder operation [\#2383](https://github.com/TheHive-Project/TheHive/issues/2383)
8+
- [Enhancement] Accept operations in analyzer reports [\#2384](https://github.com/TheHive-Project/TheHive/issues/2384)
9+
- [Enhancement] Add queries to filter observables based on the type of object it belongs to [\#2385](https://github.com/TheHive-Project/TheHive/issues/2385)
10+
11+
**Fixed bugs:**
12+
13+
- [Bug] Unable to use AWS S3 as storage backend [\#2316](https://github.com/TheHive-Project/TheHive/issues/2316)
14+
- [Bug] Typo on migration elasticsearch http config [\#2374](https://github.com/TheHive-Project/TheHive/issues/2374)
15+
316
## [4.1.19](https://github.com/TheHive-Project/TheHive/milestone/89) (2022-04-07)
417

518
**Implemented enhancements:**

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Dependencies._
22
import com.typesafe.sbt.packager.Keys.bashScriptDefines
33
import org.thp.ghcl.Milestone
44

5-
val thehiveVersion = "4.1.19-1"
5+
val thehiveVersion = "4.1.20-1"
66
val scala212 = "2.12.13"
77
val scala213 = "2.13.1"
88
val supportedScalaVersions = List(scala212, scala213)

cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/controllers/v0/Conversion.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ object Conversion {
4747
.withFieldComputed(_.id, _._id.toString)
4848
.withFieldConst(_._type, "case_artifact_job")
4949
.withFieldConst(_.case_artifact, None)
50+
.withFieldComputed(_.operations, a => JsArray(a.operations).toString)
5051
.enableMethodAccessors
5152
.transform
5253
)
@@ -80,6 +81,7 @@ object Conversion {
8081
Some(observableWithExtraOutput.toValue((richObservable, JsObject.empty, Some(Left(richCase)))))
8182
}
8283
)
84+
.withFieldComputed(_.operations, a => JsArray(a.operations).toString)
8385
.enableMethodAccessors
8486
.transform
8587
}

cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/models/ActionOperation.scala

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,25 @@ import play.api.libs.json._
77
*/
88
trait ActionOperation
99

10-
case class AddTagToCase(tag: String) extends ActionOperation
11-
case class AddTagToArtifact(tag: String) extends ActionOperation
12-
case class CreateTask(title: String, description: String) extends ActionOperation
13-
case class AddCustomFields(name: String, tpe: String, value: JsValue) extends ActionOperation
14-
case class CloseTask() extends ActionOperation
15-
case class MarkAlertAsRead() extends ActionOperation
16-
case class AddLogToTask(content: String, owner: Option[String]) extends ActionOperation
17-
case class AddTagToAlert(tag: String) extends ActionOperation
18-
case class AddArtifactToCase(data: String, dataType: String, message: String) extends ActionOperation
19-
case class AssignCase(owner: String) extends ActionOperation
10+
case class AddTagToCase(tag: String) extends ActionOperation
11+
case class AddTagToArtifact(tag: String) extends ActionOperation
12+
case class CreateTask(title: String, description: String) extends ActionOperation
13+
case class AddCustomFields(name: String, tpe: String, value: JsValue) extends ActionOperation
14+
case class CloseTask() extends ActionOperation
15+
case class MarkAlertAsRead() extends ActionOperation
16+
case class AddLogToTask(content: String, owner: Option[String]) extends ActionOperation
17+
case class AddTagToAlert(tag: String) extends ActionOperation
18+
case class AddArtifactToCase(
19+
data: String,
20+
dataType: String,
21+
message: String,
22+
tlp: Option[Int],
23+
ioc: Option[Boolean],
24+
sighted: Option[Boolean],
25+
ignoreSimilarity: Option[Boolean],
26+
tags: Option[Seq[String]]
27+
) extends ActionOperation
28+
case class AssignCase(owner: String) extends ActionOperation
2029

2130
object ActionOperation {
2231
val addTagToCaseFormat: OFormat[AddTagToCase] = Json.format[AddTagToCase]

cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/models/Job.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ case class Job(
2929
endDate: Date, // end date of the job or if it is not finished date of the last check
3030
report: Option[JsObject],
3131
cortexId: String,
32-
cortexJobId: String
32+
cortexJobId: String,
33+
operations: Seq[JsObject]
3334
)
3435

3536
case class RichJob(
@@ -50,5 +51,5 @@ case class RichJob(
5051
def report: Option[JsObject] = job.report
5152
def cortexId: String = job.cortexId
5253
def cortexJobId: String = job.cortexJobId
53-
54+
def operations: Seq[JsObject] = job.operations
5455
}

cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/ActionOperationSrv.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,20 @@ class ActionOperationSrv @Inject() (
9393
_ <- logSrv.create(Log(content, new Date()), t, None)
9494
} yield updateOperation(operation)
9595

96-
case AddArtifactToCase(data, dataType, message) =>
96+
case AddArtifactToCase(data, dataType, message, tlp, ioc, sighted, ignoreSimilarity, tags) =>
9797
for {
9898
c <- relatedCase.fold[Try[Case with Entity]](Failure(InternalError("Unable to apply action AddArtifactToCase without case")))(Success(_))
9999
organisation <- organisationSrv.getOrFail(authContext.organisation)
100100
_ <- caseSrv.createObservable(
101101
c,
102102
Observable(
103103
message = Some(message),
104-
tlp = 2,
105-
ioc = false,
106-
sighted = false,
107-
ignoreSimilarity = None,
104+
tlp = tlp.getOrElse(2),
105+
ioc = ioc.getOrElse(false),
106+
sighted = sighted.getOrElse(false),
107+
ignoreSimilarity = ignoreSimilarity,
108108
dataType = dataType,
109-
tags = Nil,
109+
tags = tags.getOrElse(Nil),
110110
relatedId = c._id,
111111
organisationIds = Set(organisation._id)
112112
),

cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/ActionSrv.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class ActionSrv @Inject() (
9696
job.report.flatMap(_.full),
9797
client.name,
9898
job.id,
99-
job.report.fold[Seq[JsObject]](Nil)(_.operations)
99+
Nil
100100
)
101101
createdAction <- Future.fromTry {
102102
db.tryTransaction { implicit graph =>

cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/JobSrv.scala

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class JobSrv @Inject() (
4242
observableTypeSrv: ObservableTypeSrv,
4343
attachmentSrv: AttachmentSrv,
4444
reportTagSrv: ReportTagSrv,
45+
actionOperationSrv: ActionOperationSrv,
4546
serviceHelper: ServiceHelper,
4647
auditSrv: CortexAuditSrv,
4748
organisationSrv: OrganisationSrv,
@@ -130,6 +131,7 @@ class JobSrv @Inject() (
130131
.withFieldConst(_.report, None)
131132
.withFieldConst(_.cortexId, "tbd")
132133
.withFieldComputed(_.cortexJobId, _.id)
134+
.withFieldConst(_.operations, Nil)
133135
.transform
134136

135137
/**
@@ -167,11 +169,31 @@ class JobSrv @Inject() (
167169
.availableCortexClients(connector.clients, authContext.organisation)
168170
.find(_.name == cortexId)
169171
.fold[Future[CortexClient]](Future.failed(NotFoundError(s"Cortex $cortexId not found")))(Future.successful)
170-
job <- Future.fromTry(updateJobStatus(jobId, cortexJob))
171-
_ <- importCortexArtifacts(job, cortexJob, cortexClient)
172-
_ <- Future.fromTry(importAnalyzerTags(job, cortexJob))
172+
operations <- Future.fromTry(executeOperations(jobId, cortexJob))
173+
job <- Future.fromTry(updateJobStatus(jobId, cortexJob, operations))
174+
_ <- importCortexArtifacts(job, cortexJob, cortexClient)
175+
_ <- Future.fromTry(importAnalyzerTags(job, cortexJob))
173176
} yield job
174177

178+
def executeOperations(jobId: EntityId, cortexJob: CortexJob)(implicit authContext: AuthContext): Try[Seq[ActionOperationStatus]] =
179+
db.tryTransaction { implicit graph =>
180+
get(jobId)
181+
.observable
182+
.project(_.by.by(_.`case`.option))
183+
.getOrFail("Observable")
184+
.map {
185+
case (relatedObservable, relatedCase) =>
186+
cortexJob
187+
.report
188+
.fold[Seq[ActionOperation]](Nil)(_.operations.map(_.as[ActionOperation]))
189+
.map { operation =>
190+
actionOperationSrv
191+
.execute(relatedObservable, operation, relatedCase, None)
192+
.fold(t => ActionOperationStatus(operation, success = false, t.getMessage), identity)
193+
}
194+
}
195+
}
196+
175197
/**
176198
* Update job status, set the endDate and remove artifacts from report
177199
*
@@ -180,7 +202,9 @@ class JobSrv @Inject() (
180202
* @param authContext the authentication context
181203
* @return the updated job
182204
*/
183-
private def updateJobStatus(jobId: EntityId, cortexJob: CortexJob)(implicit authContext: AuthContext): Try[Job with Entity] =
205+
private def updateJobStatus(jobId: EntityId, cortexJob: CortexJob, operations: Seq[ActionOperationStatus])(implicit
206+
authContext: AuthContext
207+
): Try[Job with Entity] =
184208
db.tryTransaction { implicit graph =>
185209
getOrFail(jobId).flatMap { job =>
186210
val report = cortexJob.report.flatMap(r => r.full orElse r.errorMessage.map(m => Json.obj("errorMessage" -> m)))
@@ -193,6 +217,7 @@ class JobSrv @Inject() (
193217
.update(_.endDate, endDate)
194218
.update(_._updatedAt, Some(new Date))
195219
.update(_._updatedBy, Some(authContext.userId))
220+
.update(_.operations, operations.map(o => Json.toJsObject(o)))
196221
.getOrFail("Job")
197222
observable <- get(job).observable.getOrFail("Observable")
198223
_ <-

cortex/connector/src/test/resources/cortex-jobs.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,21 @@
8787
{
8888
"data": "192.168.1.1",
8989
"message": "myIp",
90-
"tags": [],
90+
"tags": ["tag-test"],
9191
"tlp": 2,
9292
"dataType": "ip"
9393
}
9494
],
9595
"operations": [
96+
{
97+
"type": "AddArtifactToCase",
98+
"data": "myData",
99+
"dataType": "other",
100+
"message": "test-operation",
101+
"tlp": 3,
102+
"ignoreSimilarity": false,
103+
"tags": ["tag1", "tag2"]
104+
}
96105
]
97106
},
98107
"tlp": 2,

0 commit comments

Comments
 (0)