#!/usr/local/bin/perl # $Id$ # License: OSI Artistic License # Author: (c) 2010 Matthew Wall ## no critic (InputOutput::RequireCheckedSyscalls) ## no critic (RegularExpressions) ## no critic (ProhibitPackageVars) # The configuration file and ngshared.pm must be in this directory: use lib '/usr/local/etc/nagios/nagiosgraph'; use POSIX; use English qw(-no_match_vars); use strict; use warnings; emitheader(); #checkstyles(); checkmodules(); checkng(); dumpenv(); dumpinc(); dumpngconfig(); dumpfiles(); dumpdirs(); emitfooter(); exit 0; sub emitheader { print <<"EOB"; Content-Type: text/html nagiosgraph: configuration EOB print "

nagiosgraph configuration on $ENV{SERVER_NAME}

\n"; my $ts = strftime '%d %b %Y %H:%M:%S %Z', localtime time; print "$ts
\n"; return; } sub emitfooter { print '' . "\n"; return; } sub checkstyles { print "

a
b
c

\n"; print "

a
b
c

\n"; print "

a
b
c

\n"; print "

a
b
c

\n"; return; } sub dumpenv { print "

Environment

\n"; print "
\n"; print "
\n";
    foreach my $i (sort keys %ENV) {
	print "$i=$ENV{$i}\n";
    }
    print "
\n"; return; } sub dumpinc { print "

Include Paths

\n"; print "
\n"; print "
\n";
    for my $i (@INC) {
        print $i . "\n";
    }
    print "
\n"; print "
\n"; return; } sub printrow { my ($style, $func, $msg, $errmsg) = @_; $errmsg ||= q(); print " $func:$msg$errmsg\n"; return; } sub checkmodule { my ($func, $optional) = @_; my $statusstr = 'not installed'; my $status = $optional ? 'warning' : 'critical'; my $rval = eval "{ require $func; }"; ## no critic (ProhibitStringyEval) if (defined $rval && $rval == 1) { $statusstr = $func->VERSION; $status = 'ok'; } printrow($status, $func, $statusstr); return; } sub checkmodules { print '

PERL modules

' . "\n"; print '
' . "\n"; print '' . "\n"; print "\n"; checkmodule('Carp'); checkmodule('CGI'); checkmodule('Data::Dumper'); checkmodule('Digest::MD5'); checkmodule('File::Basename'); checkmodule('File::Find'); checkmodule('MIME::Base64'); checkmodule('POSIX'); checkmodule('RRDs'); checkmodule('Time::HiRes'); print "\n"; checkmodule('GD', 1); checkmodule('Nagios::Config', 1); print '
required
optional
' . "\n"; print '
' . "\n"; return; } sub checkngshared { my ($failures) = @_; my $func = 'ngshared.pm'; my $status = 'ok'; my $style = 'ok'; my $errmsg = q(); my $rval = eval { require ngshared; }; if (! defined $rval || $rval != 1) { $status = 'fail'; $style = 'critical'; $errmsg = 'cannot load ngshared.pm
' . 'not found in any of these locations:
' . "\n"; for my $ii (@INC) { $errmsg .= $ii . '
' . "\n"; } push @{$failures}, $errmsg; } printrow($style, $func, $status, $errmsg); return; } sub checkngversion { my ($failures) = @_; my $func = 'version'; my $status = 'ok'; my $style = 'ok'; my $errmsg = q(); if ($ngshared::VERSION) { $status = $ngshared::VERSION; } else { $status = 'fail'; $style = 'critical'; $errmsg = 'cannot initialize/import ngshared.pm'; } if ($status eq 'fail') { push @{$failures}, $errmsg; } printrow($style, $func, $status, $errmsg); return; } sub checkngconf { my ($failures) = @_; my $func = 'nagiosgraph.conf'; my $status = 'ok'; my $style = 'ok'; my $errmsg = q(); $errmsg = ngshared::readconfig('showconfig', 'cgilogfile'); if ($errmsg ne q()) { $status = 'fail'; $style = 'critical'; $errmsg = 'cannot read nagiosgraph configuration file:
' . $errmsg; } if ($status eq 'fail') { push @{$failures}, $errmsg; } printrow($style, $func, $status, $errmsg); return; } sub checkmaprules { my ($failures) = @_; my $func = 'map file'; my $status = 'ok'; my $errmsg = q(); if ($ngshared::Config{mapfile}) { $errmsg = ngshared::getrules($ngshared::Config{mapfile}); if ($errmsg ne q()) { $status = 'fail'; } } else { $status = 'fail'; $errmsg = 'map file is not defined'; } my $style = $status eq 'ok' ? 'ok' : 'critical'; if ($status eq 'fail') { push @{$failures}, $errmsg; } printrow($style, $func, $status, $errmsg); return; } # verifty that we have a functional nagiosgraph installation. sub checkng { my $rval; my $status; my @failures; print '

nagiosgraph

' . "\n"; print '' . "\n"; checkngshared(\@failures); checkngversion(\@failures); if (scalar @failures) { print '
' . "\n"; emitfooter(); exit 1; } checkngconf(\@failures); checkdir('rrddir', 'RRD directory', \@failures); checkfile('logfile', 'log file', \@failures); checkfile('cgilogfile', 'CGI log file', \@failures, 1); # TODO: check for read/write access by nagios user checkmaprules(\@failures); print '' . "\n"; if (scalar @failures) { emitfooter(); exit 1; } return; } sub dumpngconfig { my $cfgname = $ngshared::CFGNAME; my $blah = $ngshared::CFGNAME; # keep perl from whining at us my %vars = %ngshared::Config; print '

base configuration

'; print '
'; print '

' . $INC[0] . q(/) . $cfgname . '

' . "\n"; print "
\n";
    foreach my $n (sort keys %vars) {
        print $n . q(=);
        if (ref($vars{$n}) eq 'ARRAY') {
            print "\n";
            for my $ii (@{$vars{$n}}) {
                print q(  ) . $ii . "\n";
            }
        } elsif (ref($vars{$n}) eq 'HASH') {
            print "\n";
            my %hash = %{$vars{$n}};
            for my $ii (sort keys %hash) {
                print q(  ) . $ii . q(=) . $hash{$ii} . "\n";
            }
        } else {
            print $vars{$n} . "\n";
        }
    }
    print "
\n"; print '
'; return; } sub dumpfiles { dumpfile('mapfile','map rules'); dumpfile('labelfile','labels'); dumpfile('hostdb','host settings'); dumpfile('servdb','service settings'); dumpfile('groupdb','group settings'); dumpfile('datasetdb','data sources'); dumpfile('rrdoptsfile','RRD options'); return; } sub dumpdirs { dumpdir($INC[0],'contents of config directory'); dumpdir($ngshared::Config{'rrddir'},'contents of RRD directory'); return; } sub dumpfile { my ($key, $desc) = @_; my %vars = %ngshared::Config; print '

' . $desc . '

'; print '
'; if ($vars{$key}) { my $fn = ngshared::getcfgfn($vars{$key}); print '

' . $fn . '

'; print '
';
        if (open my $FH, '<', $fn) {
            while (<$FH>) {
                my $line = $_;
                next if $line =~ /^\s*\#/;
                print $line;
            }
            close $FH or print "close failed for $fn: $OS_ERROR";
        } else {
            print "cannot read $fn: $OS_ERROR";
        }
        print '
'; } else { print '' . $key . ' is not defined'; } print '
'; return; } # FIXME: do the recursive listing in pure perl sub dumpdir { my ($dir, $desc) = @_; print '

' . $desc . '

'; print '
'; print '
' . "\n";
    print `ls -lRa $dir`; ## no critic (InputOutput::ProhibitBacktickOperators)
    print "\n" . '
' . "\n"; print '
'; return; } sub checkdir { my ($key, $desc, $failures) = @_; my $status = 'ok'; my $errmsg = q(); if ($ngshared::Config{$key}) { my $dir = ngshared::getcfgfn($ngshared::Config{$key}); if (-d $dir) { if (! -r $dir) { $status = 'fail'; $errmsg = 'www user cannot read directory'; } } else { $status = 'fail'; $errmsg = 'directory does not exist'; } } else { $status = 'fail'; $errmsg = 'directory is not defined'; } my $style = $status eq 'ok' ? 'ok' : 'critical'; if ($status eq 'fail') { push @{$failures}, $errmsg; } printrow($style, $desc, $status, $errmsg); return; } sub checkfile { my ($key, $desc, $failures, $optional) = @_; my $status = 'ok'; my $errmsg = q(); if ($ngshared::Config{$key}) { my $fn = ngshared::getcfgfn($ngshared::Config{$key}); if (-f $fn) { if (! -r $fn) { $status = 'fail'; $errmsg = 'www user cannot read file'; } } else { $status = 'fail'; $errmsg = 'file does not exist'; } } else { $status = 'fail'; $errmsg = 'file is not defined'; } my $style = $status eq 'ok' ? 'ok' : 'warning'; if ($status eq 'fail' && ! $optional) { push @{$failures}, $errmsg; $style = 'critical'; } printrow($style, $desc, $status, $errmsg); return; } __END__ =head1 NAME showconfig.cgi - Show nagiosgraph configuration =head1 DESCRIPTION This is a CGI script that is designed to be run on a web server. It displays the nagiosgraph configuration. =head1 USAGE B =head1 REQUIRED ARGUMENTS None. =head1 OPTIONS None. =head1 EXIT STATUS =head1 DIAGNOSTICS =head1 CONFIGURATION This script refers to the nagiosgraph library B and the nagiosgraph configuration file B. =head1 DEPENDENCIES None. =head1 INSTALLATION Copy B and B to a configuration directory such as /etc/nagiosgraph. Copy this file to a CGI script directory on a web server and ensure that it is executable by the web server. Modify the B line to point to the configuration directory. Edit B as needed. =head1 INCOMPATIBILITIES None. =head1 BUGS AND LIMITATIONS The exports for ngshared need to be cleaned up so that it is a proper module. =head1 SEE ALSO B B B B B B B =head1 AUTHOR Matthew Wall, 2010. =head1 LICENSE AND COPYRIGHT Copyright (C) 2010 Matthew Wall This program is free software; you can redistribute it and/or modify it under the terms of the OSI Artistic License see: http://www.opensource.org/licenses/artistic-license-2.0.php 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.