From b871c1fb553b83c1c82228e8541a623210804222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 17 Jun 2022 12:13:23 +0200 Subject: [PATCH] Added token view and generation in user views --- .../godmode/users/configure_user.php | 91 +++++++++++++------ pandora_console/include/functions_api.php | 17 ++++ pandora_console/include/functions_users.php | 58 ++++++++++++ pandora_console/include/javascript/pandora.js | 19 ++++ pandora_console/operation/users/user_edit.php | 22 ++++- 5 files changed, 175 insertions(+), 32 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 67a269bc66..19d2d7ff0c 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -1,19 +1,34 @@ <?php +/** + * User definition. + * + * @category Manage users + * @package Pandora FMS + * @subpackage Community + * @version 1.0.0 + * @license See below + * + * ______ ___ _______ _______ ________ + * | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __| + * | __/| _ | | _ || _ | _| _ | | ___| |__ | + * |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______| + * + * ============================================================================ + * Copyright (c) 2005-2022 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation for version 2. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ============================================================================ + */ -// Pandora FMS - http://pandorafms.com -// ================================================== -// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas -// Please see http://pandorafms.org for full contribution list -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation for version 2. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// Load global vars +// Begin. global $config; - +hd($_REQUEST); check_login(); require_once $config['homedir'].'/vendor/autoload.php'; @@ -47,7 +62,7 @@ if ($enterprise_include) { } -if (!is_metaconsole()) { +if (is_metaconsole() === false) { date_default_timezone_set('UTC'); include 'include/javascript/timezonepicker/includes/parser.inc'; @@ -113,7 +128,7 @@ if (! check_acl($config['id_user'], 0, 'UM')) { return; } -if (is_ajax()) { +if (is_ajax() === true) { $delete_profile = (bool) get_parameter('delete_profile'); if ($delete_profile) { $id2 = (string) get_parameter('id_user'); @@ -158,14 +173,14 @@ if (is_ajax()) { __('There was a problem deleting the user') ); - // Delete the user in all the consoles + // Delete the user in all the consoles. if (defined('METACONSOLE')) { $servers = metaconsole_get_servers(); foreach ($servers as $server) { - // Connect to the remote console + // Connect to the remote console. metaconsole_connect($server); - // Delete the user + // Delete the user. $result = delete_user($id_user); if ($result) { db_pandora_audit( @@ -174,10 +189,10 @@ if (is_ajax()) { ); } - // Restore the db connection + // Restore the db connection. metaconsole_restore_db(); - // Log to the metaconsole too + // Log to the metaconsole too. if ($result) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, @@ -208,7 +223,7 @@ if ($id) { $header_title = ' » '.__('Create user'); } -// Header +// Header. if ($meta) { user_meta_print_header(); $sec = 'advanced'; @@ -262,6 +277,7 @@ $new_user = (bool) get_parameter('new_user'); $create_user = (bool) get_parameter('create_user'); $add_profile = (bool) get_parameter('add_profile'); $update_user = (bool) get_parameter('update_user'); +$renewAPIToken = (bool) get_parameter('renewAPIToken'); $status = get_parameter('status', -1); $json_profile = get_parameter('json_profile', ''); @@ -398,8 +414,13 @@ if ($create_user) { } } + // Generate a new API Token if user has login capability. + if ($values['not_login'] === false) { + // Generate new API token. + $values['api_token'] = api_token_generate(); + } - if ($id == '') { + if (empty($id) === true) { ui_print_error_message(__('User ID cannot be empty')); $is_err = true; $user_info = $values; @@ -547,6 +568,7 @@ if ($update_user) { $values['timezone'] = (string) get_parameter('timezone'); $values['default_event_filter'] = (int) get_parameter('default_event_filter'); $values['default_custom_view'] = (int) get_parameter('default_custom_view'); + $values['api_token'] = ((bool) get_parameter('renewAPIToken') === true) ? api_token_generate() : (string) get_parameter('api_token'); if (users_is_admin() === false && (bool) $values['is_admin'] !== false) { db_pandora_audit( @@ -1264,6 +1286,21 @@ $session_time .= html_print_input_text( 'class="input_line_small"' ).'</div>'; +$apiToken = '<div class="label_select_simple">'; +$apiToken .= '<p class="edit_user_labels">'.__('API Token'); +$apiToken .= ui_print_help_tip( + __('The next string is your passphrase for use with the API instead user/password. Click over the string for renew the token.'), + true +).'</p>'; +$apiToken .= html_print_input_hidden('api_token', $user_info['api_token'], true); +$apiToken .= sprintf( + '<i class="clickable" onClick="javascript:renewAPIToken(\'%s\', \'%s\', \'%s\')">%s</i>', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_profile_form', + $user_info['api_token'] +); +$apiToken .= '</div>'; $user_groups = implode(',', array_keys((users_get_groups($id, 'AR', $display_all_group)))); @@ -1402,7 +1439,7 @@ if (!$id) { $user_id_create = $user_id; } -if (is_metaconsole()) { +if (is_metaconsole() === true) { $access_or_pagination = $meta_access; } else { $access_or_pagination = $size_pagination; @@ -1418,14 +1455,14 @@ if ($id != '' && !$is_err) { echo '<div id="user_form"> <div class="user_edit_first_row"> - <div class="edit_user_info white_box">'.$div_user_info.'</div> - <div class="edit_user_autorefresh white_box"><p class="bolder">Extra info</p>'.$email.$phone.$not_login.$local_user.$session_time.'</div> -</div> + <div class="edit_user_info white_box">'.$div_user_info.'</div> + <div class="edit_user_autorefresh white_box"><p class="bolder">Extra info</p>'.$email.$phone.$not_login.$local_user.$session_time.$apiToken.'</div> +</div> <div class="user_edit_second_row white_box"> <div class="edit_user_options">'.$language.$access_or_pagination.$skin.$home_screen.$default_event_filter.$double_authentication.'</div> <div class="edit_user_timezone">'.$timezone; -if (!is_metaconsole()) { +if (is_metaconsole() === false) { echo '<div id="timezone-picker"> <img id="timezone-image" src="'.$local_file.'" width="'.$map_width.'" height="'.$map_height.'" usemap="#timezone-map" /> <img class="timezone-pin" src="include/javascript/timezonepicker/images/pin.png" class="pdd_t_4px" /> diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index d2c4f11823..2e7feb5e4c 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -17707,3 +17707,20 @@ function api_set_enable_disable_discovery_task($id_task, $thrash2, $other) } } } + + +/** + * Check if token is correct. + * + * @param string $token Token for check. + * + * @return integer Id of user. If returns 0 there is not valid token. + */ +function api_token_check(string $token) +{ + if (empty($token) === true) { + return 0; + } else { + return (int) db_get_value('id_user', 'tusuario', 'api_token', $token); + } +} diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index f4e6e25be8..808e98d5dd 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -877,3 +877,61 @@ function users_get_users_group_by_group($id_group) return $users; } + + +/** + * Generates a cryptographically secure chain for use with API. + * + * @return string + */ +function api_token_generate() +{ + // Generate a cryptographically secure chain. + $generateToken = bin2hex(openssl_random_pseudo_bytes(16)); + // Check if token exists in DB. + $tokenExists = (bool) api_token_check($generateToken); + // If not exists, can be assigned. In other case, try again. + return ($tokenExists === false) ? $generateToken : api_token_generate(); +} + + +/** + * Returns User API Token + * + * @param integer $idUser Id of the user. + * + * @return string + */ +function users_get_API_token(int $idUser) +{ + $apiToken = db_get_value('api_token', 'tusuario', 'id_user', $idUser); + + return $apiToken; +} + + +/** + * Renews the API Token. + * + * @param integer $idUser Id of the user. + * + * @return boolean Return true if the token was renewed. + */ +function users_renew_API_token(int $idUser) +{ + $apiToken = api_token_generate(); + + if (empty($apiToken) === false) { + $result = db_process_sql_update( + 'tusuario', + ['api_token' => $apiToken], + ['id_user' => $idUser] + ); + + if ($result !== false) { + return true; + } + } + + return false; +} diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index eb8118a911..b12745afdf 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -2057,3 +2057,22 @@ $.fn.filterByText = function(textbox) { }); }); }; + +/** + * Confirm Dialog for API token renewal request. + * + * @param {string} title Title for show. + * @param {string} message Message for show. + * @param {string} form Form to attach renewAPIToken element. + */ +function renewAPIToken(title, message, form) { + confirmDialog({ + title: title, + message: message, + onAccept: function() { + $("#" + form) + .append("<input type='hidden' name='renewAPIToken' value='1'>") + .submit(); + } + }); +} diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index f76fbfff31..443e9dab82 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -80,6 +80,7 @@ if (isset($_GET['modified']) && !$view_mode) { $upd_info['id_skin'] = get_parameter('skin', $user_info['id_skin']); $upd_info['default_event_filter'] = get_parameter('event_filter', null); $upd_info['block_size'] = get_parameter('block_size', $config['block_size']); + $upd_info['api_token'] = ((bool) get_parameter('renewAPIToken') === true) ? api_token_generate() : (string) get_parameter('api_token'); $default_block_size = get_parameter('default_block_size', 0); if ($default_block_size) { @@ -111,14 +112,14 @@ if (isset($_GET['modified']) && !$view_mode) { $section = io_safe_output($upd_info['section']); - if (($section == 'Event list') || ($section == 'Group view') - || ($section == 'Alert detail') || ($section == 'Tactical view') - || ($section == 'Default') + if (($section === 'Event list') || ($section === 'Group view') + || ($section === 'Alert detail') || ($section === 'Tactical view') + || ($section === 'Default') ) { $upd_info['data_section'] = ''; - } else if ($section == 'Dashboard') { + } else if ($section === 'Dashboard') { $upd_info['data_section'] = $dashboard; - } else if ($section == 'Visual console') { + } else if ($section === 'Visual console') { $upd_info['data_section'] = $visual_console; } @@ -258,6 +259,17 @@ if (is_metaconsole() === false && is_management_allowed() === false) { $user_id = '<div class="label_select_simple"><p class="edit_user_labels">'.__('User ID').': </p>'; $user_id .= '<span>'.$id.'</span></div>'; +$user_id .= '<div class="label_select_simple"><p class="edit_user_labels">'.__('API Token').': </p>'; +$user_id .= html_print_input_hidden('api_token', $user_info['api_token'], true); +$user_id .= sprintf( + '<i class="clickable" onClick="javascript:renewAPIToken(\'%s\',\'%s\', \'%s\')">%s</i>', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_mod', + $user_info['api_token'] +); +$user_id .= '</div>'; + $full_name = ' <div class="label_select_simple">'.html_print_input_text_extended( 'fullname', $user_info['fullname'],