From b1621c7302f3c8e74e3b08a941e2a58514e88c18 Mon Sep 17 00:00:00 2001 From: slerena Date: Wed, 23 Apr 2008 15:06:48 +0000 Subject: [PATCH] 2008-04-23 Sancho Lerena * Config.pm: Added dataserver_thread config token * bin/pandora_plugin: Some minimal thread improvements (yield) * bin/pandora_server: Uses dataserver_thread token to set up number of starting threads. * bin/pandora_network: Added more thread yields. * util/plugin: Added new directory for "standard" plugins. Added the first plugins here. Expect more in the future :-) * plugin/openvpn_pandoraplugin.pl: Connects to openvpn daemon and report number of active sessions. * plugin/ssh-exec_pandoraplugin.pl: Execute a remote command using Perl (Net::SSH::Perl) SSH functions. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@815 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f --- pandora_server/ChangeLog | 20 +++ pandora_server/bin/pandora_network | 1 + pandora_server/bin/pandora_plugin | 20 +-- pandora_server/bin/pandora_server | 6 +- pandora_server/lib/PandoraFMS/Config.pm | 6 +- .../util/plugin/openvpn_pandoraplugin.pl | 137 ++++++++++++++++++ .../util/plugin/ssh-exec_pandoraplugin.pl | 134 +++++++++++++++++ 7 files changed, 305 insertions(+), 19 deletions(-) create mode 100755 pandora_server/util/plugin/openvpn_pandoraplugin.pl create mode 100755 pandora_server/util/plugin/ssh-exec_pandoraplugin.pl diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog index 67e59918e3..d14a483743 100644 --- a/pandora_server/ChangeLog +++ b/pandora_server/ChangeLog @@ -1,3 +1,23 @@ +2008-04-23 Sancho Lerena + + * Config.pm: Added dataserver_thread config token + + * bin/pandora_plugin: Some minimal thread improvements (yield) + + * bin/pandora_server: Uses dataserver_thread token to set up + number of starting threads. + + * bin/pandora_network: Added more thread yields. + + * util/plugin: Added new directory for "standard" plugins. + Added the first plugins here. Expect more in the future :-) + + * plugin/openvpn_pandoraplugin.pl: Connects to openvpn daemon + and report number of active sessions. + + * plugin/ssh-exec_pandoraplugin.pl: Execute a remote command + using Perl (Net::SSH::Perl) SSH functions. + 2008-04-22 Ramon Novoa * bin/pandora_plugin, bin/pandora_prediction, diff --git a/pandora_server/bin/pandora_network b/pandora_server/bin/pandora_network index 51cee7bc1f..82527ee111 100755 --- a/pandora_server/bin/pandora_network +++ b/pandora_server/bin/pandora_network @@ -146,6 +146,7 @@ sub pandora_network_consumer ($$) { LOOP: while (1) { if ($counter > 10) { + threads->yield; sleep (1); $counter = 0; } diff --git a/pandora_server/bin/pandora_plugin b/pandora_server/bin/pandora_plugin index 507b827372..014b874dc9 100755 --- a/pandora_server/bin/pandora_plugin +++ b/pandora_server/bin/pandora_plugin @@ -134,6 +134,7 @@ sub pandora_plugin_consumer ($$) { LOOP: while (1) { if ($counter > 10) { + threads->yield; sleep (1); $counter = 0; } @@ -148,7 +149,6 @@ sub pandora_plugin_consumer ($$) { } $data_id_agent_module = shift(@pending_task); -#print "[CLIENT] Pop out of queue module (pending queue) $data_id_agent_module \n"; delete($pending_task_hash{$data_id_agent_module}); $current_task_hash{$data_id_agent_module}=1; } @@ -157,7 +157,6 @@ sub pandora_plugin_consumer ($$) { eval { # Call network execution process # exec_network_module ( $pa_config, $data_id_agent_module, $dbh); -print "[CLIENT] Executing module $data_id_agent_module \n"; exec_plugin_module ($pa_config, $data_id_agent_module, $dbh); }; if ($@){ @@ -169,10 +168,10 @@ print "[CLIENT] Executing module $data_id_agent_module \n"; # not been processed, but has been freed from task queue { lock $queue_lock; -#print "[CLIENT] Removing from queue (current task) module $data_id_agent_module \n"; delete($current_task_hash{$data_id_agent_module}); } $counter = 0; + threads->yield; } } @@ -181,7 +180,6 @@ sub pandora_plugin_producer ($) { print " [*] Starting up Plugin Producer Thread ...\n"; my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 }); - my $server_id = $pa_config->{'server_id'}; # Initialize variables for posterior usage @@ -239,13 +237,11 @@ sub pandora_plugin_producer ($) { ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() OR tagente_modulo.flag = 1 ) ORDER BY last_execution_try ASC"; } -#print "[DEBUG] SQL is $query1 \n"; $exec_sql1 = $dbh->prepare($query1); $exec_sql1 ->execute; while (@sql_data1 = $exec_sql1->fetchrow_array()) { $data_id_agente_modulo = $sql_data1[0]; $data_flag = $sql_data1[1]; -print "[DEBUG] Procesando candidato $data_id_agente_modulo\n"; # Skip modules already queued if ((!defined($pending_task_hash{$data_id_agente_modulo})) && @@ -255,16 +251,14 @@ print "[DEBUG] Procesando candidato $data_id_agente_modulo\n"; } # Locking scope, do not remove redundant { } { -#print "[DEBUG] Metiendo $data_id_agente_modulo en cola \n"; lock $queue_lock; push (@pending_task, $data_id_agente_modulo); $pending_task_hash {$data_id_agente_modulo}=1; } } } - #logger ($pa_config, "Items in Network Pending Queue: ".scalar(@pending_task), 5); -#print "[DEBUG] Items in Network Pending Queue: ".scalar(@pending_task); $exec_sql1->finish(); + threads->yield; sleep($pa_config->{"server_threshold"}); } # Main loop } @@ -336,17 +330,15 @@ sub exec_plugin_module { $module_result = 0; # If comes here, this is a successfull exec }; -# print "[DEBUG] Output for $plugin_command is --$module_data-- \n"; # Timeout if ($@ =~ /PANDORA PLUGIN SERVER TIMED OUT/) { logger ($pa_config, "[ERROR] Plugin Task for module ".$agent_module->{'id_agente_modulo'}." causes a system timeout in exec", 1); logger ($pa_config, "Executing plugin command '$plugin_command'", 9); -print "[DEBUG] Executing plugin TIMEOUT\n"; + # General error, not timed-out } elsif ($module_result == 1) { logger ($pa_config, "[ERROR] Plugin Task for module ".$agent_module->{'id_agente_modulo'}." causes an unknown system error", 1); logger ($pa_config, "[ERROR] $@", 1); -print "[DEBUG] Executing plugin ERROR $@\n"; } sub timed_out { @@ -359,7 +351,6 @@ print "[DEBUG] Executing plugin ERROR $@\n"; # If module execution get a valid value if ($module_result == 0) { -print "[DEBUG] MODULERESULT = 0\n"; my %part; $part{'name'}[0] = $agent_module->{'nombre'}; $part{'description'}[0] = ""; @@ -383,7 +374,6 @@ print "[DEBUG] MODULERESULT = 0\n"; } # Generic_proc elsif (2 == $agent_module->{'id_tipo_modulo'}) { -print "[DEBUG FINAL]: ".$agent_module->{'nombre'}." ".$module_data." ".$tipo_modulo." ".$agent_name. " ".$timestamp; module_generic_proc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh); } elsif ( (19 == $agent_module->{'id_tipo_modulo'}) || (20 == $agent_module->{'id_tipo_modulo'}) ) { @@ -391,7 +381,6 @@ print "[DEBUG FINAL]: ".$agent_module->{'nombre'}." ".$module_data." ".$tipo } else { # Unknown module!, this IS a problem logger ($pa_config, "Plugin Server Problem with unknown module type '$tipo_modulo'", 0); -print "[DEBUG] Executing plugin UNKONWN MODULE TYPE$@\n"; $module_result = 1; } # Update agent last contact @@ -401,7 +390,6 @@ print "[DEBUG] Executing plugin UNKONWN MODULE TYPE$@\n"; # If something went wrong in module processing... if ($module_result != 0){ -print "[DEBUG] MODULERESULT != 0\n"; # If module execution get a INVALID value if ($agent_module->{'intervalo'} == 0){ diff --git a/pandora_server/bin/pandora_server b/pandora_server/bin/pandora_server index d78f359351..1f39cbbb63 100755 --- a/pandora_server/bin/pandora_server +++ b/pandora_server/bin/pandora_server @@ -3,6 +3,7 @@ # Pandora Data Server ########################################################################## # Copyright (c) 2004-2008 Sancho Lerena, slerena@gmail.com +# Copyright (c) 2008 Ramon Novoa, rnovoa@artica.es # Copyright (c) 2005-2008 Artica Soluciones Tecnologicas S.L # # This program is free software; you can redistribute it and/or @@ -68,7 +69,7 @@ if ( $pa_config{"daemon"} eq "1" ){ } # Launch all data_consumer threads -for (my $ax=0; $ax < $pa_config{'plugin_threads'}; $ax++){ +for (my $ax=0; $ax < $pa_config{"dataserver_threads"}; $ax++){ threads->new( \&pandora_data_consumer, \%pa_config, $ax); } @@ -186,7 +187,8 @@ sub pandora_data_consumer ($$) { LOOP: while (1) { if ($counter > 10) { - $counter = 0; + $counter = 0; + threads->yield; sleep (1); } diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 2afa928544..606fec0793 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -38,7 +38,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "2.0-dev"; -my $pandora_build="PS080404"; +my $pandora_build="PS080422"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash @@ -180,6 +180,7 @@ sub pandora_loadconfig { $pa_config->{"wmi_threads"} = 3; # Introduced on 2.0 $pa_config->{"wmi_timeout"} = 5; # Introduced on 2.0 $pa_config->{"compound_max_depth"} = 5; # Maximum nested compound alert depth. Not in config file. + $pa_config->{"dataserver_threads"} = 3; # Introduced on 2.0 # Check for UID0 if ($pa_config->{"quiet"} != 0){ @@ -347,6 +348,9 @@ sub pandora_loadconfig { elsif ($parametro =~ m/^plugin_timeout\s([0-9]*)/i) { $pa_config->{'plugin_timeout'}= clean_blank($1); } + elsif ($parametro =~ m/^dataserver_threads\s([0-9]*)/i) { + $pa_config->{'dataserver_threads'}= clean_blank($1); + } elsif ($parametro =~ m/^server_keepalive\s([0-9]*)/i) { $pa_config->{"keepalive"} = clean_blank($1); $pa_config->{"keepalive_orig"} = clean_blank($1); diff --git a/pandora_server/util/plugin/openvpn_pandoraplugin.pl b/pandora_server/util/plugin/openvpn_pandoraplugin.pl new file mode 100755 index 0000000000..11d036ce97 --- /dev/null +++ b/pandora_server/util/plugin/openvpn_pandoraplugin.pl @@ -0,0 +1,137 @@ +#!/usr/bin/perl +################################################################################## +# OpenVPN Plugin for Pandora FMS 2.0 +# (c) Sancho Lerena 2008, slerena@gmail.com +# This is the first plugin for Pandora FMS 2.0 plugin server +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +################################################################################## + +my $cfg_remote_host = ""; +my $cfg_remote_port = ""; +my $cfg_password = ""; +my $cfg_timeout = 10; +my $cfg_quiet = 0; + +use Net::Telnet; +use Getopt::Std; +use strict; + +# ------------------------------------------------------------------------------------------ +# This function show a brief doc. +# ------------------------------------------------------------------------------------------ +sub help { + print "OpenVPN Plugin for Pandora FMS 2.0, (c) Sancho Lerena 2008 \n"; + print "Syntax: \n\n"; + print "\t -a \n\t -w \n\t -p \n\t -t \n\t -q\n"; + print "\n"; +} + +# ------------------------------------------------------------------------------------------ +# Print an error and exit the program. +# ------------------------------------------------------------------------------------------ +sub error { + if ($cfg_quiet == 0) { + print (STDERR "[err] $_[0]\n"); + } + exit 1; +} + + +# ------------------------------------------------------------------------------------------ +# Read configuration from commandline parameters +# ------------------------------------------------------------------------------------------ +sub config { + my %opts; + my $tmp; + + # Get options + if (getopts ('a:w:p:t:hq', \%opts) == 0 || defined ($opts{'h'})) { + help (); + exit 1; + } + + # Address + if (defined ($opts{'a'})) { + $cfg_remote_host = $opts{'a'}; + if ($cfg_remote_host !~ /^[a-zA-Z\.]+$/ && ($cfg_remote_host !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ + || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 + || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) { + error ("Address $cfg_remote_host is not valid."); + } + } + + # Password + if (defined ($opts{'w'})) { + $cfg_password = $opts{'w'}; + } + + # Timeout + if (defined ($opts{'t'})) { + $cfg_timeout = $opts{'t'}; + } + + # Port + if (defined ($opts{'p'})) { + $cfg_remote_port = $opts{'p'}; + if (($cfg_remote_port > 65550) || ($cfg_remote_port < 1)){ + error ("Port $cfg_remote_port is not valid."); + } + } + + # Quiet mode + if (defined ($opts{'q'})) { + $cfg_quiet = 1; + } + + if (($cfg_remote_host eq "") || ($cfg_remote_port eq "")){ + error ("You need to define remote host and remote port to use this plugin"); + } +} + +# ------------------------------------------------------------------------------------------ +# This function connects and get number of users currently connected to OpenVPN +# ------------------------------------------------------------------------------------------ + +sub get_users { + my $line; + my $exit = 0; + my $clients = 0; + eval { + my $telnet = new Net::Telnet ( Timeout=>$cfg_timeout, Errmode=>'die', Port => $cfg_remote_port); + $telnet->open($cfg_remote_host); + $telnet->waitfor('/ENTER PASSWORD/i'); + $telnet->print($cfg_password); + $telnet->waitfor('/OpenVPN Management Interface/i'); + $telnet->print("status 2"); + while ($exit == 0) { + $line = $telnet->getline; + if ($line =~ m/END/i){ + $exit = 1; + } + if ($line =~ m/^CLIENT_LIST/i){ + $clients++; + } + } + $telnet->print("quit"); + $telnet->close(); + }; + return $clients; +} + +# ------------------------------------------------------------------------------------------ +# Main program +# ------------------------------------------------------------------------------------------ + + config(); + print get_users(); + exit; diff --git a/pandora_server/util/plugin/ssh-exec_pandoraplugin.pl b/pandora_server/util/plugin/ssh-exec_pandoraplugin.pl new file mode 100755 index 0000000000..d4e2083058 --- /dev/null +++ b/pandora_server/util/plugin/ssh-exec_pandoraplugin.pl @@ -0,0 +1,134 @@ +#!/usr/bin/perl +################################################################################## +# OpenVPN Plugin for Pandora FMS 2.0 +# (c) Sancho Lerena 2008, slerena@gmail.com +# This is the first plugin for Pandora FMS 2.0 plugin server +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +################################################################################## + +my $cfg_remote_host = ""; +my $cfg_remote_port = "22"; +my $cfg_password = ""; +my $cfg_user = ""; +my $cfg_command = ""; +my $cfg_timeout = 10; +my $cfg_quiet = 0; + +use Net::SSH::Perl; +use Getopt::Std; +use strict; + +# ------------------------------------------------------------------------------------------ +# This function show a brief doc. +# ------------------------------------------------------------------------------------------ +sub help { + print "SSH-Exec Plugin for Pandora FMS 2.0, (c) Sancho Lerena 2008 \n"; + print "Syntax: \n\n"; + print "\t -a \n\t -u \n\t -w \n\t -p \n\t -c \n\t -t \n\t -q\n"; + print "\n"; +} + +# ------------------------------------------------------------------------------------------ +# Print an error and exit the program. +# ------------------------------------------------------------------------------------------ +sub error { + if ($cfg_quiet == 0) { + print (STDERR "[err] $_[0]\n"); + } + exit 1; +} + + +# ------------------------------------------------------------------------------------------ +# Read configuration from commandline parameters +# ------------------------------------------------------------------------------------------ +sub config { + my %opts; + my $tmp; + + # Get options + if (getopts ('u:c:a:w:p:t:hq', \%opts) == 0 || defined ($opts{'h'})) { + help (); + exit 1; + } + + # Address + if (defined ($opts{'a'})) { + $cfg_remote_host = $opts{'a'}; + if ($cfg_remote_host !~ /^[a-zA-Z\.]+$/ && ($cfg_remote_host !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ + || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 + || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) { + error ("Address $cfg_remote_host is not valid."); + } + } + + # Password + if (defined ($opts{'w'})) { + $cfg_password = $opts{'w'}; + } + + # Command + if (defined ($opts{'c'})) { + $cfg_command = $opts{'c'}; + } + + # User + if (defined ($opts{'u'})) { + $cfg_user = $opts{'u'}; + } + + # Timeout + if (defined ($opts{'t'})) { + $cfg_timeout = $opts{'t'}; + } + + # Port + if (defined ($opts{'p'})) { + $cfg_remote_port = $opts{'p'}; + if (($cfg_remote_port > 65550) || ($cfg_remote_port < 1)){ + error ("Port $cfg_remote_port is not valid."); + } + } + + # Quiet mode + if (defined ($opts{'q'})) { + $cfg_quiet = 1; + } + + if (($cfg_remote_host eq "") || ($cfg_remote_port eq "")){ + error ("You need to define remote host and remote port to use this plugin"); + } +} + +# ------------------------------------------------------------------------------------------ +# This function exec a remote command using SSH +# ------------------------------------------------------------------------------------------ +sub ssh_exec { + my $out; + my $err; + my $exit; + my $ssh = Net::SSH::Perl->new($cfg_remote_host, options => [ "Port $cfg_remote_port", + "BatchMode yes" ]); + $ssh->login($cfg_user, $cfg_password); + ($out, $err, $exit) = $ssh->cmd($cfg_command); + return $out; +} + +# ------------------------------------------------------------------------------------------ +# Main program +# ------------------------------------------------------------------------------------------ + + config(); + print ssh_exec(); + exit; +