Skip to content

Commit

Permalink
#312 Add API to describe attributes of an entity
Browse files Browse the repository at this point in the history
  • Loading branch information
nadouani committed Oct 19, 2017
1 parent 142e4db commit 29845a1
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 9 deletions.
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ object Dependencies {
val reflections = "org.reflections" % "reflections" % "0.9.11"
val zip4j = "net.lingala.zip4j" % "zip4j" % "1.3.2"
val akkaTest = "com.typesafe.akka" %% "akka-stream-testkit" % "2.5.4"
val elastic4play = "org.cert-bdf" %% "elastic4play" % "1.3.1"
val elastic4play = "org.cert-bdf" %% "elastic4play" % "1.4.0-SNAPSHOT"
}
}
35 changes: 35 additions & 0 deletions thehive-backend/app/controllers/DescribeCtrl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package controllers

import javax.inject.{ Inject, Singleton }

import scala.concurrent.ExecutionContext

import play.api.mvc.{ AbstractController, Action, AnyContent, ControllerComponents }

import models.Roles

import org.elastic4play.controllers.{ Authenticated, Renderer }
import org.elastic4play.models.Attribute
import org.elastic4play.models.JsonFormat.attributeDefinitionWrites
import org.elastic4play.services.{ DBLists, ModelSrv }

@Singleton
class DescribeCtrl @Inject() (
dblists: DBLists,
modelSrv: ModelSrv,
authenticated: Authenticated,
renderer: Renderer,
components: ControllerComponents,
implicit val ec: ExecutionContext) extends AbstractController(components) {

def describe(modelName: String): Action[AnyContent] = authenticated(Roles.read) { implicit request
modelSrv(modelName)
.map { model
val attributeDefinitions = model.attributes.flatMap {
case attribute: Attribute[t] attribute.format.definition(dblists, attribute)
}
renderer.toOutput(OK, attributeDefinitions)
}
.getOrElse(NotFound(s"Model $modelName not found"))
}
}
6 changes: 3 additions & 3 deletions thehive-backend/app/models/Alert.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ trait AlertAttributes {
Attribute("alert", "startDate", OptionalAttributeFormat(F.dateFmt), Nil, None, ""),
Attribute("alert", "attachment", OptionalAttributeFormat(F.attachmentFmt), Nil, None, ""),
Attribute("alert", "remoteAttachment", OptionalAttributeFormat(F.objectFmt(remoteAttachmentAttributes)), Nil, None, ""),
Attribute("alert", "tlp", OptionalAttributeFormat(F.numberFmt), Nil, None, ""),
Attribute("alert", "tlp", OptionalAttributeFormat(TlpAttributeFormat), Nil, None, ""),
Attribute("alert", "tags", MultiAttributeFormat(F.stringFmt), Nil, None, ""),
Attribute("alert", "ioc", OptionalAttributeFormat(F.booleanFmt), Nil, None, ""))
}
Expand All @@ -55,9 +55,9 @@ trait AlertAttributes {
val caze: A[Option[String]] = optionalAttribute("case", F.stringFmt, "Id of the case, if created")
val title: A[String] = attribute("title", F.textFmt, "Title of the alert")
val description: A[String] = attribute("description", F.textFmt, "Description of the alert")
val severity: A[Long] = attribute("severity", F.numberFmt, "Severity if the alert (0-3)", 2L)
val severity: A[Long] = attribute("severity", SeverityAttributeFormat, "Severity if the alert (0-3)", 2L)
val tags: A[Seq[String]] = multiAttribute("tags", F.stringFmt, "Alert tags")
val tlp: A[Long] = attribute("tlp", F.numberFmt, "TLP level", 2L)
val tlp: A[Long] = attribute("tlp", TlpAttributeFormat, "TLP level", 2L)
val artifacts: A[Seq[JsObject]] = multiAttribute("artifacts", F.objectFmt(artifactAttributes), "Artifact of the alert")
val caseTemplate: A[Option[String]] = optionalAttribute("caseTemplate", F.stringFmt, "Case template to use")
val status: A[AlertStatus.Value] = attribute("status", F.enumFmt(AlertStatus), "Status of the alert", AlertStatus.New)
Expand Down
2 changes: 1 addition & 1 deletion thehive-backend/app/models/Artifact.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ trait ArtifactAttributes { _: AttributeDef ⇒
val message: A[Option[String]] = optionalAttribute("message", F.textFmt, "Description of the artifact in the context of the case")
val startDate: A[Date] = attribute("startDate", F.dateFmt, "Creation date", new Date)
val attachment: A[Option[Attachment]] = optionalAttribute("attachment", F.attachmentFmt, "Artifact file content", O.readonly)
val tlp: A[Long] = attribute("tlp", F.numberFmt, "TLP level", 2L)
val tlp: A[Long] = attribute("tlp", TlpAttributeFormat, "TLP level", 2L)
val tags: A[Seq[String]] = multiAttribute("tags", F.stringFmt, "Artifact tags")
val ioc: A[Boolean] = attribute("ioc", F.booleanFmt, "Artifact is an IOC", false)
val status: A[ArtifactStatus.Value] = attribute("status", F.enumFmt(ArtifactStatus), "Status of the artifact", ArtifactStatus.Ok)
Expand Down
26 changes: 26 additions & 0 deletions thehive-backend/app/models/AttributeFormat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package models

import play.api.libs.json.JsNumber

import org.elastic4play.models.{ Attribute, AttributeDefinition, NumberAttributeFormat }
import org.elastic4play.services.DBLists

object SeverityAttributeFormat extends NumberAttributeFormat {
override def definition(dblists: DBLists, attribute: Attribute[Long]): Seq[AttributeDefinition] =
Seq(AttributeDefinition(
attribute.name,
name,
attribute.description,
Seq(JsNumber(1), JsNumber(2), JsNumber(3)),
Seq("low", "medium", "high")))
}

object TlpAttributeFormat extends NumberAttributeFormat {
override def definition(dblists: DBLists, attribute: Attribute[Long]): Seq[AttributeDefinition] =
Seq(AttributeDefinition(
attribute.name,
name,
attribute.description,
Seq(JsNumber(0), JsNumber(1), JsNumber(2), JsNumber(3)),
Seq("white", "green", "amber", "red")))
}
4 changes: 2 additions & 2 deletions thehive-backend/app/models/Case.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ trait CaseAttributes { _: AttributeDef ⇒
val caseId: A[Long] = attribute("caseId", F.numberFmt, "Id of the case (auto-generated)", O.model)
val title: A[String] = attribute("title", F.textFmt, "Title of the case")
val description: A[String] = attribute("description", F.textFmt, "Description of the case")
val severity: A[Long] = attribute("severity", F.numberFmt, "Severity if the case is an incident (0-3)", 2L)
val severity: A[Long] = attribute("severity", SeverityAttributeFormat, "Severity if the case is an incident (0-3)", 2L)
val owner: A[String] = attribute("owner", F.stringFmt, "Owner of the case")
val startDate: A[Date] = attribute("startDate", F.dateFmt, "Creation date", new Date)
val endDate: A[Option[Date]] = optionalAttribute("endDate", F.dateFmt, "Resolution date")
val tags: A[Seq[String]] = multiAttribute("tags", F.stringFmt, "Case tags")
val flag: A[Boolean] = attribute("flag", F.booleanFmt, "Flag of the case", false)
val tlp: A[Long] = attribute("tlp", F.numberFmt, "TLP level", 2L)
val tlp: A[Long] = attribute("tlp", TlpAttributeFormat, "TLP level", 2L)
val status: A[CaseStatus.Value] = attribute("status", F.enumFmt(CaseStatus), "Status of the case", CaseStatus.Open)
val metrics: A[JsValue] = attribute("metrics", F.metricsFmt, "List of metrics", JsObject(Nil))
val resolutionStatus: A[Option[CaseResolutionStatus.Value]] = optionalAttribute("resolutionStatus", F.enumFmt(CaseResolutionStatus), "Resolution status of the case")
Expand Down
4 changes: 2 additions & 2 deletions thehive-backend/app/models/CaseTemplate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ trait CaseTemplateAttributes { _: AttributeDef ⇒
val templateName: A[String] = attribute("name", F.stringFmt, "Name of the template")
val titlePrefix: A[Option[String]] = optionalAttribute("titlePrefix", F.textFmt, "Title of the case")
val description: A[Option[String]] = optionalAttribute("description", F.textFmt, "Description of the case")
val severity: A[Option[Long]] = optionalAttribute("severity", F.numberFmt, "Severity if the case is an incident (0-5)")
val severity: A[Option[Long]] = optionalAttribute("severity", SeverityAttributeFormat, "Severity if the case is an incident (0-5)")
val tags: A[Seq[String]] = multiAttribute("tags", F.stringFmt, "Case tags")
val flag: A[Option[Boolean]] = optionalAttribute("flag", F.booleanFmt, "Flag of the case")
val tlp: A[Option[Long]] = optionalAttribute("tlp", F.numberFmt, "TLP level")
val tlp: A[Option[Long]] = optionalAttribute("tlp", TlpAttributeFormat, "TLP level")
val status: A[CaseTemplateStatus.Value] = attribute("status", F.enumFmt(CaseTemplateStatus), "Status of the case", CaseTemplateStatus.Ok)
val metricNames: A[Seq[String]] = multiAttribute("metricNames", F.stringFmt, "List of acceptable metric name")
val customFields: A[Option[JsValue]] = optionalAttribute("customFields", F.customFields, "List of acceptable custom fields")
Expand Down
2 changes: 2 additions & 0 deletions thehive-backend/conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ POST /api/stream controllers.StreamCtrl.create(
GET /api/stream/status controllers.StreamCtrl.status
GET /api/stream/:streamId controllers.StreamCtrl.get(streamId)

GET /api/describe/:modelName controllers.DescribeCtrl.describe(modelName)

-> /api/connector connectors.ConnectorRouter

GET /*file controllers.AssetCtrl.get(file)

0 comments on commit 29845a1

Please sign in to comment.