From 6682bad19f579b82a0ce68cad7efe531dda265e7 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 21 Jun 2019 12:03:25 +0200 Subject: [PATCH 01/12] first steps credential store --- pandora_console/extras/mr/28.sql | 11 + .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 13 + .../godmode/groups/credential_store.php | 184 +++++++++++++ pandora_console/godmode/groups/group_list.php | 258 +++++++++++------- .../include/functions_credential_store.php | 97 +++++++ pandora_console/include/functions_ui.php | 10 +- pandora_console/pandoradb.sql | 14 + 7 files changed, 483 insertions(+), 104 deletions(-) create mode 100644 pandora_console/godmode/groups/credential_store.php create mode 100644 pandora_console/include/functions_credential_store.php diff --git a/pandora_console/extras/mr/28.sql b/pandora_console/extras/mr/28.sql index bab07bead8..d0acd0d99f 100644 --- a/pandora_console/extras/mr/28.sql +++ b/pandora_console/extras/mr/28.sql @@ -42,4 +42,15 @@ ALTER TABLE `tusuario` ADD COLUMN `ehorus_user_level_user` VARCHAR(60); ALTER TABLE `tusuario` ADD COLUMN `ehorus_user_level_pass` VARCHAR(45); ALTER TABLE `tusuario` ADD COLUMN `ehorus_user_level_enabled` TINYINT(1) DEFAULT '1'; +CREATE TABLE IF NOT EXISTS `tcredential_store` ( + `identifier` varchar(100) NOT NULL, + `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, + `product` text, + `username` text, + `password` text, + `extra_1` text, + `extra_2` text, + PRIMARY KEY (`identifier`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 2c9ff7e7de..ad2bd904b9 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -2192,3 +2192,16 @@ CREATE TABLE `tvisual_console_elements_cache` ( ON UPDATE CASCADE ) engine=InnoDB DEFAULT CHARSET=utf8; +-- --------------------------------------------------------------------- +-- Table `tcredential_store` +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tcredential_store` ( + `identifier` varchar(100) NOT NULL, + `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, + `product` text, + `username` text, + `password` text, + `extra_1` text, + `extra_2` text, + PRIMARY KEY (`identifier`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/pandora_console/godmode/groups/credential_store.php b/pandora_console/godmode/groups/credential_store.php new file mode 100644 index 0000000000..f51533bcdc --- /dev/null +++ b/pandora_console/godmode/groups/credential_store.php @@ -0,0 +1,184 @@ + 'noaccess']; + } + + include 'general/noaccess.php'; + return; +} + +// Required files. +ui_require_css_file('credential_store'); +require_once $config['homedir'].'/include/functions_credential_store.php'; + +if (is_ajax()) { + $draw = get_parameter('draw', 0); + $filter = get_parameter('filter', []); + + if ($draw) { + // Datatables offset, limit and order. + $start = get_parameter('start', 0); + $length = get_parameter('length', $config['block_size']); + $order = get_datatable_order(true); + try { + ob_start(); + + $fields = [ + 'cs.*', + 'tg.nombre as `group`', + ]; + + // Retrieve data. + $data = credentials_get_all( + // Fields. + $fields, + // Filter. + $filter, + // Offset. + $start, + // Limit. + $length, + // Order. + $order['direction'], + // Sort field. + $order['field'] + ); + + // Retrieve counter. + $count = credentials_get_all( + 'count', + $filter + ); + + if ($data) { + $data = array_reduce( + $data, + function ($carry, $item) { + // Transforms array of arrays $data into an array + // of objects, making a post-process of certain fields. + $tmp = (object) $item; + $tmp->username = io_safe_output($tmp->username); + $carry[] = $tmp; + return $carry; + } + ); + } + + // Datatables format: RecordsTotal && recordsfiltered. + echo json_encode( + [ + 'data' => $data, + 'recordsTotal' => $count, + 'recordsFiltered' => $count, + ] + ); + // Capture output. + $response = ob_get_clean(); + } catch (Exception $e) { + return json_encode(['error' => $e->getMessage()]); + } + + // If not valid, show error with issue. + json_decode($response); + if (json_last_error() == JSON_ERROR_NONE) { + // If valid dump. + echo $response; + } else { + echo json_encode( + ['error' => $response] + ); + } + + + return; + } + + return; +} + + + +// Load interface. +try { + $columns = [ + 'group', + 'identifier', + 'product', + 'username', + 'options', + ]; + + $column_names = [ + __('Group'), + __('Identifier'), + __('Product'), + __('User'), + [ + 'text' => __('Options'), + 'class' => 'action_buttons', + ], + ]; + + // Load datatables user interface. + ui_print_datatable( + [ + 'class' => 'info_table events', + 'style' => 'width: 100%', + 'columns' => $columns, + 'column_names' => $column_names, + 'ajax_url' => 'godmode/groups/credential_store', + 'ajax_postprocess' => 'process_datatables_item(item)', + 'no_sortable_columns' => [-1], + ] + ); +} catch (Exception $e) { + echo $e->getMessage(); +} + +?> + + diff --git a/pandora_console/godmode/groups/group_list.php b/pandora_console/godmode/groups/group_list.php index ee61cdaf79..8cb3c106c1 100644 --- a/pandora_console/godmode/groups/group_list.php +++ b/pandora_console/godmode/groups/group_list.php @@ -1,20 +1,36 @@ $v) { $agents[$keys_prefix.$k] = $v; unset($agents[$k]); if ($all_agents) { - // Unserialize to get the status + // Unserialize to get the status. if ($serialized && is_metaconsole()) { $agent_info = explode($serialized_separator, $k); $agent_disabled = db_get_value_filter( @@ -174,7 +193,8 @@ if (is_ajax()) { ['id_agente' => $agent_info[1]] ); } else if (!$serialized && is_metaconsole()) { - // Cannot retrieve the disabled status. Mark all as not disabled + // Cannot retrieve the disabled status. + // Mark all as not disabled. $agent_disabled = 0; } else { $agent_disabled = db_get_value_filter( @@ -226,11 +246,13 @@ if (! check_acl($config['id_user'], 0, 'PM')) { } $sec = defined('METACONSOLE') ? 'advanced' : 'gagente'; -$url_tree = "index.php?sec=$sec&sec2=godmode/groups/group_list&tab=tree"; -$url_groups = "index.php?sec=$sec&sec2=godmode/groups/group_list&tab=groups"; +$url_credbox = 'index.php?sec='.$sec.'&sec2=godmode/groups/group_list&tab=credbox'; +$url_tree = 'index.php?sec='.$sec.'&sec2=godmode/groups/group_list&tab=tree'; +$url_groups = 'index.php?sec='.$sec.'&sec2=godmode/groups/group_list&tab=groups'; + $buttons['tree'] = [ 'active' => false, - 'text' => "".html_print_image( + 'text' => ''.html_print_image( 'images/gm_massive_operations.png', true, [ @@ -241,7 +263,7 @@ $buttons['tree'] = [ $buttons['groups'] = [ 'active' => false, - 'text' => "".html_print_image( + 'text' => ''.html_print_image( 'images/group.png', true, [ @@ -250,21 +272,38 @@ $buttons['groups'] = [ ).'', ]; +$buttons['credbox'] = [ + 'active' => false, + 'text' => ''.html_print_image( + 'images/key.png', + true, + [ + 'title' => __('Credential Store'), + ] + ).'', +]; + $tab = (string) get_parameter('tab', 'groups'); -// Marks correct tab +$title = __('Groups defined in %s', get_product_name()); +// Marks correct tab. switch ($tab) { case 'tree': $buttons['tree']['active'] = true; break; + case 'credbox': + $buttons['credbox']['active'] = true; + $title = __('Credential store'); + break; + case 'groups': default: $buttons['groups']['active'] = true; break; } -// Header +// Header. if (defined('METACONSOLE')) { agents_meta_print_header(); echo '
'; @@ -272,7 +311,7 @@ if (defined('METACONSOLE')) { echo '
'; } else { ui_print_page_header( - __('Groups defined in %s', get_product_name()), + $title, 'images/group.png', false, 'group_list_tab', @@ -281,12 +320,19 @@ if (defined('METACONSOLE')) { ); } +// Load credential store view before parse list-tree forms. +if ($tab == 'credbox') { + include_once __DIR__.'/credential_store.php'; + // Stop script. + return; +} + $create_group = (bool) get_parameter('create_group'); $update_group = (bool) get_parameter('update_group'); $delete_group = (bool) get_parameter('delete_group'); $pure = get_parameter('pure', 0); -// Create group +// Create group. if (($create_group) && (check_acl($config['id_user'], 0, 'PM'))) { $name = (string) get_parameter('name'); $icon = (string) get_parameter('icon'); @@ -301,7 +347,7 @@ if (($create_group) && (check_acl($config['id_user'], 0, 'PM'))) { $check = db_get_value('nombre', 'tgrupo', 'nombre', $name); $propagate = (bool) get_parameter('propagate'); - // Check if name field is empty + // Check if name field is empty. if ($name != '') { if (!$check) { $values = [ @@ -328,12 +374,11 @@ if (($create_group) && (check_acl($config['id_user'], 0, 'PM'))) { ui_print_error_message(__('Each group must have a different name')); } } else { - // $result = false; ui_print_error_message(__('Group must have a name')); } } -// Update group +// Update group. if ($update_group) { $id_group = (int) get_parameter('id_group'); $name = (string) get_parameter('name'); @@ -349,49 +394,35 @@ if ($update_group) { $contact = (string) get_parameter('contact'); $other = (string) get_parameter('other'); - // Check if name field is empty + // Check if name field is empty. if ($name != '') { - switch ($config['dbtype']) { - case 'mysql': - $sql = sprintf( - 'UPDATE tgrupo SET nombre = "%s", - icon = "%s", disabled = %d, parent = %d, custom_id = "%s", propagate = %d, id_skin = %d, description = "%s", contact = "%s", other = "%s", password = "%s" - WHERE id_grupo = %d', - $name, - empty($icon) ? '' : substr($icon, 0, -4), - !$alerts_enabled, - $id_parent, - $custom_id, - $propagate, - $skin, - $description, - $contact, - $other, - $group_pass, - $id_group - ); - break; - - case 'postgresql': - case 'oracle': - $sql = sprintf( - 'UPDATE tgrupo SET nombre = \'%s\', - icon = \'%s\', disabled = %d, parent = %d, custom_id = \'%s\', propagate = %d, id_skin = %d, description = \'%s\', contact = \'%s\', other = \'%s\' - WHERE id_grupo = %d', - $name, - substr($icon, 0, -4), - !$alerts_enabled, - $id_parent, - $custom_id, - $propagate, - $skin, - $description, - $contact, - $other, - $id_group - ); - break; - } + $sql = sprintf( + 'UPDATE tgrupo + SET nombre = "%s", + icon = "%s", + disabled = %d, + parent = %d, + custom_id = "%s", + propagate = %d, + id_skin = %d, + description = "%s", + contact = "%s", + other = "%s", + password = "%s" + WHERE id_grupo = %d', + $name, + empty($icon) ? '' : substr($icon, 0, -4), + !$alerts_enabled, + $id_parent, + $custom_id, + $propagate, + $skin, + $description, + $contact, + $other, + $group_pass, + $id_group + ); $result = db_process_sql($sql); } else { @@ -405,7 +436,7 @@ if ($update_group) { } } -// Delete group +// Delete group. if (($delete_group) && (check_acl($config['id_user'], 0, 'PM'))) { $id_group = (int) get_parameter('id_group'); @@ -445,7 +476,14 @@ if (($delete_group) && (check_acl($config['id_user'], 0, 'PM'))) { } } + +// Credential store is loaded previously in this document to avoid +// process group tree - list forms. if ($tab == 'tree') { + /* + * Group tree view. + */ + echo html_print_image( 'images/spinner.gif', true, @@ -456,6 +494,10 @@ if ($tab == 'tree') { ); echo "
"; } else { + /* + * Group list view. + */ + $acl = ''; $search_name = ''; $offset = (int) get_parameter('offset', 0); @@ -463,17 +505,22 @@ if ($tab == 'tree') { $block_size = $config['block_size']; if (!empty($search)) { - $search_name = "AND t.nombre LIKE '%$search%'"; + $search_name = 'AND t.nombre LIKE "%'.$search.'%"'; } if (!users_can_manage_group_all('AR')) { $user_groups_acl = users_get_groups(false, 'AR'); $groups_acl = implode(',', $user_groups_ACL); if (empty($groups_acl)) { - return ui_print_info_message(['no_close' => true, 'message' => __('There are no defined groups') ]); + return ui_print_info_message( + [ + 'no_close' => true, + 'message' => __('There are no defined groups'), + ] + ); } - $acl = "AND t.id_grupo IN ($groups_acl)"; + $acl = 'AND t.id_grupo IN ('.$groups_acl.')'; } $form = "
"; @@ -488,29 +535,37 @@ if ($tab == 'tree') { echo $form; - $groups_sql = "SELECT t.*, + $groups_sql = sprintf( + 'SELECT t.*, p.nombre AS parent_name, IF(t.parent=p.id_grupo, 1, 0) AS has_child - FROM tgrupo t - LEFT JOIN tgrupo p + FROM tgrupo t + LEFT JOIN tgrupo p ON t.parent=p.id_grupo - WHERE 1=1 - $acl - $search_name + WHERE 1=1 + %s + %s ORDER BY nombre - LIMIT $offset, $block_size - "; + LIMIT %d, %d', + $acl, + $search_name, + $offset, + $block_size + ); $groups = db_get_all_rows_sql($groups_sql); if (!empty($groups)) { - // Count all groups for pagination only saw user and filters - $groups_sql_count = "SELECT count(*) + // Count all groups for pagination only saw user and filters. + $groups_sql_count = sprintf( + 'SELECT count(*) FROM tgrupo t WHERE 1=1 - $acl - $search_name - "; + %s + %s', + $acl, + $search_name + ); $groups_count = db_get_value_sql($groups_sql_count); $table = new StdClass(); @@ -545,7 +600,7 @@ if ($tab == 'tree') { $url = 'index.php?sec=gagente&sec2=godmode/groups/configure_group&id_group='.$group['id_grupo']; $url_delete = 'index.php?sec=gagente&sec2=godmode/groups/group_list&delete_group=1&id_group='.$group['id_grupo']; $table->data[$key][0] = $group['id_grupo']; - $table->data[$key][1] = "".$group['nombre'].''; + $table->data[$key][1] = ''.$group['nombre'].''; if ($group['icon'] != '') { $table->data[$key][2] = html_print_image( 'images/groups_small/'.$group['icon'].'.png', @@ -553,22 +608,25 @@ if ($tab == 'tree') { [ 'style' => '', 'class' => 'bot', - 'alt' => $group['nombre'], + 'alt' => $group['nombre'], 'title' => $group['nombre'], - false, false, false, true - ] + ], + false, + false, + false, + true ); } else { $table->data[$key][2] = ''; } - // reporting_get_group_stats - $table->data[$key][3] = $group['disabled'] ? __('Disabled') : __('Enabled'); + // Reporting_get_group_stats. + $table->data[$key][3] = ($group['disabled']) ? __('Disabled') : __('Enabled'); $table->data[$key][4] = $group['parent_name']; $table->data[$key][5] = $group['description']; $table->cellclass[$key][6] = 'action_buttons'; - $table->data[$key][6] = "".html_print_image( + $table->data[$key][6] = ''.html_print_image( 'images/config.png', true, [ diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php new file mode 100644 index 0000000000..acf15bb6be --- /dev/null +++ b/pandora_console/include/functions_credential_store.php @@ -0,0 +1,97 @@ + $v) { - $js .= $k.':'.json_encode($v).",\n"; + if (is_array($parameters['ajax_data'])) { + foreach ($parameters['ajax_data'] as $k => $v) { + $js .= $k.':'.json_encode($v).",\n"; + } } $js .= 'page: "'.$parameters['ajax_url'].'" diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index b30295bba6..bdd1bca841 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -693,6 +693,20 @@ CREATE TABLE IF NOT EXISTS `tgrupo` ( KEY `parent_index` (`parent`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- --------------------------------------------------------------------- +-- Table `tcredential_store` +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tcredential_store` ( + `identifier` varchar(100) NOT NULL, + `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, + `product` text, + `username` text, + `password` text, + `extra_1` text, + `extra_2` text, + PRIMARY KEY (`identifier`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- --------------------------------------------------------------------- -- Table `tincidencia` -- --------------------------------------------------------------------- From e9ef9b64a379e3d181e7cbeb18013c01995a24cf Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 21 Jun 2019 19:34:47 +0200 Subject: [PATCH 02/12] credential_store --- .../godmode/groups/credential_store.php | 387 +++++++++++++++++- .../include/functions_credential_store.php | 238 ++++++++++- pandora_console/include/functions_html.php | 286 +++++++++++++ pandora_console/include/functions_ui.php | 26 +- .../include/styles/credential_store.css | 12 + pandora_console/include/styles/events.css | 6 +- pandora_console/include/styles/pandora.css | 7 + pandora_console/include/styles/tables.css | 28 ++ 8 files changed, 968 insertions(+), 22 deletions(-) create mode 100644 pandora_console/include/styles/credential_store.css diff --git a/pandora_console/godmode/groups/credential_store.php b/pandora_console/godmode/groups/credential_store.php index f51533bcdc..bd08fd4df2 100644 --- a/pandora_console/godmode/groups/credential_store.php +++ b/pandora_console/godmode/groups/credential_store.php @@ -50,9 +50,105 @@ if (! check_acl($config['id_user'], 0, 'PM')) { ui_require_css_file('credential_store'); require_once $config['homedir'].'/include/functions_credential_store.php'; + if (is_ajax()) { $draw = get_parameter('draw', 0); $filter = get_parameter('filter', []); + $get_key = get_parameter('get_key', 0); + $new_key = get_parameter('new_key', 0); + $update_key = get_parameter('update_key', 0); + $delete_key = get_parameter('delete_key', 0); + + + if ($delete_key) { + $identifier = get_parameter('identifier', null); + + if (empty($identifier)) { + ajax_msg('error', __('identifier cannot be empty')); + } + + if (db_process_sql_delete( + 'tcredential_store', + ['identifier' => $identifier] + ) === false + ) { + ajax_msg('error', $config['dbconnection']->error, true); + } else { + ajax_msg('result', $identifier, true); + } + } + + if ($update_key) { + $data = get_parameter('values', null); + + if ($data === null || !is_array($data)) { + echo json_encode(['error' => __('Invalid parameters, please retry')]); + exit; + } + + $values = []; + foreach ($data as $key => $value) { + if ($key == 'identifier') { + $identifier = base64_decode($value); + } else { + $values[$key] = base64_decode($value); + } + } + + if (empty($identifier)) { + ajax_msg('error', __('identifier cannot be empty')); + } + + if (db_process_sql_update( + 'tcredential_store', + $values, + ['identifier' => $identifier] + ) === false + ) { + ajax_msg('error', $config['dbconnection']->error); + } else { + ajax_msg('result', $identifier); + } + + exit; + } + + if ($new_key) { + $data = get_parameter('values', null); + + if ($data === null || !is_array($data)) { + echo json_encode(['error' => __('Invalid parameters, please retry')]); + exit; + } + + $values = []; + foreach ($data as $key => $value) { + $values[$key] = base64_decode($value); + } + + $identifier = $values['identifier']; + + if (empty($identifier)) { + ajax_msg('error', __('identifier cannot be empty')); + } + + if (db_process_sql_insert('tcredential_store', $values) === false) { + ajax_msg('error', $config['dbconnection']->error); + } else { + ajax_msg('result', $identifier); + } + + exit; + } + + if ($get_key) { + $identifier = get_parameter('identifier', null); + + $key = get_key($identifier); + echo print_inputs($key); + + exit; + } if ($draw) { // Datatables offset, limit and order. @@ -97,6 +193,13 @@ if (is_ajax()) { // of objects, making a post-process of certain fields. $tmp = (object) $item; $tmp->username = io_safe_output($tmp->username); + + if (empty($tmp->group)) { + $tmp->group = __('All'); + } else { + $tmp->group = io_safe_output($tmp->group); + } + $carry[] = $tmp; return $carry; } @@ -129,15 +232,13 @@ if (is_ajax()) { } - return; + exit; } - return; + exit; } - - -// Load interface. +// Datatables list. try { $columns = [ 'group', @@ -158,27 +259,299 @@ try { ], ]; + $table_id = 'keystore'; // Load datatables user interface. ui_print_datatable( [ - 'class' => 'info_table events', + 'id' => $table_id, + 'class' => 'info_table', 'style' => 'width: 100%', 'columns' => $columns, 'column_names' => $column_names, 'ajax_url' => 'godmode/groups/credential_store', 'ajax_postprocess' => 'process_datatables_item(item)', 'no_sortable_columns' => [-1], + 'order' => [ + 'field' => 'identifier', + 'direction' => 'asc', + ], + 'search_button_class' => 'sub filter float-right', + 'form' => [ + 'inputs' => [ + [ + 'label' => __('Group'), + 'type' => 'select', + 'id' => 'filter_id_group', + 'name' => 'filter_id_group', + 'options' => users_get_groups_for_select( + $config['id_user'], + 'AR', + true, + true, + false + ), + ], + [ + 'label' => __('Free search'), + 'type' => 'text', + 'class' => 'mw250px', + 'id' => 'free_search', + 'name' => 'free_search', + ], + ], + ], ] ); } catch (Exception $e) { echo $e->getMessage(); } +// Auxiliar div. +$new = ''; +$details = ''; +$aux = ''; + + +echo $new.$details.$aux; + +// Create button. +echo '
'; +html_print_submit_button( + __('Add key'), + 'create', + false, + 'class="sub next"' +); +echo '
'; + ?> diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php index acf15bb6be..09d1ce100c 100644 --- a/pandora_console/include/functions_credential_store.php +++ b/pandora_console/include/functions_credential_store.php @@ -51,7 +51,7 @@ function credentials_get_all( $sort_field=null ) { $sql_filters = []; - $group_by = ''; + $order_by = ''; $pagination = ''; global $config; @@ -72,6 +72,80 @@ function credentials_get_all( throw new Exception('[credential_get_all] Fields must be an array or "count".'); } + if (isset($order)) { + $dir = 'asc'; + if ($order == 'desc') { + $dir = 'desc'; + }; + + if (in_array( + $sort_field, + [ + 'group', + 'identifier', + 'product', + 'username', + 'options', + ] + ) + ) { + $order_by = sprintf( + 'ORDER BY `%s` %s', + $sort_field, + $dir + ); + } + } + + if (isset($limit) && $limit > 0 + && isset($offset) && $offset >= 0 + ) { + $pagination = sprintf( + ' LIMIT %d OFFSET %d ', + $limit, + $offset + ); + } + + if (isset($filter['free_search']) && !empty($filter['free_search'])) { + $sql_filters[] = vsprintf( + ' AND (lower(cs.username) like lower("%%%s%%") + OR cs.identifier like "%%%s%%" + OR lower(cs.product) like lower("%%%s%%"))', + array_fill(0, 3, $filter['free_search']) + ); + } + + if (isset($filter['filter_id_group']) && $filter['filter_id_group'] > 0) { + $propagate = db_get_value( + 'propagate', + 'tgrupo', + 'id_grupo', + $filter['filter_id_group'] + ); + + if (!$propagate) { + $sql_filters[] = sprintf( + ' AND cs.id_group = %d ', + $filter['filter_id_group'] + ); + } else { + $groups = [ $filter['filter_id_group'] ]; + $childrens = groups_get_childrens($id_group, null, true); + if (!empty($childrens)) { + foreach ($childrens as $child) { + $groups[] = (int) $child['id_grupo']; + } + } + + $filter['filter_id_group'] = $groups; + $sql_filters[] = sprintf( + ' AND cs.id_group IN (%s) ', + join(',', $filter['filter_id_group']) + ); + } + } + $sql = sprintf( 'SELECT %s FROM tcredential_store cs @@ -83,7 +157,7 @@ function credentials_get_all( %s', join(',', $fields), join(',', $sql_filters), - $group_by, + $order_by, $pagination ); @@ -95,3 +169,163 @@ function credentials_get_all( return db_get_all_rows_sql($sql); } + + +/** + * Retrieves target key from keystore or false in case of error. + * + * @param string $identifier Key identifier. + * + * @return array Key or false if error. + */ +function get_key($identifier) +{ + return db_get_row_filter( + 'tcredential_store', + [ 'identifier' => $identifier ] + ); +} + + +/** + * Minor function to dump json message as ajax response. + * + * @param string $type Type: result || error. + * @param string $msg Message. + * @param boolean $delete Deletion messages. + * + * @return void + */ +function ajax_msg($type, $msg, $delete=false) +{ + $msg_err = 'Failed while saving: %s'; + $msg_ok = 'Successfully saved into keystore '; + + if ($delete) { + $msg_err = 'Failed while removing: %s'; + $msg_ok = 'Successfully deleted '; + } + + if ($type == 'error') { + echo json_encode( + [ + $type => ui_print_error_message( + __( + $msg_err, + $msg + ), + '', + true + ), + ] + ); + } else { + echo json_encode( + [ + $type => ui_print_success_message( + __( + $msg_ok, + $msg + ), + '', + true + ), + ] + ); + } + + exit; +} + + +/** + * Generates inputs for new/update forms. + * + * @param array $values Values or null. + * + * @return string Inputs. + */ +function print_inputs($values=null) +{ + if (!is_array($values)) { + $values = []; + } + + $return = ''; + $return .= html_print_input( + [ + 'label' => __('Identifier'), + 'name' => 'identifier', + 'input_class' => 'flex-row', + 'type' => 'text', + 'value' => $values['identifier'], + 'disabled' => (bool) $values['identifier'], + 'return' => true, + ] + ); + $return .= html_print_input( + [ + 'label' => __('Group'), + 'name' => 'id_group', + 'id' => 'id_group', + 'input_class' => 'flex-row', + 'type' => 'select_groups', + 'selected' => $values['id_grupo'], + 'return' => true, + 'class' => 'w50p', + ] + ); + $return .= html_print_input( + [ + 'label' => __('Product'), + 'name' => 'product', + 'input_class' => 'flex-row', + 'type' => 'text', + 'value' => $values['product'], + 'disabled' => (bool) $values['product'], + 'return' => true, + ] + ); + $return .= html_print_input( + [ + 'label' => __('Username'), + 'name' => 'username', + 'input_class' => 'flex-row', + 'type' => 'text', + 'value' => $values['username'], + 'return' => true, + ] + ); + $return .= html_print_input( + [ + 'label' => __('Password'), + 'name' => 'password', + 'input_class' => 'flex-row', + 'type' => 'password', + 'value' => $values['password'], + 'return' => true, + ] + ); + $return .= html_print_input( + [ + 'label' => __('Extra'), + 'name' => 'extra_1', + 'input_class' => 'flex-row', + 'type' => 'password', + 'value' => $values['extra_1'], + 'return' => true, + ] + ); + $return .= html_print_input( + [ + 'label' => __('Extra (2)'), + 'name' => 'extra_2', + 'input_class' => 'flex-row', + 'type' => 'password', + 'value' => $values['extra_2'], + 'return' => true, + ] + ); + + return $return; +} diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index bcb6108fec..0ead67b3ea 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -3066,3 +3066,289 @@ function html_print_link_with_params($text, $params=[], $type='text', $style='') return $html; } + + +/** + * Print input using functions html lib. + * + * @param array $data Input definition. + * + * @return string HTML code for desired input. + */ +function html_print_input($data) +{ + if (is_array($data) === false) { + return ''; + } + + $output = ''; + + if ($data['label']) { + $output = '
'; + $output .= ''; + + if (!$data['return']) { + echo $output; + } + } + + switch ($data['type']) { + case 'text': + $output .= html_print_input_text( + $data['name'], + $data['value'], + ((isset($data['alt']) === true) ? $data['alt'] : ''), + ((isset($data['size']) === true) ? $data['size'] : 50), + ((isset($data['maxlength']) === true) ? $data['maxlength'] : 255), + ((isset($data['return']) === true) ? $data['return'] : true), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['required']) === true) ? $data['required'] : false), + ((isset($data['function']) === true) ? $data['function'] : ''), + ((isset($data['class']) === true) ? $data['class'] : ''), + ((isset($data['onChange']) === true) ? $data['onChange'] : ''), + ((isset($data['autocomplete']) === true) ? $data['autocomplete'] : '') + ); + break; + + case 'image': + $output .= html_print_input_image( + $data['name'], + $data['src'], + $data['value'], + ((isset($data['style']) === true) ? $data['style'] : ''), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['options']) === true) ? $data['options'] : false) + ); + break; + + case 'text_extended': + $output .= html_print_input_text_extended( + $data['name'], + $data['value'], + $data['id'], + $data['alt'], + $data['size'], + $data['maxlength'], + $data['disabled'], + $data['script'], + $data['attributes'], + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['password']) === true) ? $data['password'] : false), + ((isset($data['function']) === true) ? $data['function'] : '') + ); + break; + + case 'password': + $output .= html_print_input_password( + $data['name'], + $data['value'], + ((isset($data['alt']) === true) ? $data['alt'] : ''), + ((isset($data['size']) === true) ? $data['size'] : 50), + ((isset($data['maxlength']) === true) ? $data['maxlength'] : 255), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['required']) === true) ? $data['required'] : false), + ((isset($data['class']) === true) ? $data['class'] : '') + ); + break; + + case 'text': + $output .= html_print_input_text( + $data['name'], + $data['value'], + ((isset($data['alt']) === true) ? $data['alt'] : ''), + ((isset($data['size']) === true) ? $data['size'] : 50), + ((isset($data['maxlength']) === true) ? $data['maxlength'] : 255), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['required']) === true) ? $data['required'] : false), + ((isset($data['function']) === true) ? $data['function'] : ''), + ((isset($data['class']) === true) ? $data['class'] : ''), + ((isset($data['onChange']) === true) ? $data['onChange'] : ''), + ((isset($data['autocomplete']) === true) ? $data['autocomplete'] : '') + ); + break; + + case 'image': + $output .= html_print_input_image( + $data['name'], + $data['src'], + $data['value'], + ((isset($data['style']) === true) ? $data['style'] : ''), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['options']) === true) ? $data['options'] : false) + ); + break; + + case 'hidden': + $output .= html_print_input_hidden( + $data['name'], + $data['value'], + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['class']) === true) ? $data['class'] : false) + ); + break; + + case 'hidden_extended': + $output .= html_print_input_hidden_extended( + $data['name'], + $data['value'], + $data['id'], + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['class']) === true) ? $data['class'] : false) + ); + break; + + case 'color': + $output .= html_print_input_color( + $data['name'], + $data['value'], + ((isset($data['class']) === true) ? $data['class'] : false), + ((isset($data['return']) === true) ? $data['return'] : false) + ); + break; + + case 'file': + $output .= html_print_input_file( + $data['name'], + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['options']) === true) ? $data['options'] : false) + ); + break; + + case 'select': + $output .= html_print_select( + $data['fields'], + $data['name'], + ((isset($data['selected']) === true) ? $data['selected'] : ''), + ((isset($data['script']) === true) ? $data['script'] : ''), + ((isset($data['nothing']) === true) ? $data['nothing'] : ''), + ((isset($data['nothing_value']) === true) ? $data['nothing_value'] : 0), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['multiple']) === true) ? $data['multiple'] : false), + ((isset($data['sort']) === true) ? $data['sort'] : true), + ((isset($data['class']) === true) ? $data['class'] : ''), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['style']) === true) ? $data['style'] : false), + ((isset($data['option_style']) === true) ? $data['option_style'] : false), + ((isset($data['size']) === true) ? $data['size'] : false), + ((isset($data['modal']) === true) ? $data['modal'] : false), + ((isset($data['message']) === true) ? $data['message'] : ''), + ((isset($data['select_all']) === true) ? $data['select_all'] : false) + ); + break; + + case 'select_from_sql': + $output .= html_print_select_from_sql( + $data['sql'], + $data['name'], + ((isset($data['selected']) === true) ? $data['selected'] : ''), + ((isset($data['script']) === true) ? $data['script'] : ''), + ((isset($data['nothing']) === true) ? $data['nothing'] : ''), + ((isset($data['nothing_value']) === true) ? $data['nothing_value'] : '0'), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['multiple']) === true) ? $data['multiple'] : false), + ((isset($data['sort']) === true) ? $data['sort'] : true), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['style']) === true) ? $data['style'] : false), + ((isset($data['size']) === true) ? $data['size'] : false), + ((isset($data['trucate_size']) === true) ? $data['trucate_size'] : GENERIC_SIZE_TEXT) + ); + break; + + case 'select_groups': + $output .= html_print_select_groups( + ((isset($data['id_user']) === true) ? $data['id_user'] : false), + ((isset($data['privilege']) === true) ? $data['privilege'] : 'AR'), + ((isset($data['returnAllGroup']) === true) ? $data['returnAllGroup'] : true), + $data['name'], + ((isset($data['selected']) === true) ? $data['selected'] : ''), + ((isset($data['script']) === true) ? $data['script'] : ''), + ((isset($data['nothing']) === true) ? $data['nothing'] : ''), + ((isset($data['nothing_value']) === true) ? $data['nothing_value'] : 0), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['multiple']) === true) ? $data['multiple'] : false), + ((isset($data['sort']) === true) ? $data['sort'] : true), + ((isset($data['class']) === true) ? $data['class'] : ''), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['style']) === true) ? $data['style'] : false), + ((isset($data['option_style']) === true) ? $data['option_style'] : false), + ((isset($data['id_group']) === true) ? $data['id_group'] : false), + ((isset($data['keys_field']) === true) ? $data['keys_field'] : 'id_grupo'), + ((isset($data['strict_user']) === true) ? $data['strict_user'] : false), + ((isset($data['delete_groups']) === true) ? $data['delete_groups'] : false), + ((isset($data['include_groups']) === true) ? $data['include_groups'] : false), + ((isset($data['size']) === true) ? $data['size'] : false), + ((isset($data['simple_multiple_options']) === true) ? $data['simple_multiple_options'] : false) + ); + break; + + case 'submit': + $output .= '
'.html_print_submit_button( + ((isset($data['label']) === true) ? $data['label'] : 'OK'), + ((isset($data['name']) === true) ? $data['name'] : ''), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['attributes']) === true) ? $data['attributes'] : ''), + ((isset($data['return']) === true) ? $data['return'] : false) + ).'
'; + break; + + case 'checkbox': + $output .= html_print_checkbox( + $data['name'], + $data['value'], + ((isset($data['checked']) === true) ? $data['checked'] : false), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['disabled']) === true) ? $data['disabled'] : false), + ((isset($data['script']) === true) ? $data['script'] : ''), + ((isset($data['disabled_hidden']) === true) ? $data['disabled_hidden'] : false) + ); + break; + + case 'switch': + $output .= html_print_switch($data); + break; + + case 'interval': + $output .= html_print_extended_select_for_time( + $data['name'], + $data['value'], + ((isset($data['script']) === true) ? $data['script'] : ''), + ((isset($data['nothing']) === true) ? $data['nothing'] : ''), + ((isset($data['nothing_value']) === true) ? $data['nothing_value'] : 0), + ((isset($data['size']) === true) ? $data['size'] : false), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['style']) === true) ? $data['selected'] : false), + ((isset($data['unique']) === true) ? $data['unique'] : false) + ); + break; + + case 'textarea': + $output .= html_print_textarea( + $data['name'], + $data['rows'], + $data['columns'], + ((isset($data['value']) === true) ? $data['value'] : ''), + ((isset($data['attributes']) === true) ? $data['attributes'] : ''), + ((isset($data['return']) === true) ? $data['return'] : false), + ((isset($data['class']) === true) ? $data['class'] : '') + ); + + default: + // Ignore. + break; + } + + if ($data['label']) { + $output .= '
'; + if (!$data['return']) { + echo ''; + } + } + + return $output; +} + + diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index e11654ce8e..dfd70db661 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -3026,27 +3026,35 @@ function ui_print_datatable(array $parameters) $filter .= $parameters['form']['html']; } - $filter .= '
    '; + $filter .= '
      '; foreach ($parameters['form']['inputs'] as $input) { $filter .= '
    • '; $filter .= ''; if ($input['type'] != 'select') { $filter .= ''; } else { // Select. - $filter .= ''; @@ -3074,7 +3082,7 @@ function ui_print_datatable(array $parameters) $filter .= '
    • '; - $filter .= '
    '; + $filter .= '
'; $filter = ui_toggle( $filter, __('Filter'), diff --git a/pandora_console/include/styles/credential_store.css b/pandora_console/include/styles/credential_store.css new file mode 100644 index 0000000000..576e70f228 --- /dev/null +++ b/pandora_console/include/styles/credential_store.css @@ -0,0 +1,12 @@ +#info_key .flex-row, +#new_key .flex-row { + margin: 1em auto; + max-width: 80%; +} + +#info_key input, +#info_key select, +#new_key input, +#new_key select { + width: 80%; +} diff --git a/pandora_console/include/styles/events.css b/pandora_console/include/styles/events.css index ff0d8ba9ac..fa1aac2e66 100644 --- a/pandora_console/include/styles/events.css +++ b/pandora_console/include/styles/events.css @@ -96,14 +96,12 @@ table.dataTable tbody td { } .sorting_desc { - background: url(http://localhost/pandora_console/images/sort_down_green.png) - no-repeat; + background: url(../../images/sort_down_green.png) no-repeat; background-position-x: left; background-position-y: center; } .sorting_asc { - background: url(http://localhost/pandora_console/images/sort_up_green.png) - no-repeat; + background: url(../../images/sort_up_green.png) no-repeat; background-position-x: left; background-position-y: center; } diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 06507058ee..015d465993 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -502,6 +502,13 @@ select:-internal-list-box { .no-text-imp { font-size: 0 !important; } +.flex-content-right { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-end; + align-content: flex-end; +} .flex-column { display: flex; flex-direction: column; diff --git a/pandora_console/include/styles/tables.css b/pandora_console/include/styles/tables.css index 3d2f63098c..a017dae715 100644 --- a/pandora_console/include/styles/tables.css +++ b/pandora_console/include/styles/tables.css @@ -312,3 +312,31 @@ a.pandora_pagination.current:hover { border-color: #b6b6b6; cursor: default; } + +/* Default datatable filter style */ +.datatable_filter.content { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; +} +.datatable_filter.content label { + margin-right: 1em; +} +.datatable_filter.content li { + flex: 1 1 auto; + margin: 1em auto; +} +.sorting_desc { + background: url(../../images/sort_down_green.png) no-repeat; + background-position-x: left; + background-position-y: center; + cursor: pointer; +} +.sorting_asc { + background: url(../../images/sort_up_green.png) no-repeat; + background-position-x: left; + background-position-y: center; + cursor: pointer; +} From e4f6a95a89a34eee8a05a20aec77a56758a2388b Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 21 Jun 2019 23:05:21 +0200 Subject: [PATCH 03/12] MR29 credential store --- pandora_console/extras/mr/28.sql | 10 ---------- pandora_console/extras/mr/29.sql | 11 +++++++++++ .../extras/pandoradb_migrate_6.0_to_7.0.mysql.sql | 2 +- pandora_console/pandoradb.sql | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/pandora_console/extras/mr/28.sql b/pandora_console/extras/mr/28.sql index d0acd0d99f..6aa30fb34c 100644 --- a/pandora_console/extras/mr/28.sql +++ b/pandora_console/extras/mr/28.sql @@ -42,15 +42,5 @@ ALTER TABLE `tusuario` ADD COLUMN `ehorus_user_level_user` VARCHAR(60); ALTER TABLE `tusuario` ADD COLUMN `ehorus_user_level_pass` VARCHAR(45); ALTER TABLE `tusuario` ADD COLUMN `ehorus_user_level_enabled` TINYINT(1) DEFAULT '1'; -CREATE TABLE IF NOT EXISTS `tcredential_store` ( - `identifier` varchar(100) NOT NULL, - `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, - `product` text, - `username` text, - `password` text, - `extra_1` text, - `extra_2` text, - PRIMARY KEY (`identifier`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; COMMIT; diff --git a/pandora_console/extras/mr/29.sql b/pandora_console/extras/mr/29.sql index 032dd407b1..033165d085 100644 --- a/pandora_console/extras/mr/29.sql +++ b/pandora_console/extras/mr/29.sql @@ -2,5 +2,16 @@ START TRANSACTION; DELETE FROM `ttipo_modulo` WHERE `nombre` LIKE 'log4x'; +CREATE TABLE IF NOT EXISTS `tcredential_store` ( + `identifier` varchar(100) NOT NULL, + `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, + `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE') default 'CUSTOM', + `username` text, + `password` text, + `extra_1` text, + `extra_2` text, + PRIMARY KEY (`identifier`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index ad2bd904b9..c4dabae30d 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -2198,7 +2198,7 @@ CREATE TABLE `tvisual_console_elements_cache` ( CREATE TABLE IF NOT EXISTS `tcredential_store` ( `identifier` varchar(100) NOT NULL, `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, - `product` text, + `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE') default 'CUSTOM', `username` text, `password` text, `extra_1` text, diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index bdd1bca841..e5c4467551 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -699,7 +699,7 @@ CREATE TABLE IF NOT EXISTS `tgrupo` ( CREATE TABLE IF NOT EXISTS `tcredential_store` ( `identifier` varchar(100) NOT NULL, `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, - `product` text, + `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE') default 'CUSTOM', `username` text, `password` text, `extra_1` text, From 5658b98f0be6c0dd3cffb99d29ea398b3bde7402 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 21 Jun 2019 23:51:22 +0200 Subject: [PATCH 04/12] intuitive credential store --- .../godmode/groups/credential_store.php | 40 +++++++- .../include/functions_credential_store.php | 91 ++++++++++++++----- pandora_console/include/functions_html.php | 3 +- .../include/styles/credential_store.css | 2 +- 4 files changed, 109 insertions(+), 27 deletions(-) diff --git a/pandora_console/godmode/groups/credential_store.php b/pandora_console/godmode/groups/credential_store.php index bd08fd4df2..729a2ff7bd 100644 --- a/pandora_console/godmode/groups/credential_store.php +++ b/pandora_console/godmode/groups/credential_store.php @@ -90,6 +90,8 @@ if (is_ajax()) { foreach ($data as $key => $value) { if ($key == 'identifier') { $identifier = base64_decode($value); + } else if ($key == 'product') { + $product = base64_decode($value); } else { $values[$key] = base64_decode($value); } @@ -99,6 +101,10 @@ if (is_ajax()) { ajax_msg('error', __('identifier cannot be empty')); } + if (empty($product)) { + ajax_msg('error', __('product cannot be empty')); + } + if (db_process_sql_update( 'tcredential_store', $values, @@ -132,6 +138,10 @@ if (is_ajax()) { ajax_msg('error', __('identifier cannot be empty')); } + if (empty($values['product'])) { + ajax_msg('error', __('product cannot be empty')); + } + if (db_process_sql_insert('tcredential_store', $values) === false) { ajax_msg('error', $config['dbconnection']->error); } else { @@ -490,12 +500,40 @@ echo ''; }) } + function calculate_inputs() { + if ($('#product :selected').val() == "CUSTOM") { + $('#div-username label').text(''); + $('#div-password label').text(''); + $('#div-extra_1 label').text(''); + $('#div-extra_2 label').text(''); + $('#div-extra_1').show(); + $('#div-extra_2').show(); + } else if ($('#product :selected').val() == "AWS") { + $('#div-username label').text(''); + $('#div-password label').text(''); + $('#div-extra_1').hide(); + $('#div-extra_2').hide(); + } else if ($('#product :selected').val() == "AZURE") { + $('#div-username label').text(''); + $('#div-password label').text(''); + $('#div-extra_1 label').text(''); + $('#div-extra_2 label').text(''); + $('#div-extra_1').show(); + $('#div-extra_2').show(); + } + } + function add_key() { // Clear form. $('#form_new :input').each(function() { $(this).val('') }); - $('#group').val(0); + $('#id_group').val(0); + $('#product').val('CUSTOM'); + + $('#product').on('change', function() { + calculate_inputs() + }); // Show form. $('#new_key').dialog({ diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php index 09d1ce100c..1a1f69a7ec 100644 --- a/pandora_console/include/functions_credential_store.php +++ b/pandora_console/include/functions_credential_store.php @@ -280,15 +280,52 @@ function print_inputs($values=null) 'label' => __('Product'), 'name' => 'product', 'input_class' => 'flex-row', - 'type' => 'text', - 'value' => $values['product'], + 'type' => 'select', + 'fields' => [ + 'CUSTOM' => __('Custom'), + 'AWS' => __('Aws'), + 'AZURE' => __('Azure'), + // 'GOOGLE' => __('Google'), + ], + 'selected' => $values['product'], 'disabled' => (bool) $values['product'], 'return' => true, ] ); + $user_label = __('Username'); + $pass_label = __('Password'); + $extra_1_label = __('Extra'); + $extra_2_label = __('Extra (2)'); + $extra1 = true; + $extra2 = true; + + // Remember to update credential_store.php also. + switch ($values['product']) { + case 'AWS': + $user_label = __('Access key ID'); + $pass_label = __('Secret access key'); + $extra1 = false; + $extra2 = false; + break; + + case 'AZURE': + $user_label = __('Account ID'); + $pass_label = __('Password'); + $extra_1_label = __('Tenant or domain name'); + $extra_2_label = __('Subscription id'); + break; + + case 'GOOGLE': + // Need further investigation. + case 'CUSTOM': + default: + // Use defaults. + break; + } + $return .= html_print_input( [ - 'label' => __('Username'), + 'label' => $user_label, 'name' => 'username', 'input_class' => 'flex-row', 'type' => 'text', @@ -298,7 +335,7 @@ function print_inputs($values=null) ); $return .= html_print_input( [ - 'label' => __('Password'), + 'label' => $pass_label, 'name' => 'password', 'input_class' => 'flex-row', 'type' => 'password', @@ -306,26 +343,32 @@ function print_inputs($values=null) 'return' => true, ] ); - $return .= html_print_input( - [ - 'label' => __('Extra'), - 'name' => 'extra_1', - 'input_class' => 'flex-row', - 'type' => 'password', - 'value' => $values['extra_1'], - 'return' => true, - ] - ); - $return .= html_print_input( - [ - 'label' => __('Extra (2)'), - 'name' => 'extra_2', - 'input_class' => 'flex-row', - 'type' => 'password', - 'value' => $values['extra_2'], - 'return' => true, - ] - ); + if ($extra1) { + $return .= html_print_input( + [ + 'label' => $extra_1_label, + 'name' => 'extra_1', + 'input_class' => 'flex-row', + 'type' => 'password', + 'value' => $values['extra_1'], + 'return' => true, + ] + ); + } + + if ($extra2) { + $return .= html_print_input( + [ + 'label' => $extra_2_label, + 'name' => 'extra_2', + 'input_class' => 'flex-row', + 'type' => 'password', + 'value' => $values['extra_2'], + 'return' => true, + 'display' => $extra2, + ] + ); + } return $return; } diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 0ead67b3ea..533822f069 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -3084,7 +3084,8 @@ function html_print_input($data) $output = ''; if ($data['label']) { - $output = '
'; + $output = '
'; $output .= ''; diff --git a/pandora_console/include/styles/credential_store.css b/pandora_console/include/styles/credential_store.css index 576e70f228..aa77985188 100644 --- a/pandora_console/include/styles/credential_store.css +++ b/pandora_console/include/styles/credential_store.css @@ -8,5 +8,5 @@ #info_key select, #new_key input, #new_key select { - width: 80%; + width: 60%; } From c11cd556ce730aa64d6b88b309a290492766d548 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Sat, 22 Jun 2019 01:10:05 +0200 Subject: [PATCH 05/12] WIP: AWS CS controller --- .../godmode/wizards/Wizard.main.php | 2 +- .../include/functions_credential_store.php | 133 +++++++++++++----- pandora_console/include/styles/discovery.css | 4 + 3 files changed, 103 insertions(+), 36 deletions(-) diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index 2398e3b1c5..2524f6d93c 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -1048,7 +1048,7 @@ class Wizard */ public static function printBigButtonsList($list_data) { - echo '
    '; + echo '
      '; array_map('self::printBigButtonElement', $list_data); echo '
    '; } diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php index 1a1f69a7ec..acc6a2c09f 100644 --- a/pandora_console/include/functions_credential_store.php +++ b/pandora_console/include/functions_credential_store.php @@ -72,41 +72,6 @@ function credentials_get_all( throw new Exception('[credential_get_all] Fields must be an array or "count".'); } - if (isset($order)) { - $dir = 'asc'; - if ($order == 'desc') { - $dir = 'desc'; - }; - - if (in_array( - $sort_field, - [ - 'group', - 'identifier', - 'product', - 'username', - 'options', - ] - ) - ) { - $order_by = sprintf( - 'ORDER BY `%s` %s', - $sort_field, - $dir - ); - } - } - - if (isset($limit) && $limit > 0 - && isset($offset) && $offset >= 0 - ) { - $pagination = sprintf( - ' LIMIT %d OFFSET %d ', - $limit, - $offset - ); - } - if (isset($filter['free_search']) && !empty($filter['free_search'])) { $sql_filters[] = vsprintf( ' AND (lower(cs.username) like lower("%%%s%%") @@ -146,6 +111,48 @@ function credentials_get_all( } } + if (isset($filter['group_list']) && is_array($filter['group_list'])) { + $sql_filters[] = sprintf( + ' AND cs.id_group IN (%s) ', + join(',', $filter['group_list']) + ); + } + + if (isset($order)) { + $dir = 'asc'; + if ($order == 'desc') { + $dir = 'desc'; + }; + + if (in_array( + $sort_field, + [ + 'group', + 'identifier', + 'product', + 'username', + 'options', + ] + ) + ) { + $order_by = sprintf( + 'ORDER BY `%s` %s', + $sort_field, + $dir + ); + } + } + + if (isset($limit) && $limit > 0 + && isset($offset) && $offset >= 0 + ) { + $pagination = sprintf( + ' LIMIT %d OFFSET %d ', + $limit, + $offset + ); + } + $sql = sprintf( 'SELECT %s FROM tcredential_store cs @@ -372,3 +379,59 @@ function print_inputs($values=null) return $return; } + + +/** + * Retrieve all identifiers available for current user. + * + * @param string $product Target product. + * + * @return array Of account identifiers. + */ +function credentials_list_accounts($product) +{ + global $config; + + check_login(); + + include_once $config['homedir'].'/include/functions_users.php'; + + static $user_groups; + + if (!isset($user_groups)) { + $user_groups = users_get_groups( + $config['id_user'], + 'AW' + ); + + // Always add group 'ALL' because 'ALL' group credentials + // must be available for all users. + if (is_array($user_groups)) { + $user_groups = ([0] + array_keys($user_groups)); + } else { + $user_groups = [0]; + } + } + + $creds = credentials_get_all( + ['identifier'], + [ + 'product' => $product, + 'group_list' => $user_groups, + ] + ); + + if ($creds === false) { + return []; + } + + $ret = array_reduce( + $creds, + function ($carry, $item) { + $carry[$item['identifier']] = $item['identifier']; + return $carry; + } + ); + + return $ret; +} diff --git a/pandora_console/include/styles/discovery.css b/pandora_console/include/styles/discovery.css index b8da30aede..0f48611cb9 100644 --- a/pandora_console/include/styles/discovery.css +++ b/pandora_console/include/styles/discovery.css @@ -2,6 +2,10 @@ * Discovery css global */ +ul.bigbuttonlist { + min-height: 200px; +} + li.discovery { display: inline-block; float: left; From 38f72bed8d7e6ee3e732d2814de26f90fda464ae Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Sat, 22 Jun 2019 13:11:35 +0200 Subject: [PATCH 06/12] AWS multi account --- .../wizards/DiscoveryTaskList.class.php | 4 +- pandora_console/include/styles/discovery.css | 5 ++ pandora_server/lib/PandoraFMS/Core.pm | 14 ++++ .../lib/PandoraFMS/DiscoveryServer.pm | 76 +++++++++---------- 4 files changed, 59 insertions(+), 40 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 9ba322d42f..1a16967f60 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -699,7 +699,7 @@ class DiscoveryTaskList extends Wizard if ($script !== false) { switch ($script['type']) { case DISCOVERY_SCRIPT_CLOUD_AWS: - return 'wiz=cloud&mode=amazonws&page=1'; + return 'wiz=cloud&mode=amazonws&ki='.$task['auth_strings'].'&page=1'; case DISCOVERY_SCRIPT_APP_VMWARE: return 'wiz=app&mode=vmware&page=0'; @@ -722,7 +722,7 @@ class DiscoveryTaskList extends Wizard case DISCOVERY_CLOUD_AWS: case DISCOVERY_CLOUD_AWS_EC2: - return 'wiz=cloud&mode=amazonws&page=1'; + return 'wiz=cloud&mode=amazonws&ki='.$task['auth_strings'].'&page=1'; case DISCOVERY_CLOUD_AWS_RDS: return 'wiz=cloud&mode=amazonws&sub=rds&page=0'; diff --git a/pandora_console/include/styles/discovery.css b/pandora_console/include/styles/discovery.css index 0f48611cb9..82b022050f 100644 --- a/pandora_console/include/styles/discovery.css +++ b/pandora_console/include/styles/discovery.css @@ -265,3 +265,8 @@ a.tip { .discovery_interval_select_width { width: 90%; } + +a.ext_link { + margin-left: 1em; + font-size: 8pt; +} diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index ee66b5ca68..861f123ef8 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -185,6 +185,7 @@ our @EXPORT = qw( pandora_exec_forced_alerts pandora_generate_alerts pandora_get_config_value + pandora_get_credential pandora_get_module_tags pandora_get_module_url_tags pandora_get_module_phone_tags @@ -3122,6 +3123,19 @@ sub pandora_get_config_value ($$) { return (defined ($config_value) ? $config_value : ""); } + +########################################################################## +## Get credential from credential store +########################################################################## +sub pandora_get_credential ($$) { + my ($dbh, $identifier) = @_; + + my $key = get_db_single_row($dbh, 'SELECT * FROM tcredential_store WHERE identifier = ?', $identifier); + + return $key; +} + + ########################################################################## =head2 C<< pandora_create_module_tags (I<$pa_config>, I<$dbh>, I<$id_agent_module>, I<$serialized_tags>) >> diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index e15511de44..067bac1555 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -113,10 +113,6 @@ sub run ($) { print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Discovery Server.", 1); my $threads = $pa_config->{'recon_threads'}; - # Prepare some environmental variables. - $ENV{'AWS_ACCESS_KEY_ID'} = pandora_get_config_value($dbh, 'aws_access_key_id'); - $ENV{'AWS_SECRET_ACCESS_KEY'} = pandora_get_config_value($dbh, 'aws_secret_access_key'); - # Use hightest value if ($pa_config->{'discovery_threads'} > $pa_config->{'recon_threads'}) { $threads = $pa_config->{'discovery_threads'}; @@ -193,42 +189,46 @@ sub data_consumer ($$) { my %cnf_extra; if ($task->{'type'} == DISCOVERY_CLOUD_AWS_EC2 || $task->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { - $cnf_extra{'aws_access_key_id'} = pandora_get_config_value($dbh, 'aws_access_key_id'); - $cnf_extra{'aws_secret_access_key'} = pandora_get_config_value($dbh, 'aws_secret_access_key'); + # auth_strings stores the crential identifier to be used. + my $key = pandora_get_credential($dbh, $task->{'auth_strings'}); + + if (ref($key) eq "HASH") { + $cnf_extra{'aws_access_key_id'} = $key->{'username'}; + $cnf_extra{'aws_secret_access_key'} = $key->{'password'}; + } else { + # Invalid credential. + return; + } + $cnf_extra{'cloud_util_path'} = pandora_get_config_value($dbh, 'cloud_util_path'); - if (!defined($ENV{'AWS_ACCESS_KEY_ID'}) || !defined($ENV{'AWS_SECRET_ACCESS_KEY'}) - || $cnf_extra{'aws_secret_access_key'} ne $ENV{'AWS_ACCESS_KEY_ID'} - || $cnf_extra{'cloud_util_path'} ne $ENV{'AWS_SECRET_ACCESS_KEY'}) { - # Environmental data is out of date. Create a tmp file to manage - # credentials. Perl limitation. We cannot update ENV here. - $cnf_extra{'creds_file'} = $pa_config->{'temporal'} . '/tmp_discovery.' . md5($task->{'id_rt'} . $task->{'name'} . time()); - eval { - open(my $__file_cfg, '> '. $cnf_extra{'creds_file'}) or die($!); - print $__file_cfg $cnf_extra{'aws_access_key_id'} . "\n"; - print $__file_cfg $cnf_extra{'aws_secret_access_key'} . "\n"; - close($__file_cfg); - set_file_permissions( - $pa_config, - $cnf_extra{'creds_file'}, - "0600" - ); - }; - if ($@) { - logger( - $pa_config, - 'Cannot instantiate configuration file for task: ' . safe_output($task->{'name'}), - 5 - ); - # A server restart will override ENV definition (see run) - logger( - $pa_config, - 'Cannot execute Discovery task: ' . safe_output($task->{'name'}) . '. Please restart the server.', - 1 - ); - # Skip this task. - return; - } + # Pass credentials by file due Perl limitations. We cannot update ENV here. + $cnf_extra{'creds_file'} = $pa_config->{'temporal'} . '/tmp_discovery.' . md5($task->{'id_rt'} . $task->{'name'} . time()); + eval { + open(my $__file_cfg, '> '. $cnf_extra{'creds_file'}) or die($!); + print $__file_cfg $cnf_extra{'aws_access_key_id'} . "\n"; + print $__file_cfg $cnf_extra{'aws_secret_access_key'} . "\n"; + close($__file_cfg); + set_file_permissions( + $pa_config, + $cnf_extra{'creds_file'}, + "0600" + ); + }; + if ($@) { + logger( + $pa_config, + 'Cannot instantiate configuration file for task: ' . safe_output($task->{'name'}), + 5 + ); + # A server restart will override ENV definition (see run) + logger( + $pa_config, + 'Cannot execute Discovery task: ' . safe_output($task->{'name'}) . '. Please restart the server.', + 1 + ); + # Skip this task. + return; } } From 180948c51c7a33b385471072603650cc55fe4486 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 24 Jun 2019 19:36:50 +0200 Subject: [PATCH 07/12] Import previous aws account --- pandora_console/extras/mr/29.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pandora_console/extras/mr/29.sql b/pandora_console/extras/mr/29.sql index 033165d085..a1e966a0e3 100644 --- a/pandora_console/extras/mr/29.sql +++ b/pandora_console/extras/mr/29.sql @@ -14,4 +14,7 @@ CREATE TABLE IF NOT EXISTS `tcredential_store` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO `tcredential_store` (`identifier`, `id_group`, `product`, `username`, `password`) VALUES ("imported_aws_account", 0, "AWS", (SELECT `value` FROM `tconfig` WHERE `token` = "aws_access_key_id" LIMIT 1), (SELECT `value` FROM `tconfig` WHERE `token` = "aws_secret_access_key" LIMIT 1)); + + COMMIT; From 882aa67b3abfbd19028195f1a106683562727d0d Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 24 Jun 2019 20:35:24 +0200 Subject: [PATCH 08/12] aws multi account viewer rc1 --- pandora_console/include/styles/firts_task.css | 4 ++++ pandora_console/include/styles/pandora.css | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/pandora_console/include/styles/firts_task.css b/pandora_console/include/styles/firts_task.css index c3650d2a8e..be75dd632d 100755 --- a/pandora_console/include/styles/firts_task.css +++ b/pandora_console/include/styles/firts_task.css @@ -78,3 +78,7 @@ div.new_task_cluster > div { #fuerte { font-size: 12px; } + +.flex-row-baseline * { + margin-right: 1em; +} diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 015d465993..965714c7d4 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -524,6 +524,12 @@ select:-internal-list-box { justify-content: space-between; align-content: center; } +.flex-row-baseline { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: baseline; +} .nowrap { flex-wrap: nowrap; From a507d28c1f38e02fa187fea9150f5967ca077044 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 25 Jun 2019 10:12:25 +0200 Subject: [PATCH 09/12] Update Aws agent names --- pandora_console/extras/mr/29.sql | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pandora_console/extras/mr/29.sql b/pandora_console/extras/mr/29.sql index a1e966a0e3..ca88b34fff 100644 --- a/pandora_console/extras/mr/29.sql +++ b/pandora_console/extras/mr/29.sql @@ -3,18 +3,23 @@ START TRANSACTION; DELETE FROM `ttipo_modulo` WHERE `nombre` LIKE 'log4x'; CREATE TABLE IF NOT EXISTS `tcredential_store` ( - `identifier` varchar(100) NOT NULL, - `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, - `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE') default 'CUSTOM', - `username` text, - `password` text, - `extra_1` text, - `extra_2` text, - PRIMARY KEY (`identifier`) + `identifier` varchar(100) NOT NULL, + `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, + `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE') default 'CUSTOM', + `username` text, + `password` text, + `extra_1` text, + `extra_2` text, + PRIMARY KEY (`identifier`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `tcredential_store` (`identifier`, `id_group`, `product`, `username`, `password`) VALUES ("imported_aws_account", 0, "AWS", (SELECT `value` FROM `tconfig` WHERE `token` = "aws_access_key_id" LIMIT 1), (SELECT `value` FROM `tconfig` WHERE `token` = "aws_secret_access_key" LIMIT 1)); +DELETE FROM `tcredential_store` WHERE `username` IS NULL AND `password` IS NULL; + +UPDATE `tagente` ta INNER JOIN `tagente` taa on ta.`id_parent` = taa.`id_agente` AND taa.`nombre` IN ("us-east-1", "us-east-2", "us-west-1", "us-west-2", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-south-1", "sa-east-1") SET ta.nombre = md5(concat((SELECT `username` FROM `tcredential_store` WHERE `identifier` = "imported_aws_account" LIMIT 1), ta.`nombre`)); + +UPDATE `tagente` SET `nombre` = md5(concat((SELECT `username` FROM `tcredential_store` WHERE `identifier` = "imported_aws_account" LIMIT 1), `nombre`)) WHERE `nombre` IN ("Aws", "us-east-1", "us-east-2", "us-west-1", "us-west-2", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-south-1", "sa-east-1"); COMMIT; From 22d936d4f3bb2675ec9019e83963a6185167ed46 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 25 Jun 2019 16:43:38 +0200 Subject: [PATCH 10/12] credential store some js controls --- pandora_console/godmode/groups/credential_store.php | 4 ++++ pandora_console/include/functions_credential_store.php | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pandora_console/godmode/groups/credential_store.php b/pandora_console/godmode/groups/credential_store.php index 729a2ff7bd..01e7f11bfa 100644 --- a/pandora_console/godmode/groups/credential_store.php +++ b/pandora_console/godmode/groups/credential_store.php @@ -386,6 +386,7 @@ echo '
'; if (!failed) { dt_.draw(0); $(".ui-dialog-content").dialog("close"); + $('.ui-dialog-content').remove(); } else { $(this).dialog('close'); } @@ -406,6 +407,7 @@ echo '
'; text: '', click: function(e) { $(this).dialog('close'); + $(this).remove(); } }, { @@ -462,6 +464,7 @@ echo ''; text: '', click: function(e) { $(this).dialog('close'); + $(this).remove(); } }, { @@ -552,6 +555,7 @@ echo ''; text: "", click: function(e) { $(this).dialog('close'); + $(this).remove(); } }, { diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php index acc6a2c09f..accc9348fd 100644 --- a/pandora_console/include/functions_credential_store.php +++ b/pandora_console/include/functions_credential_store.php @@ -277,7 +277,7 @@ function print_inputs($values=null) 'id' => 'id_group', 'input_class' => 'flex-row', 'type' => 'select_groups', - 'selected' => $values['id_grupo'], + 'selected' => $values['id_group'], 'return' => true, 'class' => 'w50p', ] @@ -288,6 +288,7 @@ function print_inputs($values=null) 'name' => 'product', 'input_class' => 'flex-row', 'type' => 'select', + 'script' => 'calculate_inputs()', 'fields' => [ 'CUSTOM' => __('Custom'), 'AWS' => __('Aws'), From e1bf12a1fb9c8fc8c1bb2166063c1be902d4c421 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 25 Jun 2019 18:21:23 +0200 Subject: [PATCH 11/12] Credential store --- .../godmode/groups/credential_store.php | 157 +++++++++++------- .../include/functions_credential_store.php | 7 +- 2 files changed, 99 insertions(+), 65 deletions(-) diff --git a/pandora_console/godmode/groups/credential_store.php b/pandora_console/godmode/groups/credential_store.php index 01e7f11bfa..9a822dc986 100644 --- a/pandora_console/godmode/groups/credential_store.php +++ b/pandora_console/godmode/groups/credential_store.php @@ -49,16 +49,21 @@ if (! check_acl($config['id_user'], 0, 'PM')) { // Required files. ui_require_css_file('credential_store'); require_once $config['homedir'].'/include/functions_credential_store.php'; - +require_once $config['homedir'].'/include/functions_io.php'; if (is_ajax()) { $draw = get_parameter('draw', 0); $filter = get_parameter('filter', []); $get_key = get_parameter('get_key', 0); + $new_form = get_parameter('new_form', 0); $new_key = get_parameter('new_key', 0); $update_key = get_parameter('update_key', 0); $delete_key = get_parameter('delete_key', 0); + if ($new_form) { + echo print_inputs(); + exit; + } if ($delete_key) { $identifier = get_parameter('identifier', null); @@ -130,6 +135,9 @@ if (is_ajax()) { $values = []; foreach ($data as $key => $value) { $values[$key] = base64_decode($value); + if ($key == 'identifier') { + $values[$key] = preg_replace('/\s+/', '-', trim($values[$key])); + } } $identifier = $values['identifier']; @@ -318,8 +326,7 @@ try { // Auxiliar div. $new = ''; +$new .= ''; $details = ''; $aux = ''; @@ -386,7 +393,7 @@ echo ''; if (!failed) { dt_.draw(0); $(".ui-dialog-content").dialog("close"); - $('.ui-dialog-content').remove(); + cleanupDOM(); } else { $(this).dialog('close'); } @@ -407,7 +414,8 @@ echo ''; text: '', click: function(e) { $(this).dialog('close'); - $(this).remove(); + cleanupDOM(); + } }, { @@ -464,7 +472,7 @@ echo ''; text: '', click: function(e) { $(this).dialog('close'); - $(this).remove(); + cleanupDOM(); } }, { @@ -503,6 +511,15 @@ echo ''; }) } + function cleanupDOM() { + $('#div-identifier').empty(); + $('#div-product').empty(); + $('#div-username').empty(); + $('#div-password').empty(); + $('#div-extra_1').empty(); + $('#div-extra_2').empty(); + } + function calculate_inputs() { if ($('#product :selected').val() == "CUSTOM") { $('#div-username label').text(''); @@ -528,66 +545,82 @@ echo ''; function add_key() { // Clear form. - $('#form_new :input').each(function() { - $(this).val('') - }); - $('#id_group').val(0); - $('#product').val('CUSTOM'); - - $('#product').on('change', function() { - calculate_inputs() - }); - - // Show form. - $('#new_key').dialog({ - width: 580, - height: 400, - position: { - my: 'center', - at: 'center', - of: window, - collision: 'fit' + $('#form_update').empty(); + $('#form_update').html('Loading...'); + $.ajax({ + method: 'post', + url: '', + data: { + page: 'godmode/groups/credential_store', + new_form: 1 }, - title: "", - buttons: [ - { - class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel', - text: "", - click: function(e) { - $(this).dialog('close'); - $(this).remove(); - } - }, - { - class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next', - text: 'OK', - click: function(e) { - var values = {}; + success: function(data) { + $('#form_new').html(data); + $('#id_group').val(0); + // By default AWS. + $('#product').val('AWS'); + calculate_inputs(); - $('#form_new :input').each(function() { - values[this.name] = btoa($(this).val()); - }); + $('#product').on('change', function() { + calculate_inputs() + }); - $.ajax({ - method: 'post', - url: '', - data: { - page: 'godmode/groups/credential_store', - new_key: 1, - values: values - }, - datatype: "json", - success: function (data) { - handle_response(data); - }, - error: function(e) { - handle_response(e); + // Show form. + $('#new_key').dialog({ + width: 580, + height: 400, + position: { + my: 'center', + at: 'center', + of: window, + collision: 'fit' + }, + title: "", + buttons: [ + { + class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel', + text: "", + click: function(e) { + $(this).dialog('close'); + cleanupDOM(); } - }); - } - }, - ] - }); + }, + { + class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next', + text: 'OK', + click: function(e) { + var values = {}; + + console.log($('#form_new')); + + $('#form_new :input').each(function() { + values[this.name] = btoa($(this).val()); + }); + + $.ajax({ + method: 'post', + url: '', + data: { + page: 'godmode/groups/credential_store', + new_key: 1, + values: values + }, + datatype: "json", + success: function (data) { + handle_response(data); + }, + error: function(e) { + handle_response(e); + } + }); + } + }, + ] + }); + } + }) + + } $(document).ready(function(){ diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php index accc9348fd..e49bd71399 100644 --- a/pandora_console/include/functions_credential_store.php +++ b/pandora_console/include/functions_credential_store.php @@ -268,6 +268,7 @@ function print_inputs($values=null) 'value' => $values['identifier'], 'disabled' => (bool) $values['identifier'], 'return' => true, + 'script' => 'alert(\'puta\')', ] ); $return .= html_print_input( @@ -290,9 +291,9 @@ function print_inputs($values=null) 'type' => 'select', 'script' => 'calculate_inputs()', 'fields' => [ - 'CUSTOM' => __('Custom'), - 'AWS' => __('Aws'), - 'AZURE' => __('Azure'), + // 'CUSTOM' => __('Custom'), + 'AWS' => __('Aws'), + // 'AZURE' => __('Azure'), // 'GOOGLE' => __('Google'), ], 'selected' => $values['product'], From fdf2a983d291ca0e49d374da458f2797b712566a Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 26 Jun 2019 10:39:18 +0200 Subject: [PATCH 12/12] general review credential store --- pandora_console/include/functions_credential_store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/include/functions_credential_store.php b/pandora_console/include/functions_credential_store.php index e49bd71399..cf09e6d67b 100644 --- a/pandora_console/include/functions_credential_store.php +++ b/pandora_console/include/functions_credential_store.php @@ -403,7 +403,7 @@ function credentials_list_accounts($product) if (!isset($user_groups)) { $user_groups = users_get_groups( $config['id_user'], - 'AW' + 'AR' ); // Always add group 'ALL' because 'ALL' group credentials