diff --git a/pandora_agents/pc/Linux/pandora_agent.conf b/pandora_agents/pc/Linux/pandora_agent.conf index 4ad837f943..e25a82a517 100644 --- a/pandora_agents/pc/Linux/pandora_agent.conf +++ b/pandora_agents/pc/Linux/pandora_agent.conf @@ -234,6 +234,21 @@ module_description Number of cron task files module_unit files module_end +# This module /var/log/syslog file, under the module name "syslog" +# And search for "ssh" string into it, sending only that information. +module_begin +module_name Syslog +module_description Search for ssh string into /var/log/syslog file +module_type log +module_regexp /var/log/syslog +module_pattern ssh +module_end + +#Hardening plugin for security compliance analysis. Enable to use it. +#module_begin +#module_plugin /usr/share/pandora_agent/plugins/pandora_hardening -t 150 +#module_absoluteinterval 7d +#module_end # Plugin example @@ -241,11 +256,6 @@ module_end module_plugin pandora_df -# This parses /var/log/syslog file, under the module name "syslog" -# And search for "ssh" string into it, sending only that information. - -module_plugin grep_log /var/log/syslog Syslog ssh - # Get disk space free in MB #module_begin #module_name disk_root_free @@ -270,7 +280,6 @@ module_plugin grep_log /var/log/syslog Syslog ssh #module_end # Plugin for inventory on the agent. - # module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users process ip route # Example of preconditions @@ -303,4 +312,13 @@ module_plugin grep_log /var/log/syslog Syslog ssh # This plugin runs several security checks in a Linux system -#module_plugin pandora_security_check \ No newline at end of file +#module_plugin pandora_security_check + +# Extraction module example +#module_begin +#module_name Collector +#module_description Logs extraction module +#module_type log +#module_regexp /var/log/logfile.log +#module_pattern .* +#module_end \ No newline at end of file diff --git a/pandora_agents/pc/Win32/pandora_agent.conf b/pandora_agents/pc/Win32/pandora_agent.conf index 621c1d24ac..b064eba730 100644 --- a/pandora_agents/pc/Win32/pandora_agent.conf +++ b/pandora_agents/pc/Win32/pandora_agent.conf @@ -1,6 +1,6 @@ # Base config file for Pandora FMS Windows Agent # (c) 2006-2023 Pandora FMS -# Version 7.0NG.774 +# Version 7.0NG.774 # This program is Free Software, you can redistribute it and/or modify it # under the terms of the GNU General Public Licence as published by the Free Software # Foundation; either version 2 of the Licence or any later version @@ -147,22 +147,23 @@ module_max_critical 20 module_end # Log events + +# Get logs from System source. module_begin module_name System Events (TermService) -module_type async_string -module_logevent module_description Log Events coming from Terminal Service +module_type log +module_logevent module_source System -module_application TermService module_end +# Get logs from Security source. module_begin -module_name Security Events (Invalid Login) -module_type async_string -module_description Security log events for invalid login attempt +module_name Security Events +module_description Security log events +module_type log module_logevent module_source Security -module_eventcode 529 module_end # Check if Dhcp service is enabled @@ -219,6 +220,12 @@ module_plugin cscript.exe //B "%ProgramFiles%\Pandora_Agent\util\df.vbs" # module_description Free space on drive D: (%) # module_end +# Hardening plugin for security compliance analysis. +# module_begin +# module_plugin "%PROGRAMFILES%\Pandora_Agent\util\pandora_hardening.exe -t 150" +# module_absoluteinterval 7d +# module_end + # Sample of Windows inventory module (ONLY ENTERPRISE)! #module_begin #module_name Inventory @@ -344,4 +351,13 @@ module_plugin cscript.exe //B "%ProgramFiles%\Pandora_Agent\util\df.vbs" #module_condition (3,8) cmd.exe /c echo range >> c:\log.txt #module_exec echo 5 #module_description Postcondition test module +#module_end + +# Example of collector module +#module_begin +#module_name Collector +#module_description Logs extraction module +#module_type log +#module_regexp /var/log/logfile.log +#module_pattern .* #module_end \ No newline at end of file diff --git a/pandora_agents/shellscript/linux/pandora_agent.conf b/pandora_agents/shellscript/linux/pandora_agent.conf index 98c137741e..49e8866f9a 100644 --- a/pandora_agents/shellscript/linux/pandora_agent.conf +++ b/pandora_agents/shellscript/linux/pandora_agent.conf @@ -157,12 +157,32 @@ module_exec last | head -1 module_description Last Login module_end -# Plugin example +#Hardening plugin for security compliance analysis. Enable to use it. +#module_begin +#module_plugin /usr/share/pandora_agent/plugins/pandora_hardening -t 150 +#module_absoluteinterval 7d +#module_end -# This parses /var/log/syslog file, under the module name "syslog" +# This module parses /var/log/syslog file, under the module name "syslog" # And search for "ssh" string into it, sending only that information. +module_begin +module_name Syslog +module_description Search for ssh string into /var/log/syslog file +module_type log +module_regexp /var/log/syslog +module_pattern ssh +module_end -module_plugin grep_log /var/log/syslog Syslog ssh +# Plugin example # Plugin for inventory on the agent. # module_plugin inventory 1 cpu ram video nic hd cdrom software + +# Extraction module example +#module_begin +#module_name Collector +#module_description Logs extraction module +#module_type log +#module_regexp /var/log/logfile.log +#module_pattern .* +#module_end \ No newline at end of file diff --git a/pandora_agents/shellscript/mac_osx/pandora_agent.conf b/pandora_agents/shellscript/mac_osx/pandora_agent.conf index b4b3c35ac8..ba9c0079a3 100644 --- a/pandora_agents/shellscript/mac_osx/pandora_agent.conf +++ b/pandora_agents/shellscript/mac_osx/pandora_agent.conf @@ -372,13 +372,32 @@ module_end #module_description XGrid #module_end +#Hardening plugin for security compliance analysis. Enable to use it. +#module_begin +#module_plugin /usr/share/pandora_agent/plugins/pandora_hardening -t 150 +#module_absoluteinterval 7d +#module_end + +# This module parses /var/log/syslog file, under the module name "syslog" +# And search for "ssh" string into it, sending only that information. +module_begin +module_name Syslog +module_description Log collection modules +module_type log +module_regexp /var/log/syslog +module_pattern ssh +module_end + # Plugin example -# This parses /var/log/syslog file, under the module name "syslog" -# And search for "ssh" string into it, sending only that information. - -#module_plugin grep_log /var/log/syslog Syslog ssh - # Plugin for inventory on the agent. - # module_plugin inventory 1 cpu ram video nic hd cdrom software + +# Extraction module example +#module_begin +#module_name Collector +#module_description Logs extraction module +#module_type log +#module_regexp /var/log/logfile.log +#module_pattern .* +#module_end \ No newline at end of file diff --git a/pandora_agents/unix/Linux/pandora_agent.conf b/pandora_agents/unix/Linux/pandora_agent.conf index 10458ddba5..42fddd39f5 100644 --- a/pandora_agents/unix/Linux/pandora_agent.conf +++ b/pandora_agents/unix/Linux/pandora_agent.conf @@ -271,11 +271,17 @@ module_plugin pandora_netusage module_plugin autodiscover --default # Plugin for inventory on the agent. -#module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users route +# module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users route # Log collection modules. This will collect log files for forensic analysis and store everything # This is for LOG monitoring. Different than log monitoring. -#module_plugin grep_log_module /var/log/messages Syslog \.\* +module_begin +module_name Syslog +module_description Log collection modules +module_type log +module_regexp /var/log/messages +module_pattern .* +module_end # Another samples of monitoring modules @@ -317,9 +323,9 @@ module_plugin autodiscover --default #module_absoluteinterval 7d #module_end -# Logs extraction +# Extraction module example #module_begin -#module_name Syslog +#module_name Collector #module_description Logs extraction module #module_type log #module_regexp /var/log/logfile.log diff --git a/pandora_agents/win32/bin/pandora_agent.conf b/pandora_agents/win32/bin/pandora_agent.conf index bae2841fd5..c0a1560b38 100644 --- a/pandora_agents/win32/bin/pandora_agent.conf +++ b/pandora_agents/win32/bin/pandora_agent.conf @@ -179,6 +179,22 @@ module_description Total number of TCP connections active module_group Networking module_end +# Get logs from System source. +module_begin +module_name Eventlog_System +module_type log +module_logevent +module_source System +module_end + +# Get logs from Security source. +module_begin +module_name Eventlog_Security +module_type log +module_logevent +module_source Security +module_end + # Example plugin to retrieve drive usage module_plugin cscript.exe //B "%ProgramFiles%\Pandora_Agent\util\df_percent_used.vbs" @@ -273,22 +289,6 @@ module_plugin "%PROGRAMFILES%\Pandora_Agent\util\autodiscover.exe" --default #module_type generic_data_string #module_end -# Get logs from System source. Need enterprise version. -#module_begin -#module_name Eventlog_System -#module_type log -#module_logevent -#module_source System -#module_end - -# Get logs from Security source. Need enterprise version. -#module_begin -#module_name Eventlog_Security -#module_type log -#module_logevent -#module_source Security -#module_end - # Get logs from Application source. Need enterprise version. #module_begin #module_name Eventlog_Application diff --git a/pandora_console/extras/mr/67.sql b/pandora_console/extras/mr/67.sql index 2805daec78..06253a5f54 100644 --- a/pandora_console/extras/mr/67.sql +++ b/pandora_console/extras/mr/67.sql @@ -3,13 +3,21 @@ START TRANSACTION; ALTER TABLE `tevento` ADD COLUMN `event_custom_id` TEXT NULL AFTER `module_status`; --- Telegram and vonage default alerts -UPDATE talert_actions - SET field2='[PANDORA] Alert FIRED on _agent_ / _module_ / _timestamp_ / _data_' - WHERE id=9; -UPDATE talert_actions - SET field2='[PANDORA] Alert FIRED on _agent_ / _module_ / _timestamp_ / _data_' - WHERE id=11; +SET @exist = (SELECT count(*) FROM information_schema.columns WHERE TABLE_NAME='tmetaconsole_agent' AND COLUMN_NAME='transactional_agent' AND table_schema = DATABASE()); +SET @sqlstmt = IF (@exist>0, 'ALTER TABLE `tmetaconsole_agent` DROP COLUMN `transactional_agent`', 'SELECT ""'); +prepare stmt from @sqlstmt; +execute stmt; + +SET @exist = (SELECT count(*) FROM information_schema.columns WHERE TABLE_NAME='tagente' AND COLUMN_NAME='transactional_agent' AND table_schema = DATABASE()); +SET @sqlstmt = IF (@exist>0, 'ALTER TABLE `tagente` DROP COLUMN `transactional_agent`', 'SELECT ""'); +prepare stmt from @sqlstmt; +execute stmt; + +ALTER TABLE `tdashboard` +ADD COLUMN `date_range` TINYINT NOT NULL DEFAULT 0 AFTER `cells_slideshow`, +ADD COLUMN `date_from` INT NOT NULL DEFAULT 0 AFTER `date_range`, +ADD COLUMN `date_to` INT NOT NULL DEFAULT 0 AFTER `date_from`; + -- Delete table tagent_access DROP TABLE IF EXISTS tagent_access; @@ -18,10 +26,8 @@ ALTER TABLE `tevent_rule` DROP COLUMN `operator_user_comment`; ALTER TABLE treport_content ADD check_unknowns_graph tinyint DEFAULT 0 NULL; -ALTER TABLE `tevent_filter` -ADD COLUMN `regex` TEXT NULL AFTER `private_filter_user`; +ALTER TABLE `tevent_filter` ADD COLUMN `regex` TEXT NULL AFTER `private_filter_user`; -- Update macros for plugin oracle - UPDATE `tdiscovery_apps` SET `version` = '1.1' WHERE `short_name` = 'pandorafms.oracle'; SET @id_app := (SELECT `id_app` FROM `tdiscovery_apps` WHERE `short_name` = 'pandorafms.oracle'); @@ -35,11 +41,6 @@ UPDATE `trecon_task` SET `setup_complete` = 1 WHERE `id_app` = @id_app; -- Update lts updates UPDATE tconfig SET value='1' WHERE token='lts_updates'; -ALTER TABLE `tdashboard` -ADD COLUMN `date_range` TINYINT NOT NULL DEFAULT 0 AFTER `cells_slideshow`, -ADD COLUMN `date_from` INT NOT NULL DEFAULT 0 AFTER `date_range`, -ADD COLUMN `date_to` INT NOT NULL DEFAULT 0 AFTER `date_from`; - SELECT @generic_data := `id_tipo` FROM `ttipo_modulo` WHERE `nombre` = "generic_data"; SELECT @generic_proc := `id_tipo` FROM `ttipo_modulo` WHERE `nombre` = "generic_proc"; SELECT @async_data := `id_tipo` FROM `ttipo_modulo` WHERE `nombre` = "async_data"; @@ -47,6 +48,10 @@ SELECT @async_proc := `id_tipo` FROM `ttipo_modulo` WHERE `nombre` = "async_proc UPDATE `tagente_modulo` INNER JOIN `tservice` ON `tagente_modulo`.`custom_integer_1` = `tservice`.`id` SET `tagente_modulo`.`id_tipo_modulo` = @generic_data WHERE `tagente_modulo`.`id_tipo_modulo` = @async_data; UPDATE `tagente_modulo` INNER JOIN `tservice` ON `tagente_modulo`.`custom_integer_1` = `tservice`.`id` SET `tagente_modulo`.`id_tipo_modulo` = @generic_proc WHERE `tagente_modulo`.`id_tipo_modulo` = @async_proc; +-- Telegram and vonage default alerts +UPDATE talert_actions SET field2='[PANDORA] Alert FIRED on _agent_ / _module_ / _timestamp_ / _data_' WHERE id=9; +UPDATE talert_actions SET field2='[PANDORA] Alert FIRED on _agent_ / _module_ / _timestamp_ / _data_' WHERE id=11; + UPDATE `tdiscovery_apps` SET `version` = '1.2' WHERE `short_name` = 'pandorafms.vmware'; COMMIT; diff --git a/pandora_console/godmode/massive/massive_delete_action_alerts.php b/pandora_console/godmode/massive/massive_delete_action_alerts.php index cad37a3a29..0cd712e124 100644 --- a/pandora_console/godmode/massive/massive_delete_action_alerts.php +++ b/pandora_console/godmode/massive/massive_delete_action_alerts.php @@ -111,7 +111,8 @@ if ($delete) { $alerts_agent_modules = []; foreach ($agent_alerts['simple'] as $agent_alert) { if ((in_array($agent_alert['id_alert_template'], $id_alert_templates)) && (in_array($agent_alert['id_agent_module'], $modules_id))) { - $alerts_agent_modules = array_merge($alerts_agent_modules, alerts_get_alerts_agent_module($agent_alert['id_agent_module'], true, false, 'id')); + // $alerts_agent_modules = array_merge($alerts_agent_modules, alerts_get_alerts_agent_module($agent_alert['id_agent_module'], true, false, 'id')); + $alerts_agent_modules[] = $agent_alert['id']; } } @@ -126,7 +127,7 @@ if ($delete) { $agent_module_actions = []; foreach ($alerts_agent_modules as $alert_agent_module) { - $agent_module_actions = alerts_get_alert_agent_module_actions($alert_agent_module['id'], ['id', 'id_alert_action']); + $agent_module_actions = alerts_get_alert_agent_module_actions($alert_agent_module, ['id', 'id_alert_action']); foreach ($agent_module_actions as $agent_module_action) { foreach ($actions as $action) { diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 171e16870b..64710a0c58 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -478,8 +478,8 @@ if ($access_console_node === true) { } } - $sub2['godmode/setup/setup§ion=ehorus']['text'] = __('Pandora RC'); - $sub2['godmode/setup/setup§ion=ehorus']['refr'] = 0; + $sub2['godmode/setup/setup§ion=pandorarc']['text'] = __('Pandora RC'); + $sub2['godmode/setup/setup§ion=pandorarc']['refr'] = 0; $sub2['godmode/setup/setup§ion=ITSM']['text'] = __('ITSM'); $sub2['godmode/setup/setup§ion=ITSM']['refr'] = 0; diff --git a/pandora_console/godmode/setup/setup.php b/pandora_console/godmode/setup/setup.php index 0f3b494fc5..1de74e1123 100644 --- a/pandora_console/godmode/setup/setup.php +++ b/pandora_console/godmode/setup/setup.php @@ -184,7 +184,7 @@ $buttons['ITSM'] = [ $buttons['ehorus'] = [ 'active' => false, - 'text' => ''.html_print_image( + 'text' => ''.html_print_image( 'images/RC.png', true, [ @@ -297,7 +297,7 @@ switch ($section) { $help_header = 'setup_flow_tab'; break; - case 'ehorus': + case 'pandorarc': $buttons['ehorus']['active'] = true; $subpage = __('Pandora RC'); $help_header = 'setup_ehorus_tab'; @@ -442,7 +442,7 @@ switch ($section) { include_once $config['homedir'].'/godmode/setup/setup_visuals.php'; break; - case 'ehorus': + case 'pandorarc': include_once $config['homedir'].'/godmode/setup/setup_ehorus.php'; break; diff --git a/pandora_console/images/widgets/service_level.png b/pandora_console/images/widgets/service_level.png new file mode 100644 index 0000000000..685744641f Binary files /dev/null and b/pandora_console/images/widgets/service_level.png differ diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index 641a9f93f7..0bb6612376 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -306,32 +306,48 @@ function format_for_graph( } -function human_milliseconds_to_string($seconds) +function human_milliseconds_to_string($seconds, $size_text='large') { $ret = ''; // get the days $days = intval(intval($seconds) / (360000 * 24)); if ($days > 0) { - $ret .= "$days days "; + if ($size_text === 'short') { + $ret .= str_replace(' ', '', "$days d").' '; + } else { + $ret .= "$days days "; + } } // get the hours $hours = ((intval($seconds) / 360000) % 24); if ($hours > 0) { - $ret .= "$hours hours "; + if ($size_text === 'short') { + $ret .= str_replace(' ', '', "$hours h").' '; + } else { + $ret .= "$hours hours "; + } } // get the minutes $minutes = ((intval($seconds) / 6000) % 60); if ($minutes > 0) { - $ret .= "$minutes minutes "; + if ($size_text === 'short') { + $ret .= str_replace(' ', '', "$minutes m").' '; + } else { + $ret .= "$minutes minutes "; + } } // get the seconds $seconds = ((intval($seconds) / 100) % 60); if ($seconds > 0) { - $ret .= "$seconds seconds"; + if ($size_text === 'short') { + $ret .= str_replace(' ', '', "$seconds s").' '; + } else { + $ret .= "$seconds seconds "; + } } return $ret; diff --git a/pandora_console/include/functions_cron_task.php b/pandora_console/include/functions_cron_task.php index 9de0520ccd..40a6e159cc 100644 --- a/pandora_console/include/functions_cron_task.php +++ b/pandora_console/include/functions_cron_task.php @@ -459,17 +459,17 @@ function cron_task_start_gotty(bool $restart_mode=true) // Check prev process running and kill it (only if port changed in setup params). if (empty($config['restart_gotty_next_cron_port']) === false) { - config_update_value('restart_gotty_next_cron_port', ''); - - $prevProcessRunning = shell_exec("pgrep -f 'pandora_gotty.*-p ".$config['restart_gotty_next_cron_port']."'"); + $prevProcessRunning = shell_exec("pgrep -af 'pandora_gotty.*-p ".$config['restart_gotty_next_cron_port']."' | grep -v 'pgrep'"); if (empty($prevProcessRunning) === false) { shell_exec("pkill -f 'pandora_gotty.*-p ".$config['restart_gotty_next_cron_port']."'"); } + + config_update_value('restart_gotty_next_cron_port', ''); } // Check if gotty is running on the configured port. - $processRunning = shell_exec("pgrep -f 'pandora_gotty.*-p ".$config['gotty_port']."'"); + $processRunning = shell_exec("pgrep -af 'pandora_gotty.*-p ".$config['gotty_port']."' | grep -v 'pgrep'"); $start_proc = true; diff --git a/pandora_console/include/functions_modules.php b/pandora_console/include/functions_modules.php index 5add1570d8..ea776d6fe3 100755 --- a/pandora_console/include/functions_modules.php +++ b/pandora_console/include/functions_modules.php @@ -4770,7 +4770,231 @@ function export_agents_module_csv($filters) /** - * Check if modules are compatible with MADE server. + * Function to return Mean Time Between Failure, Mean Time To Solution (in seconds) + * and Availability of a module + * + * @param string $datetime_from Start time of the interval. + * + * @param string $datetime_to End time of the interval. + * + * @param string $id_agentmodule id_agentmodule of the module + * + * @return array Returns an array with the data + */ +function service_level_module_data($datetime_from, $datetime_to, $id_agentmodule) +{ + $data = []; + $data['mtbf'] = false; + $data['mtrs'] = false; + $data['availability'] = false; + $data['critical_events'] = false; + $data['warning_events'] = false; + $data['last_status_change'] = false; + $data['module_name'] = false; + + $availability = 0; + $type = ''; + if ((bool) is_metaconsole() === true) { + if (enterprise_include_once('include/functions_metaconsole.php') !== ENTERPRISE_NOT_HOOK) { + $server_id = []; + $server_id['id'] = explode('|', $id_agentmodule)[0]; + $id_agentmodule = explode('|', $id_agentmodule)[1]; + $server_name = db_get_row_filter('tmetaconsole_setup', $server_id, 'server_name'); + $connection = metaconsole_get_connection($server_name); + if (metaconsole_load_external_db($connection) !== NOERR) { + // Restore db connection. + metaconsole_restore_db(); + return $data; + } + } + } + + $uncompressed_data = db_uncompress_module_data( + $id_agentmodule, + $datetime_from, + $datetime_to + ); + + $first_utimestamp = 0; + foreach ($uncompressed_data as $data_module) { + foreach ($data_module['data'] as $subdata) { + if (!empty($subdata['datos'])) { + $first_utimestamp = $subdata['utimestamp']; + if (isset($subdata['type'])) { + $type = $subdata['type']; + } + + break; + } + } + } + + $interval_time = ($datetime_to - $datetime_from); + $current_time = time(); + $sql = 'SELECT utimestamp, event_type FROM tevento + WHERE id_agentmodule = '.$id_agentmodule.' + AND utimestamp >= '.$datetime_from.' + AND utimestamp <= '.$datetime_to.' + ORDER BY utimestamp DESC'; + + $events_time = db_get_all_rows_sql($sql); + + // Count events. + $sql = 'SELECT COUNT(*) as critical_events FROM tevento + WHERE id_agentmodule= '.$id_agentmodule.' + AND utimestamp >= '.$datetime_from.' + AND utimestamp <= '.$datetime_to.' + AND (event_type = "going_up_critical" OR event_type = "going_down_critical")'; + + $critical_events = db_get_sql($sql); + + $sql = 'SELECT COUNT(*) as warning_events FROM tevento + WHERE id_agentmodule= '.$id_agentmodule.' + AND utimestamp >= '.$datetime_from.' + AND utimestamp <= '.$datetime_to.' + AND (event_type = "going_up_warning" OR event_type = "going_down_warning")'; + + $warning_events = db_get_sql($sql); + + if ($events_time !== false && count($events_time) > 0) { + $failed_event = []; + $normal_event = []; + $events_time = array_reverse($events_time); + $mtrs_events = []; + foreach ($events_time as $key => $event) { + if ($event['event_type'] === 'going_up_critical' || $event['event_type'] === 'going_down_critical') { + $failed_event[] = $event['utimestamp']; + $mtrs_events[]['failed_event'] = $event['utimestamp']; + } + + if ($event['event_type'] === 'going_up_normal' + || $event['event_type'] === 'going_down_normal' + || $event['event_type'] === 'going_up_warning' + || $event['event_type'] === 'going_down_warning' + ) { + $normal_event[] = $event['utimestamp']; + $mtrs_events[]['normal_event'] = $event['utimestamp']; + } + } + + $process_mtrs_events = []; + + if (empty($mtrs_events) === false) { + $last_event_key = ''; + foreach ($mtrs_events as $key => $val) { + if (key($val) !== $last_event_key) { + $last_event_key = key($val); + $process_mtrs_events[] = $val; + } + } + } + + $mtrs_array = []; + if (empty($normal_event) === true) { + $mtrs_array[] = ($current_time - $failed_event[0]); + } else if (empty($failed_event) === true) { + $mtrs_array[] = 0; + } else { + $last_value = ''; + foreach ($process_mtrs_events as $key => $val) { + $current_value = $val[key($val)]; + if ($last_value !== '') { + $mtrs_array[] = ($current_value - $last_value); + } + + $last_value = $current_value; + } + + $last_mtrs_event = key(end($process_mtrs_events)); + if ($last_mtrs_event === 'failed_event') { + $mtrs_array[] = ($current_time - $last_value); + } + } + + $mtbf_array = []; + + if (!empty($failed_event) === true) { + if (count($failed_event) > 1) { + for ($i = 1; $i <= array_key_last($failed_event); $i++) { + $mtbf_array[] = ($failed_event[$i] - ($failed_event[($i - 1)])); + } + } else { + $mtbf_array[] = 0; + } + } else { + $mtbf_array[] = 0; + } + + $total_time_failed = array_sum($mtrs_array); + $total_time_ok = ($interval_time - $total_time_failed); + if (count($events_time) === 1) { + if ((int) $first_utimestamp !== 0) { + $availability = round((($total_time_ok / $interval_time) * 100), 2); + } + } else { + $availability = round((($total_time_ok / $interval_time) * 100), 2); + } + + if ($critical_events > 1) { + $mtbf = round(array_sum($mtbf_array) / count($mtbf_array)); + } else { + $mtbf = false; + } + + if (count($mtrs_array) === 1 && (int) $first_utimestamp !== 0) { + $mtrs = round($total_time_failed / count($mtrs_array)); + } else if (count($mtrs_array) > 1 && (int) $first_utimestamp !== 0) { + $mtrs = round((array_sum($mtrs_array) / count($mtrs_array))); + } else { + $mtrs = false; + } + + $data['mtbf'] = $mtbf; + $data['mtrs'] = $mtrs; + $data['availability'] = $availability; + } else { + $data['mtbf'] = false; + $data['mtrs'] = false; + $data['availability'] = false; + } + + // Get last status change. + $sql = 'SELECT last_status_change FROM tagente_estado + WHERE id_agente_modulo = '.$id_agentmodule.' '; + + $last_status_change = db_get_sql($sql); + + // Get module name. + /* + $sql = 'SELECT nombre FROM tagente_modulo + WHERE id_agente_modulo = '.$id_agentmodule;*/ + + $sql = 'SELECT tagente_modulo.nombre as nombre, tagente.alias as alias + FROM tagente_modulo INNER JOIN tagente + ON tagente_modulo.id_agente = tagente.id_agente + WHERE id_agente_modulo = '.$id_agentmodule.' '; + $sql_query = db_get_all_rows_sql($sql); + + $data['critical_events'] = $critical_events; + $data['warning_events'] = $warning_events; + $data['last_status_change'] = $last_status_change; + $data['module_name'] = $sql_query[0]['nombre']; + if ((bool) is_metaconsole() === true) { + $data['agent_alias'] = $server_name['server_name'].' » '.$sql_query[0]['alias']; + } else { + $data['agent_alias'] = $sql_query[0]['alias']; + } + + if ((bool) is_metaconsole() === true) { + metaconsole_restore_db(); + } + + return $data; +} + + +/* + Check if modules are compatible with MADE server. * * @param integer $id_tipo_modulo * @retur boolean True if compatible, false otherwise. diff --git a/pandora_console/include/lib/Dashboard/Widget.php b/pandora_console/include/lib/Dashboard/Widget.php index ca48e6d61a..8ed3ece7f9 100644 --- a/pandora_console/include/lib/Dashboard/Widget.php +++ b/pandora_console/include/lib/Dashboard/Widget.php @@ -466,6 +466,10 @@ class Widget $className .= '\HeatmapWidget'; break; + case 'service_level': + $className .= '\ServiceLevelWidget'; + break; + case 'security_hardening': if (\enterprise_installed() === false) { $not_installed = true; diff --git a/pandora_console/include/lib/Dashboard/Widgets/service_level.php b/pandora_console/include/lib/Dashboard/Widgets/service_level.php new file mode 100644 index 0000000000..8184495587 --- /dev/null +++ b/pandora_console/include/lib/Dashboard/Widgets/service_level.php @@ -0,0 +1,672 @@ +width = $width; + + // Height. + $this->height = $height; + + // Grid Width. + $this->gridWidth = $gridWidth; + + // Options. + $this->values = $this->decoders($this->getOptionsWidget()); + + // Positions. + $this->position = $this->getPositionWidget(); + + // Page. + $this->page = basename(__FILE__); + + // ClassName. + $class = new \ReflectionClass($this); + $this->className = $class->getShortName(); + + // Title. + $this->title = __('Service Level Detail'); + + // Name. + if (empty($this->name) === true) { + $this->name = 'service_level'; + } + + // This forces at least a first configuration. + $this->configurationRequired = false; + if (isset($this->values['mModules']) === false) { + $this->configurationRequired = true; + } + + $this->overflow_scrollbars = false; + } + + + /** + * Decoders hack for retrocompability. + * + * @param array $decoder Values. + * + * @return array Returns the values ​​with the correct key. + */ + public function decoders(array $decoder): array + { + $values = []; + // Retrieve global - common inputs. + $values = parent::decoders($decoder); + + if (isset($decoder['interval']) === true) { + $values['interval'] = $decoder['interval']; + } else { + $values['interval'] = '28800'; + } + + if (isset($decoder['show_agents']) === true) { + $values['show_agents'] = $decoder['show_agents']; + } else { + $values['show_agents'] = '0'; + } + + if (isset($decoder['mTypeShow']) === true) { + $values['mTypeShow'] = $decoder['mTypeShow']; + } + + if (isset($decoder['mGroup']) === true) { + $values['mGroup'] = $decoder['mGroup']; + } + + if (isset($decoder['mRecursion']) === true) { + $values['mRecursion'] = $decoder['mRecursion']; + } + + if (isset($decoder['mModuleGroup']) === true) { + $values['mModuleGroup'] = $decoder['mModuleGroup']; + } + + if (isset($decoder['mAgents']) === true) { + $values['mAgents'] = $decoder['mAgents']; + } + + if (isset($decoder['mShowCommonModules']) === true) { + $values['mShowCommonModules'] = $decoder['mShowCommonModules']; + } + + if (isset($decoder['mModules']) === true) { + $values['mModules'] = $decoder['mModules']; + } + + return $values; + } + + + /** + * Generates inputs for form (specific). + * + * @return array Of inputs. + * + * @throws Exception On error. + */ + public function getFormInputs(): array + { + $values = $this->values; + + // Retrieve global - common inputs. + $inputs = parent::getFormInputs(); + + // Interval. + $fields = [ + '604800' => __('1 week'), + '172800' => __('48 hours'), + '86400' => __('24 hours'), + '43200' => __('12 hours'), + '28800' => __('8 hours'), + + ]; + + $inputs[] = [ + 'label' => __('Interval'), + 'arguments' => [ + 'type' => 'select', + 'fields' => $fields, + 'name' => 'interval-'.$this->cellId, + 'selected' => $values['interval'], + 'return' => true, + ], + ]; + + // Show agent. + $inputs[] = [ + 'label' => __('Show agents'), + 'arguments' => [ + 'type' => 'switch', + 'name' => 'show_agents-'.$this->cellId, + 'value' => $values['show_agents'], + 'return' => true, + ], + ]; + + $return_all_group = false; + + if (users_can_manage_group_all('RM') || $this->values['mGroup'] == 0) { + $return_all_group = true; + } + + $mgroup = ''; + if (isset($this->values['mGroup']) === false) { + $sql = sprintf( + 'SELECT id_group FROM tdashboard WHERE id = %d', + $this->dashboardId + ); + + $group_dahsboard = db_get_value_sql($sql); + if ($group_dahsboard > 0) { + $mgroup = $group_dahsboard; + } + } + + if (is_metaconsole() === true) { + $this->values['mAgents'] = $this->getIdCacheAgent($this->values['mAgents']); + } + + $inputs[] = [ + 'class' => 'flex flex-row', + 'id' => 'select_multiple_modules_filtered', + 'arguments' => [ + 'type' => 'select_multiple_modules_filtered', + 'uniqId' => $this->cellId, + 'mGroup' => (isset($this->values['mGroup']) === true) ? $this->values['mGroup'] : $mgroup, + 'mRecursion' => (isset($this->values['mRecursion']) === true) ? $this->values['mRecursion'] : '', + 'mModuleGroup' => (isset($this->values['mModuleGroup']) === true) ? $this->values['mModuleGroup'] : '', + 'mAgents' => (isset($this->values['mAgents']) === true) ? $this->values['mAgents'] : '', + 'mShowCommonModules' => (isset($this->values['mShowCommonModules']) === true) ? $this->values['mShowCommonModules'] : '', + 'mModules' => (isset($this->values['mModules']) === true) ? $this->values['mModules'] : '', + 'mShowSelectedOtherGroups' => true, + 'mReturnAllGroup' => $return_all_group, + 'mMetaFields' => ((bool) is_metaconsole()), + 'commonModulesSwitch' => true, + ], + ]; + + return $inputs; + } + + + /** + * Get Post for widget. + * + * @return array + */ + public function getPost():array + { + // Retrieve global - common inputs. + $values = parent::getPost(); + + $values['interval'] = \get_parameter('interval-'.$this->cellId, '28800'); + + $values['show_agents'] = \get_parameter('show_agents-'.$this->cellId, '0'); + + $values['mTypeShow'] = \get_parameter( + 'filtered-type-show-'.$this->cellId + ); + + $values['mGroup'] = \get_parameter( + 'filtered-module-group-'.$this->cellId + ); + $values['mRecursion'] = \get_parameter_switch( + 'filtered-module-recursion-'.$this->cellId + ); + $values['mModuleGroup'] = \get_parameter( + 'filtered-module-module-group-'.$this->cellId + ); + $values['mAgents'] = \get_parameter( + 'filtered-module-agents-'.$this->cellId + ); + if (is_metaconsole() === true) { + $values['mAgents'] = $this->getRealIdAgentNode($values['mAgents']); + } + + $values['mShowCommonModules'] = \get_parameter( + 'filtered-module-show-common-modules-'.$this->cellId + ); + $values['mModules'] = explode( + ',', + \get_parameter( + 'filtered-module-modules-'.$this->cellId + ) + ); + + return $values; + } + + + /** + * Draw widget. + * + * @return string; + */ + public function load() + { + global $config; + + $output = ''; + if (check_acl($config['id_user'], 0, 'AR') === 0) { + $output .= '
'; + $output .= ui_print_error_message( + __('You don\'t have access'), + '', + true + ); + $output .= '
'; + return $output; + } + + $interval_range = []; + $current_timestamp = time(); + $interval_range['start'] = ($current_timestamp - $this->values['interval']); + $interval_range['end'] = $current_timestamp; + + $reduceAllModules = array_reduce( + $this->values['mModules'], + function ($carry, $item) { + if ($item === null) { + return $carry; + } + + if (is_metaconsole() === true) { + $item = explode('|', $item); + $serverId = $item[0]; + $fullname = $item[1]; + if ($this->values['mShowCommonModules'] !== 'on') { + $item = explode(' » ', $fullname); + $name = $item[1]; + $carry['modules_selected'][$serverId][$name] = null; + $carry['modules'][$name] = null; + } else { + $carry['modules'][$fullname] = null; + } + } else { + $carry['modules'][$item] = null; + } + + return $carry; + } + ); + + $allModules = $reduceAllModules['modules']; + $visualData = []; + // Extract info agents selected. + $target_agents = explode(',', $this->values['mAgents']); + foreach ($target_agents as $agent_id) { + try { + if (is_metaconsole() === true && str_contains($agent_id, '|') === true) { + $server_agent = explode('|', $agent_id); + } else { + $id_agente = $agent_id; + } + + if ((bool) is_metaconsole() === true) { + if (isset($server_agent) === true) { + $id_agente = $server_agent[1]; + $tserver = $server_agent[0]; + } else { + $tmeta_agent = db_get_row_filter( + 'tmetaconsole_agent', + [ 'id_agente' => $id_agente ] + ); + $id_agente = $tmeta_agent['id_tagente']; + $tserver = $tmeta_agent['id_tmetaconsole_setup']; + } + + if (metaconsole_connect(null, $tserver) !== NOERR) { + continue; + } + } + + $agent = new Agent((int) $id_agente); + $visualData[$agent_id]['agent_status'] = $agent->lastStatus(); + $visualData[$agent_id]['agent_name'] = $agent->name(); + $visualData[$agent_id]['agent_alias'] = $agent->alias(); + $visualData[$agent_id]['modules'] = []; + if (empty($allModules) === false) { + if (is_metaconsole() === true && $this->values['mShowCommonModules'] !== 'on') { + if (isset($reduceAllModules['modules_selected'][$tserver]) === true) { + $modules = $agent->searchModules( + ['nombre' => array_keys($reduceAllModules['modules_selected'][$tserver])] + ); + } else { + $modules = null; + } + } else { + $modules = $agent->searchModules( + ['nombre' => array_keys($allModules)] + ); + } + } + + $visualData[$agent_id]['modules'] = $allModules; + + if ((bool) is_metaconsole() === true) { + metaconsole_restore_db(); + } + + foreach ($modules as $module) { + if ($module === null) { + continue; + } + + $data_module_array = $module->toArray(); + $visualData[$agent_id]['modules'][$module->name()] = []; + $last_status = $module->getStatus()->toArray(); + $visualData[$agent_id]['modules'][$module->name()]['last_status_change'] = $last_status['last_status_change']; + + // Mean Time Between Failure. + // Mean Time To Solution. + // Availability. + if ((bool) is_metaconsole() === true) { + $module_id = $tserver.'|'.$data_module_array['id_agente_modulo']; + } else { + $module_id = $data_module_array['id_agente_modulo']; + } + + $module_data = service_level_module_data($interval_range['start'], $interval_range['end'], $module_id); + $visualData[$agent_id]['modules'][$module->name()]['mtrs'] = ($module_data['mtrs'] !== false) ? human_milliseconds_to_string(($module_data['mtrs'] * 100), 'short') : '-'; + $visualData[$agent_id]['modules'][$module->name()]['mtbf'] = ($module_data['mtbf'] !== false) ? human_milliseconds_to_string(($module_data['mtbf'] * 100), 'short') : '-'; + $visualData[$agent_id]['modules'][$module->name()]['availability'] = ($module_data['availability'] !== false) ? $module_data['availability'] : '100'; + $visualData[$agent_id]['modules'][$module->name()]['critical_events'] = ($module_data['critical_events'] !== false) ? $module_data['critical_events'] : ''; + $visualData[$agent_id]['modules'][$module->name()]['warning_events'] = ($module_data['warning_events'] !== false) ? $module_data['warning_events'] : ''; + $visualData[$agent_id]['modules'][$module->name()]['last_status_change'] = ($module_data['last_status_change'] !== false) ? $module_data['last_status_change'] : ''; + $visualData[$agent_id]['modules'][$module->name()]['agent_alias'] = ($module_data['agent_alias'] !== false) ? $module_data['agent_alias'] : ''; + $visualData[$agent_id]['modules'][$module->name()]['module_name'] = ($module_data['module_name'] !== false) ? $module_data['module_name'] : ''; + } + } catch (\Exception $e) { + echo 'Error: ['.$agent_id.']'.$e->getMessage(); + } + } + + $table = new \stdClass(); + + $table->width = '100%'; + $table->class = 'databox filters filter-table-adv'; + + $table->head = []; + $show_agents = $this->values['show_agents']; + if ($show_agents === 'on') { + $table->head[0] = __('Agent / Modules'); + } else { + $table->head[0] = __('Modules'); + } + + $table->head[1] = __('% Av.'); + $table->head[2] = __('MTBF'); + $table->head[3] = __('MTRS'); + $table->head[4] = __('Crit. Events').ui_print_help_tip(__('Counted only critical events generated automatic by the module'), true); + $table->head[5] = __('Warn. Events').ui_print_help_tip(__('Counted only warning events generated automatic by the module'), true); + $table->head[6] = __('Last change'); + $table->data = []; + $table->cellstyle = []; + $row = 0; + foreach ($visualData as $agent_id => $data) { + foreach ($data['modules'] as $module_name => $module_data) { + if (isset($module_data) === true) { + if ($show_agents === 'on') { + $table->data[$row][0] = $module_data['agent_alias'].' / '.$module_data['module_name']; + $table->cellstyle[$row][0] = 'text-align:left'; + } else { + $table->data[$row][0] = $module_data['module_name']; + $table->cellstyle[$row][0] = 'text-align:left'; + } + + $table->data[$row][1] = $module_data['availability'].'%'; + $table->data[$row][2] = $module_data['mtbf']; + $table->data[$row][3] = $module_data['mtrs']; + $table->data[$row][4] = $module_data['critical_events']; + $table->data[$row][5] = $module_data['warning_events']; + $table->data[$row][6] = date(TIME_FORMAT, $module_data['last_status_change']); + } + + $row++; + } + } + + $height = (count($table->data) * 32); + $style = 'min-width:400px; min-height:'.$height.'px;'; + $output = '
'; + $output .= html_print_table($table, true); + $output .= '
'; + + return $output; + } + + + /** + * Get description. + * + * @return string. + */ + public static function getDescription() + { + return __('Service Level Detail'); + } + + + /** + * Get Name. + * + * @return string. + */ + public static function getName() + { + return 'service_level'; + } + + + /** + * Get size Modal Configuration. + * + * @return array + */ + public function getSizeModalConfiguration(): array + { + $size = [ + 'width' => 800, + 'height' => 270, + ]; + + return $size; + } + + + /** + * Return array with the real id agent and server. + * + * @param string $id_agents_cache String with the agents cache id. + * + * @return string $agents_servers with the real id agent and server. + */ + public function getRealIdAgentNode($id_agents_cache) + { + $agents_servers = []; + $target_agents = explode(',', $id_agents_cache); + foreach ($target_agents as $agent_id) { + $id_agente = $agent_id; + $tmeta_agent = db_get_row_filter( + 'tmetaconsole_agent', + ['id_agente' => $id_agente] + ); + + $id_agente = $tmeta_agent['id_tagente']; + $tserver = $tmeta_agent['id_tmetaconsole_setup']; + $agents_servers[] = $tserver.'|'.$id_agente; + } + + return implode(',', $agents_servers); + } + + + /** + * Return string with the cache id agent in metaconsole. + * + * @param string $id_agents String with the agents and server id. + * + * @return string $cache_id_agents with the cache id agent. + */ + public function getIdCacheAgent($id_agents) + { + $target_agents = explode(',', $id_agents); + $cache_id_agents = []; + foreach ($target_agents as $agent_id) { + if (str_contains($agent_id, '|') === false) { + $cache_id_agents[] = $agent_id; + continue; + } + + $server_agent = explode('|', $agent_id); + $tmeta_agent = db_get_row_filter( + 'tmetaconsole_agent', + [ + 'id_tagente' => $server_agent[1], + 'id_tmetaconsole_setup' => $server_agent[0], + ] + ); + $cache_id_agents[] = $tmeta_agent['id_agente']; + } + + return implode(',', $cache_id_agents); + } + + +} diff --git a/pandora_console/include/styles/dashboards.css b/pandora_console/include/styles/dashboards.css index 5a263b9246..1bcf43a16f 100644 --- a/pandora_console/include/styles/dashboards.css +++ b/pandora_console/include/styles/dashboards.css @@ -284,6 +284,11 @@ li#div-textarea label { display: initial; } +.content-widget .container-top { + height: 100%; + width: 99%; +} + .widget-groups-status { display: flex; flex-direction: row; diff --git a/pandora_console/include/styles/pandora_black.css b/pandora_console/include/styles/pandora_black.css index 1e2cc377fc..a3025c3a33 100644 --- a/pandora_console/include/styles/pandora_black.css +++ b/pandora_console/include/styles/pandora_black.css @@ -784,6 +784,11 @@ form ul.form_flex { width: 100%; } +.content-widget .container-top { + height: 100%; + width: 99%; +} + .container-layout { border-radius: 5px; border: 3px dashed #fff; diff --git a/pandora_console/operation/agentes/pandora_networkmap.view.php b/pandora_console/operation/agentes/pandora_networkmap.view.php index 5256c10871..3cbe53e815 100644 --- a/pandora_console/operation/agentes/pandora_networkmap.view.php +++ b/pandora_console/operation/agentes/pandora_networkmap.view.php @@ -1205,57 +1205,6 @@ if (is_ajax() === true) { return; } - if ($get_agents_in_group) { - $id = (int) get_parameter('id', 0); - $group = (int) get_parameter('group', -1); - - $return = []; - $return['correct'] = false; - - if ($group != -1) { - $where_id_agente = ' 1=1 '; - - $agents_in_networkmap = db_get_all_rows_filter( - 'titem', - [ - 'id_map' => $id, - 'deleted' => 0, - ] - ); - if ($agents_in_networkmap !== false) { - $ids = []; - foreach ($agents_in_networkmap as $agent) { - if ($agent['type'] == 0) { - $ids[] = $agent['source_data']; - } - } - - $where_id_agente = ' id_agente NOT IN ('.implode(',', $ids).')'; - } - - - $sql = 'SELECT id_agente, alias - FROM tagente - WHERE id_grupo = '.$group.' AND '.$where_id_agente.' - ORDER BY alias ASC'; - - $agents = db_get_all_rows_sql($sql); - - if ($agents !== false) { - $return['agents'] = []; - foreach ($agents as $agent) { - $return['agents'][$agent['id_agente']] = $agent['alias']; - } - - $return['correct'] = true; - } - } - - echo json_encode($return); - - return; - } - if ($get_agent_info) { $id_agent = (int) get_parameter('id_agent');