new: [fast api auth] added

- added a new optional functionality to temporarily store hashed API keys in redis
  - The duration of the temporary storage is controllable by a setting (defaults to 3 minutes)
  - the hashing function used is an hmac sha-512 function, with the key being stored in a generated file on the instance
  - this cuts the query times of extremely fast endpoints down drastically on heavy repeated use (such as warninglists/checkValue)
pull/9176/merge
iglocska 2024-04-23 13:20:45 +02:00
parent fa9ff6f88e
commit 4c75abbb70
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
3 changed files with 42 additions and 0 deletions

1
.gitignore vendored
View File

@ -95,6 +95,7 @@ app/Lib/EventWarning/Custom/*
/app/Config/database.php
/app/Config/core.php
/app/Config/config.php
/app/Config/hmac_key.php
/app/Console/Command/training.json
/app/Lib/cakephp
/app/webroot/gpg.asc

View File

@ -241,6 +241,7 @@ class AppController extends Controller
) {
// REST authentication
if ($this->_isRest() || $this->_isAutomation()) {
// disable CSRF for REST access
$this->Security->csrfCheck = false;
$loginByAuthKeyResult = $this->__loginByAuthKey();
@ -1143,6 +1144,23 @@ class AppController extends Controller
protected function _checkAuthUser($authkey)
{
if (Configure::read('Security.api_key_quick_lookup')) {
$redis = RedisTool::init();
if (file_exists(APP . 'Config/hmac_key.php')) {
include(APP . 'Config/hmac_key.php');
$hashed_authkey = hash_hmac('sha512', $authkey, $hmac_key);
if ($redis && $redis->exists('misp:fast_authkey_lookup:' . $hashed_authkey)) {
$user = RedisTool::deserialize($redis->get('misp:fast_authkey_lookup:' . $hashed_authkey));
if ($user) {
return $user;
}
}
} else {
App::uses('RandomTool', 'Tools');
$hmac_key = RandomTool::random_str(true, 40);
file_put_contents(APP . 'Config/hmac_key.php', sprintf('<?php%s$hmac_key = \'%s\';', PHP_EOL, $hmac_key));
}
}
if (Configure::read('Security.advanced_authkeys')) {
$user = $this->User->AuthKey->getAuthUserByAuthKey($authkey);
} else {
@ -1156,6 +1174,13 @@ class AppController extends Controller
return false;
}
$user['logged_by_authkey'] = true;
if (Configure::read('Security.api_key_quick_lookup') && !empty($hmac_key) && $redis) {
$expiration = Configure::read('Security.api_key_quick_lookup_expiration') ? Configure::read('Security.api_key_quick_lookup_expiration') : 180;
if ($redis) {
$hashed_authkey = hash_hmac('sha512', $authkey, $hmac_key);
$redis->setex('misp:fast_authkey_lookup:' . $hashed_authkey, $expiration, RedisTool::serialize($user));
}
}
return $user;
}

View File

@ -6484,6 +6484,22 @@ class Server extends AppModel
'editable' => false,
'redacted' => true
),
'api_key_quick_lookup' => [
'level' => self::SETTING_CRITICAL,
'description' => __('Allow for the temporary storing of hashed API keys in redis for a short period of time, to allow for faster authentication of consecutive API requests. This is a massive speed-up for tools unable to continue the session, querying fast endpoints of MISP in rapid succession, at the cost of storing HMAC hashed api keys in redis.'),
'value' => false,
'null' => true,
'test' => 'testBool',
'type' => 'boolean',
],
'api_key_quick_lookup_expiration' => [
'level' => self::SETTING_CRITICAL,
'description' => __('If the api key quick lookup is enabled, this setting will allow you to tune the expiration of the keys in redis. A longer expiration means fewer costly lookups during high frequency queries, at the cost of longer persistence. When an API key is revoked, they stay valid until this expiration kicks in. The value is specified in seconds.'),
'value' => 180,
'null' => true,
'test' => 'testForNumeric',
'type' => 'numeric',
],
'alert_on_suspicious_logins' => [
'level' => 1,
'description' => __('When enabled, MISP will alert users of logins from new devices / suspicious logins. Please make sure that your logs table has additional indexes (on the user_id and action fields) for this not to be a performance bottleneck for now (expected to be resolved soon).'),