From 14561f58896913b4883b9cb5f433b9db568575b5 Mon Sep 17 00:00:00 2001 From: Robin Riclet Date: Tue, 2 Feb 2021 14:41:37 +0100 Subject: [PATCH] #1766 Added missing fields --- .../org/thp/thehive/dto/v1/Pattern.scala | 48 ++++++++++++++----- .../thehive/controllers/v1/Conversion.scala | 6 ++- .../thehive/controllers/v1/PatternCtrl.scala | 2 +- .../app/org/thp/thehive/models/Pattern.scala | 40 ++++++++++------ .../controllers/v1/PatternCtrlTest.scala | 12 ++++- thehive/test/resources/data/Pattern.json | 10 +++- 6 files changed, 85 insertions(+), 33 deletions(-) diff --git a/dto/src/main/scala/org/thp/thehive/dto/v1/Pattern.scala b/dto/src/main/scala/org/thp/thehive/dto/v1/Pattern.scala index 36c0a6c977..655047b559 100644 --- a/dto/src/main/scala/org/thp/thehive/dto/v1/Pattern.scala +++ b/dto/src/main/scala/org/thp/thehive/dto/v1/Pattern.scala @@ -11,9 +11,16 @@ case class InputPattern( kill_chain_phases: Seq[InputKillChainPhase], url: String, `type`: String, - x_mitre_platforms: Seq[String], + revoked: Boolean, x_mitre_data_sources: Seq[String], - x_mitre_is_subtechnique: Option[Boolean], + x_mitre_defense_bypassed: Seq[String], + x_mitre_detection: Option[String], + x_mitre_is_subtechnique: Boolean, + // TODO x_mitre_tactic_type ? + // TODO x_mitre_permissions_required ? + x_mitre_platforms: Seq[String], + x_mitre_remote_support: Boolean, + x_mitre_system_requirements: Seq[String], x_mitre_version: Option[String] ) @@ -55,14 +62,19 @@ object InputPattern { for { references <- (json \ "external_references").validate[Seq[InputReference]] mitreReference = references.find(ref => isSourceNameValid(ref.source_name)) - name <- (json \ "name").validate[String] - description <- (json \ "description").validateOpt[String] - kill_chain_phases <- (json \ "kill_chain_phases").validateOpt[Seq[InputKillChainPhase]] - techniqueType <- (json \ "type").validate[String] - x_mitre_platforms <- (json \ "x_mitre_platforms").validateOpt[Seq[String]] - x_mitre_data_sources <- (json \ "x_mitre_data_sources").validateOpt[Seq[String]] - x_mitre_is_subtechnique <- (json \ "x_mitre_is_subtechnique").validateOpt[Boolean] - x_mitre_version <- (json \ "x_mitre_version").validateOpt[String] + name <- (json \ "name").validate[String] + description <- (json \ "description").validateOpt[String] + kill_chain_phases <- (json \ "kill_chain_phases").validateOpt[Seq[InputKillChainPhase]] + techniqueType <- (json \ "type").validate[String] + revoked <- (json \ "revoked").validateOpt[Boolean] + x_mitre_data_sources <- (json \ "x_mitre_data_sources").validateOpt[Seq[String]] + x_mitre_defense_bypassed <- (json \ "x_mitre_defense_bypassed").validateOpt[Seq[String]] + x_mitre_detection <- (json \ "x_mitre_detection").validateOpt[String] + x_mitre_is_subtechnique <- (json \ "x_mitre_is_subtechnique").validateOpt[Boolean] + x_mitre_platforms <- (json \ "x_mitre_platforms").validateOpt[Seq[String]] + x_mitre_remote_support <- (json \ "x_mitre_remote_support").validateOpt[Boolean] + x_mitre_system_requirements <- (json \ "x_mitre_system_requirements").validateOpt[Seq[String]] + x_mitre_version <- (json \ "x_mitre_version").validateOpt[String] } yield InputPattern( mitreReference.flatMap(_.external_id).getOrElse(""), name, @@ -70,9 +82,14 @@ object InputPattern { kill_chain_phases.getOrElse(Seq()), mitreReference.flatMap(_.url).getOrElse(""), techniqueType, - x_mitre_platforms.getOrElse(Seq()), + revoked.getOrElse(false), x_mitre_data_sources.getOrElse(Seq()), - x_mitre_is_subtechnique, + x_mitre_defense_bypassed.getOrElse(Seq()), + x_mitre_detection, + x_mitre_is_subtechnique.getOrElse(false), + x_mitre_platforms.getOrElse(Seq()), + x_mitre_remote_support.getOrElse(false), + x_mitre_system_requirements.getOrElse(Seq()), x_mitre_version ) } @@ -96,8 +113,13 @@ case class OutputPattern( tactics: Set[String], url: String, patternType: String, - platforms: Seq[String], + revoked: Boolean, dataSources: Seq[String], + defenseBypassed: Seq[String], + detection: Option[String], + platforms: Seq[String], + remoteSupport: Boolean, + systemRequirements: Seq[String], version: Option[String], parent: Option[String] ) diff --git a/thehive/app/org/thp/thehive/controllers/v1/Conversion.scala b/thehive/app/org/thp/thehive/controllers/v1/Conversion.scala index 79d6957549..990b5b96a2 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/Conversion.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/Conversion.scala @@ -501,8 +501,12 @@ object Conversion { .withFieldRenamed(_.external_id, _.patternId) .withFieldComputed(_.tactics, _.kill_chain_phases.map(_.phase_name).toSet) .withFieldRenamed(_.`type`, _.patternType) - .withFieldRenamed(_.x_mitre_platforms, _.platforms) .withFieldRenamed(_.x_mitre_data_sources, _.dataSources) + .withFieldRenamed(_.x_mitre_defense_bypassed, _.defenseBypassed) + .withFieldRenamed(_.x_mitre_detection, _.detection) + .withFieldRenamed(_.x_mitre_platforms, _.platforms) + .withFieldRenamed(_.x_mitre_remote_support, _.remoteSupport) + .withFieldRenamed(_.x_mitre_system_requirements, _.systemRequirements) .withFieldRenamed(_.x_mitre_version, _.revision) .transform } diff --git a/thehive/app/org/thp/thehive/controllers/v1/PatternCtrl.scala b/thehive/app/org/thp/thehive/controllers/v1/PatternCtrl.scala index a8f25c3068..fff3edf948 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/PatternCtrl.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/PatternCtrl.scala @@ -112,7 +112,7 @@ class PatternCtrl @Inject() ( else for { pattern <- patternSrv.createEntity(inputPattern.toPattern) - _ = if (inputPattern.x_mitre_is_subtechnique.getOrElse(false)) linkPattern(pattern) + _ = if (inputPattern.x_mitre_is_subtechnique) linkPattern(pattern) } yield pattern private def linkPattern(child: Pattern with Entity)(implicit graph: Graph, authContext: AuthContext): Try[Unit] = { diff --git a/thehive/app/org/thp/thehive/models/Pattern.scala b/thehive/app/org/thp/thehive/models/Pattern.scala index bb03474404..c1c0505b21 100644 --- a/thehive/app/org/thp/thehive/models/Pattern.scala +++ b/thehive/app/org/thp/thehive/models/Pattern.scala @@ -13,8 +13,13 @@ case class Pattern( tactics: Set[String], url: String, patternType: String, - platforms: Seq[String], + revoked: Boolean, dataSources: Seq[String], + defenseBypassed: Seq[String], + detection: Option[String], + platforms: Seq[String], + remoteSupport: Boolean, + systemRequirements: Seq[String], revision: Option[String] ) @@ -22,18 +27,23 @@ case class Pattern( case class PatternPattern() case class RichPattern(pattern: Pattern with Entity, parent: Option[Pattern with Entity]) { - def patternId: String = pattern.patternId - def name: String = pattern.name - def description: Option[String] = pattern.description - def tactics: Set[String] = pattern.tactics - def url: String = pattern.url - def patternType: String = pattern.patternType - def platforms: Seq[String] = pattern.platforms - def dataSources: Seq[String] = pattern.dataSources - def version: Option[String] = pattern.revision - def _id: EntityId = pattern._id - def _createdAt: Date = pattern._createdAt - def _createdBy: String = pattern._createdBy - def _updatedAt: Option[Date] = pattern._updatedAt - def _updatedBy: Option[String] = pattern._updatedBy + def patternId: String = pattern.patternId + def name: String = pattern.name + def description: Option[String] = pattern.description + def tactics: Set[String] = pattern.tactics + def url: String = pattern.url + def patternType: String = pattern.patternType + def revoked: Boolean = pattern.revoked + def dataSources: Seq[String] = pattern.dataSources + def defenseBypassed: Seq[String] = pattern.defenseBypassed + def detection: Option[String] = pattern.detection + def platforms: Seq[String] = pattern.platforms + def remoteSupport: Boolean = pattern.remoteSupport + def systemRequirements: Seq[String] = pattern.systemRequirements + def version: Option[String] = pattern.revision + def _id: EntityId = pattern._id + def _createdAt: Date = pattern._createdAt + def _createdBy: String = pattern._createdBy + def _updatedAt: Option[Date] = pattern._updatedAt + def _updatedBy: Option[String] = pattern._updatedBy } diff --git a/thehive/test/org/thp/thehive/controllers/v1/PatternCtrlTest.scala b/thehive/test/org/thp/thehive/controllers/v1/PatternCtrlTest.scala index 3df975824e..c3b331236a 100644 --- a/thehive/test/org/thp/thehive/controllers/v1/PatternCtrlTest.scala +++ b/thehive/test/org/thp/thehive/controllers/v1/PatternCtrlTest.scala @@ -16,8 +16,13 @@ case class TestPattern( tactics: Set[String], url: String, patternType: String, - platforms: Seq[String], + revoked: Boolean, dataSources: Seq[String], + defenseBypassed: Seq[String], + detection: Option[String], + platforms: Seq[String], + remoteSupport: Boolean, + systemRequirements: Seq[String], version: Option[String] ) @@ -62,7 +67,12 @@ class PatternCtrlTest extends PlaySpecification with TestAppBuilder { Set("testTactic1", "testTactic2"), "http://test.pattern.url", "unit-test", + revoked = false, + Seq(), + Seq(), + None, Seq(), + remoteSupport = true, Seq(), Some("1.0") ) diff --git a/thehive/test/resources/data/Pattern.json b/thehive/test/resources/data/Pattern.json index 9a4a23e2ef..98be700a1b 100644 --- a/thehive/test/resources/data/Pattern.json +++ b/thehive/test/resources/data/Pattern.json @@ -10,8 +10,11 @@ ], "url": "http://test.pattern.url", "patternType": "unit-test", - "platforms": [], + "revoked": false, "dataSources": [], + "defenseBypassed": [], + "platforms": [], + "remoteSupport": true, "revision": "1.0" }, { @@ -25,8 +28,11 @@ ], "url": "http://test.pattern2.url", "patternType": "unit-test", - "platforms": [], + "revoked": false, "dataSources": [], + "defenseBypassed": [], + "platforms": [], + "remoteSupport": false, "revision": "1.1" } ]