1
0
mirror of https://github.com/librenms/librenms-agent.git synced 2024-05-09 09:54:52 +00:00
István Sárándi 7e55d1cd5d Update fail2ban extend script to new JSON format (#181)
As seen at [this location](7fab99cfc1/includes/polling/functions.inc.php (L768)) the JSON output needs to contain a `data` field. The poller php script actually also extracts this `data` field as one of the first steps, see at [this line](c3007b483a/includes/polling/applications/fail2ban.inc.php (L36)).
Before I changed these parts the graph didn't show up because the RRD files simply weren't generated as an exception occurred in the poller. This fixes this problem.
2018-06-25 09:10:00 -05:00

239 lines
5.2 KiB
Perl

#!/usr/bin/env perl
# Author: Zane C. Bowers-Hadley <vvelox@vvelox.net>
# https://docs.librenms.org/#Extensions/Applications/#fail2ban
# See the above for additional information not documented in the POD below.
=head1 DESCRIPTION
A basic SNMP extend for polling fail2ban for LibreNMS.
=head1 SWITCHES
=head2 -c
Prints the cache file.
=head2 -C <file>
Uses the specified file as the cache file.
If not specified, /var/cache/fail2ban is used.
=head2 -f <fail2ban-client>
This is the path to the fail2ban-client if needed.
If not specified, "/usr/bin/env fail2ban-client" is used.
=head2 -p
Pretty prints the JSON.
=head2 -u
Updates the cache.
=head2 -U
When used with -c, allows attempted cache updating if the file is older
than 360 seconds or does not exist.
=head1 CRON EXAMPLE
*/3 * * * * /etc/snmp/fail2ban -u
or
*/3 * * * * /etc/snmp/fail2ban -u -C /foo/bar/cache
3 minutes is used as LibreNMS runs every 5 minutes, this helps ensure it
is most likely up to date in between runs.
=head1 SNMPD SETUP EXAMPLES
extend fail2ban /etc/snmp/fail2ban
The above will set it up for basic uncached usage.
This is likely fine for most configurations.
extend fail2ban /etc/snmp/fail2ban -c
Will use the cache.
extend fail2ban /etc/snmp/fail2ban -c -U
Will use the cache and update if needed.
extend fail2ban /etc/snmp/fail2ban -f /foo/bin/fail2ban-client
Run it with fail2ban being installed under /foo the the path to
fail2ban-cleint being /foo/bin/fail2ban-client.
=cut
use strict;
use warnings;
use Getopt::Std;
use JSON;
#fail2ban-client path
my $f2bc="/usr/bin/env fail2ban-client";
#the path to the cache
my $cache='/var/cache/fail2ban';
$Getopt::Std::STANDARD_HELP_VERSION = 1;
sub main::VERSION_MESSAGE {
print "fail2ban-client SNMP extend 1.0.0\n";
};
sub main::HELP_MESSAGE {
print "\n".
"-c Print from the cache.\n".
"-C <file> Use this as the cache file.\n".
"-f <fail2ban-client> The fail2ban-client path if needed.".
"-p Pretty prints the JSON.\n".
"-u Update the cache, '".$cache."'\n".
"-U When used with -c, allow update of the cache file if it does not exist or is older than 360 seconds.".
"\n".
"Unless -c or -u is given, it just talks to fail2ban-client and prints the results.\n";
}
#generats stats
sub stats{
my %toReturn;
$toReturn{data}={};
$toReturn{data}{total}=0; # total number in jails
$toReturn{data}{jails}={}; # each jail
$toReturn{error}=0; # error code, 0 if good
$toReturn{errorString}=''; # detailed description of any errors
$toReturn{version}='1'; # format version of the returned data
#gets a list of jails
my $jailsOutput=`$f2bc status`;
$toReturn{error}=$?;
if ( $? == -1){
$toReturn{errorString}='failed to run fail2ban-client';
}
elsif ($? & 127) {
$toReturn{errorString}= sprintf "fail2ban-client died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
$toReturn{error}=$? >> 8;
$toReturn{errorString}="fail2ban-client exited with ".$toReturn{error};
}
if ( $toReturn{error} == 0 ){
my @jailsOutputA=split(/\n/, $jailsOutput);
my ( $jailsS )=grep( /Jail\ list/, @jailsOutputA );
$jailsS=~s/.*\://;
$jailsS=~s/\s//g;
my @jails=split(/\,/, $jailsS);
#process jails
my $int=0;
while(defined($jails[$int])){
#get the total for this jail
my $jailStatusOutput=`$f2bc status $jails[$int]`;
my @jailStatusOutputA=split(/\n/, $jailStatusOutput);
my ( $jailTotal )=grep(/Currently\ banned\:/, @jailStatusOutputA);
$jailTotal=~s/.*\://;
$jailTotal=~s/\s//g;
#tally the total and add this jail to the list
$toReturn{data}{total} = $toReturn{data}{total} + $jailTotal;
$toReturn{data}{jails}{ $jails[$int] } = $jailTotal;
$int++;
}
}
my $j=JSON->new;
if ( $_[0] ){
$j->pretty(1);
return $j->encode( \%toReturn );
}
return $j->encode( \%toReturn )."\n";
}
#updates $cache
sub cacheUpdate{
my $stats=stats($_[0]);
open(my $writefh, ">", $cache) or die "Can't open '".$cache."'";
print $writefh $stats;
close($writefh);
}
#prints $cache
sub cachePrint{
my $old='';
open(my $readfh, "<", $cache) or die "Can't open '".$cache."'";
# if this is over 2048, something is most likely wrong
read($readfh , $old , 10240);
close($readfh);
print $old;
}
#gets the options
my %opts=();
getopts('puUcC:f:', \%opts);
#use custom cache file if needed
if ( defined( $opts{C} ) ){
$cache=$opts{C};
}
#use custom fail2ban location if needed
if ( defined( $opts{f} ) ){
$f2bc=$opts{f};
}
#use the cache
if ( defined( $opts{c} ) ){
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($cache);
if (( -f $cache ) && defined( $mtime ) && ( (time-$mtime) < 360 )){
#cache exists and time is fine
cachePrint;
exit 0;
}else{
#cache does not exist or is old
if ( $opts{U} ){
#allowed to update it via -U
cacheUpdate( $opts{p} );
cachePrint;
exit 0;
}else{
#-U not given
warn("'".$cache."' does not exist or is to old and -U was not given");
exit 1;
}
}
warn('we should never get here...');
exit 2;
}
#update the cache
if (defined( $opts{u} )){
cacheUpdate( $opts{p} );
exit 0;
}
#no cache opions given, just print it
print &stats( $opts{p} );
exit 0;