chg: [CLI] Optimise cake user authkey_valid

pull/9498/head
Jakub Onderka 2024-01-15 19:02:41 +01:00
parent b4602e74f1
commit b5f3c2fae5
3 changed files with 51 additions and 16 deletions

View File

@ -35,6 +35,11 @@ class UserShell extends AppShell
]); ]);
$parser->addSubcommand('authkey_valid', [ $parser->addSubcommand('authkey_valid', [
'help' => __('Check if given authkey by STDIN is valid.'), 'help' => __('Check if given authkey by STDIN is valid.'),
'parser' => [
'options' => [
'disableStdLog' => ['help' => __('Do not show logs in STDOUT or STDERR.'), 'boolean' => true],
],
],
]); ]);
$parser->addSubcommand('block', [ $parser->addSubcommand('block', [
'help' => __('Immediately block user.'), 'help' => __('Immediately block user.'),
@ -230,28 +235,37 @@ class UserShell extends AppShell
*/ */
public function authkey_valid() public function authkey_valid()
{ {
if ($this->params['disableStdLog']) {
$this->_useLogger(false);
}
$cache = []; $cache = [];
$randomKey = random_bytes(16); $randomKey = random_bytes(16);
do { $advancedAuthKeysEnabled = (bool)Configure::read('Security.advanced_authkeys');
while (true) {
$authkey = fgets(STDIN); // read line from STDIN $authkey = fgets(STDIN); // read line from STDIN
$authkey = trim($authkey); $authkey = trim($authkey);
if (strlen($authkey) !== 40) { if (strlen($authkey) !== 40) {
fwrite(STDOUT, "0\n"); // authkey is not in valid format echo "0\n"; // authkey is not in valid format
$this->log("Authkey in incorrect format provided.", LOG_WARNING); $this->log("Authkey in incorrect format provided.", LOG_WARNING);
continue; continue;
} }
$time = time();
// Generate hash from authkey to not store raw authkey in memory // Generate hash from authkey to not store raw authkey in memory
$keyHash = sha1($authkey . $randomKey, true); $keyHash = sha1($authkey . $randomKey, true);
// If authkey is in cache and is fresh, use info from cache
$time = time();
if (isset($cache[$keyHash]) && $cache[$keyHash][1] > $time) { if (isset($cache[$keyHash]) && $cache[$keyHash][1] > $time) {
fwrite(STDOUT, $cache[$keyHash][0] ? "1\n" : "0\n"); echo $cache[$keyHash][0] ? "1\n" : "0\n";
continue; continue;
} }
$user = false; $user = false;
for ($i = 0; $i < 5; $i++) { for ($i = 0; $i < 5; $i++) {
try { try {
if (Configure::read('Security.advanced_authkeys')) { if ($advancedAuthKeysEnabled) {
$user = $this->User->AuthKey->getAuthUserByAuthKey($authkey); $user = $this->User->AuthKey->getAuthUserByAuthKey($authkey);
} else { } else {
$user = $this->User->getAuthUserByAuthkey($authkey); $user = $this->User->getAuthUserByAuthkey($authkey);
@ -269,18 +283,34 @@ class UserShell extends AppShell
} }
} }
$user = (bool)$user;
if (!$user) { if (!$user) {
$start = substr($authkey, 0, 4); $valid = null;
$end = substr($authkey, -4); } else if ($user['disabled']) {
$authKeyToStore = $start . str_repeat('*', 32) . $end; $valid = false;
$this->log("Not valid authkey $authKeyToStore provided.", LOG_WARNING); } else {
$valid = true;
} }
// Cache results for 5 seconds echo $valid ? "1\n" : "0\n";
$cache[$keyHash] = [$user, $time + 5];
fwrite(STDOUT, $user ? "1\n" : "0\n"); if ($valid) {
} while (true); // Cache results for 60 seconds if key is valid
$cache[$keyHash] = [true, $time + 60];
} else {
// Cache results for 5 seconds if key is invalid
$cache[$keyHash] = [false, $time + 5];
$start = substr($authkey, 0, 4);
$end = substr($authkey, -4);
$authKeyForLog = $start . str_repeat('*', 32) . $end;
if ($valid === false) {
$this->log("Authkey $authKeyForLog belongs to user {$user['id']} that is disabled.", LOG_WARNING);
} else {
$this->log("Authkey $authKeyForLog is invalid or expired.", LOG_WARNING);
}
}
}
} }
public function block() public function block()

View File

@ -207,7 +207,7 @@ class AuthKey extends AppModel
*/ */
private function updateUniqueIp(array $authkey) private function updateUniqueIp(array $authkey)
{ {
if (Configure::read("MISP.disable_seen_ips_authkeys")) { if (PHP_SAPI === 'cli' || Configure::read("MISP.disable_seen_ips_authkeys")) {
return; return;
} }

View File

@ -740,7 +740,7 @@ class User extends AppModel
], ],
]); ]);
if (empty($user)) { if (empty($user)) {
return $user; return null;
} }
return $this->rearrangeToAuthForm($user); return $this->rearrangeToAuthForm($user);
} }
@ -937,6 +937,11 @@ class User extends AppModel
*/ */
public function describeAuthFields() public function describeAuthFields()
{ {
static $fields; // generate array just once
if ($fields) {
return $fields;
}
$fields = $this->schema(); $fields = $this->schema();
// Do not include keys, because they are big and usually not necessary // Do not include keys, because they are big and usually not necessary
unset($fields['gpgkey']); unset($fields['gpgkey']);