From e8cf6bb38558cee67002420ee29d9f5daed51801 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Tue, 11 Sep 2018 22:36:52 -0500 Subject: [PATCH] Fix API auth issues (#9185) * Fix API auth issues Api access page now creates tokens with the correct ID. Correctly creates users for legacy user tokens. Fix Ldap comparison Laravel Util class to make code easier to access/read * More api access page fixes * fix style --- LibreNMS/Authentication/LdapAuthorizer.php | 2 +- LibreNMS/Util/Laravel.php | 116 +++++++++++++++++++++ app/Providers/LegacyUserProvider.php | 19 +++- app/Providers/TokenUserProvider.php | 13 ++- html/pages/api-access.inc.php | 39 ++++--- includes/functions.php | 69 +----------- 6 files changed, 168 insertions(+), 90 deletions(-) create mode 100644 LibreNMS/Util/Laravel.php diff --git a/LibreNMS/Authentication/LdapAuthorizer.php b/LibreNMS/Authentication/LdapAuthorizer.php index fd62063285..22631d18b9 100644 --- a/LibreNMS/Authentication/LdapAuthorizer.php +++ b/LibreNMS/Authentication/LdapAuthorizer.php @@ -194,7 +194,7 @@ class LdapAuthorizer extends AuthorizerBase public function getUser($user_id) { foreach ($this->getUserlist() as $user) { - if ($user['user_id'] === $user_id) { + if ((int)$user['user_id'] === (int)$user_id) { return $user; } } diff --git a/LibreNMS/Util/Laravel.php b/LibreNMS/Util/Laravel.php new file mode 100644 index 0000000000..da743f4914 --- /dev/null +++ b/LibreNMS/Util/Laravel.php @@ -0,0 +1,116 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Util; + +use App; +use Illuminate\Database\Events\QueryExecuted; +use LibreNMS\Config; +use LibreNMS\DB\Eloquent; +use Log; + +class Laravel +{ + public static function enableQueryDebug() + { + $db = Eloquent::DB(); + + if ($db && !$db->getEventDispatcher()->hasListeners('Illuminate\Database\Events\QueryExecuted')) { + $db->listen(function (QueryExecuted $query) { + // collect bindings and make them a little more readable + $bindings = collect($query->bindings)->map(function ($item) { + if ($item instanceof \Carbon\Carbon) { + return $item->toDateTimeString(); + } + + return $item; + })->toJson(); + + if (class_exists('Log')) { + Log::debug("SQL[%Y{$query->sql} %y$bindings%n {$query->time}ms] \n", ['color' => true]); + } else { + c_echo("SQL[%Y{$query->sql} %y$bindings%n {$query->time}ms] \n"); + } + }); + } + } + + public static function disableQueryDebug() + { + $db = Eloquent::DB(); + + if ($db) { + // remove all query executed event handlers + $db->getEventDispatcher()->flush('Illuminate\Database\Events\QueryExecuted'); + } + } + + public static function enableCliDebugOutput() + { + if (class_exists('Log')) { + $logger = Log::getMonolog(); + + // only install if not existing + $install = true; + $logfile = Config::get('log_file', base_path('logs/librenms.log')); + foreach ($logger->getHandlers() as $handler) { + if ($handler instanceof \Monolog\Handler\StreamHandler) { + if ($handler->getUrl() == 'php://stdout') { + $install = false; + } elseif ($handler->getUrl() == $logfile) { + // send to librenms log file if not a cli app + if (!App::runningInConsole()) { + set_error_handler(function ($errno, $errstr, $errfile, $errline) { + Log::error("$errno $errfile:$errline $errstr"); + }); + $handler->setLevel(\Monolog\Logger::DEBUG); + } + } + } + } + + if ($install) { + $handler = new \Monolog\Handler\StreamHandler( + 'php://stdout', + \Monolog\Logger::DEBUG + ); + + $handler->setFormatter(new CliColorFormatter()); + + $logger->pushHandler($handler); + } + } + } + + public static function disableCliDebugOutput() + { + if (class_exists('Log')) { + $handlers = Log::getMonolog()->getHandlers(); + if (isset($handlers[0]) && $handlers[0]->getUrl() == 'php://stdout') { + Log::getMonolog()->popHandler(); + } + } + } +} diff --git a/app/Providers/LegacyUserProvider.php b/app/Providers/LegacyUserProvider.php index 239325e9ef..8192a82dd7 100644 --- a/app/Providers/LegacyUserProvider.php +++ b/app/Providers/LegacyUserProvider.php @@ -34,6 +34,7 @@ use LibreNMS\Authentication\LegacyAuth; use LibreNMS\Exceptions\AuthenticationException; use Request; use Session; +use Toastr; class LegacyUserProvider implements UserProvider { @@ -50,6 +51,21 @@ class LegacyUserProvider implements UserProvider return $this->fetchUserByName($username); } + /** + * Retrieve a user by their legacy auth specific identifier. + * + * @param int $identifier + * @return \Illuminate\Contracts\Auth\Authenticatable|null + */ + public function retrieveByLegacyId($identifier) + { + error_reporting(0); + $legacy_user = LegacyAuth::get()->getUser($identifier); + error_reporting(-1); + + return $this->fetchUserByName($legacy_user['username']); + } + /** * Retrieve a user by their unique identifier and "remember me" token. * @@ -181,10 +197,11 @@ class LegacyUserProvider implements UserProvider error_reporting(-1); } catch (AuthenticationException $ae) { - // + Toastr::error($ae->getMessage()); } if (empty($new_user)) { + Toastr::info("No user ($auth_id) [$username]"); return null; } } diff --git a/app/Providers/TokenUserProvider.php b/app/Providers/TokenUserProvider.php index 141f60f46f..7a5c57595e 100644 --- a/app/Providers/TokenUserProvider.php +++ b/app/Providers/TokenUserProvider.php @@ -72,10 +72,17 @@ class TokenUserProvider extends LegacyUserProvider implements UserProvider return $user; } - // missing user for existing token, create it - $user_id = ApiToken::idFromToken($credentials['api_token']); + // missing user for existing token, create it assuming legacy auth_id + $api_token = ApiToken::where('token_hash', $credentials['api_token'])->first(); + $user = $this->retrieveByLegacyId($api_token->user_id); - return $this->retrieveById($user_id); + // update token user_id + if ($user) { + $api_token->user_id = $user->user_id; + $api_token->save(); + } + + return $user; } /** diff --git a/html/pages/api-access.inc.php b/html/pages/api-access.inc.php index 197ce62aec..cfd50e064e 100644 --- a/html/pages/api-access.inc.php +++ b/html/pages/api-access.inc.php @@ -12,6 +12,8 @@ * the source code distribution for details. */ +use App\Models\ApiToken; +use App\Models\User; use LibreNMS\Authentication\LegacyAuth; if (LegacyAuth::user()->hasGlobalAdmin()) { @@ -56,8 +58,8 @@ if (LegacyAuth::user()->hasGlobalAdmin()) {
- + + '.$user_details->username.' + '.$user_details->auth_type.' + '.$api->token_hash.' + + '.$api->description.' + + '; } diff --git a/includes/functions.php b/includes/functions.php index 69e456e5fc..689a7a3032 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -37,8 +37,6 @@ function set_debug($state = true, $silence = false) $debug = $state; // set to global - $db = \LibreNMS\DB\Eloquent::DB(); - restore_error_handler(); // disable Laravel error handler if (isset($debug) && $debug) { @@ -47,75 +45,16 @@ function set_debug($state = true, $silence = false) ini_set('log_errors', 0); error_reporting(E_ALL & ~E_NOTICE); - if (class_exists('Log')) { - $logger = Log::getMonolog(); - - // only install if not existing - $install = true; - $logfile = Config::get('log_file', base_path('logs/librenms.log')); - foreach ($logger->getHandlers() as $handler) { - if ($handler instanceof \Monolog\Handler\StreamHandler) { - if ($handler->getUrl() == 'php://stdout') { - $install = false; - } elseif ($handler->getUrl() == $logfile) { - // send to librenms log file if not a cli app - if (!App::runningInConsole()) { - set_error_handler(function ($errno, $errstr, $errfile, $errline) { - Log::error("$errno $errfile:$errline $errstr"); - }); - $handler->setLevel(\Monolog\Logger::DEBUG); - } - } - } - } - - if ($install) { - $handler = new \Monolog\Handler\StreamHandler( - 'php://stdout', - \Monolog\Logger::DEBUG - ); - - $handler->setFormatter(new LibreNMS\Util\CliColorFormatter()); - - $logger->pushHandler($handler); - } - } - - if ($db && !$db->getEventDispatcher()->hasListeners('Illuminate\Database\Events\QueryExecuted')) { - $db->listen(function (QueryExecuted $query) { - // collect bindings and make them a little more readable - $bindings = collect($query->bindings)->map(function ($item) { - if ($item instanceof \Carbon\Carbon) { - return $item->toDateTimeString(); - } - - return $item; - })->toJson(); - - if (class_exists('Log')) { - Log::debug("SQL[%Y{$query->sql} %y$bindings%n {$query->time}ms] \n", ['color' => true]); - } else { - c_echo("SQL[%Y{$query->sql} %y$bindings%n {$query->time}ms] \n"); - } - }); - } + \LibreNMS\Util\Laravel::enableCliDebugOutput(); + \LibreNMS\Util\Laravel::enableQueryDebug(); } else { ini_set('display_errors', 0); ini_set('display_startup_errors', 0); ini_set('log_errors', 1); error_reporting($silence ? 0 : E_ERROR); - if (class_exists('Log')) { - $handlers = Log::getMonolog()->getHandlers(); - if (isset($handlers[0]) && $handlers[0]->getUrl() == 'php://stdout') { - Log::getMonolog()->popHandler(); - } - } - - if ($db) { - // remove all query executed event handlers - $db->getEventDispatcher()->flush('Illuminate\Database\Events\QueryExecuted'); - } + \LibreNMS\Util\Laravel::enableCliDebugOutput(); + \LibreNMS\Util\Laravel::disableQueryDebug(); } return $debug;