mirror of https://github.com/MISP/MISP
Merge branch 'develop' of github.com:MISP/MISP into develop
commit
e394cfbe66
|
@ -243,7 +243,8 @@ CREATE TABLE IF NOT EXISTS event_reports (
|
|||
`deleted` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT u_uuid UNIQUE (uuid),
|
||||
INDEX `name` (`name`)
|
||||
INDEX `name` (`name`),
|
||||
INDEX `event_id` (`event_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
@ -455,7 +456,7 @@ CREATE TABLE IF NOT EXISTS `galaxy_clusters` (
|
|||
`collection_uuid` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`type` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`tag_name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`tag_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
|
||||
`description` text COLLATE utf8_bin NOT NULL,
|
||||
`galaxy_id` int(11) NOT NULL,
|
||||
`source` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
|
|
|
@ -125,8 +125,8 @@ class AppController extends Controller
|
|||
}
|
||||
if (!$this->_isRest()) {
|
||||
$this->__contentSecurityPolicy();
|
||||
}
|
||||
$this->response->header('X-XSS-Protection', '1; mode=block');
|
||||
}
|
||||
|
||||
if (!empty($this->params['named']['sql'])) {
|
||||
$this->sql_dump = intval($this->params['named']['sql']);
|
||||
|
@ -446,22 +446,9 @@ class AppController extends Controller
|
|||
} else {
|
||||
// User not authenticated correctly
|
||||
// reset the session information
|
||||
$redis = $this->User->setupRedis();
|
||||
// Do not log every fail, but just once per hour
|
||||
if ($redis && !$redis->exists('misp:auth_fail_throttling:' . $authKeyToStore)) {
|
||||
$redis->setex('misp:auth_fail_throttling:' . $authKeyToStore, 3600, 1);
|
||||
if ($this->_shouldLog($authKeyToStore)) {
|
||||
$this->loadModel('Log');
|
||||
$this->Log->create();
|
||||
$log = array(
|
||||
'org' => 'SYSTEM',
|
||||
'model' => 'User',
|
||||
'model_id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'action' => 'auth_fail',
|
||||
'title' => "Failed authentication using API key ($authKeyToStore)",
|
||||
'change' => null,
|
||||
);
|
||||
$this->Log->save($log);
|
||||
$this->Log->createLogEntry('SYSTEM', 'auth_fail', 'User', 0, "Failed authentication using API key ($authKeyToStore)");
|
||||
}
|
||||
$this->Session->destroy();
|
||||
}
|
||||
|
@ -548,8 +535,10 @@ class AppController extends Controller
|
|||
}
|
||||
|
||||
if ($user['disabled']) {
|
||||
if ($this->_shouldLog('disabled:' . $user['id'])) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->createLogEntry($user, 'auth_fail', 'User', $user['id'], 'Login attempt by disabled user.');
|
||||
}
|
||||
|
||||
$this->Auth->logout();
|
||||
if ($this->_isRest()) {
|
||||
|
@ -565,11 +554,33 @@ class AppController extends Controller
|
|||
if (isset($user['authkey_expiration']) && $user['authkey_expiration']) {
|
||||
$time = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time();
|
||||
if ($user['authkey_expiration'] < $time) {
|
||||
if ($this->_shouldLog('expired:' . $user['authkey_id'])) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->createLogEntry($user, 'auth_fail', 'User', $user['id'], "Login attempt by expired auth key {$user['authkey_id']}.");
|
||||
}
|
||||
$this->Auth->logout();
|
||||
throw new ForbiddenException('Auth key is expired');
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($user['allowed_ips'])) {
|
||||
App::uses('CidrTool', 'Tools');
|
||||
$cidrTool = new CidrTool($user['allowed_ips']);
|
||||
$remoteIp = $this->_remoteIp();
|
||||
if ($remoteIp === null) {
|
||||
$this->Auth->logout();
|
||||
throw new ForbiddenException('Auth key is limited to IP address, but IP address not found');
|
||||
}
|
||||
if (!$cidrTool->contains($remoteIp)) {
|
||||
if ($this->_shouldLog('not_allowed_ip:' . $user['authkey_id'] . ':' . $remoteIp)) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->createLogEntry($user, 'auth_fail', 'User', $user['id'], "Login attempt from not allowed IP address for auth key {$user['authkey_id']}.");
|
||||
}
|
||||
$this->Auth->logout();
|
||||
throw new ForbiddenException('It is not possible to use this Auth key from your IP address');
|
||||
}
|
||||
}
|
||||
|
||||
$isUserRequest = !$this->_isRest() && !$this->request->is('ajax') && !$this->_isAutomation();
|
||||
// Next checks makes sense just for user direct HTTP request, so skip REST and AJAX calls
|
||||
if (!$isUserRequest) {
|
||||
|
@ -632,7 +643,7 @@ class AppController extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$remoteAddress = trim($_SERVER['REMOTE_ADDR']);
|
||||
$remoteAddress = $this->_remoteIp();
|
||||
|
||||
$pipe = $redis->multi(Redis::PIPELINE);
|
||||
// keep for 30 days
|
||||
|
@ -680,11 +691,7 @@ class AppController extends Controller
|
|||
$change .= PHP_EOL . 'Request body: ' . $payload;
|
||||
}
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
try {
|
||||
$this->Log->createLogEntry($user, 'request', 'User', $user['id'], 'Paranoid log entry', $change);
|
||||
} catch (Exception $e) {
|
||||
// When `MISP.log_skip_db_logs_completely` is enabled, Log::createLogEntry method throws exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1261,7 +1268,7 @@ class AppController extends Controller
|
|||
|
||||
private function __sessionMassage()
|
||||
{
|
||||
if (!empty(Configure::read('MISP.uuid'))) {
|
||||
if (empty(Configure::read('Session.cookie')) && !empty(Configure::read('MISP.uuid'))) {
|
||||
Configure::write('Session.cookie', 'MISP-' . Configure::read('MISP.uuid'));
|
||||
}
|
||||
if (!empty(Configure::read('Session.cookieTimeout')) || !empty(Configure::read('Session.timeout'))) {
|
||||
|
@ -1454,10 +1461,10 @@ class AppController extends Controller
|
|||
if ($this->userRole['perm_site_admin']) {
|
||||
return true;
|
||||
}
|
||||
if ($this->userRole['perm_modify_org'] && $event['Event']['orgc_id'] == $this->Auth->user('org_id')) {
|
||||
if ($this->userRole['perm_modify_org'] && $event['Event']['orgc_id'] == $this->Auth->user()['org_id']) {
|
||||
return true;
|
||||
}
|
||||
if ($this->userRole['perm_modify'] && $event['Event']['user_id'] == $this->Auth->user('id')) {
|
||||
if ($this->userRole['perm_modify'] && $event['Event']['user_id'] == $this->Auth->user()['id']) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1501,17 +1508,47 @@ class AppController extends Controller
|
|||
throw new RuntimeException("User with ID {$sessionUser['id']} not exists.");
|
||||
}
|
||||
if (isset($sessionUser['authkey_id'])) {
|
||||
// Reload authkey
|
||||
$this->loadModel('AuthKey');
|
||||
if (!$this->AuthKey->exists($sessionUser['authkey_id'])) {
|
||||
$authKey = $this->AuthKey->find('first', [
|
||||
'conditions' => ['id' => $sessionUser['authkey_id'], 'user_id' => $user['id']],
|
||||
'fields' => ['id', 'expiration', 'allowed_ips'],
|
||||
'recursive' => -1,
|
||||
]);
|
||||
if (empty($authKey)) {
|
||||
throw new RuntimeException("Auth key with ID {$sessionUser['authkey_id']} not exists.");
|
||||
}
|
||||
$user['authkey_id'] = $authKey['AuthKey']['id'];
|
||||
$user['authkey_expiration'] = $authKey['AuthKey']['expiration'];
|
||||
$user['allowed_ips'] = $authKey['AuthKey']['allowed_ips'];
|
||||
}
|
||||
foreach (['authkey_id', 'authkey_expiration', 'logged_by_authkey'] as $copy) {
|
||||
if (isset($sessionUser[$copy])) {
|
||||
$user[$copy] = $sessionUser[$copy];
|
||||
}
|
||||
if (isset($sessionUser['logged_by_authkey'])) {
|
||||
$user['logged_by_authkey'] = $sessionUser['logged_by_authkey'];
|
||||
}
|
||||
$this->Auth->login($user);
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
protected function _remoteIp()
|
||||
{
|
||||
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
|
||||
return isset($_SERVER[$ipHeader]) ? trim($_SERVER[$ipHeader]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return bool Returns true if the same log defined by $key was not stored in last hour
|
||||
*/
|
||||
protected function _shouldLog($key)
|
||||
{
|
||||
$redis = $this->User->setupRedis();
|
||||
if ($redis && !$redis->exists('misp:auth_fail_throttling:' . $key)) {
|
||||
$redis->setex('misp:auth_fail_throttling:' . $key, 3600, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,8 +71,34 @@ class AuthKeysController extends AppController
|
|||
|
||||
public function edit($id)
|
||||
{
|
||||
$this->set('metaGroup', 'admin');
|
||||
$this->set('metaAction', 'authkeys_edit');
|
||||
$this->CRUD->edit($id, [
|
||||
'conditions' => $this->__prepareConditions(),
|
||||
'afterFind' => function (array $authKey) {
|
||||
unset($authKey['AuthKey']['authkey']);
|
||||
if (is_array($authKey['AuthKey']['allowed_ips'])) {
|
||||
$authKey['AuthKey']['allowed_ips'] = implode("\n", $authKey['AuthKey']['allowed_ips']);
|
||||
}
|
||||
$authKey['AuthKey']['expiration'] = date('Y-m-d H:i:s', $authKey['AuthKey']['expiration']);
|
||||
return $authKey;
|
||||
},
|
||||
'fields' => ['comment', 'allowed_ips', 'expiration'],
|
||||
]);
|
||||
if ($this->IndexFilter->isRest()) {
|
||||
return $this->restResponsePayload;
|
||||
}
|
||||
$this->set('dropdownData', [
|
||||
'user' => $this->User->find('list', [
|
||||
'sort' => ['username' => 'asc'],
|
||||
'conditions' => ['id' => $this->request->data['AuthKey']['user_id']],
|
||||
])
|
||||
]);
|
||||
$this->set('menuData', [
|
||||
'menuList' => $this->_isSiteAdmin() ? 'admin' : 'globalActions',
|
||||
'menuItem' => 'authKeyAdd',
|
||||
]);
|
||||
$this->set('edit', true);
|
||||
$this->set('validity', Configure::read('Security.advanced_authkeys_validity'));
|
||||
$this->render('add');
|
||||
}
|
||||
|
||||
public function add($user_id = false)
|
||||
|
|
|
@ -687,7 +687,7 @@ class ACLComponent extends Component
|
|||
'register' => array('*'),
|
||||
'registrations' => array('perm_site_admin'),
|
||||
'resetAllSyncAuthKeys' => array(),
|
||||
'resetauthkey' => array('*'),
|
||||
'resetauthkey' => ['AND' => ['self_management_enabled', 'perm_auth']],
|
||||
'request_API' => array('*'),
|
||||
'routeafterlogin' => array('*'),
|
||||
'statistics' => array('*'),
|
||||
|
|
|
@ -145,13 +145,21 @@ class CRUDComponent extends Component
|
|||
if (empty($id)) {
|
||||
throw new NotFoundException(__('Invalid %s.', $modelName));
|
||||
}
|
||||
$data = $this->Controller->{$modelName}->find('first',
|
||||
isset($params['get']) ? $params['get'] : [
|
||||
$query = isset($params['get']) ? $params['get'] : [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'id' => $id
|
||||
]
|
||||
]);
|
||||
],
|
||||
];
|
||||
if (!empty($params['conditions'])) {
|
||||
$query['conditions']['AND'][] = $params['conditions'];
|
||||
}
|
||||
/** @var Model $model */
|
||||
$model = $this->Controller->{$modelName};
|
||||
$data = $model->find('first', $query);
|
||||
if (isset($params['afterFind'])) {
|
||||
$data = $params['afterFind']($data);
|
||||
}
|
||||
if ($this->Controller->request->is('post') || $this->Controller->request->is('put')) {
|
||||
$input = $this->Controller->request->data;
|
||||
if (empty($input[$modelName])) {
|
||||
|
@ -171,7 +179,10 @@ class CRUDComponent extends Component
|
|||
$data[$modelName][$field] = $fieldData;
|
||||
}
|
||||
}
|
||||
if ($this->Controller->{$modelName}->save($data)) {
|
||||
if (isset($params['beforeSave'])) {
|
||||
$data = $params['beforeSave']($data);
|
||||
}
|
||||
if ($model->save($data)) {
|
||||
$message = __('%s updated.', $modelName);
|
||||
if ($this->Controller->IndexFilter->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->Controller->RestResponse->viewData($data, 'json');
|
||||
|
@ -182,7 +193,9 @@ class CRUDComponent extends Component
|
|||
}
|
||||
} else {
|
||||
if ($this->Controller->IndexFilter->isRest()) {
|
||||
|
||||
$controllerName = $this->Controller->params['controller'];
|
||||
$actionName = $this->Controller->params['action'];
|
||||
$this->Controller->restResponsePayload = $this->Controller->RestResponse->saveFailResponse($controllerName, $actionName, false, $model->validationErrors, 'json');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -4938,6 +4938,7 @@ class EventsController extends AppController
|
|||
if (!$event) {
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
$mayModify = $this->__canModifyEvent($event);
|
||||
$eventId = $event['Event']['id'];
|
||||
|
||||
$this->loadModel('Module');
|
||||
|
@ -5108,7 +5109,7 @@ class EventsController extends AppController
|
|||
$this->set('module', $module);
|
||||
$this->set('eventId', $eventId);
|
||||
$this->set('event', $event);
|
||||
$this->set('mayModify', $this->__canModifyEvent($event));
|
||||
$this->set('mayModify', $mayModify);
|
||||
}
|
||||
|
||||
public function exportModule($module, $id, $standard = false)
|
||||
|
|
|
@ -558,8 +558,8 @@ class GalaxiesController extends AppController
|
|||
if (empty($clusters)) {
|
||||
throw new MethodNotAllowedException('Invalid Galaxy.');
|
||||
}
|
||||
$this->Galaxy->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $clusters);
|
||||
foreach ($clusters as $k => $cluster) {
|
||||
$clusters[$k] = $this->Galaxy->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $clusters[$k]);
|
||||
$clusters[$k] = $this->Galaxy->GalaxyCluster->attachExtendFromInfo($this->Auth->user(), $clusters[$k]);
|
||||
}
|
||||
$galaxy = $this->Galaxy->find('first', array(
|
||||
|
|
|
@ -96,16 +96,18 @@ class GalaxyClustersController extends AppController
|
|||
)
|
||||
);
|
||||
return $this->RestResponse->viewData($clusters, $this->response->type());
|
||||
} else {
|
||||
}
|
||||
|
||||
$this->paginate['conditions']['AND'][] = $contextConditions;
|
||||
$this->paginate['conditions']['AND'][] = $searchConditions;
|
||||
$this->paginate['conditions']['AND'][] = $aclConditions;
|
||||
$this->paginate['contain'] = array_merge($this->paginate['contain'], array('Org', 'Orgc', 'SharingGroup', 'GalaxyClusterRelation', 'TargetingClusterRelation'));
|
||||
$clusters = $this->paginate();
|
||||
|
||||
$this->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $clusters);
|
||||
|
||||
$tagIds = array();
|
||||
foreach ($clusters as $k => $cluster) {
|
||||
$clusters[$k] = $this->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $clusters[$k]);
|
||||
$clusters[$k] = $this->GalaxyCluster->attachExtendFromInfo($this->Auth->user(), $clusters[$k]);
|
||||
$clusters[$k]['GalaxyCluster']['relation_counts'] = array(
|
||||
'out' => count($clusters[$k]['GalaxyClusterRelation']),
|
||||
|
@ -151,7 +153,7 @@ class GalaxyClustersController extends AppController
|
|||
$this->set('list', $clusters);
|
||||
$this->set('galaxy_id', $galaxyId);
|
||||
$this->set('custom_cluster_count', $customClusterCount);
|
||||
}
|
||||
|
||||
if ($this->request->is('ajax')) {
|
||||
$this->layout = 'ajax';
|
||||
$this->render('ajax/index');
|
||||
|
@ -179,7 +181,9 @@ class GalaxyClustersController extends AppController
|
|||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($cluster, $this->response->type());
|
||||
} else {
|
||||
$cluster = $this->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $cluster);
|
||||
$clusters = [$cluster];
|
||||
$this->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $clusters);
|
||||
$cluster = $clusters[0];
|
||||
$cluster = $this->GalaxyCluster->attachExtendFromInfo($this->Auth->user(), $cluster);
|
||||
$this->set('id', $id);
|
||||
$this->set('galaxy', ['Galaxy' => $cluster['GalaxyCluster']['Galaxy']]);
|
||||
|
|
|
@ -2434,9 +2434,9 @@ misp.direct_call(relative_path, body)
|
|||
}
|
||||
|
||||
$message = 'CSP reported violation';
|
||||
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
|
||||
if (isset($_SERVER[$ipHeader])) {
|
||||
$message .= ' from IP ' . $_SERVER[$ipHeader];
|
||||
$remoteIp = $this->_remoteIp();
|
||||
if ($remoteIp) {
|
||||
$message .= ' from IP ' . $remoteIp;
|
||||
}
|
||||
$this->log("$message: " . json_encode($report['csp-report'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
|
||||
|
|
|
@ -1294,24 +1294,22 @@ class UsersController extends AppController
|
|||
|
||||
public function resetauthkey($id = null, $alert = false)
|
||||
{
|
||||
if (!$this->_isAdmin() && Configure::read('MISP.disableUserSelfManagement')) {
|
||||
throw new MethodNotAllowedException('User self-management has been disabled on this instance.');
|
||||
}
|
||||
if (!$this->request->is('post') && !$this->request->is('put')) {
|
||||
throw new MethodNotAllowedException(__('This functionality is only accessible via POST requests.'));
|
||||
}
|
||||
if ($id == 'me') {
|
||||
if ($id === 'me') {
|
||||
$id = $this->Auth->user('id');
|
||||
// Reset just current auth key
|
||||
$keyId = isset($this->Auth->user()['authkey_id']) ? $this->Auth->user()['authkey_id'] : null;
|
||||
} else {
|
||||
$keyId = null;
|
||||
}
|
||||
if (!$this->userRole['perm_auth']) {
|
||||
throw new MethodNotAllowedException(__('Invalid action.'));
|
||||
}
|
||||
$newkey = $this->User->resetauthkey($this->Auth->user(), $id, $alert);
|
||||
$newkey = $this->User->resetauthkey($this->Auth->user(), $id, $alert, $keyId);
|
||||
if ($newkey === false) {
|
||||
throw new MethodNotAllowedException(__('Invalid user.'));
|
||||
}
|
||||
if (!$this->_isRest()) {
|
||||
$this->Flash->success(__('New authkey generated.', true));
|
||||
$this->Flash->success(__('New authkey generated.'));
|
||||
$this->redirect($this->referer());
|
||||
} else {
|
||||
return $this->RestResponse->saveSuccessResponse('User', 'resetauthkey', $id, $this->response->type(), 'Authkey updated: ' . $newkey);
|
||||
|
|
|
@ -66,6 +66,26 @@ class CidrTool
|
|||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cidr
|
||||
* @return bool
|
||||
*/
|
||||
public static function validate($cidr)
|
||||
{
|
||||
$parts = explode('/', $cidr, 2);
|
||||
$ipBytes = inet_pton($parts[0]);
|
||||
if ($ipBytes === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$maximumNetmask = strlen($ipBytes) === 4 ? 32 : 128;
|
||||
if (isset($parts[1]) && ($parts[1] > $maximumNetmask || $parts[1] < 0)) {
|
||||
return false; // Netmask part of CIDR is invalid
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using solution from https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/IpUtils.php
|
||||
*
|
||||
|
|
|
@ -89,7 +89,7 @@ class AppModel extends Model
|
|||
45 => false, 46 => false, 47 => false, 48 => false, 49 => false, 50 => false,
|
||||
51 => false, 52 => false, 53 => false, 54 => false, 55 => false, 56 => false,
|
||||
57 => false, 58 => false, 59 => false, 60 => false, 61 => false, 62 => false,
|
||||
63 => true, 64 => false, 65 => false
|
||||
63 => true, 64 => false, 65 => false, 66 => false, 67 => false,
|
||||
);
|
||||
|
||||
public $advanced_updates_description = array(
|
||||
|
@ -1568,6 +1568,13 @@ class AppModel extends Model
|
|||
INDEX `value` (`value`(255))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
|
||||
break;
|
||||
case 66:
|
||||
$sqlArray[] = "ALTER TABLE `galaxy_clusters` MODIFY COLUMN `tag_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '';";
|
||||
$indexArray[] = ['event_reports', 'event_id'];
|
||||
break;
|
||||
case 67:
|
||||
$sqlArray[] = "ALTER TABLE `auth_keys` ADD `allowed_ips` text DEFAULT NULL;";
|
||||
break;
|
||||
case 'fixNonEmptySharingGroupID':
|
||||
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
|
||||
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
|
||||
|
@ -1821,18 +1828,19 @@ class AppModel extends Model
|
|||
}
|
||||
}
|
||||
|
||||
private function __addIndex($table, $field, $length = false)
|
||||
private function __addIndex($table, $field, $length = null, $unique = false)
|
||||
{
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$index = $unique ? 'UNIQUE INDEX' : 'INDEX';
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$addIndex = "CREATE INDEX idx_" . $table . "_" . $field . " ON " . $table . " (" . $field . ");";
|
||||
$addIndex = "CREATE $index idx_" . $table . "_" . $field . " ON " . $table . " (" . $field . ");";
|
||||
} else {
|
||||
if (!$length) {
|
||||
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`);";
|
||||
$addIndex = "ALTER TABLE `" . $table . "` ADD $index `" . $field . "` (`" . $field . "`);";
|
||||
} else {
|
||||
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`(" . $length . "));";
|
||||
$addIndex = "ALTER TABLE `" . $table . "` ADD $index `" . $field . "` (`" . $field . "`(" . $length . "));";
|
||||
}
|
||||
}
|
||||
$result = true;
|
||||
|
@ -1841,7 +1849,7 @@ class AppModel extends Model
|
|||
try {
|
||||
$this->query($addIndex);
|
||||
} catch (Exception $e) {
|
||||
$duplicate = (strpos($e->getMessage(), '1061') !== false);
|
||||
$duplicate = strpos($e->getMessage(), '1061') !== false;
|
||||
$errorMessage = $e->getMessage();
|
||||
$result = false;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('RandomTool', 'Tools');
|
||||
App::uses('CidrTool', 'Tools');
|
||||
|
||||
/**
|
||||
* @property User $User
|
||||
|
@ -26,7 +27,6 @@ class AuthKey extends AppModel
|
|||
// massage the data before we send it off for validation before saving anything
|
||||
public function beforeValidate($options = array())
|
||||
{
|
||||
//parent::beforeValidate();
|
||||
if (empty($this->data['AuthKey']['id'])) {
|
||||
if (empty($this->data['AuthKey']['uuid'])) {
|
||||
$this->data['AuthKey']['uuid'] = CakeText::uuid();
|
||||
|
@ -42,10 +42,32 @@ class AuthKey extends AppModel
|
|||
$this->data['AuthKey']['authkey_end'] = substr($authkey, -4);
|
||||
$this->data['AuthKey']['authkey_raw'] = $authkey;
|
||||
$this->authkey_raw = $authkey;
|
||||
}
|
||||
|
||||
if (!empty($this->data['AuthKey']['allowed_ips'])) {
|
||||
if (is_string($this->data['AuthKey']['allowed_ips'])) {
|
||||
$this->data['AuthKey']['allowed_ips'] = trim($this->data['AuthKey']['allowed_ips']);
|
||||
if (empty($this->data['AuthKey']['allowed_ips'])) {
|
||||
$this->data['AuthKey']['allowed_ips'] = [];
|
||||
} else {
|
||||
$this->data['AuthKey']['allowed_ips'] = explode("\n", $this->data['AuthKey']['allowed_ips']);
|
||||
$this->data['AuthKey']['allowed_ips'] = array_map('trim', $this->data['AuthKey']['allowed_ips']);
|
||||
}
|
||||
}
|
||||
if (!is_array($this->data['AuthKey']['allowed_ips'])) {
|
||||
$this->invalidate('allowed_ips', 'Allowed IPs must be array');
|
||||
}
|
||||
foreach ($this->data['AuthKey']['allowed_ips'] as $cidr) {
|
||||
if (!CidrTool::validate($cidr)) {
|
||||
$this->invalidate('allowed_ips', "$cidr is not valid IP range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$creationTime = isset($this->data['AuthKey']['created']) ? $this->data['AuthKey']['created'] : time();
|
||||
$validity = Configure::read('Security.advanced_authkeys_validity');
|
||||
if (empty($this->data['AuthKey']['expiration'])) {
|
||||
$this->data['AuthKey']['expiration'] = $validity ? strtotime("+$validity days") : 0;
|
||||
$this->data['AuthKey']['expiration'] = $validity ? strtotime("+$validity days", $creationTime) : 0;
|
||||
} else {
|
||||
$expiration = is_numeric($this->data['AuthKey']['expiration']) ?
|
||||
(int)$this->data['AuthKey']['expiration'] :
|
||||
|
@ -54,11 +76,33 @@ class AuthKey extends AppModel
|
|||
if ($expiration === false) {
|
||||
$this->invalidate('expiration', __('Expiration must be in YYYY-MM-DD format.'));
|
||||
}
|
||||
if ($validity && $expiration > strtotime("+$validity days")) {
|
||||
if ($validity && $expiration > strtotime("+$validity days", $creationTime)) {
|
||||
$this->invalidate('expiration', __('Maximal key validity is %s days.', $validity));
|
||||
}
|
||||
$this->data['AuthKey']['expiration'] = $expiration;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function afterFind($results, $primary = false)
|
||||
{
|
||||
foreach ($results as $key => $val) {
|
||||
if (isset($val['AuthKey']['allowed_ips'])) {
|
||||
$results[$key]['AuthKey']['allowed_ips'] = $this->jsonDecode($val['AuthKey']['allowed_ips']);
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function beforeSave($options = array())
|
||||
{
|
||||
if (isset($this->data['AuthKey']['allowed_ips'])) {
|
||||
if (empty($this->data['AuthKey']['allowed_ips'])) {
|
||||
$this->data['AuthKey']['allowed_ips'] = null;
|
||||
} else {
|
||||
$this->data['AuthKey']['allowed_ips'] = json_encode($this->data['AuthKey']['allowed_ips']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -71,9 +115,9 @@ class AuthKey extends AppModel
|
|||
{
|
||||
$start = substr($authkey, 0, 4);
|
||||
$end = substr($authkey, -4);
|
||||
$existing_authkeys = $this->find('all', [
|
||||
$possibleAuthkeys = $this->find('all', [
|
||||
'recursive' => -1,
|
||||
'fields' => ['id', 'authkey', 'user_id', 'expiration'],
|
||||
'fields' => ['id', 'authkey', 'user_id', 'expiration', 'allowed_ips'],
|
||||
'conditions' => [
|
||||
'OR' => [
|
||||
'expiration >' => time(),
|
||||
|
@ -84,12 +128,13 @@ class AuthKey extends AppModel
|
|||
]
|
||||
]);
|
||||
$passwordHasher = $this->getHasher();
|
||||
foreach ($existing_authkeys as $existing_authkey) {
|
||||
if ($passwordHasher->check($authkey, $existing_authkey['AuthKey']['authkey'])) {
|
||||
$user = $this->User->getAuthUser($existing_authkey['AuthKey']['user_id']);
|
||||
foreach ($possibleAuthkeys as $possibleAuthkey) {
|
||||
if ($passwordHasher->check($authkey, $possibleAuthkey['AuthKey']['authkey'])) {
|
||||
$user = $this->User->getAuthUser($possibleAuthkey['AuthKey']['user_id']);
|
||||
if ($user) {
|
||||
$user['authkey_id'] = $existing_authkey['AuthKey']['id'];
|
||||
$user['authkey_expiration'] = $existing_authkey['AuthKey']['expiration'];
|
||||
$user['authkey_id'] = $possibleAuthkey['AuthKey']['id'];
|
||||
$user['authkey_expiration'] = $possibleAuthkey['AuthKey']['expiration'];
|
||||
$user['allowed_ips'] = $possibleAuthkey['AuthKey']['allowed_ips'];
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
@ -97,26 +142,67 @@ class AuthKey extends AppModel
|
|||
return false;
|
||||
}
|
||||
|
||||
public function resetauthkey($id)
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param int|null $keyId
|
||||
* @return false|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function resetAuthKey($userId, $keyId = null)
|
||||
{
|
||||
$existing_authkeys = $this->find('all', [
|
||||
$time = time();
|
||||
|
||||
if ($keyId) {
|
||||
$currentAuthkey = $this->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'user_id' => $id
|
||||
'id' => $keyId,
|
||||
'user_id' => $userId,
|
||||
],
|
||||
]);
|
||||
if (empty($currentAuthkey)) {
|
||||
throw new RuntimeException("Key with ID $keyId for user with ID $userId not found.");
|
||||
}
|
||||
$currentAuthkey['AuthKey']['expiration'] = $time;
|
||||
if (!$this->save($currentAuthkey)) {
|
||||
throw new RuntimeException("Key with ID $keyId could not be saved.");
|
||||
}
|
||||
$comment = __("Created by resetting auth key %s\n%s", $keyId, $currentAuthkey['AuthKey']['comment']);
|
||||
$allowedIps = isset($currentAuthkey['AuthKey']['allowed_ips']) ? $currentAuthkey['AuthKey']['allowed_ips'] : [];
|
||||
return $this->createnewkey($userId, $comment, $allowedIps);
|
||||
} else {
|
||||
$existingAuthkeys = $this->find('all', [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'OR' => [
|
||||
'expiration >' => $time,
|
||||
'expiration' => 0
|
||||
],
|
||||
'user_id' => $userId
|
||||
]
|
||||
]);
|
||||
foreach ($existing_authkeys as $key) {
|
||||
$key['AuthKey']['expiration'] = time();
|
||||
foreach ($existingAuthkeys as $key) {
|
||||
$key['AuthKey']['expiration'] = $time;
|
||||
$this->save($key);
|
||||
}
|
||||
return $this->createnewkey($id);
|
||||
return $this->createnewkey($userId);
|
||||
}
|
||||
}
|
||||
|
||||
public function createnewkey($id)
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param string $comment
|
||||
* @param array $allowedIps
|
||||
* @return false|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createnewkey($userId, $comment = '', array $allowedIps = [])
|
||||
{
|
||||
$newKey = [
|
||||
'authkey' => (new RandomTool())->random_str(true, 40),
|
||||
'user_id' => $id
|
||||
'user_id' => $userId,
|
||||
'comment' => $comment,
|
||||
'allowed_ips' => empty($allowedIps) ? null : $allowedIps,
|
||||
];
|
||||
$this->create();
|
||||
if ($this->save($newKey)) {
|
||||
|
@ -175,6 +261,18 @@ class AuthKey extends AppModel
|
|||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* When key is modified, update `date_modified` for user that was assigned to that key, so session data
|
||||
* will be realoaded.
|
||||
* @see AppController::_refreshAuth
|
||||
*/
|
||||
public function afterSave($created, $options = array())
|
||||
{
|
||||
parent::afterSave($created, $options);
|
||||
$userId = $this->data['AuthKey']['user_id'];
|
||||
$this->User->updateAll(['date_modified' => time()], ['User.id' => $userId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* When key is deleted, update after `date_modified` for user that was assigned to that key, so session data
|
||||
* will be realoaded and canceled.
|
||||
|
|
|
@ -1226,7 +1226,7 @@ class Feed extends AppModel
|
|||
$md5Values = array_map('md5', array_column($values, 'value'));
|
||||
|
||||
$redis->del('misp:feed_cache:' . $feedId);
|
||||
foreach (array_chunk($md5Values, 1000) as $k => $chunk) {
|
||||
foreach (array_chunk($md5Values, 5000) as $k => $chunk) {
|
||||
$pipe = $redis->multi(Redis::PIPELINE);
|
||||
if (method_exists($redis, 'sAddArray')) {
|
||||
$redis->sAddArray('misp:feed_cache:' . $feedId, $chunk);
|
||||
|
@ -1238,7 +1238,7 @@ class Feed extends AppModel
|
|||
}
|
||||
}
|
||||
$pipe->exec();
|
||||
$this->jobProgress($jobId, __('Feed %s: %s/%s values cached.', $feedId, $k * 1000, count($md5Values)));
|
||||
$this->jobProgress($jobId, __('Feed %s: %s/%s values cached.', $feedId, $k * 5000, count($md5Values)));
|
||||
}
|
||||
$redis->set('misp:feed_cache_timestamp:' . $feedId, time());
|
||||
return true;
|
||||
|
|
|
@ -832,11 +832,30 @@ class GalaxyCluster extends AppModel
|
|||
return $element;
|
||||
}
|
||||
|
||||
public function attachExtendByInfo($user, $cluster)
|
||||
/**
|
||||
* @param array $user
|
||||
* @param array $clusters
|
||||
* @return void
|
||||
*/
|
||||
public function attachExtendByInfo(array $user, array &$clusters)
|
||||
{
|
||||
$extensions = $this->fetchGalaxyClusters($user, array('conditions' => array('extends_uuid' => $cluster['GalaxyCluster']['uuid'])));
|
||||
$cluster['GalaxyCluster']['extended_by'] = $extensions;
|
||||
return $cluster;
|
||||
if (empty($clusters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$clusterUuids = array_column(array_column($clusters, 'GalaxyCluster'), 'uuid');
|
||||
$extensions = $this->fetchGalaxyClusters($user, [
|
||||
'conditions' => ['extends_uuid' => $clusterUuids],
|
||||
]);
|
||||
foreach ($clusters as &$cluster) {
|
||||
$extendedBy = [];
|
||||
foreach ($extensions as $extension) {
|
||||
if ($cluster['GalaxyCluster']['uuid'] === $extension['GalaxyCluster']['extends_uuid']) {
|
||||
$extendedBy[] = $extension;
|
||||
}
|
||||
}
|
||||
$cluster['GalaxyCluster']['extended_by'] = $extendedBy;
|
||||
}
|
||||
}
|
||||
|
||||
public function attachExtendFromInfo($user, $cluster)
|
||||
|
@ -896,7 +915,7 @@ class GalaxyCluster extends AppModel
|
|||
if (!$isGalaxyTag) {
|
||||
return null;
|
||||
}
|
||||
$conditions = array('LOWER(GalaxyCluster.tag_name)' => strtolower($name));
|
||||
$conditions = array('GalaxyCluster.tag_name' => $name);
|
||||
}
|
||||
$cluster = $this->fetchGalaxyClusters($user, array(
|
||||
'conditions' => $conditions,
|
||||
|
@ -924,7 +943,7 @@ class GalaxyCluster extends AppModel
|
|||
if (count(array_filter($namesOrIds, 'is_numeric')) === count($namesOrIds)) { // all elements are numeric
|
||||
$conditions = array('GalaxyCluster.id' => $namesOrIds);
|
||||
} else {
|
||||
$conditions = array('LOWER(GalaxyCluster.tag_name)' => array_map('strtolower', $namesOrIds));
|
||||
$conditions = array('GalaxyCluster.tag_name' => $namesOrIds);
|
||||
}
|
||||
|
||||
$options = ['conditions' => $conditions];
|
||||
|
@ -1451,7 +1470,7 @@ class GalaxyCluster extends AppModel
|
|||
foreach ($events as $event) {
|
||||
foreach ($event['EventTag'] as $eventTag) {
|
||||
if ($eventTag['Tag']['is_galaxy']) {
|
||||
$clusterTagNames[$eventTag['Tag']['id']] = strtolower($eventTag['Tag']['name']);
|
||||
$clusterTagNames[$eventTag['Tag']['id']] = $eventTag['Tag']['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1461,7 +1480,7 @@ class GalaxyCluster extends AppModel
|
|||
}
|
||||
|
||||
$options = [
|
||||
'conditions' => ['LOWER(GalaxyCluster.tag_name)' => $clusterTagNames],
|
||||
'conditions' => ['GalaxyCluster.tag_name' => $clusterTagNames],
|
||||
'contain' => ['Galaxy', 'GalaxyElement'],
|
||||
];
|
||||
$clusters = $this->fetchGalaxyClusters($user, $options);
|
||||
|
|
|
@ -92,7 +92,7 @@ class Job extends AppModel
|
|||
}
|
||||
}
|
||||
try {
|
||||
if ($this->save($jobData)) {
|
||||
if ($this->save($jobData, ['atomic' => false])) {
|
||||
return true;
|
||||
}
|
||||
$this->log("Could not save progress for job $jobId because of validation errors: " . json_encode($this->validationErrors), LOG_NOTICE);
|
||||
|
|
|
@ -199,7 +199,7 @@ class Log extends AppModel
|
|||
* @param int $modelId
|
||||
* @param string $title
|
||||
* @param string|array $change
|
||||
* @return array
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
|
@ -238,6 +238,10 @@ class Log extends AppModel
|
|||
));
|
||||
|
||||
if (!$result) {
|
||||
if ($action === 'request' && !empty(Configure::read('MISP.log_paranoid_skip_db'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new Exception("Cannot save log because of validation errors: " . json_encode($this->validationErrors));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ App::uses('GpgTool', 'Tools');
|
|||
|
||||
/**
|
||||
* @property-read array $serverSettings
|
||||
* @property Organisation $Organisation
|
||||
*/
|
||||
class Server extends AppModel
|
||||
{
|
||||
|
@ -1259,16 +1260,23 @@ class Server extends AppModel
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCurrentServerSettings()
|
||||
{
|
||||
$this->Module = ClassRegistry::init('Module');
|
||||
$serverSettings = $this->serverSettings;
|
||||
$moduleTypes = array('Enrichment', 'Import', 'Export', 'Cortex');
|
||||
$serverSettings = $this->readModuleSettings($serverSettings, $moduleTypes);
|
||||
return $serverSettings;
|
||||
}
|
||||
|
||||
private function readModuleSettings($serverSettings, $moduleTypes)
|
||||
/**
|
||||
* @param array $serverSettings
|
||||
* @param array $moduleTypes
|
||||
* @return array
|
||||
*/
|
||||
private function readModuleSettings(array $serverSettings, array $moduleTypes)
|
||||
{
|
||||
$this->Module = ClassRegistry::init('Module');
|
||||
foreach ($moduleTypes as $moduleType) {
|
||||
|
@ -1277,12 +1285,12 @@ class Server extends AppModel
|
|||
foreach ($results as $module => $data) {
|
||||
foreach ($data as $result) {
|
||||
$setting = array('level' => 1, 'errorMessage' => '');
|
||||
if ($result['type'] == 'boolean') {
|
||||
if ($result['type'] === 'boolean') {
|
||||
$setting['test'] = 'testBool';
|
||||
$setting['type'] = 'boolean';
|
||||
$setting['description'] = __('Enable or disable the %s module.', $module);
|
||||
$setting['value'] = false;
|
||||
} elseif ($result['type'] == 'orgs') {
|
||||
} elseif ($result['type'] === 'orgs') {
|
||||
$setting['description'] = __('Restrict the %s module to the given organisation.', $module);
|
||||
$setting['value'] = 0;
|
||||
$setting['test'] = 'testLocalOrg';
|
||||
|
@ -1359,15 +1367,11 @@ class Server extends AppModel
|
|||
|
||||
public function serverSettingsRead($unsorted = false)
|
||||
{
|
||||
$this->Module = ClassRegistry::init('Module');
|
||||
$serverSettings = $this->getCurrentServerSettings();
|
||||
$currentSettings = Configure::read();
|
||||
if (Configure::read('Plugin.Enrichment_services_enable')) {
|
||||
$this->readModuleSettings($serverSettings, array('Enrichment'));
|
||||
}
|
||||
$finalSettingsUnsorted = $this->__serverSettingsRead($serverSettings, $currentSettings);
|
||||
foreach ($finalSettingsUnsorted as $key => $temp) {
|
||||
if (in_array($temp['tab'], array_keys($this->__settingTabMergeRules))) {
|
||||
if (isset($this->__settingTabMergeRules[$temp['tab']])) {
|
||||
$finalSettingsUnsorted[$key]['tab'] = $this->__settingTabMergeRules[$temp['tab']];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1106,7 +1106,7 @@ class User extends AppModel
|
|||
return $results;
|
||||
}
|
||||
|
||||
public function resetauthkey($user, $id, $alert = false)
|
||||
public function resetauthkey($user, $id, $alert = false, $keyId = null)
|
||||
{
|
||||
$this->id = $id;
|
||||
if (!$id || !$this->exists($id)) {
|
||||
|
@ -1123,8 +1123,7 @@ class User extends AppModel
|
|||
$this->extralog(
|
||||
$user,
|
||||
'reset_auth_key',
|
||||
sprintf(
|
||||
__('Authentication key for user %s (%s) updated.'),
|
||||
__('Authentication key for user %s (%s) updated.',
|
||||
$updatedUser['User']['id'],
|
||||
$updatedUser['User']['email']
|
||||
),
|
||||
|
@ -1133,7 +1132,7 @@ class User extends AppModel
|
|||
);
|
||||
} else {
|
||||
$this->AuthKey = ClassRegistry::init('AuthKey');
|
||||
$newkey = $this->AuthKey->resetauthkey($id);
|
||||
$newkey = $this->AuthKey->resetAuthKey($id, $keyId);
|
||||
}
|
||||
if ($alert) {
|
||||
$baseurl = Configure::read('MISP.external_baseurl');
|
||||
|
|
|
@ -72,9 +72,9 @@ class OidcAuthenticate extends BaseAuthenticate
|
|||
}
|
||||
|
||||
if ($user['role_id'] != $roleId) {
|
||||
$user['role_id'] = $roleId;
|
||||
$this->userModel()->updateField($user, 'role_id', $roleId);
|
||||
$this->log($mispUsername, "User role changed from {$user['role_id']} to $roleId.");
|
||||
$user['role_id'] = $roleId;
|
||||
}
|
||||
|
||||
$this->log($mispUsername, 'Logged in.');
|
||||
|
@ -182,20 +182,18 @@ class OidcAuthenticate extends BaseAuthenticate
|
|||
]);
|
||||
$roleNameToId = array_change_key_case($roleNameToId); // normalize role names to lowercase
|
||||
|
||||
$userRole = null;
|
||||
foreach ($roles as $role) {
|
||||
if (isset($roleMapper[$role])) {
|
||||
$roleId = $roleMapper[$role];
|
||||
if (!is_numeric($roleId)) {
|
||||
$roleId = mb_strtolower($roleId);
|
||||
if (isset($roleNameToId[$roleId])) {
|
||||
$roleId = $roleNameToId[$roleId];
|
||||
foreach ($roleMapper as $oidcRole => $mispRole) {
|
||||
if (in_array($oidcRole, $roles, true)) {
|
||||
if (!is_numeric($mispRole)) {
|
||||
$mispRole = mb_strtolower($mispRole);
|
||||
if (isset($roleNameToId[$mispRole])) {
|
||||
$mispRole = $roleNameToId[$mispRole];
|
||||
} else {
|
||||
$this->log($mispUsername, "MISP Role with name `$roleId` not found, skipping.");
|
||||
$this->log($mispUsername, "MISP Role with name `$mispRole` not found, skipping.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return $roleId; // first match wins
|
||||
return $mispRole; // first match wins
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', [
|
||||
'data' => [
|
||||
'title' => __('Add auth key'),
|
||||
'title' => isset($edit) ? __('Edit auth key') : __('Add auth key'),
|
||||
'description' => __('Auth keys are used for API access. A user can have more than one authkey, so if you would like to use separate keys per tool that queries MISP, add additional keys. Use the comment field to make identifying your keys easier.'),
|
||||
'fields' => [
|
||||
[
|
||||
|
@ -13,7 +13,14 @@ echo $this->element('genericElements/Form/genericForm', [
|
|||
[
|
||||
'field' => 'comment',
|
||||
'label' => __('Comment'),
|
||||
'class' => 'span6'
|
||||
'class' => 'span6',
|
||||
'rows' => 4,
|
||||
],
|
||||
[
|
||||
'field' => 'allowed_ips',
|
||||
'label' => __('Allowed IPs'),
|
||||
'class' => 'span6',
|
||||
'rows' => 4,
|
||||
],
|
||||
[
|
||||
'field' => 'expiration',
|
||||
|
|
|
@ -63,12 +63,17 @@
|
|||
'data_path' => 'AuthKey.last_used',
|
||||
'element' => 'datetime',
|
||||
'requirements' => $keyUsageEnabled,
|
||||
'empty' => __('Never'),
|
||||
],
|
||||
[
|
||||
'name' => __('Comment'),
|
||||
'sort' => 'AuthKey.comment',
|
||||
'data_path' => 'AuthKey.comment',
|
||||
],
|
||||
[
|
||||
'name' => __('Allowed IPs'),
|
||||
'data_path' => 'AuthKey.allowed_ips',
|
||||
],
|
||||
],
|
||||
'title' => empty($ajax) ? __('Authentication key Index') : false,
|
||||
'description' => empty($ajax) ? __('A list of API keys bound to a user.') : false,
|
||||
|
@ -80,7 +85,16 @@
|
|||
'AuthKey.id'
|
||||
),
|
||||
'icon' => 'eye',
|
||||
'dbclickAction' => true
|
||||
'dbclickAction' => true,
|
||||
'title' => 'View auth key',
|
||||
],
|
||||
[
|
||||
'url' => $baseurl . '/auth_keys/edit',
|
||||
'url_params_data_paths' => array(
|
||||
'AuthKey.id'
|
||||
),
|
||||
'icon' => 'edit',
|
||||
'title' => 'Edit auth key',
|
||||
],
|
||||
[
|
||||
'onclick' => sprintf(
|
||||
|
|
|
@ -15,9 +15,7 @@ if (isset($keyUsage)) {
|
|||
$uniqueIps = null;
|
||||
}
|
||||
|
||||
echo $this->element(
|
||||
'genericElements/SingleViews/single_view',
|
||||
[
|
||||
echo $this->element('genericElements/SingleViews/single_view', [
|
||||
'title' => 'Auth key view',
|
||||
'data' => $data,
|
||||
'fields' => [
|
||||
|
@ -45,6 +43,16 @@ echo $this->element(
|
|||
'key' => __('Comment'),
|
||||
'path' => 'AuthKey.comment'
|
||||
],
|
||||
[
|
||||
'key' => __('Allowed IPs'),
|
||||
'type' => 'custom',
|
||||
'function' => function (array $data) {
|
||||
if (is_array($data['AuthKey']['allowed_ips'])) {
|
||||
return implode("<br>", array_map('h', $data['AuthKey']['allowed_ips']));
|
||||
}
|
||||
return __('All');
|
||||
}
|
||||
],
|
||||
[
|
||||
'key' => __('Created'),
|
||||
'path' => 'AuthKey.created',
|
||||
|
@ -75,5 +83,4 @@ echo $this->element(
|
|||
'requirement' => isset($keyUsage),
|
||||
]
|
||||
],
|
||||
]
|
||||
);
|
||||
]);
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
}
|
||||
if (empty($data) && !empty($field['empty'])) {
|
||||
$data = $field['empty'];
|
||||
}
|
||||
} else {
|
||||
$data = $this->Time->time($data);
|
||||
}
|
||||
if (!empty($field['onClick'])) {
|
||||
$data = sprintf(
|
||||
'<span onClick="%s">%s</span>',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<?= $field['function']($data);
|
|
@ -526,4 +526,3 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" class="keyboardShortcutsConfig" value="/shortcuts/global_menu.json" />
|
||||
|
|
|
@ -127,6 +127,5 @@
|
|||
echo $this->Html->css('distribution-graph');
|
||||
echo $this->Html->script('network-distribution-graph');
|
||||
?>
|
||||
<input type="hidden" class="keyboardShortcutsConfig" value="/shortcuts/event_index.json" />
|
||||
<?php
|
||||
if (!$ajax) echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event-collection', 'menuItem' => 'index'));
|
||||
|
|
|
@ -580,4 +580,3 @@ $(function () {
|
|||
});
|
||||
});
|
||||
</script>
|
||||
<input type="hidden" value="/shortcuts/event_view.json" class="keyboardShortcutsConfig" />
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php
|
||||
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'galaxies', 'menuItem' => 'view_cluster'));
|
||||
|
||||
$extendedFromHtml = '';
|
||||
if (!empty($cluster['GalaxyCluster']['extended_from'])) {
|
||||
$element = $this->element('genericElements/IndexTable/Fields/links', array(
|
||||
|
@ -37,13 +35,21 @@
|
|||
$extendedByHtml = sprintf('<ul>%s</ul>', implode('', $extendByLinks));
|
||||
}
|
||||
|
||||
$description = $this->Markdown->cleanup($cluster['GalaxyCluster']['description']);
|
||||
|
||||
$table_data = array();
|
||||
$table_data[] = array('key' => __('Cluster ID'), 'value' => $cluster['GalaxyCluster']['id']);
|
||||
$table_data[] = array('key' => __('Name'), 'value' => $cluster['GalaxyCluster']['value']);
|
||||
$table_data[] = array('key' => __('Parent Galaxy'), 'value' => $cluster['GalaxyCluster']['Galaxy']['name'] ? $cluster['GalaxyCluster']['Galaxy']['name'] : $cluster['GalaxyCluster']['Galaxy']['type']);
|
||||
$table_data[] = array('key' => __('Description'), 'value' => $cluster['GalaxyCluster']['description']);
|
||||
$table_data[] = array('key' => __('Published'), 'boolean' => $cluster['GalaxyCluster']['published'], 'class' => (!$cluster['GalaxyCluster']['published'] ? 'background-red bold': ''));
|
||||
$table_data[] = array('key' => __('Default'), 'boolean' => $cluster['GalaxyCluster']['default'], 'class' => (!$cluster['GalaxyCluster']['published'] ? 'black': 'black'));
|
||||
$table_data[] = array('key' => __('Description'), 'value' => $description, 'value_class' => 'md');
|
||||
if (!$cluster['GalaxyCluster']['default']) {
|
||||
$table_data[] = [
|
||||
'key' => __('Published'),
|
||||
'boolean' => $cluster['GalaxyCluster']['published'],
|
||||
'class' => !$cluster['GalaxyCluster']['published'] ? 'background-red bold' : ''
|
||||
];
|
||||
}
|
||||
$table_data[] = array('key' => __('Default'), 'boolean' => $cluster['GalaxyCluster']['default'], 'class' => 'black');
|
||||
$table_data[] = array('key' => __('Version'), 'value' => $cluster['GalaxyCluster']['version']);
|
||||
$table_data[] = array('key' => __('UUID'), 'value' => $cluster['GalaxyCluster']['uuid'], 'value_class' => 'quickSelect');
|
||||
$table_data[] = array('key' => __('Collection UUID'), 'value' => $cluster['GalaxyCluster']['collection_uuid'], 'value_class' => 'quickSelect');
|
||||
|
@ -98,6 +104,12 @@
|
|||
</div>
|
||||
<div id="elements_content"></div>
|
||||
</div>
|
||||
<?= $this->element('genericElements/assetLoader', array(
|
||||
'js' => array(
|
||||
'markdown-it',
|
||||
),
|
||||
));
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$.get("<?= $baseurl ?>/galaxy_elements/index/<?php echo $cluster['GalaxyCluster']['id']; ?>", function(data) {
|
||||
|
@ -110,4 +122,10 @@ $(function () {
|
|||
$("#relations_container").html(data);
|
||||
});
|
||||
});
|
||||
|
||||
md = window.markdownit('default');
|
||||
md.disable(['image'])
|
||||
var $md = $('.md');
|
||||
$md.html(md.render($md.text()));
|
||||
</script>
|
||||
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'galaxies', 'menuItem' => 'view_cluster'));
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
App::uses('AppHelper', 'View/Helper');
|
||||
|
||||
class MarkdownHelper extends AppHelper
|
||||
{
|
||||
/**
|
||||
* Converts markdown formatted string to text
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function toText($string)
|
||||
{
|
||||
$string = $this->cleanup($string);
|
||||
// Remove markdown style links
|
||||
$string = preg_replace('/\[([^]]+)]\([^)]+\)/', '$1', $string);
|
||||
// Remove citations
|
||||
$string = preg_replace('/\(Citation: [^)]+\)/', '', $string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
public function cleanup($string)
|
||||
{
|
||||
// Remove <code> blocks and replace by ticks
|
||||
$string = preg_replace('/<code>([^<]+)<\/code>/', '`$1`', $string);
|
||||
return $string;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
function queueInterval(k, id) {
|
||||
intervalArray[k] = setInterval(function() {
|
||||
if (tabIsActive) {
|
||||
if (!document.hidden) {
|
||||
$.getJSON('<?php echo $baseurl; ?>/jobs/getGenerateCorrelationProgress/' + id, function(data) {
|
||||
var x = document.getElementById("bar" + id);
|
||||
x.style.width = data+"%";
|
||||
|
|
|
@ -102,7 +102,6 @@
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
var tabIsActive = true;
|
||||
var baseurl = '<?php echo $baseurl; ?>';
|
||||
var here = '<?php
|
||||
if (substr($this->params['action'], 0, 6) === 'admin_') {
|
||||
|
@ -111,13 +110,6 @@
|
|||
echo $baseurl . '/' . h($this->params['controller']) . '/' . h($this->params['action']);
|
||||
}
|
||||
?>';
|
||||
$(document).ready(function(){
|
||||
$(window).blur(function() {
|
||||
tabIsActive = false;
|
||||
});
|
||||
$(window).focus(function() {
|
||||
tabIsActive = true;
|
||||
});
|
||||
<?php
|
||||
if (!Configure::read('MISP.disable_auto_logout') and $me):
|
||||
?>
|
||||
|
@ -125,7 +117,6 @@
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
));
|
||||
?>
|
||||
</head>
|
||||
<body>
|
||||
<body data-controller="<?= h($this->params['controller']) ?>" data-action="<?= h($this->params['action']) ?>">
|
||||
<div id="popover_form" class="ajax_popover_form"></div>
|
||||
<div id="popover_form_large" class="ajax_popover_form ajax_popover_form_large"></div>
|
||||
<div id="popover_form_x_large" class="ajax_popover_form ajax_popover_form_x_large"></div>
|
||||
|
@ -71,7 +71,8 @@
|
|||
'bootstrap-datepicker',
|
||||
'bootstrap-colorpicker',
|
||||
'misp',
|
||||
'keyboard-shortcuts'
|
||||
'keyboard-shortcuts-definition',
|
||||
'keyboard-shortcuts',
|
||||
)
|
||||
));
|
||||
echo $this->element('footer');
|
||||
|
@ -98,7 +99,6 @@
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
var tabIsActive = true;
|
||||
var baseurl = '<?php echo $baseurl; ?>';
|
||||
var here = '<?php
|
||||
if (substr($this->params['action'], 0, 6) === 'admin_') {
|
||||
|
@ -107,12 +107,6 @@
|
|||
echo $baseurl . '/' . h($this->params['controller']) . '/' . h($this->params['action']);
|
||||
}
|
||||
?>';
|
||||
$(function(){
|
||||
$(window).blur(function() {
|
||||
tabIsActive = false;
|
||||
}).focus(function() {
|
||||
tabIsActive = true;
|
||||
});
|
||||
<?php
|
||||
if (!Configure::read('MISP.disable_auto_logout') && isset($me) && $me):
|
||||
?>
|
||||
|
@ -120,7 +114,6 @@
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -174,13 +174,11 @@ td.searchLabelCancel{
|
|||
|
||||
form .error-message {
|
||||
border-color: #b94a48;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
background-color: #f2dede;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
|
||||
/* Form */
|
||||
div.form,
|
||||
div.index,
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
function getShortcutsDefinition() {
|
||||
var shortcuts = [
|
||||
{
|
||||
"key": "l",
|
||||
"description": "Go to event list",
|
||||
"action": function () {
|
||||
document.location.href = baseurl + '/events/index';
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "e",
|
||||
"description": "Go to add event page",
|
||||
"action": function () {
|
||||
document.location.href = baseurl + '/events/add';
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var $body = $(document.body);
|
||||
if ($body.data('controller') === 'events' && $body.data('action') === 'view') {
|
||||
shortcuts.push({
|
||||
"key": "t",
|
||||
"description": "Open the tag selection modal",
|
||||
"action": function () {
|
||||
$('.addTagButton').first().click();
|
||||
}
|
||||
});
|
||||
shortcuts.push({
|
||||
"key": "f",
|
||||
"description": "Open the freetext import modal",
|
||||
"action": function () {
|
||||
$('#freetext-button').click();
|
||||
}
|
||||
});
|
||||
shortcuts.push({
|
||||
"key": "a",
|
||||
"description": "Add an attribute",
|
||||
"action": function () {
|
||||
$('#create-button').click();
|
||||
}
|
||||
});
|
||||
shortcuts.push({
|
||||
"key": "s",
|
||||
"description": "Focus the filter attribute bar",
|
||||
"action": function () {
|
||||
$('#quickFilterField').focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($body.data('controller') === 'events' && $body.data('action') === 'index') {
|
||||
shortcuts.push({
|
||||
"key": "s",
|
||||
"description": "Focus the filter events bar",
|
||||
"action": function () {
|
||||
$('#quickFilterField').focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
return shortcuts;
|
||||
}
|
|
@ -21,13 +21,7 @@ let keyboardShortcutsManager = {
|
|||
init() {
|
||||
/* Codacy comment to notify that baseurl is a read-only global variable. */
|
||||
/* global baseurl */
|
||||
let shortcutURIs = [];
|
||||
for(let keyboardShortcutElement of $('.keyboardShortcutsConfig')) {
|
||||
shortcutURIs.push(keyboardShortcutElement.value);
|
||||
this.ajaxGet(baseurl + keyboardShortcutElement.value).then((response) => {
|
||||
this.mapKeyboardShortcuts(JSON.parse(response));
|
||||
});
|
||||
}
|
||||
this.mapKeyboardShortcuts(getShortcutsDefinition());
|
||||
this.setKeyboardListener();
|
||||
},
|
||||
|
||||
|
@ -61,7 +55,7 @@ let keyboardShortcutsManager = {
|
|||
* @param {} config The shortcut JSON list: [{key: string, description: string, action: string(eval-able JS code)}]
|
||||
*/
|
||||
mapKeyboardShortcuts(config) {
|
||||
for(let shortcut of config.shortcuts) {
|
||||
for(let shortcut of config) {
|
||||
this.shortcutKeys.set(shortcut.key, shortcut);
|
||||
}
|
||||
this.addShortcutListToHTML();
|
||||
|
@ -77,38 +71,13 @@ let keyboardShortcutsManager = {
|
|||
if(this.shortcutKeys.has(keyboardEvent.key)) {
|
||||
let activeElement = document.activeElement.tagName;
|
||||
if(!this.ESCAPED_TAG_NAMES.includes(activeElement)) {
|
||||
eval(this.shortcutKeys.get(keyboardEvent.key).action);
|
||||
this.shortcutKeys.get(keyboardEvent.key).action();
|
||||
}
|
||||
} else if(this.NAVIGATION_KEYS.includes(keyboardEvent.key)) {
|
||||
window.dispatchEvent(new CustomEvent(this.EVENTS[keyboardEvent.key], {detail: keyboardEvent}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Queries the given URL with a GET request and returns a Promise
|
||||
* that resolves when the response arrives.
|
||||
* @param string url The URL to fetch.
|
||||
*/
|
||||
ajaxGet(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let req = new XMLHttpRequest();
|
||||
req.open("GET", url);
|
||||
req.onload = function() {
|
||||
if (req.status === 200) {
|
||||
resolve(req.response);
|
||||
} else {
|
||||
reject(new Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
reject(new Error("Network error"));
|
||||
};
|
||||
|
||||
req.send();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Inits the keyboard shortcut manager's main routine and the click event on the keyboard shortcut triangle at the bottom of the screen.
|
||||
|
|
|
@ -4808,7 +4808,7 @@ $(document.body).on('click', 'a[data-paginator]', function (e) {
|
|||
});
|
||||
|
||||
function queryEventLock(event_id) {
|
||||
if (tabIsActive) {
|
||||
if (!document.hidden) {
|
||||
$.ajax({
|
||||
url: baseurl + "/events/checkLocks/" + event_id,
|
||||
type: "get",
|
||||
|
@ -4826,7 +4826,7 @@ function queryEventLock(event_id) {
|
|||
}
|
||||
|
||||
function checkIfLoggedIn() {
|
||||
if (tabIsActive) {
|
||||
if (!document.hidden) {
|
||||
$.get(baseurl + "/users/checkIfLoggedIn.json")
|
||||
.fail(function (xhr) {
|
||||
if (xhr.status === 403) {
|
||||
|
@ -5298,7 +5298,8 @@ function submitGenericFormInPlace() {
|
|||
$('#genericModal').modal('hide').remove();
|
||||
$('body').append(data);
|
||||
$('#genericModal').modal();
|
||||
}
|
||||
},
|
||||
error: xhrFailCallback,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"shortcuts": [
|
||||
{
|
||||
"key": "s",
|
||||
"description": "Focus the filter events bar",
|
||||
"action": "$('#quickFilterField').focus()"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"shortcuts": [
|
||||
{
|
||||
"key": "t",
|
||||
"description": "Open the tag selection modal",
|
||||
"action": "$('.addTagButton').first().click()"
|
||||
},
|
||||
{
|
||||
"key": "f",
|
||||
"description": "Open the freetext import modal",
|
||||
"action": "$('#freetext-button').click()"
|
||||
},
|
||||
{
|
||||
"key": "a",
|
||||
"description": "Add an attribute",
|
||||
"action": "$('#create-button').click()"
|
||||
},
|
||||
{
|
||||
"key": "s",
|
||||
"description": "Focus the filter attribute bar",
|
||||
"action": "$('#quickFilterField').focus()"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"shortcuts": [
|
||||
{
|
||||
"key": "l",
|
||||
"description": "Go to event list",
|
||||
"action": "document.location.href = baseurl + '/events/index'"
|
||||
},
|
||||
{
|
||||
"key": "e",
|
||||
"description": "Go to add event page",
|
||||
"action": "document.location.href = baseurl + '/events/add'"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -483,6 +483,17 @@
|
|||
"column_type": "text",
|
||||
"column_default": null,
|
||||
"extra": ""
|
||||
},
|
||||
{
|
||||
"column_name": "allowed_ips",
|
||||
"is_nullable": "YES",
|
||||
"data_type": "text",
|
||||
"character_maximum_length": "65535",
|
||||
"numeric_precision": null,
|
||||
"collation_name": "utf8mb4_unicode_ci",
|
||||
"column_type": "text",
|
||||
"column_default": null,
|
||||
"extra": ""
|
||||
}
|
||||
],
|
||||
"bruteforces": [
|
||||
|
@ -2356,7 +2367,7 @@
|
|||
"data_type": "varchar",
|
||||
"character_maximum_length": "255",
|
||||
"numeric_precision": null,
|
||||
"collation_name": "utf8_bin",
|
||||
"collation_name": "utf8_unicode_ci",
|
||||
"column_type": "varchar(255)",
|
||||
"column_default": "",
|
||||
"extra": ""
|
||||
|
@ -7654,7 +7665,8 @@
|
|||
"event_reports": {
|
||||
"id": true,
|
||||
"uuid": true,
|
||||
"name": false
|
||||
"name": false,
|
||||
"event_id": false
|
||||
},
|
||||
"event_tags": {
|
||||
"id": true,
|
||||
|
@ -7974,5 +7986,5 @@
|
|||
"id": true
|
||||
}
|
||||
},
|
||||
"db_version": "65"
|
||||
"db_version": "67"
|
||||
}
|
||||
|
|
|
@ -562,6 +562,29 @@ class TestSecurity(unittest.TestCase):
|
|||
|
||||
self.__delete_advanced_authkey(auth_key["id"])
|
||||
|
||||
def test_advanced_authkeys_invalid_ip(self):
|
||||
with self.__setting("Security.advanced_authkeys", True):
|
||||
auth_key = self.__create_advanced_authkey(self.test_usr.id, {
|
||||
"allowed_ips": ["1.2.3.4"],
|
||||
})
|
||||
|
||||
# Try to login
|
||||
with self.assertRaises(PyMISPError):
|
||||
PyMISP(url, auth_key["authkey_raw"])
|
||||
|
||||
self.__delete_advanced_authkey(auth_key["id"])
|
||||
|
||||
def test_advanced_authkeys_allow_all(self):
|
||||
with self.__setting("Security.advanced_authkeys", True):
|
||||
auth_key = self.__create_advanced_authkey(self.test_usr.id, {
|
||||
"allowed_ips": ["0.0.0.0/0"],
|
||||
})
|
||||
|
||||
# Try to login
|
||||
PyMISP(url, auth_key["authkey_raw"])
|
||||
|
||||
self.__delete_advanced_authkey(auth_key["id"])
|
||||
|
||||
def test_authkey_keep_session(self):
|
||||
with self.__setting( "Security.authkey_keep_session", True):
|
||||
logged_in = PyMISP(url, self.test_usr.authkey)
|
||||
|
|
Loading…
Reference in New Issue