-
Notifications
You must be signed in to change notification settings - Fork 640
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#1766 WIP: Add a section to manage attack pattern catalogs
- Loading branch information
Showing
10 changed files
with
525 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
frontend/app/scripts/controllers/admin/attack/AttackPatternListCtrl.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
(function() { | ||
'use strict'; | ||
|
||
angular.module('theHiveControllers') | ||
.controller('AttackPatternListCtrl', AttackPatternListCtrl) | ||
.controller('AttackPatternDialogCtrl', AttackPatternDialogCtrl) | ||
.controller('AttackPatternImportCtrl', AttackPatternImportCtrl); | ||
|
||
function AttackPatternListCtrl($scope, $uibModal, PaginatedQuerySrv, FilteringSrv, AttackPatternSrv, NotificationSrv, ModalSrv, appConfig) { | ||
var self = this; | ||
|
||
this.appConfig = appConfig; | ||
|
||
self.load = function() { | ||
this.loading = true; | ||
|
||
this.list = new PaginatedQuerySrv({ | ||
name: 'attack-patterns', | ||
root: undefined, | ||
objectType: 'pattern', | ||
version: 'v1', | ||
scope: $scope, | ||
sort: self.filtering.context.sort, | ||
loadAll: false, | ||
pageSize: self.filtering.context.pageSize, | ||
filter: this.filtering.buildQuery(), | ||
baseFilter: { | ||
_field: 'patternType', | ||
_value:'attack-pattern' | ||
}, | ||
operations: [ | ||
{'_name': 'listPattern'} | ||
], | ||
extraData: ['enabled'], | ||
onUpdate: function() { | ||
self.loading = false; | ||
} | ||
}); | ||
}; | ||
|
||
self.show = function(patternId) { | ||
$uibModal.open({ | ||
animation: true, | ||
templateUrl: 'views/partials/admin/attack/view.html', | ||
controller: 'AttackPatternDialogCtrl', | ||
controllerAs: '$modal', | ||
size: 'max', | ||
resolve: { | ||
pattern: function() { | ||
return AttackPatternSrv.get(patternId); | ||
} | ||
} | ||
}); | ||
}; | ||
|
||
|
||
self.import = function () { | ||
var modalInstance = $uibModal.open({ | ||
animation: true, | ||
templateUrl: 'views/partials/admin/attack/import.html', | ||
controller: 'AttackPatternImportCtrl', | ||
controllerAs: '$vm', | ||
size: 'lg', | ||
resolve: { | ||
appConfig: self.appConfig | ||
} | ||
}); | ||
|
||
modalInstance.result | ||
.then(function() { | ||
self.load(); | ||
}) | ||
.catch(function(err){ | ||
if(err && !_.isString(err)) { | ||
NotificationSrv.error('Pattern import', err.data, err.status); | ||
} | ||
}); | ||
}; | ||
|
||
this.toggleFilters = function () { | ||
this.filtering.toggleFilters(); | ||
}; | ||
|
||
this.filter = function () { | ||
self.filtering.filter().then(this.applyFilters); | ||
}; | ||
|
||
this.clearFilters = function () { | ||
this.filtering.clearFilters() | ||
.then(self.search); | ||
}; | ||
|
||
this.removeFilter = function (index) { | ||
self.filtering.removeFilter(index) | ||
.then(self.search); | ||
}; | ||
|
||
this.search = function () { | ||
self.load(); | ||
self.filtering.storeContext(); | ||
}; | ||
this.addFilterValue = function (field, value) { | ||
this.filtering.addFilterValue(field, value); | ||
this.search(); | ||
}; | ||
|
||
self.$onInit = function() { | ||
self.filtering = new FilteringSrv('pattern', 'attack-pattern.list', { | ||
version: 'v1', | ||
defaults: { | ||
showFilters: true, | ||
showStats: false, | ||
pageSize: 15, | ||
sort: ['+name'] | ||
}, | ||
defaultFilter: [] | ||
}); | ||
|
||
self.filtering.initContext('list') | ||
.then(function() { | ||
self.load(); | ||
|
||
$scope.$watch('$vm.list.pageSize', function (newValue) { | ||
self.filtering.setPageSize(newValue); | ||
}); | ||
}); | ||
}; | ||
} | ||
|
||
function AttackPatternDialogCtrl($uibModalInstance, AttackPatternSrv, NotificationSrv, pattern) { | ||
this.pattern = pattern; | ||
|
||
this.ok = function () { | ||
$uibModalInstance.close(); | ||
}; | ||
|
||
this.cancel = function () { | ||
$uibModalInstance.dismiss('cancel'); | ||
}; | ||
} | ||
|
||
function AttackPatternImportCtrl($uibModalInstance, AttackPatternSrv, NotificationSrv, appConfig) { | ||
this.appConfig = appConfig; | ||
this.formData = {}; | ||
|
||
this.ok = function () { | ||
AttackPatternSrv.import(this.formData) | ||
.then(function() { | ||
$uibModalInstance.close(); | ||
}, function(response) { | ||
NotificationSrv.error('AttackPatternImportCtrl', response.data, response.status); | ||
}); | ||
}; | ||
|
||
this.cancel = function () { | ||
$uibModalInstance.dismiss('cancel'); | ||
}; | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
|
||
(function() { | ||
'use strict'; | ||
angular.module('theHiveServices') | ||
.service('AttackPatternSrv', function($http, QuerySrv) { | ||
var baseUrl = './api/v1/pattern'; | ||
|
||
this.list = function() { | ||
return QuerySrv.call('v1', [ | ||
{ _name: 'listPattern' } | ||
], { | ||
name:'list-attack-patterns' | ||
}); | ||
}; | ||
|
||
this.get = function(id) { | ||
return $http.get(baseUrl + '/' + id) | ||
.then(function(response){ | ||
return response.data; | ||
}); | ||
}; | ||
|
||
this.import = function(post) { | ||
var postData = { | ||
file: post.attachment | ||
}; | ||
|
||
return $http({ | ||
method: 'POST', | ||
url: baseUrl + '/import/attack', | ||
headers: { | ||
'Content-Type': undefined | ||
}, | ||
transformRequest: function (data) { | ||
var formData = new FormData(), | ||
copy = angular.copy(data, {}); | ||
|
||
angular.forEach(data, function (value, key) { | ||
if (Object.getPrototypeOf(value) instanceof Blob || Object.getPrototypeOf(value) instanceof File) { | ||
formData.append(key, value); | ||
delete copy[key]; | ||
} | ||
}); | ||
|
||
return formData; | ||
}, | ||
data: postData | ||
}); | ||
}; | ||
}); | ||
|
||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<form class="" name="form" ng-submit="$vm.ok()"> | ||
<div class="modal-header bg-primary"> | ||
<h3 class="modal-title">Import MITRE ATT&CK patterns</h3> | ||
</div> | ||
<div class="modal-body"> | ||
|
||
<div class="filter-panel mb-s"> | ||
<h4>Download the official MITRE ATT&CK library</h4> | ||
<p>You can download the latest archive of the official MITRE ATT&CK patterns <a target="_blank" href="https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json?version=TheHive-{{$vm.appConfig.versions.TheHive}}">from here</a></p> | ||
</div> | ||
|
||
<div class="form-group"> | ||
<label class="control-label">MITRE ATT&CK patterns</label> | ||
<input type="hidden" name="attachment" ng-model="$vm.formData.attachment.status" required> | ||
<div file-chooser="" filemodel="$vm.formData.attachment"></div> | ||
</div> | ||
</div> | ||
<div class="modal-footer"> | ||
<button class="btn btn-default pull-left" type="button" ng-click="$vm.cancel()">Cancel</button> | ||
<button class="btn btn-primary pull-right" type="submit" ng-disabled="form.$invalid">Yes, Import it</button> | ||
</div> | ||
</form> |
Oops, something went wrong.