From 8b0e157b1a43b887ba751c13abb0fd237246852d Mon Sep 17 00:00:00 2001 From: Nabil Adouani Date: Tue, 12 Feb 2019 14:54:56 +0100 Subject: [PATCH 01/29] #863 Add more details to the alert and case audit logs in search page --- ui/app/views/directives/search/audit.html | 125 ++++++++++++++++------ ui/app/views/directives/search/task.html | 2 +- 2 files changed, 95 insertions(+), 32 deletions(-) diff --git a/ui/app/views/directives/search/audit.html b/ui/app/views/directives/search/audit.html index 0458e7ab5b..215427b40c 100644 --- a/ui/app/views/directives/search/audit.html +++ b/ui/app/views/directives/search/audit.html @@ -1,39 +1,102 @@ -
- - {{value.operation}} of {{value.objectType}}
- {{value.stats.name}} -
- - {{value.operation}} of {{value.objectType}}
- {{value.stats.title || value.details.title}} -
- - {{value.operation}} of task
- {{value.stats.title || value.details.title}} -
- - {{value.operation}} of task log - - - {{value.operation}} of observable
- {{value.stats.data}} -
- - {{value.operation}} of observable job
- {{value.stats.analyzerName}} -
- - {{value.operation}} of alert
- {{value.stats.title}} -
-
-
+
- {{getUserInfo.get(value.createdBy) | getField: 'name'}} + by {{getUserInfo.get(value.createdBy) | getField: 'name'}} Occurred on
+ +
+
+ +
+
+ +
+ + {{getUserInfo.get(value.stats.owner) | getField: 'name'}} + + + + + + ( + Closed + on + {{value.stats.endDate | showDate}} + as + {{value.stats.resolutionStatus}}) + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + Date: + {{value.stats.date | showDate}} + + + Type: + {{value.stats.type}} + + + Reference: + {{value.stats.sourceRef}} + + + Source: + {{value.stats.source}} + +
+
+
Details (ExpandCollapse)
{{value.details | flattern | json}}
diff --git a/ui/app/views/directives/search/task.html b/ui/app/views/directives/search/task.html index fdf590e6ba..0eec85211a 100644 --- a/ui/app/views/directives/search/task.html +++ b/ui/app/views/directives/search/task.html @@ -7,7 +7,7 @@ {{getUserInfo.get(value.owner) | getField: 'name'}} - +
From e9ee614d58c427393bb16c61f53fee86e15ceabb Mon Sep 17 00:00:00 2001 From: Nabil Adouani Date: Tue, 12 Feb 2019 16:27:37 +0100 Subject: [PATCH 02/29] #485 Disallow clicking on dashboard items in edit mode --- .../dashboard/DashboardViewCtrl.js | 20 +++++++++---------- .../scripts/directives/dashboard/counter.js | 18 +++++++---------- ui/app/scripts/directives/dashboard/donut.js | 7 +++++-- ui/app/scripts/directives/dashboard/item.js | 10 +++++----- ui/app/views/directives/dashboard/item.html | 6 +++--- ui/app/views/partials/dashboard/view.html | 2 +- 6 files changed, 31 insertions(+), 32 deletions(-) diff --git a/ui/app/scripts/controllers/dashboard/DashboardViewCtrl.js b/ui/app/scripts/controllers/dashboard/DashboardViewCtrl.js index 4c2c404e28..7e3805a96d 100644 --- a/ui/app/scripts/controllers/dashboard/DashboardViewCtrl.js +++ b/ui/app/scripts/controllers/dashboard/DashboardViewCtrl.js @@ -82,7 +82,7 @@ this.periodFilter = this.buildDashboardPeriodFilter(period); $scope.$broadcast('refresh-chart', this.periodFilter); - } + }; this.removeContainer = function(index) { var row = this.definition.items[index]; @@ -95,28 +95,28 @@ promise = ModalUtilsSrv.confirm('Remove widget', 'Are you sure you want to remove this item', { okText: 'Yes, remove it', flavor: 'danger' - }) + }); } promise.then(function() { - self.definition.items.splice(index, 1) + self.definition.items.splice(index, 1); }); - } + }; this.saveDashboard = function() { var copy = _.pick(this.dashboard, 'title', 'description', 'status'); copy.definition = angular.toJson(this.definition); DashboardSrv.update(this.dashboard.id, copy) - .then(function(response) { + .then(function(/*response*/) { self.options.editLayout = false; self.resizeCharts(); NotificationSrv.log('The dashboard has been successfully updated', 'success'); }) .catch(function(err) { NotificationSrv.error('DashboardEditCtrl', err.data, err.status); - }) - } + }); + }; this.removeItem = function(rowIndex, colIndex) { @@ -151,15 +151,15 @@ } return item; - } + }; this.itemDragStarted = function(colIndex, row) { row.items.splice(colIndex, 1); - } + }; this.exportDashboard = function() { DashboardSrv.exportDashboard(this.dashboard); - } + }; this.resizeCharts = function() { $timeout(function() { diff --git a/ui/app/scripts/directives/dashboard/counter.js b/ui/app/scripts/directives/dashboard/counter.js index 8d8825e0a6..6997297622 100644 --- a/ui/app/scripts/directives/dashboard/counter.js +++ b/ui/app/scripts/directives/dashboard/counter.js @@ -56,29 +56,25 @@ name: name, label: serie.label, value: data[name] || 0 - } + }; }); - }, function(err) { + }, function(/*err*/) { scope.error = true; NotificationSrv.log('Failed to fetch data, please edit the widget definition', 'error'); }); }; scope.openSearch = function(item) { - var criteria = [{ _type: scope.options.entity }, item.serie.query]; - - if (scope.globalQuery && scope.globalQuery !== '*') { - criteria.push(scope.globalQuery); + if(scope.mode === 'edit') { + return; } - var searchQuery = { - _and: _.without(criteria, null, undefined, '') - }; + var filters = (scope.options.filters || []).concat(item.serie.filters || []); GlobalSearchSrv.saveSection(scope.options.entity, { - search: null, - filters: scope.options.filters.concat(item.serie.filters) + search: filters.length === 0 ? '*' : null, + filters: filters }); $state.go('app.search'); }; diff --git a/ui/app/scripts/directives/dashboard/donut.js b/ui/app/scripts/directives/dashboard/donut.js index a0f4393bc3..078d657031 100644 --- a/ui/app/scripts/directives/dashboard/donut.js +++ b/ui/app/scripts/directives/dashboard/donut.js @@ -81,8 +81,11 @@ names: scope.options.names || {}, colors: scope.options.colors || {}, onclick: function(d) { + if(scope.mode === 'edit') { + return; + } + var fieldDef = scope.entity.attributes[scope.options.field]; - var fieldType = fieldDef.type; var data = { field: scope.options.field, @@ -107,7 +110,7 @@ } }; }, - function(err) { + function(/*err*/) { scope.error = true; NotificationSrv.log('Failed to fetch data, please edit the widget definition', 'error'); } diff --git a/ui/app/scripts/directives/dashboard/item.js b/ui/app/scripts/directives/dashboard/item.js index 5863d8188c..837ea15e26 100644 --- a/ui/app/scripts/directives/dashboard/item.js +++ b/ui/app/scripts/directives/dashboard/item.js @@ -1,6 +1,6 @@ (function() { 'use strict'; - angular.module('theHiveDirectives').directive('dashboardItem', function(DashboardSrv, UserSrv, $uibModal, $timeout, $q) { + angular.module('theHiveDirectives').directive('dashboardItem', function(DashboardSrv, UserSrv, $uibModal, $timeout) { return { restrict: 'E', replace: true, @@ -13,13 +13,13 @@ autoload: '=', refreshOn: '@', resizeOn: '@', - mode: '@', + mode: '=', showEdit: '=', showRemove: '=', onRemove: '&' }, templateUrl: 'views/directives/dashboard/item.html', - link: function(scope, element) { + link: function(scope/*, element*/) { scope.typeClasses = DashboardSrv.typeClasses; scope.timeIntervals = DashboardSrv.timeIntervals; scope.aggregations = DashboardSrv.aggregations; @@ -35,7 +35,7 @@ scope.query = null; if(scope.component.id) { - scope.$on('edit-chart-' + scope.component.id, function(data) { + scope.$on('edit-chart-' + scope.component.id, function(/*data*/) { scope.editItem(); }); } @@ -72,7 +72,7 @@ if(serie.filters) { serie.query = DashboardSrv.buildFiltersQuery(scope.metadata[entity || serie.entity].attributes, serie.filters); } - }) + }); scope.component.options = definition; diff --git a/ui/app/views/directives/dashboard/item.html b/ui/app/views/directives/dashboard/item.html index adb6435556..08bd60745c 100644 --- a/ui/app/views/directives/dashboard/item.html +++ b/ui/app/views/directives/dashboard/item.html @@ -1,7 +1,7 @@

- {{component.options.title || 'No title'}} + {{component.options.title || 'No title'}} {{mode}}

@@ -13,11 +13,11 @@

-
+
dnd-drop="$vm.itemInserted(item, $vm.definition.items, rowIndex, index)"> Date: Tue, 12 Feb 2019 17:09:57 +0100 Subject: [PATCH 03/29] #829 Fix error handling on observable dialog --- ui/app/scripts/controllers/case/ObservableCreationCtrl.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ui/app/scripts/controllers/case/ObservableCreationCtrl.js b/ui/app/scripts/controllers/case/ObservableCreationCtrl.js index e644dd38a3..1dc5f1adb6 100644 --- a/ui/app/scripts/controllers/case/ObservableCreationCtrl.js +++ b/ui/app/scripts/controllers/case/ObservableCreationCtrl.js @@ -142,16 +142,13 @@ $scope.handleSaveFailure = function(response) { $scope.pendingAsync = false; - if (response.status === 400) { + if (response.status === 400 && response.data.type === 'ConflictError') { $scope.failedObservables = $scope.getFailedObservables(response.data); $scope.step = 'error'; - } else { - if(response.data.type === "java.io.IOException") { + if(response.data.type) { NotificationSrv.error('ObservableCreationCtrl', response.data.message, response.status); - } else if(response.data.type === "InternalError") { - NotificationSrv.error('ObservableCreationCtrl', response.data.message, response.status); } else { NotificationSrv.error('ObservableCreationCtrl', 'An unexpected error occurred while creating the observables', response.status); } From 2279f6adff4656007db7040b1b0c0f664c302924 Mon Sep 17 00:00:00 2001 From: Nabil Adouani Date: Tue, 12 Feb 2019 17:39:33 +0100 Subject: [PATCH 04/29] #829 Don't close observable creation dialog if it fails --- ui/app/scripts/controllers/case/ObservableCreationCtrl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/scripts/controllers/case/ObservableCreationCtrl.js b/ui/app/scripts/controllers/case/ObservableCreationCtrl.js index 1dc5f1adb6..0e9b05c56e 100644 --- a/ui/app/scripts/controllers/case/ObservableCreationCtrl.js +++ b/ui/app/scripts/controllers/case/ObservableCreationCtrl.js @@ -153,7 +153,7 @@ NotificationSrv.error('ObservableCreationCtrl', 'An unexpected error occurred while creating the observables', response.status); } - $uibModalInstance.close(response); + //$uibModalInstance.close(response); } }; From cd436ea294289d3dce2c73c3cecddd3a59b7ae78 Mon Sep 17 00:00:00 2001 From: To-om Date: Tue, 12 Feb 2019 18:15:26 +0100 Subject: [PATCH 05/29] #871 Fix MISP synchro log message --- thehive-misp/app/connectors/misp/MispSynchro.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/thehive-misp/app/connectors/misp/MispSynchro.scala b/thehive-misp/app/connectors/misp/MispSynchro.scala index 37fbd84fe1..eca5e3ba7d 100644 --- a/thehive-misp/app/connectors/misp/MispSynchro.scala +++ b/thehive-misp/app/connectors/misp/MispSynchro.scala @@ -134,9 +134,10 @@ class MispSynchro @Inject() ( } def synchronize(mispConnection: MispConnection, lastSyncDate: Option[Date])(implicit authContext: AuthContext): Source[Try[Alert], NotUsed] = { - logger.info(s"Synchronize MISP ${mispConnection.name} from $lastSyncDate") + val syncFrom = mispConnection.syncFrom(lastSyncDate.getOrElse(new Date(0))) + logger.info(s"Last synchronization of MISP ${mispConnection.name} is ${lastSyncDate.fold("Never")(_.toString)}, synchronize from $syncFrom") // get events that have been published after the last synchronization - mispSrv.getEventsFromDate(mispConnection, mispConnection.syncFrom(lastSyncDate.getOrElse(new Date(0)))) + mispSrv.getEventsFromDate(mispConnection, syncFrom) // get related alert .mapAsyncUnordered(1) { event ⇒ logger.trace(s"Looking for alert misp:${event.source}:${event.sourceRef}") From adbec9085c6337b72e5c5e85b07ee4e88a098e51 Mon Sep 17 00:00:00 2001 From: ZAch Priddy Date: Tue, 12 Feb 2019 20:39:55 -0800 Subject: [PATCH 06/29] Fix Update Label to Warning --- ui/app/views/directives/search/alert.html | 2 +- ui/app/views/partials/alert/list.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/app/views/directives/search/alert.html b/ui/app/views/directives/search/alert.html index 603ac007b1..180e6627ca 100644 --- a/ui/app/views/directives/search/alert.html +++ b/ui/app/views/directives/search/alert.html @@ -39,7 +39,7 @@
Status:
- {{value.status}} + {{value.status}}
diff --git a/ui/app/views/partials/alert/list.html b/ui/app/views/partials/alert/list.html index 8b3bfcbab5..34a018504f 100644 --- a/ui/app/views/partials/alert/list.html +++ b/ui/app/views/partials/alert/list.html @@ -114,7 +114,7 @@

List of alerts ({{$vm.list.total || 0}} of {{alertEvents.c {{::event.type}} - {{::event.status}} + {{::event.status}}
From e179b6e4ad346336cb82de3e9117d9e416215df1 Mon Sep 17 00:00:00 2001 From: To-om Date: Wed, 13 Feb 2019 09:19:24 +0100 Subject: [PATCH 07/29] #869 Use observable TLP if possible when executing a responder --- .../connectors/cortex/services/ActionOperation.scala | 12 ++++++++++++ .../connectors/cortex/services/CortexActionSrv.scala | 12 ++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/thehive-cortex/app/connectors/cortex/services/ActionOperation.scala b/thehive-cortex/app/connectors/cortex/services/ActionOperation.scala index 061d5dc5dd..8a13182648 100644 --- a/thehive-cortex/app/connectors/cortex/services/ActionOperation.scala +++ b/thehive-cortex/app/connectors/cortex/services/ActionOperation.scala @@ -139,6 +139,18 @@ class ActionOperationSrv @Inject() ( } } + def findArtifactEntity(entity: BaseEntity): Future[Artifact] = { + import org.elastic4play.services.QueryDSL._ + + (entity, entity.model) match { + case (a: Artifact, _) ⇒ Future.successful(a) + case (_, model: ChildModelDef[_, _, _, _]) ⇒ + findSrv(model.parentModel, "_id" ~= entity.parentId.getOrElse(throw InternalError(s"Child entity $entity has no parent ID")), Some("0-1"), Nil) + ._1.runWith(Sink.head).flatMap(findArtifactEntity _) + case _ ⇒ Future.failed(BadRequestError("Artifact not found")) + } + } + def execute(entity: BaseEntity, operation: ActionOperation)(implicit authContext: AuthContext): Future[ActionOperation] = { if (operation.status == ActionOperationStatus.Waiting) { Retry()(classOf[VersionConflictEngineException]) { diff --git a/thehive-cortex/app/connectors/cortex/services/CortexActionSrv.scala b/thehive-cortex/app/connectors/cortex/services/CortexActionSrv.scala index 6b6f068c30..35819f25b1 100644 --- a/thehive-cortex/app/connectors/cortex/services/CortexActionSrv.scala +++ b/thehive-cortex/app/connectors/cortex/services/CortexActionSrv.scala @@ -72,10 +72,14 @@ class CortexActionSrv @Inject() ( def findResponderFor(entityType: String, entityId: String): Future[Seq[Responder]] = { for { - (tlp, pap) ← getEntity(entityType, entityId) - .flatMap(actionOperationSrv.findCaseEntity) - .map { caze ⇒ (caze.tlp(), caze.pap()) } - .recover { case _ ⇒ (0L, 0L) } + entity ← getEntity(entityType, entityId) + artifactTlp ← actionOperationSrv + .findArtifactEntity(entity) + .map(a ⇒ Some(a.tlp())) + .recover { case _ ⇒ None } + (tlp, pap) ← actionOperationSrv.findCaseEntity(entity) + .map { caze ⇒ (artifactTlp.getOrElse(caze.tlp()), caze.pap()) } + .recover { case _ ⇒ (artifactTlp.getOrElse(0L), 0L) } query = Json.obj( "dataTypeList" → s"thehive:$entityType") responders ← findResponders(query) From 639558ff08ec0b3100ce4d7fc1d0797994ffdd82 Mon Sep 17 00:00:00 2001 From: Nabil Adouani Date: Wed, 13 Feb 2019 11:55:17 +0100 Subject: [PATCH 08/29] #870 Add alert id copy link --- ui/app/scripts/controllers/alert/AlertEventCtrl.js | 6 +++++- ui/app/views/partials/alert/event.dialog.html | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ui/app/scripts/controllers/alert/AlertEventCtrl.js b/ui/app/scripts/controllers/alert/AlertEventCtrl.js index 692c86733e..1176842eee 100644 --- a/ui/app/scripts/controllers/alert/AlertEventCtrl.js +++ b/ui/app/scripts/controllers/alert/AlertEventCtrl.js @@ -1,7 +1,7 @@ (function() { 'use strict'; angular.module('theHiveControllers') - .controller('AlertEventCtrl', function($scope, $rootScope, $state, $uibModal, $uibModalInstance, CustomFieldsCacheSrv, CaseResolutionStatus, AlertingSrv, NotificationSrv, event, templates) { + .controller('AlertEventCtrl', function($scope, $rootScope, $state, $uibModal, $uibModalInstance, CustomFieldsCacheSrv, CaseResolutionStatus, AlertingSrv, NotificationSrv, clipboard, event, templates) { var self = this; var eventId = event.id; @@ -254,6 +254,10 @@ } }; + self.copyId = function(id) { + clipboard.copyText(id); + }; + self.load(); }); })(); diff --git a/ui/app/views/partials/alert/event.dialog.html b/ui/app/views/partials/alert/event.dialog.html index 50d1a948ad..84d5c44c2e 100644 --- a/ui/app/views/partials/alert/event.dialog.html +++ b/ui/app/views/partials/alert/event.dialog.html @@ -1,5 +1,7 @@