Skip to content

Commit

Permalink
Merge branch 'hotfix/2.0.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed Apr 13, 2018
2 parents 0a3a733 + 4fd981f commit b6aad26
Show file tree
Hide file tree
Showing 19 changed files with 162 additions and 40 deletions.
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
# Change Log

## [2.0.3](https://github.com/TheHive-Project/Cortex/tree/2.0.3) (2018-04-09)
## [2.0.4](https://github.com/TheHive-Project/Cortex/tree/2.0.4) (2018-04-13)
[Full Changelog](https://github.com/TheHive-Project/Cortex/compare/2.0.3...2.0.4)

**Implemented enhancements:**

- Let a Read/Analyze User Display/Change their API Key [\#89](https://github.com/TheHive-Project/Cortex/issues/89)

**Fixed bugs:**

- Strictly filter the list of analyzers in the run dialog [\#95](https://github.com/TheHive-Project/Cortex/issues/95)
- Updating users by orgAdmin users fails silently [\#94](https://github.com/TheHive-Project/Cortex/issues/94)
- Fix analyzer configurations icons [\#93](https://github.com/TheHive-Project/Cortex/issues/93)
- Wrong page redirection [\#92](https://github.com/TheHive-Project/Cortex/issues/92)
- Sort analyzers list by name [\#91](https://github.com/TheHive-Project/Cortex/issues/91)
- Cortex 2.0.3 docker container having cortex analyzer errors [\#90](https://github.com/TheHive-Project/Cortex/issues/90)
- Install python3 requirements for analyzers in public docker image [\#58](https://github.com/TheHive-Project/Cortex/issues/58)

**Closed issues:**

- Insufficient Rights To Perform This Action [\#87](https://github.com/TheHive-Project/Cortex/issues/87)

## [2.0.3](https://github.com/TheHive-Project/Cortex/tree/2.0.3) (2018-04-09)
[Full Changelog](https://github.com/TheHive-Project/Cortex/compare/2.0.2...2.0.3)

**Implemented enhancements:**
Expand Down
2 changes: 1 addition & 1 deletion app/org/thp/cortex/controllers/AnalyzerCtrl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import javax.inject.{ Inject, Singleton }

import scala.concurrent.{ ExecutionContext, Future }

import play.api.libs.json.{ JsNull, JsObject, Json }
import play.api.libs.json.{ JsObject, Json }
import play.api.mvc.{ AbstractController, Action, AnyContent, ControllerComponents }

import akka.stream.Materializer
Expand Down
3 changes: 1 addition & 2 deletions app/org/thp/cortex/controllers/MispCtrl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package org.thp.cortex.controllers

import javax.inject.Inject
import org.elastic4play.controllers.{ Authenticated, Fields, FieldsBodyParser, Renderer }
import org.elastic4play.services.QueryDSL
import org.thp.cortex.models.Roles
import org.thp.cortex.services.{ AnalyzerSrv, MispSrv }
import play.api.Logger
import play.api.libs.json.{ JsObject, JsValue, Json }
import play.api.libs.json.{ JsObject, JsValue }
import play.api.mvc._

import scala.concurrent.{ ExecutionContext, Future }
Expand Down
8 changes: 6 additions & 2 deletions app/org/thp/cortex/controllers/UserCtrl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,11 @@ class UserCtrl @Inject() (
}

@Timed
def getKey(userId: String): Action[AnyContent] = authenticated(Roles.orgAdmin, Roles.superAdmin).async { implicit request
def getKey(userId: String): Action[AnyContent] = authenticated().async { implicit request
for {
_ checkUserOrganization(userId)
_ if (userId == request.userId || request.roles.contains(Roles.orgAdmin) || request.roles.contains(Roles.superAdmin)) Future.successful(())
else Future.failed(AuthorizationError("You are not authorized to perform this operation"))
key authSrv.getKey(userId)
} yield Ok(key)
}
Expand All @@ -226,9 +228,11 @@ class UserCtrl @Inject() (
}

@Timed
def renewKey(userId: String): Action[AnyContent] = authenticated(Roles.orgAdmin, Roles.superAdmin).async { implicit request
def renewKey(userId: String): Action[AnyContent] = authenticated().async { implicit request
for {
_ checkUserOrganization(userId)
_ if (userId == request.userId || request.roles.contains(Roles.orgAdmin) || request.roles.contains(Roles.superAdmin)) Future.successful(())
else Future.failed(AuthorizationError("You are not authorized to perform this operation"))
key authSrv.renewKey(userId)
} yield Ok(key)
}
Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ dockerCommands ~= { dc =>
"pip3 install -U pip setuptools && " +
"cd /opt && " +
"git clone https://github.com/CERT-BDF/Cortex-Analyzers.git && " +
"pip install $(sort -u Cortex-Analyzers/analyzers/*/requirements.txt) && " +
"sort -u Cortex-Analyzers/analyzers/*/requirements.txt | grep -v ';python_version' | xargs -n 1 pip3 install || true"),
"for I in Cortex-Analyzers/analyzers/*/requirements.txt; do pip2 install -r $I; done && " +
"for I in Cortex-Analyzers/analyzers/*/requirements.txt; do pip3 install -r $I || true; done"),
Cmd("ADD", "var", "/var"),
Cmd("ADD", "etc", "/etc"),
ExecCmd("RUN", "chown", "-R", "daemon:root", "/var/log/cortex"),
Expand Down
1 change: 1 addition & 0 deletions conf/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ search {
}

auth.provider = ["local"]
auth.method.basic = false

# Datastore
datastore {
Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version in ThisBuild := "2.0.3"
version in ThisBuild := "2.0.4"
2 changes: 1 addition & 1 deletion www/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cortex",
"version": "2.0.3",
"version": "2.0.4",
"description": "A powerfull observable analysis engine",
"license": "AGPL-v3",
"homepage": "https://github.com/TheHive-Project/Cortex",
Expand Down
2 changes: 1 addition & 1 deletion www/src/app/components/header/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<div class="container-fluid">
<div class="navbar-header">
<!-- <a href class="navbar-brand"><b>Cortex</b></a> -->
<a class="navbar-brand" ui-sref="main.analyzers">
<a class="navbar-brand" ui-sref="index">
<img alt="Cortex" src="../../../assets/images/logo-small.svg">
</a>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,17 @@ export default class UserEditController {
return;
}

let postData = _.pick(this.formData, 'name', 'roles', 'organization');
let postData;
let promise;

if (
this.AuthService.currentUser.roles.indexOf(this.Roles.SUPERADMIN) !== -1
) {
postData = _.pick(this.formData, 'name', 'roles', 'organization');
} else {
postData = _.pick(this.formData, 'name', 'roles');
}

if (this.user.id) {
promise = this.UserService.update(this.user.id, postData);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ export default class UsersListController {
`User ${mode === 'edit' ? 'updated' : 'created'} successfully`
);
})
.catch(rejection => {
if (rejection && rejection.type === 'ConflictError') {
// Handle user uniquness
.catch(err => {
if (!_.isString(err)) {
this.NotificationService.error('Unable to update the user.');
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export default class OrganizationConfigsController {
};
}

isSet(config) {
return _.indexOf([undefined, null, ''], config) === -1;
}

edit(config) {
let modal = this.$uibModal.open({
controller: ConfigurationEditController,
Expand All @@ -26,11 +30,11 @@ export default class OrganizationConfigsController {
size: 'lg',
resolve: {
configuration: () => {
let defaultValues = {
string: null,
number: 0,
boolean: true
};
// let defaultValues = {
// string: null,
// number: 0,
// boolean: true
// };
let conf = angular.copy(config);

_.forEach(conf.configurationItems, item => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ <h4 class="media-heading">
<div ng-repeat="item in config.configurationItems">
<small class="mr-xxs">
<strong><i class="mr-xxs fa" ng-class="{
'fa-check text-success': config.config[item.name] !== undefined,
'fa-times text-danger': config.config[item.name] === undefined
'fa-check text-success': $ctrl.isSet(config.config[item.name]),
'fa-times text-danger': !$ctrl.isSet(config.config[item.name])
}"></i> {{item.name}}:</strong> {{item.description}}
<span ng-if="item.defaultValue">(<em>Default:</em> {{item.defaultValue}})</span>
</small>
Expand Down
2 changes: 1 addition & 1 deletion www/src/app/pages/analyzers/analyzer.run.modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ <h3 class="modal-title">Run analysis</h3>
</label>
<div class="col-sm-10">
<ul class="nav nav-pills nav-stacked">
<li ng-repeat="a in $modal.analyzers | filter:{dataTypeList: $modal.observable.dataType}">
<li ng-repeat="a in $modal.analyzers | filter:{dataTypeList: $modal.observable.dataType}:true">
<a href ng-click="$modal.toggleAnalyzer(a)">
<i class="fa text-primary" ng-class="{true: 'fa-check-square' , false: 'fa-square-o'}[a.active]"></i> {{a.name}}
</a>
Expand Down
3 changes: 2 additions & 1 deletion www/src/app/pages/analyzers/analyzers.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export default class AnalyzersController extends PageController {
this.SearchService.configure({
objectType: 'analyzer',
filter: this.buildQuery(),
range: this.buildRange()
range: this.buildRange(),
sort: '+name'
})
.search()
.then(response => {
Expand Down
30 changes: 17 additions & 13 deletions www/src/app/pages/analyzers/analyzers.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,23 @@ export default class AnalyzerService {
list() {
let defered = this.$q.defer();

this.$http.get('./api/analyzer', { params: { range: 'all' } }).then(
response => {
this.analyzers = response.data;
this.dataTypes = _.sortBy(
_.uniq(_.flatten(_.map(response.data, 'dataTypeList')))
);

defered.resolve(response.data);
},
response => {
defered.reject(response);
}
);
this.$http
.get('./api/analyzer', {
params: { range: 'all', sort: '+name' }
})
.then(
response => {
this.analyzers = response.data;
this.dataTypes = _.sortBy(
_.uniq(_.flatten(_.map(response.data, 'dataTypeList')))
);

defered.resolve(response.data);
},
response => {
defered.reject(response);
}
);

return defered.promise;
}
Expand Down
2 changes: 1 addition & 1 deletion www/src/app/pages/maintenance/maintenance.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<div class="col-md-8 col-md-offset-2">

<div class="alert alert-warning center-block" role="alert">
<p class="text-center">TheHive needs to update its database</p>
<p class="text-center">Cortex needs to update its database</p>
<br>
<div class="text-center">
<button type="button" class="btn btn-sm btn-default" ng-click="$ctrl.migrate()" ng-hide="$ctrl.migrating">Update Database</button>
Expand Down
55 changes: 53 additions & 2 deletions www/src/app/pages/settings/settings.page.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ export default class SettingsPageController {
$scope,
$state,
UserService,
ModalService,
NotificationService,
resizeService
resizeService,
clipboard
) {
'ngInject';

Expand All @@ -16,8 +18,10 @@ export default class SettingsPageController {
this.$state = $state;

this.UserService = UserService;
this.ModalService = ModalService;
this.NotificationService = NotificationService;
this.resizeService = resizeService;
this.clipboard = clipboard;

this.basicData = {};
this.passData = {
Expand All @@ -26,6 +30,7 @@ export default class SettingsPageController {
password: '',
passwordConfirm: ''
};
this.keyData = {};
}

$onInit() {
Expand All @@ -41,6 +46,9 @@ export default class SettingsPageController {
this.canChangePass =
this.config.config.capabilities.indexOf('changePassword') !== -1;

this.canChangeKey =
this.config.config.capabilities.indexOf('authByKey') !== -1;

this.$scope.$watch('$ctrl.avatar', value => {
if (!value) {
return;
Expand Down Expand Up @@ -93,7 +101,11 @@ export default class SettingsPageController {
this.passData.password !== '' &&
this.passData.password === this.passData.passwordConfirm
) {
this.UserService.changePass(this.currentUser.id, this.passData.currentPassword, this.passData.password)
this.UserService.changePass(
this.currentUser.id,
this.passData.currentPassword,
this.passData.password
)
.then(() => {
this.NotificationService.log(
'Your password has been successfully updated',
Expand Down Expand Up @@ -134,4 +146,43 @@ export default class SettingsPageController {
form.avatar.$setValidity('maxsize', true);
form.avatar.$setPristine(true);
}

getKey() {
this.UserService.getKey(this.currentUser.id).then(key => {
this.keyData.key = key;
});
}

createKey() {
let modalInstance = this.ModalService.confirm(
'Renew API Key',
'Are you sure you want to renew your API Key?',
{
flavor: 'danger',
okText: 'Yes, renew it'
}
);

modalInstance.result
.then(() => this.UserService.setKey(this.currentUser.id))
.then(() => {
delete this.keyData.key;
this.NotificationService.success(
'API key has been successfully renewed.'
);
})
.catch(err => {
if (!_.isString(err)) {
this.NotificationService.error('Unable to lock the user.');
}
});
}

copyKey() {
this.clipboard.copyText(this.keyData.key);
delete this.keyData.key;
this.NotificationService.success(
'API key has been successfully copied to clipboard.'
);
}
}
30 changes: 30 additions & 0 deletions www/src/app/pages/settings/settings.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,36 @@ <h3 class="box-title">
</div>
</form>

<!-- Update API Key -->
<form ng-if="$ctrl.canChangeKey">
<div class="box box-primary">
<div class="box-header" ng-if="$ctrl.currentUser.hasKey">
<h3 class="box-title">API Key</h3>
</div>
<div class="box-body">
<div class="callout callout-warning mv-0" ng-if="!$ctrl.currentUser.hasKey">
<h4>You don't have any API key.</h4>
<p> Please contact your organization's administrator.</p>
</div>
<div class="form-group" ng-if="$ctrl.currentUser.hasKey">
<p>You have an API key defined. You can renew it if needed.</p>
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-default" ng-click="$ctrl.createKey()">Renew</span>
<span class="btn btn-primary" ng-click="$ctrl.getKey()" ng-if="!$ctrl.keyData.key">Reveal</span>
</span>
<input class="form-control" readonly ng-model="$ctrl.keyData.key" ng-if="$ctrl.keyData.key">
<span class="input-group-btn" ng-if="$ctrl.keyData.key">
<button class="btn btn-primary" type="button" ng-click="$ctrl.copyKey()">
<i class="fa fa-copy"></i>
</button>
</span>
</div>
</div>
</div>
</div>
</form>

</div>
</div>

Expand Down

0 comments on commit b6aad26

Please sign in to comment.