2017-11-14 15:17:27 +01:00
#!/usr/bin/perl
# Pandora FMS Agent Plugin for Monitoring FTP servers
2023-06-23 23:44:33 +02:00
# Mario Pulido (c) Pandora FMS <info@pandorafms.com> 2012
2017-11-14 15:17:27 +01:00
# v1.0, 18 Jun 2012
# ------------------------------------------------------------------------
use strict ;
use warnings ;
use Data::Dumper ;
use Net::FTP ;
2019-09-10 14:26:50 +02:00
use Net::SFTP::Foreign ;
2017-11-14 15:17:27 +01:00
use Time::HiRes qw ( gettimeofday ) ;
my $ archivo_cfg = $ ARGV [ 0 ] ;
# Hash with this plugin setup
my % plugin_setup ;
# FLUSH in each IO
$| = 1 ;
my $ version = "v1r1" ;
# ----------------------------------------------------------------------------
# This cleans DOS-like line and cleans ^M character. VERY Important when you process .conf edited from DOS
# ----------------------------------------------------------------------------
sub parse_dosline ($)
{
my $ str = $ _ [ 0 ] ;
$ str =~ s/\r//g ;
return $ str ;
}
sub clean_blank ($)
{
my $ input = $ _ [ 0 ] ;
$ input =~ s/[\s\r\n]*//g ;
return $ input ;
}
# ----------------------------------------------------------------------------
# print_module
#
# This function return a pandora FMS valid module fiven name, type, value, description
# ----------------------------------------------------------------------------
sub print_module ($$$$)
{
my $ MODULE_NAME = $ _ [ 0 ] ;
my $ MODULE_TYPE = $ _ [ 1 ] ;
my $ MODULE_VALUE = $ _ [ 2 ] ;
my $ MODULE_DESC = $ _ [ 3 ] ;
# If not a string type, remove all blank spaces!
if ( $ MODULE_TYPE !~ m/string/ )
{
$ MODULE_VALUE = clean_blank ( $ MODULE_VALUE ) ;
}
print "<module>\n" ;
print "<name><![CDATA[$MODULE_NAME]]></name>\n" ;
print "<type>$MODULE_TYPE</type>\n" ;
print "<data><![CDATA[$MODULE_VALUE]]></data>\n" ;
print "<description><![CDATA[$MODULE_DESC]]></description>\n" ;
print "</module>\n" ;
}
# ----------------------------------------------------------------------------
# load_external_setup
#
# Load external file containing configuration
# ----------------------------------------------------------------------------
sub load_external_setup ($) ; # Declaration due a recursive call to itself on includes
sub load_external_setup ($)
{
my $ archivo_cfg = $ _ [ 0 ] ;
my $ buffer_line ;
my @ config_file ;
my $ parametro = "" ;
# Collect items from config file and put in an array
if ( ! open ( CFG , "< $archivo_cfg" ) ) {
print "[ERROR] Error opening configuration file $archivo_cfg: $!.\n" ;
exit 1 ;
}
while ( <CFG> ) {
$ buffer_line = parse_dosline ( $ _ ) ;
# Parse configuration file, this is specially difficult because can contain SQL code, with many things
if ( $ buffer_line !~ /^\#/ ) { # begins with anything except # (for commenting)
if ( $ buffer_line =~ m/(.+)\s(.*)/ ) {
push @ config_file , $ buffer_line ;
}
}
}
close ( CFG ) ;
foreach ( @ config_file )
{
$ parametro = $ _ ;
if ( $ parametro =~ m/^conf\_ftp\_user\s(.*)/i ) {
$ plugin_setup { "conf_ftp_user" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_pass\s(.*)/i ) {
$ plugin_setup { "conf_ftp_pass" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_host\s(.*)/i ) {
$ plugin_setup { "conf_ftp_host" } = $ 1 ;
}
2019-09-10 14:26:50 +02:00
if ( $ parametro =~ m/^conf\_ftp\_port\s(.*)/i ) {
$ plugin_setup { "conf_ftp_port" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_sftp\s(.*)/i ) {
$ plugin_setup { "conf_ftp_sftp" } = $ 1 ;
}
2017-11-14 15:17:27 +01:00
if ( $ parametro =~ m/^conf\_ftp\_putfile\s(.*)/i ) {
$ plugin_setup { "conf_ftp_putfile" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_getfile\s(.*)/i ) {
$ plugin_setup { "conf_ftp_getfile" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_putname\s(.*)/i ) {
$ plugin_setup { "conf_ftp_putname" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_getname\s(.*)/i ) {
$ plugin_setup { "conf_ftp_getname" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_compare_file\s(.*)/i ) {
$ plugin_setup { "conf_ftp_compare_file" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_local\_comp_file\s(.*)/i ) {
$ plugin_setup { "conf_local_comp_file" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_local\_downcomp_file\s(.*)/i ) {
$ plugin_setup { "conf_local_downcomp_file" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_operating\_system\s(.*)/i ) {
$ plugin_setup { "conf_operating_system" } = $ 1 ;
}
if ( $ parametro =~ m/^conf\_ftp\_compare\s(.*)/i ) {
$ plugin_setup { "conf_ftp_compare" } = $ 1 ;
}
}
}
#-------------------------------------------------------------------------
#
# Main function
#
#--------------------------------------------------------------------------
# Parse external configuration file
# Load config file from command line
if ( $# ARGV == - 1 )
{
print "I need at least one parameter: Complete path to external configuration file \n" ;
print "\n" ;
print "Pandora_Plugin_FTP Version $version\n" ;
exit ;
}
# Check for file
if ( ! - f $ archivo_cfg )
{
printf "\n [ERROR] Cannot open configuration file at $archivo_cfg. \n\n" ;
exit 1 ;
}
load_external_setup ( $ archivo_cfg ) ;
#-------------------------------------------------------------------------
# Start session in FTP server
#--------------------------------------------------------------------------
2019-09-10 14:26:50 +02:00
my $ ftp ;
if ( ( $ plugin_setup { "conf_ftp_sftp" } ) && ( $ plugin_setup { "conf_ftp_sftp" } == 1 ) ) {
if ( $ plugin_setup { "conf_ftp_port" } ) {
#port => $plugin_setup{"port"},
$ ftp = Net::SFTP::Foreign - > new ( host = > $ plugin_setup { "conf_ftp_host" } , port = > $ plugin_setup { "conf_ftp_port" } , stderr_discard = > 1 , user = > $ plugin_setup { "conf_ftp_user" } , password = > $ plugin_setup { "conf_ftp_pass" } , expect_log_user = > 'false' ) ;
if ( $ ftp - > error ) {
die ( $ ftp - > error ) ;
}
} else {
$ ftp = Net::SFTP::Foreign - > new ( host = > $ plugin_setup { "conf_ftp_host" } , stderr_discard = > 1 , user = > $ plugin_setup { "conf_ftp_user" } , password = > $ plugin_setup { "conf_ftp_pass" } , expect_log_user = > 'false' ) ;
if ( $ ftp - > error ) {
die ( $ ftp - > error ) ;
}
}
} else {
if ( $ plugin_setup { "conf_ftp_port" } ) {
$ ftp = Net::FTP - > new ( host = > $ plugin_setup { "conf_ftp_host" } , port = > $ plugin_setup { "conf_ftp_port" } ) or die ( "Unable to connect to server: $!" ) ; #Connect FTP server
} else {
$ ftp = Net::FTP - > new ( $ plugin_setup { "conf_ftp_host" } ) or die ( "Unable to connect to server: $!" ) ; #Connect FTP server
}
$ ftp - > login ( $ plugin_setup { "conf_ftp_user" } , $ plugin_setup { "conf_ftp_pass" } ) or die ( "Failed Login: $!" ) ; # Login at FTP server
2017-11-14 15:17:27 +01:00
#print_module ( "Disp_FTP_$plugin_setup{conf_ftp_host}" , "generic_proc", 1, " Determines whether FTP login to $plugin_setup{conf_ftp_host} has been successful or not" );
2019-09-10 14:26:50 +02:00
}
2017-11-14 15:17:27 +01:00
#-------------------------------------------------------------------------
# Returns the module that shows the time and transfer rate.(Upload a file)
#--------------------------------------------------------------------------
my $ clock0 = gettimeofday ( ) ;
2019-09-10 14:26:50 +02:00
$ ftp - > put ( $ plugin_setup { "conf_ftp_putfile" } , $ plugin_setup { "conf_ftp_putname" } ) or die ( "Cannot upload file to server" ) ; # Upload file at FTP server
2017-11-14 15:17:27 +01:00
my $ clock1 = gettimeofday ( ) ;
my $ clockd = $ clock1 - $ clock0 ; # Calculate upload transfer time
2019-09-10 14:26:50 +02:00
my $ putrate = $ ftp - > stat ( $ plugin_setup { "conf_ftp_putname" } ) - > size / $ clockd ; # Calculate rate transfer
2017-11-14 15:17:27 +01:00
my $ time_puftp = sprintf ( "%.2f" , $ clockd ) ;
my $ rate_puftp = sprintf ( "%.2f" , $ putrate ) ;
print_module ( "PUT_file_transfer_time_$plugin_setup{conf_ftp_putname}" , "generic_data" , $ time_puftp , " Show the time it takes to upload $plugin_setup{conf_ftp_putname} , at FTP server " ) ;
print_module ( "PUT_file_transfer_rate_$plugin_setup{conf_ftp_putname}" , "generic_data" , $ rate_puftp , " Show rate transfer to upload $plugin_setup{conf_ftp_putname} , at FTP server in B/s " ) ;
#-------------------------------------------------------------------------
# Returns the module that shows the time and transfer rate (Download a file)
#--------------------------------------------------------------------------
my $ clock2 = gettimeofday ( ) ;
$ ftp - > get ( $ plugin_setup { "conf_ftp_getfile" } , $ plugin_setup { "conf_ftp_getname" } ) ;
my $ clock3 = gettimeofday ( ) ;
my $ clockg = $ clock3 - $ clock2 ;
2019-09-10 14:26:50 +02:00
#$ftp->stat($plugin_setup{"conf_ftp_getname"})->size;
my $ getrate = $ ftp - > stat ( $ plugin_setup { "conf_ftp_getname" } ) - > size / $ clockg ;
2017-11-14 15:17:27 +01:00
my $ time_getftp = sprintf ( "%.2f" , $ clockg ) ;
my $ rate_getftp = sprintf ( "%.2f" , $ getrate ) ;
print_module ( "GET_file_transfer_time_$plugin_setup{conf_ftp_getfile}" , "generic_data" , $ time_getftp , " Show the time it takes to download $plugin_setup{conf_ftp_getfile} , at FTP server " ) ;
print_module ( "GET_file_transfer_rate_$plugin_setup{conf_ftp_getfile}" , "generic_data" , $ rate_getftp , " Show rate transfer to download $plugin_setup{conf_ftp_getfile} , at FTP server in B/s " ) ;
#-------------------------------------------------------------------------
# Returns the module that compares file changes between a server_file and local_file
#--------------------------------------------------------------------------
my $ compare_unix ;
my $ compare_wdos ;
# Download file server
$ ftp - > get ( $ plugin_setup { "conf_ftp_compare_file" } , $ plugin_setup { "conf_local_downcomp_file" } ) ;
# Compare file between server_file and local_file
if ( $ plugin_setup { "conf_operating_system" } eq "Unix" ) {
$ compare_unix = `cmp $plugin_setup{"conf_local_downcomp_file"} $plugin_setup{"conf_local_comp_file"} ; echo \$?` ;
if ( $ compare_unix == 0 ) {
print_module ( "FTP_Maching_files" , "generic_proc" , 1 , " Compare a server file and a local file " ) ;
}
else {
print_module ( "FTP_Maching_files" , "generic_proc" , 0 , " Compare a server file and a local file $plugin_setup{conf_ftp_compare_file} " ) ;
if ( $ plugin_setup { "conf_ftp_compare" } eq "write" ) {
my $ write_option = `mv $plugin_setup{conf_local_downcomp_file} $plugin_setup{conf_local_comp_file}` ;
}
}
}
if ( $ plugin_setup { "conf_operating_system" } eq "Windows" ) {
my $ compare_wdos = `fc $plugin_setup{"conf_local_downcomp_file"} $plugin_setup{"conf_local_comp_file"} > diff.txt` ;
my $ archivo = "diff.txt" ;
my $ peso = - s $ archivo ;
if ( $ peso > 79 ) {
print_module ( "FTP_Maching_files" , "generic_proc" , 0 , " Compare a server file and a local file $plugin_setup{conf_ftp_compare_file} " ) ;
if ( $ plugin_setup { "conf_ftp_compare" } eq "write" ) {
my $ write_option = `move /Y $plugin_setup{conf_local_downcomp_file} $plugin_setup{conf_local_comp_file}` ;
}
} else {
print_module ( "FTP_Maching_files" , "generic_proc" , 1 , " Compare a server file and a local file " )
}
}