From: Peter Palfrader Date: Tue, 31 Mar 2009 17:19:40 +0000 (+0200) Subject: Move files into specific directories in source X-Git-Url: https://git.adam-barratt.org.uk/?a=commitdiff_plain;h=42e99da9d896a33803e763c746e9a103183b6b34;hp=dd1a60aa0efd9914ffce41c495858e5ca20fe600;p=mirror%2Fdsa-nagios.git Move files into specific directories in source --- diff --git a/dsa-nagios-checks/apt-status-check b/dsa-nagios-checks/apt-status-check deleted file mode 100755 index 1d4ac92..0000000 --- a/dsa-nagios-checks/apt-status-check +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/perl -Tw - -# $Id: nagios-check-apt-updates 352 2008-05-20 21:36:54Z weasel $ - -# nagios check for debian (security) updates, -# based on net-snmp glue to security updates via apt-get. -# Copyright (C) 2004 SILVER SERVER Gmbh -# Copyright (C) 2004, 2005, 2006, 2007, 2008 Peter Palfrader -# -# 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; either version 2 of the License, or -# (at your option) any later version. -# -# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -use strict; -use English; -use Getopt::Long; -use IO::Handle; -use IPC::Open2; -use IPC::Open3; - -$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; -delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; - -my $APT = '/usr/bin/apt-get'; -my $VERBOSE; - -sub do_check($$$$$$) { - my ($pre_command, $timeout, $noupdate, $name, $updates_security, $updates_other) = @_; - my $fh; - my $pid; - my @command; - - unless ($noupdate) { - print STDERR "Running $APT update in $name\n" if $VERBOSE; - @command = ($APT, 'update'); - unshift @command, @$pre_command; - $fh = new IO::Handle; - $pid = open3(\*STDIN, $fh, $fh, @command) or die ("Cannot run $APT update in $name: $!\n"); - local $SIG{ALRM} = sub { die "Timeout for apt-get update.\n" }; - alarm $timeout; - my @ignore=<$fh>; - alarm 0; - close $fh; - waitpid $pid, 0; - if ($CHILD_ERROR) { # program failed - die("$APT update returned with non-zero exit code in $name: ".($CHILD_ERROR / 256)."\n"); - }; - }; - - print STDERR "Running $APT --simulate upgrade in $name\n" if $VERBOSE; - @command = ($APT, qw{--simulate upgrade}); - unshift @command, @$pre_command; - $fh = new IO::Handle; - $pid = open2($fh, \*STDIN, @command) or die ("Cannot run $APT --simulate upgrade | sort -u in $name: $!\n"); - local $SIG{ALRM} = sub { die "Timeout for apt-get --simulate upgrade.\n" }; - alarm $timeout; - my @lines=<$fh>; - close $fh; - alarm 0; - waitpid $pid, 0; - if ($CHILD_ERROR) { # program failed - die("$APT --simulate upgrade | sort -u returned with non-zero exit code in $name: ".($CHILD_ERROR / 256)."\n"); - }; - - @lines = sort {$a cmp $b} @lines; - my %uniq; - @lines = grep {!$uniq{$_}++} @lines; - - print STDERR "Processing information for $name\n" if $VERBOSE; - for my $line (@lines) { - if ($line =~ m/^Inst\s+(\S+)\s+/) { - my $package = $1; - if ($line =~ m/^Inst\s+\S+\s+.*security/i) { - push @$updates_security, $package.($name ne '/' ? "($name)" : ''); - } else { - push @$updates_other, $package.($name ne '/' ? "($name)" : ''); - }; - } - } -} - - - -my $VERSION = '0.0.3 - $Rev: 352 $'; -my $use_sudo = 1; -my $params; - -# nagios exit codes -my $OK = 0; -my $WARNING = 1; -my $CRITICAL = 2; -my $UNKNOWN = 3; - -$params->{'chroots'} = []; -$params->{'vservers'} = []; -$params->{'timeout'} = 20; -Getopt::Long::config('bundling'); -if (!GetOptions ( - '--help' => \$params->{'help'}, - '--version' => \$params->{'version'}, - '--sudo' => \$params->{'sudo'}, - '--noupdate' => \$params->{'noupdate'}, - '--nosudo' => \$params->{'nosudo'}, - '--verbose' => \$params->{'verbose'}, - '--warnifupdates' => \$params->{'warnifupdates'}, - '--timeout=i' => \$params->{'timeout'}, - '--chroot=s' => $params->{'chroots'}, - '--vserver=s' => $params->{'vservers'} - )) { - die ("Usage: $PROGRAM_NAME [--help|--version] [--sudo|--nosudo] [--timeout=] [--verbose]\n"); -}; -if ($params->{'help'}) { - print "nagios-check-apt-updates $VERSION\n"; - print "Usage: $PROGRAM_NAME [--help|--version] [--sudo|--nosudo] [--verbose]\n"; - print "Reports packages to upgrade, updating the list if necessary.\n"; - print "\n"; - print " --help Print this short help.\n"; - print " --version Report version number.\n"; - print " --sudo Use sudo to call apt-get (default).\n"; - print " --noupdate Do not run apt-get update first.\n"; - print " --nosudo Do not use sudo to call apt-get.\n"; - print " --warnifupdates Exit with a WARNING status if any updates are available.\n"; - print " --timeout= Timeout in seconds for each of the two apt-get runs.\n"; - print " --verbose Be a little verbose.\n"; - print " --chroot= Run check in path.\n"; - print " --vserver= Run check in vserver.\n"; - print "\n"; - print "Note that for --sudo (default) you will need entries in /etc/sudoers like these:\n"; - print "nagios ALL=(ALL) NOPASSWD: /usr/bin/apt-get update\n"; - print "nagios ALL=(ALL) NOPASSWD: /usr/bin/apt-get --simulate upgrade\n"; - print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/chroot /chroot-ia32 /usr/bin/apt-get update\n"; - print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/chroot /chroot-ia32 /usr/bin/apt-get --simulate upgrade\n"; - print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/vserver phpserver exec /usr/bin/apt-get update\n"; - print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/vserver phpserver exec /usr/bin/apt-get --simulate upgrade\n"; - print "\n"; - exit (0); -}; -if ($params->{'version'}) { - print "nagios-check-apt-updates $VERSION\n"; - print "nagios check for availability of debian (security) updates\n"; - print "Copyright (c) 2004 SILVER SERVER Gmbh\n"; - print "Copyright (c) 2004,2005 Peter Palfrader \n"; - exit (0); -}; -if ($params->{'sudo'} && $params->{'nosudo'}) { - die ("$PROGRAM_NAME: --sudo and --nosudo are mutually exclusive.\n"); -}; -if ($params->{'sudo'}) { - $use_sudo = 1; -}; -if ($params->{'nosudo'}) { - $use_sudo = 0; -}; -if (scalar @{$params->{'chroots'}} == 0 && scalar @{$params->{'vservers'}} == 0) { - $params->{'chroots'} = ['/']; -}; -$VERBOSE = $params->{'verbose'}; - - -$SIG{'__DIE__'} = sub { - print STDERR @_; - exit $UNKNOWN; -}; - - -my @updates_security; -my @updates_other; - - -# Make sure chroot paths are nice; -my @chroots = (); -for my $root (@{$params->{'chroots'}}) { - if ($root =~ m#^(/[a-zA-Z0-9/.-]*)$#) { - push @chroots, $1; - } else { - die ("Chroot path $root is not nice.\n"); - }; -}; -for my $root (@chroots) { - my @pre_command = (); - unshift @pre_command, 'chroot', $root if ($root ne '/'); - unshift @pre_command, 'sudo' if $use_sudo; - do_check(\@pre_command, $params->{'timeout'}, $params->{'noupdate'}, $root, \@updates_security, \@updates_other); -} - -# Make sure vserver names are nice; -my @vservers = (); -for my $vserver (@{$params->{'vservers'}}) { - if ($vserver =~ m#^([a-zA-Z0-9.-]+)$#) { - push @vservers, $1; - } else { - die ("Vserver name $vserver is not nice.\n"); - }; -}; -for my $vserver (@vservers) { - my @pre_command = (); - unshift @pre_command, '/usr/sbin/vserver', $vserver, 'exec'; - unshift @pre_command, 'sudo' if $use_sudo; - do_check(\@pre_command, $params->{'timeout'}, $params->{'noupdate'}, $vserver, \@updates_security, \@updates_other); -} - - - - -my $exit = $OK; - -my $updateinfo; -if (@updates_security) { - $updateinfo .= 'Security updates ('.(scalar @updates_security).'): '.join(', ', @updates_security)."; "; - $exit = $CRITICAL; -} -if (@updates_other) { - $updateinfo .= 'Other Updates ('.(scalar @updates_other).'): '.join(', ', @updates_other)."; "; - $exit = $WARNING if ($params->{'warnifupdates'} and $exit == $OK); -}; -$updateinfo = 'No updates available' unless defined $updateinfo; - - -print $updateinfo,"\n"; -exit $exit; diff --git a/dsa-nagios-checks/checks/dsa-check-config b/dsa-nagios-checks/checks/dsa-check-config new file mode 100755 index 0000000..0d62402 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-config @@ -0,0 +1,68 @@ +#!/bin/sh + +# Check that debian-admin is in /etc/aliases for root. +# Peter Palfrader, 2008 + +#my %ERRORS = ( OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => -1 ); + +set -e +err=0 + +log() { + if [ "$0" == "ok" ] && [ "$err" == 0 ]; then + err=0 + elif [ "$1" == "warn" ] && [ "$err" -lt 1 ]; then + err=1 + elif [ "$1" == "critical" ] && [ "$err" -lt 2 ]; then + err=2 + elif [ "$1" == "unknown" ] && [ "$err" == 0 ]; then + err=3 + fi + if [ "`eval echo \\$$1`" = "" ]; then + eval $1="\"$2\"" + else + eval $1="\"`eval echo \\$$1`; $2\"" + fi +} + + +check_aliases() { + if ! [ -e /etc/aliases ]; then + log unknown "/etc/aliases not found" + return + fi + + if egrep '^root:.*debian-admin@debian.org' /etc/aliases > /dev/null; then + log ok "debian-admin found in aliases" + return + fi + + log warn "debian-admin not found in root entry in aliases" +} + +check_ldap_conf() { + if ! [ -e /etc/ldap/ldap.conf ]; then + log unknown "/etc/ldap/ldap.conf not found" + return + fi + + if egrep '^URI.*ldap://db.debian.org' /etc/ldap/ldap.conf > /dev/null && + egrep '^BASE.*dc=debian,dc=org' /etc/ldap/ldap.conf > /dev/null && + egrep '^TLS_CACERT.*/etc/ssl/certs/spi-cacert-2008.pem' /etc/ldap/ldap.conf > /dev/null && + egrep '^TLS_REQCERT.*hard' /etc/ldap/ldap.conf > /dev/null ; then + log ok "ldap.conf configured properly" + return + fi + + log warn "ldap.conf does not have URI, BASE, TLS_CACERT, TLS_REQCERT all configured correctly" +} + +check_aliases +check_ldap_conf + +[ "$critical" = "" ] || echo -n "Critical: $critical; " +[ "$warn" = "" ] || echo -n "Warning: $warn; " +[ "$unknown" = "" ] || echo -n "Unknown: $unknown; " +[ "$ok" = "" ] || echo -n "OK: $ok" +echo +exit $err diff --git a/dsa-nagios-checks/checks/dsa-check-dabackup b/dsa-nagios-checks/checks/dsa-check-dabackup new file mode 100755 index 0000000..f400023 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-dabackup @@ -0,0 +1,179 @@ +#!/usr/bin/perl -w + +# Check the status of da-backup backups +# Copyright 2007 Stephen Gran +# Copyright 2008 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +use strict; +use warnings; +use English; +use Getopt::Long; +use Fcntl qw(:seek); + +my $DABACKUP_CONF = '/etc/da-backup.conf'; +my $MAX_AGE = 30*60*60; +my $TOO_FRESH = 5*60; +my %CODE = ( + 'UNDEF' => -1, + 'OK' => 0, + 'WARNING' => 1, + 'CRITICAL' => 2, + 'UNKNOWN' => 3 +); +$SIG{__DIE__ } = sub() { + print shift; + exit $CODE{'UNKNOWN'}; +}; + + +my $EXITCODE = 'UNDEF'; +my %MESSAGE = (); + +sub problem($$$) { + my ($code, $msg, $resource) = @_; + $MESSAGE{$msg} = [] unless defined $MESSAGE{$msg}; + push @{$MESSAGE{$msg}}, $resource; + $EXITCODE = ($CODE{$code} > $CODE{$EXITCODE}) ? $code : $EXITCODE; +}; + + +sub help($$) { + my ($exitcode, $fd) = @_; + version ($fd, 0); + print $fd "Usage: $PROGRAM_NAME --help\n"; + print $fd "Usage: $PROGRAM_NAME"; + exit $exitcode +}; + +my $params = {}; + +Getopt::Long::config('bundling'); +if (!GetOptions ( + 'h|help' => \$params->{'help'}, + )) { + die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [-fwhv]\n"); +}; + +help(0, *STDOUT) if $params->{'help'}; +help(1, *STDERR) if scalar @ARGV > 0; + + +unless (-e $DABACKUP_CONF) { + if (-e '/etc/da-backup') { + print "WARNING: No $DABACKUP_CONF, but we have /etc/da-backup/\n"; + exit $CODE{'WARNING'}; + }; + if (-e '/var/log/da-backup') { + print "WARNING: No $DABACKUP_CONF, but we have /var/log/da-backup/\n"; + exit $CODE{'WARNING'}; + }; + print "OK: da-backup not installed\n"; + exit $CODE{'OK'}; +}; + +my $confdir; +my $logdir; + +open (FH, "< $DABACKUP_CONF") or die ("Cannot open $DABACKUP_CONF: $!\n"); +while () { + if (/confdir=(.*)/) { + $confdir = $1; + } elsif (/logdir=(.*)/) { + $logdir = $1; + }; +}; + +die ("No confdir found in $DABACKUP_CONF") unless defined $confdir; +die ("No logdir found in $DABACKUP_CONF") unless defined $logdir; + +opendir(DIR, $confdir) or die ("Cannot opendir $confdir: $!\n"); +my %conffiles = map {$_ => 1} grep { !/^\./ && !/\.bak$/} readdir(DIR); +closedir(DIR); + +opendir(DIR, $logdir) or die ("Cannot opendir $logdir: $!\n"); +my %logfiles = map {$_ => 1} grep { !/^\./ && !/\.[0-9]+(\.gz)?$/} readdir(DIR); +closedir(DIR); + +if (scalar keys %conffiles == 0) { + print "WARNING: da-backup installed but no backups configured\n"; + exit $CODE{'WARNING'}; +}; + +for my $f (keys %conffiles) { + unless (exists $logfiles{$f}) { + problem('WARNING', 'no log', $f); + } +} + +FILE: +for my $f (sort {$a cmp $b} keys %logfiles) { + unless (exists $conffiles{$f}) { + problem('WARNING', 'no config', $f); + next; + } + + my @stat = stat("$logdir/$f") or die ("Cannot stat $logdir/$f: $!\n"); + my $age = time - $stat[10]; + + if ($age < $TOO_FRESH) { # File is too new, let's use the old one + if (-e "$logdir/$f.0") { + $f .= ".0"; + my @stat = stat("$logdir/$f") or die ("Cannot stat $logdir/$f: $!\n"); + $age = time - $stat[10]; + }; + }; + + if ($age < 0) { + problem('WARNING', 'future timestamp', $f); + next; + } elsif ($age > $MAX_AGE) { + my $hage; + + if ($age > 48 * 3600) { + $hage = sprintf("%d days", $age / 24 / 3600); + } else { + $hage = sprintf("%d hours", $age / 3600); + }; + problem('WARNING', 'old', "$f ($hage)"); + next; + }; + + open(FH, "< $logdir/$f") or die ("Cannot open $logdir/$f: $!\n"); + sysseek(FH, -1024, SEEK_END); # just try it - doesn't matter if it fails + my $last2 = ''; + my $last = ''; + while () { + chomp; + if (/^sent\s+\d+\s+bytes\s+received\s+\d+\s+bytes\s+[\d\.]+\s+bytes\/sec$/) { + problem('OK', 'probably ok', $f); + close(FH); + next FILE; + }; + $last2 = $last; + $last = $_; + }; + problem('CRITICAL', 'FAILED', "$f ($last2 $last)"); +}; + +my $msg = join("; ", map {"$_: ".join(', ', @{$MESSAGE{$_}}) } (sort {$a cmp $b} keys %MESSAGE)); +print $EXITCODE, ": ", $msg, "\n"; +exit $CODE{$EXITCODE}; diff --git a/dsa-nagios-checks/checks/dsa-check-dabackup-server b/dsa-nagios-checks/checks/dsa-check-dabackup-server new file mode 100755 index 0000000..c4e4884 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-dabackup-server @@ -0,0 +1,126 @@ +#!/bin/sh + +# some tests weasel uses to check if da-backup is properly configured: +# Copyright 2008 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +set -e +set -u + +err=0 + +log() { + if [ "$1" == "warn" ] && [ "$err" -lt 1 ]; then + err=1 + elif [ "$1" == "critical" ] && [ "$err" -lt 2 ]; then + err=2 + elif [ "$1" == "unknown" ] && [ "$err" == 0 ]; then + err=3 + fi +} + +cd /etc/da-backup-manager + +# check that the files have proper names +for i in *; do + s=`cat "$i" | awk -F = '$1=="source" {print $2}'` + if [ "$s" = "master.debian.org/debian" ] && [ "$i" = "listarchive" ]; then + # historical exception + continue + fi + if [ "`echo $s | tr / -`" != "$i" ]; then + log warn + echo "Mismatch: Filename $i but backup source $s" + fi +done + +# and that source == destination everywhere +for i in *; do + s=`cat $i | awk -F = '$1=="source"{print $2}'` + d=`cat $i | awk -F = '$1=="destination"{print $2}'` + if [ "$d" != "$s" ]; then + log warn + echo "source != dest in $i. ($s != $d)" + fi +done + +# check that everything that has an entry in authorized_keys has one in /etc/da-backup-manager +rsync_targets=`tempfile` +backup_manager_sources=`tempfile` +trap "rm -f '$rsync_targets' '$backup_manager_sources'" 0 1 2 5 15 +cat /root/.ssh/authorized_keys | + grep '^command=' | + sed -e 's/",no-por.*//' -e 's/.*--ignore-errors . //' -e 's#/org/backup.debian.org/staging/##' | + sort > "$rsync_targets" +grep -h source /etc/da-backup-manager/* | + sed -e 's/source=//' | + sort > "$backup_manager_sources" +if ! diff "$rsync_targets" "$backup_manager_sources" > /dev/null; then + log warn + echo "authorized_keys vs. /etc/da-backup-manage mismatch:" + diff "$rsync_targets" "$backup_manager_sources" +fi + +# check that everything listed as either source or destination by da-backup-manager does exist - if stuff is new it might still be missing tho +for i in `awk -F = '$1=="source" {print $2}' /etc/da-backup-manager/* `; do + if ! [ -d "/org/backup.debian.org/staging/$i" ]; then + log warn + echo "Warning: source $i does not exist" + fi +done +for i in ` awk -F = '$1=="destination"{print $2}' /etc/da-backup-manager/* `; do + if ! [ -d "/org/backup.debian.org/backups/$i" ]; then + log warn + echo "Warning: destination $i does not exist (if it is new, it takes a day)" + fi +done + +# check that everything that does exist has an entry in da-backup-manager +cd /org/backup.debian.org/staging +for i in */*; do + if ! [ -d "$i" ]; then + log warn + echo "WTF: staging/$i is not a dir" + continue + fi + if ! grep "source=$i" /etc/da-backup-manager/* > /dev/null; then + log warn + echo "staging/$i is not listed anywhere in /etc/da-backup-manager" + fi +done +cd /org/backup.debian.org/backups +for i in */*; do + if ! [ -d "$i" ]; then + log warn + echo "WTF: backups/$i is not a dir" + continue + fi + if ! grep "destination=$i" /etc/da-backup-manager/* > /dev/null; then + log warn + echo "backups/$i is not listed anywhere in /etc/da-backup-manager" + fi +done + +if [ "$err" = 0 ]; then + echo "da-backup seems to be properly configured" +fi +exit $err diff --git a/dsa-nagios-checks/checks/dsa-check-hpacucli b/dsa-nagios-checks/checks/dsa-check-hpacucli new file mode 100755 index 0000000..a347388 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-hpacucli @@ -0,0 +1,216 @@ +#!/usr/bin/perl -w + +# check _physical_ disk status of disks on HP smart array controllers +# requires hpacucli +# +# does _not_ check raid status. use arrayprobe for that. + +# Copyright (c) 2008 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +use strict; + +# nagios exit codes +my %CODE = ( + 'OK' => 0, + 'WARNING' => 1, + 'CRITICAL' => 2, + 'UNKNOWN' => 3 +); + +my $EXITCODE = 'OK'; + +$SIG{'__DIE__'} = sub { + print STDERR @_; + exit $CODE{'UNKNOWN'}; +}; + +sub runcmd($) { + my ($cmd) = @_; + $cmd = "sudo hpacucli $cmd"; + open(FH, $cmd."|") or die ("Cannot run $cmd: $!"); + my @lines = ; + close FH; + die ("no results from $cmd\n") if (scalar @lines == 0); + return \@lines; +} + +sub record($) { + my ($newexit) = @_; + die "code $newexit not defined\n" unless defined $CODE{$newexit}; + + if ($CODE{$newexit} > $CODE{$EXITCODE}) { + $EXITCODE = $newexit; + }; +} + + +my $ctrlallshow = runcmd("controller all show"); +my @controllers; +for (@$ctrlallshow) { + chomp; + next if /^$/; + if (/in Slot ([0-9]+) /) { + push @controllers, $1; + next; + }; + die ("Cannot read line '$_' gotten from hpacucli controller all show\n"); +}; + +if (scalar @controllers == 0) { + print "UNKNONW: No smartarray controllers found with hpacucli\n"; + exit $CODE{'UNKNOWN'} +}; + +my @resultstr; + +for my $slot (sort @controllers) { + my $pds = runcmd("controller slot=$slot pd all show"); + my @drives; + my $nodrives = 0; + my %status; + for (@$pds) { + chomp; + next if /^$/; + next if (/^\S.*in Slot $slot/); + next if /^ *array [A-Z]$/; + if (/^ *(array [A-Z]) \(Failed\)$/) { + record('CRITICAL'); + push @{$status{'Failed'}}, $1; + } elsif (/^Error: The specified controller does not have any physical drives on it.$/) { + $nodrives = 1; + } elsif (/^ *physicaldrive (\S+) .* (OK|Predictive Failure|Failed|Rebuilding)(?:, spare)?\)$/) { + my $drive = $1; + my $status = $2; + push @{$status{$status}}, $drive; + if ($status eq 'OK') { + } elsif ($status eq 'Predictive Failure' || + $status eq 'Rebuilding') { + record('WARNING'); + } elsif ($status eq 'Failed') { + record('CRITICAL'); + } else { + record('UNKNOWN'); + }; + push @drives, $drive; + } else { + die ("Cannot read line '$_' gotten from hpacucli controller slot=$slot pd all show\n"); + }; + }; + + # Check that all drives have the proper transfer speed. + # sometimes stuff breaks and they fall back to 10mb/sec. + for my $drive (@drives) { + # skip drives that are known to have failed + next if (exists $status{'Failed'} && grep {$drive eq $_} @{$status{'Failed'}}); + my $type; + if ($drive =~ /^[0-9]+:[0-9]+$/) { # scsi drives + $type = 'SCSI'; + } elsif ($drive =~ /^[0-9]+I:[0-9]+:[0-9]+$/) { # SAS + $type = 'SAS'; + } else { + # I'm not going to run pass arguments of unknown form to the shell.. + warn ("Unknown diskdrive ID $drive\n"); + next; + } + + my $pd = runcmd("controller slot=$slot pd $drive show"); + while (defined $pd->[0] && !($pd->[0] =~ /physicaldrive/)) { + shift @$pd; + }; + shift @$pd; + my %value; + for (@$pd) { + if (m/^\s*(.*?):\s*(.*?)\s*$/) { + $value{$1} = $2; + } + } + + my $key; + my $expected; + if ($type eq 'SCSI') { + $key = 'Transfer Speed'; + if (!defined $value{'Transfer Mode'}) { + record('WARNING'); + push @{$status{'unknown transfer mode'}}, $drive; + next; + } elsif ($value{'Transfer Mode'} eq 'Ultra 3 Wide') { + $expected = '160 MB/Sec'; + } elsif ($value{'Transfer Mode'} eq 'Ultra 320 Wide') { + $expected = '320 MB/Sec'; + } else { + record('WARNING'); + push @{$status{'unknown transfer mode'}}, $drive."(".$value{'Transfer Mode'}.")"; + next; + }; + } elsif ($type eq 'SAS') { + $key = 'PHY Transfer Rate'; + if ($value{'PHY Count'} eq '2') { + $expected = '3.0GBPS, Unknown'; + } else { + $expected = '3.0GBPS'; + } + } else { + warn "Should not be here. Do not know what to do with type '$type'\n"; + next; + } + + if (!defined $value{$key}) { + record('WARNING'); + push @{$status{'unknown transfer speed'}}, $drive; + } elsif ($value{$key} ne $expected) { + record('WARNING'); + push @{$status{'bad transfer speed'}}, $drive."(".$value{$key}.")"; + }; + }; + + if ($nodrives && scalar keys %status > 0) { + push @resultstr, "Slot $slot: have no drives but status results?"; + record('UNKNOWN'); + next; + } elsif ($nodrives) { + push @resultstr, "Slot $slot: no drives"; + next; + }; + + my $cst = runcmd("controller slot=$slot show status"); + for (@$cst) { + chomp; + next if /^$/; + next if (/^\S.*in Slot $slot/); + if (/^ *(.*) Status: (.*)$/) { + my $system = $1; + my $status = $2; + push @{$status{$status}}, $system; + if ($status ne 'OK') { + record('WARNING'); + }; + } else { + die ("Cannot read line '$_' gotten from hpacucli controller slot=$slot show status\n"); + }; + }; + + my $status = join(" - ", (map { $_.": ".join(", ", @{$status{$_}}) } keys %status)); + push @resultstr, "Slot $slot: $status"; +}; + +print "$EXITCODE: ", join(" --- ", @resultstr), "\n"; +exit $CODE{$EXITCODE}; diff --git a/dsa-nagios-checks/checks/dsa-check-mirrorsync b/dsa-nagios-checks/checks/dsa-check-mirrorsync new file mode 100755 index 0000000..4637cab --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-mirrorsync @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w + +# nagios check for debian security sync checks +# +# Copyright (c) 2008 Alexander Wirt +# Copyright (c) 2009 Peter Palfrader +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +use LWP::UserAgent; +use Socket; +use strict; +use Date::Parse; +use Getopt::Long; +use Date::Parse; +use Date::Format; +use File::Basename; +use English; +use warnings; + + +sub usage($$) { + my ($fh, $exit) = @_; + my $basename = basename($PROGRAM_NAME); + my $VERSION = '0.1'; + + print $fh "$basename $VERSION\n"; + print $fh "Usage: $basename [--help|--version] [--verbose]\n"; + print $fh "\n"; + print $fh " --help Print this short help.\n"; + print $fh " --version Report version number.\n"; + print $fh " --verbose Be a little verbose.\n"; + print $fh " --host hostname to check.\n"; + print $fh " --path path to tracefile.\n"; + print $fh "\n"; + exit ($exit); +}; + + +$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +my $params; + +$params->{'host'} = 'security.debian.org'; #which host to check +$params->{'path'} = 'project/trace/security-master.debian.org'; + +my $OK = 0; +my $WARNING = 1; +my $CRITICAL = 2; +my $UNKNOWN = 3; + +if (!GetOptions ( + '--help' => \$params->{'help'}, + '--verbose' => \$params->{'verbose'}, + '--version' => \$params->{'version'}, + '--host=s' => \$params->{'host'}, + '--path=s' => \$params->{'path'}, + )) { + usage(*STDERR,1) +}; +usage(*STDOUT,0) if ($params->{'help'}); +usage(*STDERR,1) if (scalar @ARGV); + +my $host = $params->{'host'}; +my $path = $params->{'path'}; +my @slaves; +my $status; +my @exitstatus; +my $exitcode = $OK; + +@slaves = gethostbyname($params->{'host'}) or die "Can't resolve " . $params->{'host'} .": $!\n"; +@slaves = map { inet_ntoa($_) } @slaves[4 .. $#slaves]; +print "Checking the following hosts:\n" . join("\n", @slaves) . "\n" if $params->{'verbose'}; + +my @critical; + +foreach my $slave (@slaves) { + my $ua = LWP::UserAgent->new; + $ua->proxy('http', "http://$slave"); + print "Requesting http://$host/$path from $slave\n" if $params->{'verbose'}; + my $response = $ua->get("http://$host/$path"); + + + if ($response->is_success) { + my $content = $response->content; # or whatever + my ($date, $foo, $bar) = split("\n", $content); + my $synctime = str2time($date);; + print "$slave last synced $synctime\n" if $params->{'verbose'}; + $status->{$slave}->{'synced'} = $synctime; + } + else { + push @exitstatus, "$slave broken: " . $response->status_line; + $status->{$slave}->{'error'} = $response->status_line; + $exitcode = $CRITICAL; + push @critical, $slave; + } +} + + +my %seen; +my $o_sync = scalar(grep !$seen{$_}++, map{$status->{$_}->{'synced'}} keys(%{$status})); +if ($o_sync > 1) { + $exitcode = $CRITICAL; + $o_sync -= 1; + my @mirrors = sort { $status->{$a}->{'synced'} <=> $status->{$b}->{'synced'} } keys %{$status}; + push @exitstatus, "$o_sync mirror(s) not in sync (from oldest to newest): ". + join(",", splice(@mirrors,0,$o_sync)); +} else { + print "All mirrors unique\n" if $params->{'verbose'}; +} + +if ($exitcode == $CRITICAL) { + print "CRITICAL: " . join(',',@exitstatus) . "\n"; +} elsif ($exitcode == $OK) { + print "OK: all mirrors up2date\n"; +} + +foreach my $mirror (keys(%{$status})) { + if ($status->{$mirror}->{'error'}) { + print "$mirror broken: " . $status->{$mirror}->{'error'} . "\n"; + } else { + print "$mirror last synced: " . localtime($status->{$mirror}->{'synced'}) ."\n"; + } +} + +exit $exitcode; diff --git a/dsa-nagios-checks/checks/dsa-check-packages b/dsa-nagios-checks/checks/dsa-check-packages new file mode 100755 index 0000000..29e7e4d --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-packages @@ -0,0 +1,276 @@ +#!/usr/bin/perl + +# dsa-check-packages + +# checks for obsolete/local and upgradeable packages. +# +# packages for the obsolete/local check can be ignored, by +# listing their full name in /etc/nagios/obsolete-packages-ignore +# or by having a regex (starting a line with "/") that matches +# the packagename in said file. +# +# Takes one optional argument, the location of the ignore file. + + +# Copyright (C) 2008, 2009 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +use strict; +use warnings; +use English; + +my $IGNORE = "/etc/nagios/obsolete-packages-ignore"; + +my %CODE = ( + 'OK' => 0, + 'WARNING' => 1, + 'CRITICAL' => 2, + 'UNKNOWN' => 3 +); +my $EXITCODE = 'OK'; +sub record($) { + my ($newexit) = @_; + die "code $newexit not defined\n" unless defined $CODE{$newexit}; + + if ($CODE{$newexit} > $CODE{$EXITCODE}) { + $EXITCODE = $newexit; + }; +} + + + +sub get_packages { + $ENV{'COLUMNS'} = 1000; + $ENV{'LC_ALL'} = 'C'; + open(F, "dpkg -l|") or die ("Cannot run dpkg: $!\n"); + my @lines = ; + close(F); + chomp(@lines); + + shift @lines while ($lines[0] !~ /\+\+\+/); + shift @lines; + + my %pkgs; + for my $line (@lines) { + my ($state, $pkg, $version, undef) = split(/ */, $line); + $pkgs{$state}{$pkg} = { 'installed' => $version } + } + + my $installed = $pkgs{'ii'}; + delete $pkgs{'ii'}; + + open my $olderr, ">&STDERR" or die "Can't dup STDERR: $!"; + open STDERR, ">/dev/null" or die "Can't dup STDOUT: $!"; + + open (F, "apt-cache policy ".(join(" ", keys(%$installed)))." |") or die ("Cannot run apt-cache policy: $!\n"); + @lines = ; + close(F); + chomp(@lines); + open STDERR, ">&", $olderr or die "Can't dup OLDERR: $!"; + + my $line; + my $pkgname = undef; + while (defined($line = shift @lines)) { + if ($line =~ /^([^ ]*):$/) { + $pkgname = $1; + } elsif ($line =~ /^ +Installed: (.*)$/) { + # etch dpkg -l does not print epochs, so use this info, it's better + $installed->{$pkgname}{'installed'} = $1; + } elsif ($line =~ /^ +Candidate: (.*)$/) { + $installed->{$pkgname}{'candidate'} = $1; + } elsif ($line =~ /^ +\*\*\*/) { + my @l; + @l = split(/ +/, $line); + $line = shift @lines; + @l = split(/ +/, $line); + $installed->{$pkgname}{'origin'} = $l[2]; + } + } + + my (%current, %obsolete, %outofdate); + for my $pkgname (keys %$installed) { + my $pkg = $installed->{$pkgname}; + + unless (defined($pkg->{'candidate'}) && defined($pkg->{'origin'})) { + $obsolete{$pkgname} = $pkg; + next; + } + + if ($pkg->{'candidate'} ne $pkg->{'installed'}) { + $outofdate{$pkgname} = $pkg; + next; + }; + if ($pkg->{'origin'} eq '/var/lib/dpkg/status') { + $obsolete{$pkgname} = $pkg; + next; + } + $current{$pkgname} = $pkg; + } + + $pkgs{'current'} = \%current; + $pkgs{'outofdate'} = \%outofdate; + $pkgs{'obsolete'} = \%obsolete; + return \%pkgs; +} + +sub load_ignores { + my ($ignorefile, $require_file) = @_; + + my @ignores; + if (!$require_file and ! -e $ignorefile) { + return \@ignores; + } + + open (F, "< $ignorefile") or die ("Cannot open $ignorefile: $!\n"); + @ignores = ; + close F; + chomp(@ignores); + return \@ignores; +} + +sub check_ignore { + my ($pkg, $ignores) = @_; + + my $ignore_this = 0; + for my $ignore (@$ignores) { + my $ig = $ignore; + return 1 if ($ig eq $pkg); + if (substr($ig,0,1) eq '/') { + substr($ig, 0, 1, ''); + $ig =~ s,/$,,; + return 1 if ($pkg =~ /$ig/); + } + } + return 0 +} + +sub filter_ignored { + my ($packages, $ignores) = @_; + + my $obs = $packages->{'obsolete'}; + + my (%ignored, %bad); + for my $pkg (keys %$obs) { + if (check_ignore($pkg, $ignores)) { + $ignored{$pkg} = $obs->{$pkg}; + } else { + $bad{$pkg} = $obs->{$pkg}; + }; + } + delete $packages->{'obsolete'}; + $packages->{'obsolete'} = \%bad; + $packages->{'obsolete-ignored'} = \%ignored; +}; + +sub usage { + my ($fd, $exit) = @_; + print $fd "Usage: $PROGRAM_NAME []\n"; + exit $exit; +} + +my $ignorefile = $IGNORE; +my $ignorefile_userset = 0; +usage(\*STDERR, 1) if (@ARGV > 1); +if (@ARGV == 1) { + usage(\*STDOUT, 0) if ($ARGV[0] eq "-h"); + usage(\*STDOUT, 0) if ($ARGV[0] eq "--help"); + $ignorefile = $ARGV[0]; + $ignorefile_userset = 1; +}; + +my $ignores = load_ignores($ignorefile, $ignorefile_userset); +my $packages = get_packages(); + +filter_ignored($packages, $ignores); + + + +my @reportform = ( + { 'key' => 'obsolete', + 'listpackages' => 1, + 'long' => "%d local or obsolete packages: %s", + 'short' => "%d obs", + 'status' => 'WARNING' }, + { 'key' => 'outofdate', + 'listpackages' => 1, + 'long' => "%d out of date packages: %s", + 'short' => "%d updates", + 'status' => 'WARNING' }, + { 'key' => 'current', + 'listpackages' => 0, + 'long' => "%d packages current.", + 'short' => "%d ok", + 'status' => 'OK' }, + { 'key' => 'obsolete-ignored', + 'listpackages' => 1, + 'long' => "%d whitelisted local or obsolete packages: %s", + 'short' => "%d obs(ignored)", + 'status' => 'OK' }, + { 'key' => 'rc', + 'listpackages' => 1, + 'long' => "%d packages removed but not purged: %s", + 'short' => "%d rc", + 'status' => 'OK' }, + { 'key' => 'hi', + 'listpackages' => 1, + 'long' => "%d packages on hold: %s", + 'short' => "%d hi", + 'status' => 'OK' }, + { 'key' => 'pc', + 'listpackages' => 1, + 'long' => "%d packages requested to be purged but conffiles still installed: %s", + 'short' => "%d pc", + 'status' => 'WARNING' }, + ); + +my @longout; +my @shortout; +for my $form (@reportform) { + my $pkgs = $packages->{$form->{'key'}}; + delete $packages->{$form->{'key'}}; + my $num = scalar keys %$pkgs; + next unless ($num > 0); + if ($form->{'listpackages'}) { + my $list = join(", ", keys %$pkgs); + push @longout, sprintf($form->{'long'}, $num, $list); + } else { + push @longout, sprintf($form->{'long'}, $num); + }; + push @shortout, sprintf($form->{'short'}, $num); + record($form->{'status'}); +}; +if (scalar keys %$packages) { + record('WARNING'); + unshift @shortout, "unk: ".join(", ", keys %$packages); + for my $status (sort {$b cmp $a} keys %$packages) { + my $pkgs = $packages->{$status}; + my $list = join(", ", keys %$pkgs); + unshift @longout, "Unknown package status $status: $list"; + }; +} + +my $shortout = $EXITCODE.": ".join(", ", @shortout); +my $longout = join("\n", @longout); + +print $shortout,"\n"; +print $longout,"\n"; + +exit $CODE{$EXITCODE}; diff --git a/dsa-nagios-checks/checks/dsa-check-puppet b/dsa-nagios-checks/checks/dsa-check-puppet new file mode 100755 index 0000000..332261e --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-puppet @@ -0,0 +1,91 @@ +#!/usr/bin/env ruby + +require 'optparse' + +class CheckPuppet + + VERSION = '0.1' + script_name = File.basename($0) + + # default options + OPTIONS = { + :statefile => "/var/lib/puppet/state/state.yaml", + :interval => 60, + } + + o = OptionParser.new do |o| + o.set_summary_indent(' ') + o.banner = "Usage: #{script_name} [OPTIONS]" + o.define_head "The check_puppet Nagios plug-in checks that the specified " + + "puppet state file is no older than specified interval." + o.separator "" + o.separator "Mandatory arguments to long options are mandatory for " + + "short options too." + + o.on("-s", "--statefile=statefile", String, "The state file", + "Default: #{OPTIONS[:statefile]}") { |OPTIONS[:statefile]| } + o.on("-i", "--interval=value", Integer, + "Default: #{OPTIONS[:interval]} minutes") { |OPTIONS[:interval]| } + + o.separator "" + o.on_tail("-h", "--help", "Show this help message.") do + puts o + exit + end + + o.parse!(ARGV) + end + + def check_state + + # Set variables + curt = Time.now + intv = OPTIONS[:interval] * 60 + + # Check file time + @modt = 0 + begin + @modt = File.mtime("#{OPTIONS[:statefile]}") + rescue + @file = 3 + end + + diff = (curt - @modt).to_i + + @file = 2 + @file = 0 if diff <= intv + + end + + def output_status + + case @file + when 0 + state = "state file status okay updated on " + @modt.strftime("%m/%d/%Y at %H:%M:%S") + when 2 + state = "state file is missing or older than #{OPTIONS[:interval]} minutes" + when 3 + state = "state file status unknown" + end + + case @file + when 0 + status = "OK" + exitcode = 0 + when 2 + status = "CRITICAL" + exitcode = 2 + when 3 + status = "UNKNOWN" + exitcide = 3 + end + + puts "PUPPET " + status + ": " + state + exit(exitcode) + end +end + +cp = CheckPuppet.new +cp.check_state +cp.output_status + diff --git a/dsa-nagios-checks/checks/dsa-check-raid-3ware b/dsa-nagios-checks/checks/dsa-check-raid-3ware new file mode 100755 index 0000000..a9887b9 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-raid-3ware @@ -0,0 +1,111 @@ +#!/usr/bin/perl -Tw + +# Copyright (C) 2006 Peter Palfrader + +# Need to allow /usr/local/bin/tw_cli info c0 u0 status in sudoers: +# +# nagios ALL=(ALL) NOPASSWD: /usr/local/bin/tw_cli info c0 u0 status +# + +use strict; +use English; +use Getopt::Long; + +$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +my $TW_CLI = '/usr/local/bin/tw_cli'; +my $SVN_REVISION_STRING = '$Rev: 313 $'; +my ($SVN_REVISION) = ($SVN_REVISION_STRING =~ /([0-9]+)/); + $SVN_REVISION = 'unknown' unless defined $SVN_REVISION; +my $VERSION = '0.0.0.'.$SVN_REVISION; + +# nagios exit codes +my $UNKNOWN = -1; +my $OK = 0; +my $WARNING = 1; +my $CRITICAL = 2; + +my $params = { + 'no-sudo' => 0, + 'controller' => 0, + 'unit' => 0 + }; + +Getopt::Long::config('bundling'); +if (!GetOptions ( + '--help' => \$params->{'help'}, + '--version' => \$params->{'version'}, + '--verbose' => \$params->{'verbose'}, + '--controller=i' => \$params->{'controller'}, + '--unit=i' => \$params->{'unit'}, + '--no-sudo' => \$params->{'no-sudo'}, + )) { + die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--no-sudo] [--controller=] [--unit=]\n"); +}; +if ($params->{'help'}) { + print "$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--no-sudo] [--controller=] [--unit=]\n"; + print "Checks status of 3ware raid arrays.\n"; + exit (0); +}; +if ($params->{'version'}) { + print "nagios-check-raid-3ware $VERSION\n"; + print "nagios check for 3ware raids\n"; + print "Copyright (c) 2006 Peter Palfrader \n"; + exit (0); +}; + +$SIG{'__DIE__'} = sub { + print STDERR @_; + exit $UNKNOWN; +}; + +unless (-e $TW_CLI) { + print "Cannot find '$TW_CLI'.\n"; + exit $UNKNOWN; +}; + +my $sudo = $params->{'no-sudo'} ? '' : 'sudo '; +my $command = "$sudo $TW_CLI info c$params->{'controller'} u$params->{'unit'} status"; +print STDERR "Running $command\n" if $params->{'verbose'}; +open (TW, "$command|") or die ("Cannot run $command: $!\n"); +my @tw=; +close TW; +if ($CHILD_ERROR) { # program failed + die("$command returned with non-zero exit code: ".($CHILD_ERROR / 256)."\n"); +}; + + +my $exit = $UNKNOWN; +my $msg = ''; +for my $line (@tw) { + chomp $line; + next if $line =~ /^$/; + my ($device, $status) = $line =~ m#^(/c[0-9]+/u[0-9]+) status = ([A-Z]+)$#; + unless (defined($device) && defined($status)) { + print "Cannot parse line '$line'\n"; + exit $UNKNOWN; + }; + if ($status eq 'OK' || + $status eq 'VERIFYING') { + $msg .= ($msg eq '' ? '' : '; '). "$device: $status"; + $exit = $exit > $OK ? $exit : $OK; + } elsif ($status eq 'DEGRADED') { + $msg .= ($msg eq '' ? '' : '; '). "$device: $status"; + $exit = $exit > $CRITICAL ? $exit : $CRITICAL; + } elsif ($status eq 'OFFLINE') { + $msg .= ($msg eq '' ? '' : '; '). "$device: $status"; + $exit = $exit > $CRITICAL ? $exit : $CRITICAL; + } else { + $msg .= ($msg eq '' ? '' : '; '). "$device: UNKNOWN STATUS '$status'"; + $exit = $exit > $UNKNOWN ? $exit : $UNKNOWN; + }; +}; + +if ($msg eq '') { + $msg = "No devices found"; + die ("exit is not UNKNOWN but $exit") if ($exit != $UNKNOWN); +} + +print $msg,"\n"; +exit $exit; diff --git a/dsa-nagios-checks/checks/dsa-check-raid-areca b/dsa-nagios-checks/checks/dsa-check-raid-areca new file mode 100755 index 0000000..da97c98 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-raid-areca @@ -0,0 +1,267 @@ +#!/usr/bin/perl + +# downloaded as check_areca from +# http://www.nagiosexchange.org/cgi-bin/page.cgi?g=1486.html;d=1 +# on 20081001 by weasel. +# +# local changes: fix path to areca_cli + +##################################################### +#Program to check the areca RAID controller for the status of the RAID +#Created: 2007-11-27 +#Version: 1.1.0 +#Revised: 2008-07-23 +#Revised by: Erinn Looney-Triggs +#Author: Erinn Looney-Triggs +#Changelog: +#1.1: Fixed issue with newer versions of the Areca CLI > 1.72 and +#fixed a problem where the RAID name contained spaces +#(Reported by Daniel Philipp). Also did a bit of cleanup. +##################################################### + +use Carp; +use English qw( -no_match_vars ); +use Getopt::Long; #Grab command line switches +use Pod::Usage; +use strict; #Do it right +use warnings; + +$ENV{PATH} = '/usr/local/bin:/usr/bin:'; #Safer path +my $areca_cli = '/usr/local/sbin/areca-cli'; +my $timeout = '10'; #Default timeout of 10 seconds +my $VERSION = '1.1.0'; #Version number + +#Nagios plugin return values, in english +my $OK = '0'; +my $WARNING = '1'; +my $CRITICAL = '2'; +my $UNKNOWN = '3'; + +GetOptions( 'areca_cli|A=s' => \$areca_cli, + 'man' => sub { pod2usage(3) }, + 'timeout|t=i' => \$timeout, + 'usage' => sub { pod2usage(1) }, + 'version' => sub { VersionMessage() }, + 'help' => sub { pod2usage(1) }, +); + +sanity_checks(); +parse_areca( check_areca() ); + +sub check_areca{ + my @output; + + #Timer operation. Times out after $timeout seconds. + eval { + + #Set the alarm and set the timeout + local $SIG{ALRM} = sub { die "alarm\n" }; + alarm $timeout; + + #Run the command + @output = `sudo $areca_cli vsf info`; + if ($?){ + print "Command: cli vsf info failed, " + . "$OS_ERROR $CHILD_ERROR, aborting!\n"; + exit $CRITICAL; + } + + #Reset the alarm if successful + alarm 0; + }; + + #Test return value and exit if eval caught the alarm + if ($EVAL_ERROR) { + if ( $EVAL_ERROR eq "alarm\n" ) { + print "Operation timed out after $timeout seconds.\n"; + exit $CRITICAL; + } + else { + print "An unknown error has occured: $EVAL_ERROR \n"; + exit $UNKNOWN; + } + } + + return @output; +} + +sub parse_areca{ + my @output = @_; + + my $abnormal; #Holds count of non-normal returns + + my @pertinent_lines = grep (/\s\d+\s/, @output); + + for my $line (@pertinent_lines){ + #Strip of leading spaces + $line =~ s/^\s+//; + + #Split the line into discrete parts + my ( $number, $level, $capacity, $state, ) + = (split (/\s+/, "$line"))[0,-4,-3,-1]; + + #If the state is normal continue on in loop + if (lc $state eq "normal"){ + print "|Controller number: $number RAID level: $level " + . "Capacity: $capacity State: $state| "; + } + + #If state is abnormal continue on in loop but add 1 to $abnormal + else{ + print "|Controller number: $number RAID level: $level " + . "Capacity: $capacity State: $state| "; + $abnormal++; + } + } + + #If any abnormalities exist ext with a critical error. + if ($abnormal){ + exit $CRITICAL; + } + else { + exit $OK; + } + + return; #This should never be reached +} + +sub sanity_checks{ + if (! -e $areca_cli){ + print "$areca_cli does not exist, aborting!\n"; + exit $CRITICAL; + } + if (! -x $areca_cli){ + print "$areca_cli is not executable by the running user, aborting!\n"; + exit $CRITICAL; + } + + return; #This should never be reached +} + +#Version message information displayed in both --version and --help +sub main::VersionMessage { + + print <<"EOF"; +This is version $VERSION of check_areca. + +Copyright (c) 2007-2008 Erinn Looney-Triggs (erinn.looneytriggs\@gmail.com). +All rights reserved. + +This module is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License. +See http://www.fsf.org/licensing/licenses/gpl.html + +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. + +EOF + + exit 1; +} + +__END__ + +=head1 NAME + +check_areca - Checks the status of an Areca RAID via the Areca CLI utility. + +=head1 VERSION + +This documentation refers to check_areca version 1.1.0 + +=head1 USAGE + +check_areca.pl + +=head1 REQUIRED ARGUMENTS + +None + +=head1 OPTIONS + + --areca_cli (-A) Set the location of the Areca cli executable. + --help Display usage information. + --man Display the entire POD documentation + --timeout (-t) Sets the timeout, defaults to 10 seconds. + --usage Display usage information (same as --help) + --version Display the version number + + +=head1 DESCRIPTION + +This is a Nagios plugin that runs the Areca CLI to check the status of the +RAID controller. It then parses the resultant exit information and +passes the output to NRPE. + +=head1 DIAGNOSTICS + +=head2 Command: cli vsf info failed, aborting! + +For some reason the command trying to be run failed. Try running it by hand +and seeing if it runs properly. + +=head2 Operation timed out after seconds. + +Running the command failed after a certain amount of time (defaults to 10 +seconds). Try using the --timeout (-t) switch and increasing the timeout +threshold. Also try running the command by hand and see if it is hanging. + +=head2 An unknown error has occurred: + +Just what it says, running the cli command threw an unknown error and the +process died. Run the CLI command by hand and see if you receive proper +output. + +=head2 does not exist, aborting! + +The binary that the script is looking to run does not exist. By default +check_areca looks in /usr/local/areca/bin/ for the cli. However, you can +change this default by setting the --areca_cli (-A) flag from the command +line + +=head2 is not executable by the running user, aborting! + +The cli program was found but it is not executable by the current user, +usually this is the nagios user. + +=head1 CONFIGURATION AND ENVIRONMENT + +The Areca cli program should be available on the system. By default +check_areca looks in /usr/local/areca/bin/cli for the cli. You can set the +location using the --areca_cli (-A) flag from the command line. + +It is helpful to have an Areca RAID controller on the system being checked. + +=head1 DEPENDENCIES + + check_areca depends on the following modules: + POSIX Standard Perl 5.8 module + Getopt::Long Standard Perl 5.8 module + Pod::USAGE Standard Perl 5.8 module + +=head1 INCOMPATIBILITIES + +None known yet. + +=head1 BUGS AND LIMITATIONS + +Bugs, never heard of 'em ;). +If you encounter any bugs let me know. (erinn.looneytriggs@gmail.com) + +=head1 AUTHOR + +Erinn Looney-Triggs (erinn.looneytriggs@gmail.com) + +=head1 LICENCE AND COPYRIGHT + +Copyright (c) 2007-2008 Erinn Looney-Triggs (erinn.looneytriggs@gmail.com). +All rights reserved. + +This module is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License. +See L. + +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. diff --git a/dsa-nagios-checks/checks/dsa-check-raid-dac960 b/dsa-nagios-checks/checks/dsa-check-raid-dac960 new file mode 100755 index 0000000..7893365 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-raid-dac960 @@ -0,0 +1,22 @@ +#!/bin/sh + +# Nagios check for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers +# +# Some background information on the driver is available at +# http://home.germany.net/100-120220/mylex/DAC960.README +# +# Written 2008 Peter Palfrader + +if [ -e /proc/rd/status ]; then + status=`cat /proc/rd/status` + if [ "$status" = "OK" ]; then + echo "OK: all DAC960 controllers operating normally; no (non-standby) failures have occurred" + exit 0; + else + echo "CRITICAL: proc/rd/status is $status" + exit 2; + fi; +else + echo "UNKNOWN: No DAC960 controllers in the system" + exit 3; +fi diff --git a/dsa-nagios-checks/checks/dsa-check-raid-mpt b/dsa-nagios-checks/checks/dsa-check-raid-mpt new file mode 100755 index 0000000..f4f3407 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-raid-mpt @@ -0,0 +1,70 @@ +#!/usr/bin/perl -Tw + +# Copyright (C) 2008 Peter Palfrader + +# Need to allow /usr/local/bin/tw_cli info c0 u0 status in sudoers: +# +# nagios ALL=(ALL) NOPASSWD: /usr/sbin/mpt-status -s +# + +use strict; +use English; +use Getopt::Long; + +$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +my $MPT_STATUS = '/usr/sbin/mpt-status'; + +# nagios exit codes +my $UNKNOWN = -1; +my $OK = 0; +my $WARNING = 1; +my $CRITICAL = 2; + +$SIG{'__DIE__'} = sub { + print STDERR @_; + exit $UNKNOWN; +}; + +unless (-e $MPT_STATUS) { + print "Cannot find '$MPT_STATUS'.\n"; + exit $UNKNOWN; +}; + +my $command = "sudo $MPT_STATUS -s"; +open (MPT, "$command|") or die ("Cannot run $command: $!\n"); +my @tw=; +close MPT; +if ($CHILD_ERROR) { # program failed + die("$command returned with non-zero exit code: ".($CHILD_ERROR / 256)."\n"); +}; + + +my $exit = $UNKNOWN; +my $msg = ''; +for my $line (@tw) { + chomp $line; + next if $line =~ /^$/; + my ($device, $num, $status) = $line =~ m#^(log_id|vol_id|phys_id)\s+([0-9]+)\s+(.*)$#; + unless (defined($device) && defined($num) && defined($status)) { + print "Cannot parse line '$line'\n"; + exit $UNKNOWN; + }; + if ($status eq 'OPTIMAL' || + $status eq 'ONLINE') { + $msg .= ($msg eq '' ? '' : '; '). "$device $num: $status"; + $exit = $exit > $OK ? $exit : $OK; + } else { + $msg .= ($msg eq '' ? '' : '; '). "$device $num: $status"; + $exit = $exit > $CRITICAL ? $exit : $CRITICAL; + }; +}; + +if ($msg eq '') { + $msg = "No devices found"; + die ("exit is not UNKNOWN but $exit") if ($exit != $UNKNOWN); +} + +print $msg,"\n"; +exit $exit; diff --git a/dsa-nagios-checks/checks/dsa-check-raid-sw b/dsa-nagios-checks/checks/dsa-check-raid-sw new file mode 100755 index 0000000..0297036 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-raid-sw @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w +# ------------------------------------------------------------------------------ +# File Name: chech_raid.pl +# Author: Thomas Nilsen - Norway +# Date: 14/06/2003 +# Version: 0.1 +# Description: This script will check to see if any software raid +# devices are down. +# Email: thomas.nilsen@doc-s.co.uk +# WWW: www.doc-s.co.uk +# ------------------------------------------------------------------------------ +# Copyright 2003 (c) Thomas Nilsen +# Credits go to Ethan Galstad for coding Nagios +# License GPL +# ------------------------------------------------------------------------------ +# Date Author Reason +# ---- ------ ------ +# 2008-03-31 Peter Palfrader Return warning on running resync +# 2007-11-07 Peter Palfrader Return unknown if /proc/mdstat does not exist +# 05/10/2004 Peter Palfrader Make it work without that 'use util (vars)' +# 14/06/2003 TN Initial Release +# - Format of mdstat assumed to be "2 line" per +# device with [??] on the second line. +# ------------------------------------------------------------------------------ + +use strict; +use warnings; +use Getopt::Long;; +use vars qw($opt_V $opt_h $opt_t $opt_F $PROGNAME); +use lib '/usr/local/nagios/libexec/'; +my $TIMEOUT=15; +my %ERRORS = ( OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => -1 ); + + +$PROGNAME="check_raid"; + +sub print_help (); +sub print_usage (); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; +my ( $line, $stat, $state ,@device, $msg, $status, $timeout); + +$stat="/proc/mdstat"; + +#Option checking +Getopt::Long::Configure('bundling'); +$status = GetOptions( + "V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "F" => \$opt_F, "filename" => \$opt_F, + "t" => \$opt_t, "timeout" => \$opt_t); +# Version +if ($opt_V) { + print($PROGNAME,': $Revision: 0.1 $'); + exit $ERRORS{'OK'}; +} +# Help +if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; +} +# Filename supplied +if ($opt_F) { + $opt_F = shift; + $stat = $1 if ($opt_F =~ /^(.*)$/); + + if ( ! -r $stat ) { + print "Invalid mdstat file: $opt_F\n"; + exit $ERRORS{'UNKNOWN'}; + } +} + +$timeout = $TIMEOUT; +($opt_t) && ($opt_t =~ /^([0-9]+)$/) && ($timeout = $1); + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No response (alarm)\n"); + exit $ERRORS{'UNKNOWN'}; +}; +alarm($timeout); + +# Start checking the file... +open (FH, $stat) or print("UNKNOWN: Cannot open $stat: $!\n"), exit $ERRORS{'UNKNOWN'}; + +my @failed = (); +my @resyncing = (); +my $device = ''; + +# Now check the mdstat file.. +while () { + $line = $_; + if ($line =~ /^(md\S*) /) { + $device = $1; + } elsif( $line =~ / \[_|_\]|U_|_U /) { + push @failed, $device; + } + elsif ( $line =~ / resync /) { + # [==>..................] resync = 10.3% (15216320/146994624) finish=2153.2min speed=1018K/sec + my ($percent) = ($line =~ m# resync = ([0-9.]+%)#); + my ($finish) = ($line =~ m# finish=([0-9.]+min)#); + my ($speed) = ($line =~ m# speed=([0-9.]+K/sec)#); + push @resyncing, "$device ($percent done, finish in $finish at $speed)"; + } +} +close (FH); + +if (scalar @failed > 0) { + if (scalar @failed == 1) { + print "CRITICAL - Device $failed[0] has failed.\n"; + } else { + print "CRITICAL - Devices ".join(", ", @failed)." have failed.\n" + }; + exit $ERRORS{'CRITICAL'}; +} elsif (scalar @resyncing > 0 ) { + print "WARNING: Resyncing: ".(join "; ", @resyncing)."\n"; + exit $ERRORS{'WARNING'}; +} else { + print "OK - All devices are online\n"; + exit $ERRORS{'OK'}; +}; + + +sub print_usage () { + print "Usage: $PROGNAME -t -F \n"; +} + +sub print_help () { + print_revision($PROGNAME,'$Revision: 0.1 $'); + print "Copyright (c) 2003 Thomas Nilsen/Karl DeBisschop\n"; + print "\n"; + print_usage(); + print "Checks the mdstat file for errors on any configured software raid.\n +-t ( --timeout=INTEGER) + Seconds before script times out (default: 10)\n +-F ( --filename=FILE) + Full path and name to mdstat file (usually '/proc/mdstat') \n\n"; +} diff --git a/dsa-nagios-checks/checks/dsa-check-running-kernel b/dsa-nagios-checks/checks/dsa-check-running-kernel new file mode 100755 index 0000000..818288f --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-running-kernel @@ -0,0 +1,107 @@ +#!/bin/bash + +# Check if the running kernel has the same version string as the on-disk +# kernel image. + +# Copyright 2008 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +OK=0; +WARNING=1; +CRITICAL=2; +UNKNOWN=3; + +get_offset() { + local file needle + + file="$1" + needle="$2" + perl -e ' + undef $/; + $i = index(<>, "'"$needle"'"); + if ($i < 0) { + exit 1; + }; + print $i,"\n"' < "$file" +} + +get_image() { + local image GZHDR1 GZHDR2 off + + image="$1" + + GZHDR1="\x1f\x8b\x08\x00" + GZHDR2="\x1f\x8b\x08\x08" + + off=`get_offset "$image" $GZHDR1` + [ "$?" != "0" ] && off="-1" + if [ "$off" -eq "-1" ]; then + off=`get_offset "$image" $GZHDR2` + [ "$?" != "0" ] && off="-1" + fi + if [ "$off" -eq "0" ]; then + zcat < "$image" + return + elif [ "$off" -ne "-1" ]; then + (dd ibs="$off" skip=1 count=0 && dd bs=512k) < "$image" 2>/dev/null | zcat 2>/dev/null + return + fi + + echo "ERROR: Unable to extract kernel image." 2>&1 + exit 1 +} + +searched="" +for on_disk in \ + "/boot/vmlinuz-`uname -r`"\ + "/boot/vmlinux-`uname -r`"; do + + if [ -e "$on_disk" ]; then + on_disk_version="`get_image "$on_disk" | strings | grep 'Linux version' | head -n1`" + [ -z "$on_disk_version" ] || break + on_disk_version="`cat "$on_disk" | strings | grep 'Linux version' | head -n1`" + [ -z "$on_disk_version" ] || break + + echo "UNKNOWN: Failed to get a version string from image $on_disk" + exit $UNKNOWN + fi + searched="$searched $on_disk" +done + +if ! [ -e "$on_disk" ]; then + echo "WARNING: Did not find a kernel image (checked$searched) - I have no idea which kernel I am running" + exit $WARNING +fi + + +running_version="`cat /proc/version`" +if [ -z "$running_version" ] ; then + echo "UNKNOWN: Failed to get a version string from running system" + exit $UNKNOWN +fi + +if [ "$running_version" != "$on_disk_version" ]; then + echo "WARNING: Running kernel does not match on-disk kernel image: [$running_version != $on_disk_version]" + exit $WARNING +else + echo "OK: Running kernel matches on disk image: [$running_version]" + exit $OK +fi diff --git a/dsa-nagios-checks/checks/dsa-check-samhain b/dsa-nagios-checks/checks/dsa-check-samhain new file mode 100755 index 0000000..c6b3f4f --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-samhain @@ -0,0 +1,216 @@ +#!/usr/bin/perl -w + +# check_samhain.pl - check to see how many policy violations are reported +# by the samhain file integrity checker. +# +# Copyright Rainer Wichmann (2004) +# Copyright Martin Zobel-Helas (2008) +# +# License Information: +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# +############################################################################ + +# -------------------------------------------------------------------[ Uses ]-- + +use strict; +use Getopt::Long; +use vars qw($PROGNAME $SAMHAIN $opt_V $opt_h $opt_v $verbose $opt_w $opt_c $opt_t $status $msg $state $retval); +use lib "/usr/lib/nagios/plugins"; +use utils qw(%ERRORS &print_revision); + +#my $TIMEOUT = 15; +#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); +#sub print_revision ($$); + +# ----------------------------------------------------[ Function Prototypes ]-- + +sub print_help (); +sub print_usage (); +sub process_arguments (); + +# ------------------------------------------------------------[ Environment ]-- + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +# -----------------------------------------------------------------[ Global ]-- + +$PROGNAME = "dsa-check-samhain"; +$SAMHAIN = "/usr/sbin/samhain"; + +# ----------------------------------------------------------------[ options ]-- + +Getopt::Long::Configure('bundling'); +$status = process_arguments(); +if ($status){ + print "ERROR: processing arguments\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# ----------------------------------------------------------------[ timeout ]-- + +$SIG{'ALRM'} = sub { + print ("ERROR: timed out waiting for $SAMHAIN\n"); + exit $ERRORS{"WARNING"}; +}; +alarm($opt_t); + +# ----------------------------------------------------------[ start samhain ]-- + +if ( defined $SAMHAIN && -x $SAMHAIN ) { + if (! open (SHPIPE, "/usr/bin/sudo $SAMHAIN -t check --foreground -p err -s none -l none -m none 2>&1 | " ) ) { + print "ERROR: could not popen $SAMHAIN \n"; + exit $ERRORS{'UNKNOWN'}; + } +}else{ + print "ERROR: Could not find samhain executable!\n"; + exit $ERRORS{'UNKNOWN'}; +} + +# ---------------------------------------------------------[ read from pipe ]-- + +$status = 0; + +while () { + if (/POLICY/) { + ++$status; + print $_ if $verbose; + } +} + +if ($status < $opt_w) { + $msg = "OK: $status policy violations (threshold $opt_w/$opt_c)"; + $state = $ERRORS{'OK'}; +} elsif ($status >= $opt_w && $status < $opt_c) { + $msg = "WARNING: $status policy violations (threshold w=$opt_w)"; + $state = $ERRORS{'WARNING'}; +} else { + $msg = "CRITICAL: $status policy violations (threshold w=$opt_w)"; + $state = $ERRORS{'CRITICAL'}; +} + +# -------------------------------------------------------------[ close pipe ]-- + +close (SHPIPE); + +# declare an error if we also get a non-zero return code from samhain + +if ( $? ) { + $retval = $? / 256; + if ( $! ) { + print "Error closing $SAMHAIN: $!\n" if $verbose; + } else { + print "$SAMHAIN returned exit status $retval\n" if $verbose; + } + if ($state == $ERRORS{"CRITICAL"}) { + $state = $ERRORS{"CRITICAL"}; + } else { + print "ERROR: $SAMHAIN exit status $retval\n"; + exit $ERRORS{'UNKNOWN'}; + } +} + +# -------------------------------------------------------------------[ exit ]-- + +print "$msg | 'policy violations'=$status;$opt_w;$opt_c\n"; +exit $state; + + +# ------------------------------------------------------------[ Subroutines ]-- + +sub process_arguments(){ + GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "v" => \$opt_v, "verbose" => \$opt_v, + "w=i" => \$opt_w, "warning=i" => \$opt_w, + "c=i" => \$opt_c, "critical=i" => \$opt_c, + "t=i" => \$opt_t, "timeout=i" => \$opt_t + ); + + if ($opt_V) { + print_revision($PROGNAME,'$Revision: 1.0 $ '); + exit $ERRORS{'OK'}; + } + + if ($opt_h) { + print_help(); + exit $ERRORS{'OK'}; + } + + if (defined $opt_v ){ + $verbose = $opt_v; + } + + unless (defined $opt_t) { + $opt_t = $utils::TIMEOUT ; # default timeout + # $opt_t = $TIMEOUT ; + } + + unless (defined $opt_w) { + $opt_w = 1; + } + + unless (defined $opt_c) { + $opt_c = 1; + } + + if ( $opt_w > $opt_c) { + print "Warning cannot be greater than Critical!\n"; + exit $ERRORS{'UNKNOWN'}; + } + + return $ERRORS{'OK'}; +} + +sub print_usage () { + print "Usage: $PROGNAME [-w ] [-c ] [-t ]\n"; +} + +sub print_help () { + print_revision($PROGNAME, '$Revision: 1.0 $'); + print "Copyright (c) 2004 Rainer Wichmann + +This plugin checks the number of policy violations reported by the +samhain file intgrity checker + +"; + print_usage(); + print " +-w, --warning=INTEGER + Minimum number of policy violations for which a WARNING status will result +-c, --critical=INTEGER + Minimum number of policy violations for which a CRITICAL status will result +-t, --timeout=SECONDS + The number of seconds after which a the plugin will timeout +-v, --verbose + Verbose output +-h, --help + Show this help message +-V, --version + Show the version of the plugin + +"; +} + +#sub print_revision ($$) { +# my $commandName = shift; +# my $pluginRevision = shift; +# $pluginRevision =~ s/^\$Revision: //; +# $pluginRevision =~ s/ \$\s*$//; +# print "$commandName (samhain 2.2.3) $pluginRevision\n"; +#} diff --git a/dsa-nagios-checks/checks/dsa-check-soas b/dsa-nagios-checks/checks/dsa-check-soas new file mode 100755 index 0000000..9d05fff --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-soas @@ -0,0 +1,93 @@ +#!/usr/bin/ruby + +# Copyright 2006 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +require 'resolv' +require 'optparse' +require 'yaml' + +NAGIOS_STATUS = { :OK => 0, :WARNING => 1, :CRITICAL => 2, :UNKNOWN => -1 }; +@verbose = 0; +@additional_nameservers = [] + +def show_help(parser, code=0, io=STDOUT) + program_name = File.basename($0, '.*') + io.puts "Usage: #{program_name} [options] [ ...]" + io.puts parser.summarize + exit(code) +end +ARGV.options do |opts| + opts.on_tail("-h", "--help" , "Display this help screen") { show_help(opts) } + opts.on("-v", "--verbose" , String, "Be verbose") { @verbose += 1 } + opts.on("-a", "--add=HOST" , String, "Also check SOA on ") { |val| @additional_nameservers << val } + opts.parse! +end +show_help(ARGV.options, 1, STDERR) if ARGV.length == 0 + +warnings = [] +oks = [] + +dns = Resolv::DNS.new +ARGV.each{ |domain| + serial = [] + nameservers = dns.getresources(domain, Resolv::DNS::Resource::IN::NS) + nameservernames = nameservers.collect{ |ns| ns.name.to_s } + nameservernames = nameservernames.concat @additional_nameservers + nameservernames.each{ |nameserver| + puts "Testing nameserver #{nameserver} for #{domain}" if @verbose > 0 + arecords = dns.getresources(nameserver, Resolv::DNS::Resource::IN::A) + warnings << "Nameserver #{nameserver} for #{domain} has #{arecords.length} A records" if arecords.length != 1 + arecords.each{ |a| + puts " Nameserver #{nameserver} is at #{a.address}" if @verbose > 0 + begin + resolver = Resolv::DNS.new({:nameserver => a.address.to_s}) + soas = resolver.getresources(domain, Resolv::DNS::Resource::IN::SOA) + rescue SystemCallError => e + warnings << "Could not resolve #{domain} on #{nameserver}: #{e.message}" + else + resolver.close + warnings << "Nameserver #{nameserver} for #{domain} returns #{soas.length} SOAs" if soas.length != 1 + soas.each{ |soa| + puts " Nameserver #{nameserver} returns serial #{soa.serial} for #{domain}" if @verbose > 0 + serial << soa.serial unless serial.include? soa.serial + } + end + } + } + case serial.length + when 0 + warnings << "Found no serials for #{domain}" + when 1 + oks << "#{domain} is at #{serial.first}" + else + warnings << "Nameservers disagree on serials for #{domain}: found #{serial.join(', ')}" if serial.length != 1 + end +} +dns.close + +if warnings.length > 0 + puts warnings.join('; ') + exit NAGIOS_STATUS[:WARNING] +else + puts oks.join('; ') + exit NAGIOS_STATUS[:OK] +end diff --git a/dsa-nagios-checks/checks/dsa-check-statusfile b/dsa-nagios-checks/checks/dsa-check-statusfile new file mode 100755 index 0000000..a69d977 --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-statusfile @@ -0,0 +1,81 @@ +#!/usr/bin/ruby + +# Relay the status of a check that was previously run and which stored +# its result in a file to nagios. +# +# Copyright 2008 Peter Palfrader +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +require 'resolv' +require 'optparse' + +NAGIOS_STATUS = { "OK" => 0, "WARNING" => 1, "CRITICAL" => 2, "UNKNOWN" => 3 } +UNITS_TO_SECONDS = { 's' => 1, 'm' => 60, 'h' => 60*60, 'd' => 24*60*60 } + +def show_help(parser, code=0, io=STDOUT) + program_name = File.basename($0, '.*') + io.puts "Usage: #{program_name} [options] " + io.puts parser.summarize + exit(code) +end + +max_age = "26h" +ARGV.options do |opts| + opts.on_tail("-h", "--help" , "Display this help screen") { show_help(opts) } + opts.on("-a", "--age=AGE" , String, "maximum age, in seconds (or use Nm, Nh or Nd) - default is 26h") { |max_age| } + opts.parse! +end +show_help(ARGV.options, 1, STDERR) if ARGV.length != 1 + +statusfile = ARGV.shift + +# find out what the max age is that we accept +unless (m = /^([0-9]+)([smhd])?$/.match max_age) + STDERR.puts "Invalid age #{age}." + show_help(ARGV.options, 1, STDERR) if ARGV.length != 1 +end +max_age = m[1].to_i * UNITS_TO_SECONDS[m[2] ? m[2] : 's'] + +# let's see if it exists +unless File.exists? statusfile + puts "UNKNOWN: #{statusfile} does not exist." + exit NAGIOS_STATUS['UNKNOWN'] +end + + +mtime = File.stat(statusfile).mtime +if mtime + max_age < Time.now + puts "WARNING: #{statusfile} is old: #{mtime}" + exit NAGIOS_STATUS['WARNING'] +end + +status = File.new(statusfile) +returnvalue = status.readline.chomp + +unless NAGIOS_STATUS.has_key? returnvalue + puts "UNKNOWN: #{statusfile} has invalid return value: #{returnvalue}" + exit NAGIOS_STATUS['UNKNOWN'] +end + +status.readlines.each do |line| + print line +end +exit NAGIOS_STATUS[returnvalue] diff --git a/dsa-nagios-checks/checks/dsa-check-udldap-freshness b/dsa-nagios-checks/checks/dsa-check-udldap-freshness new file mode 100755 index 0000000..be2a6da --- /dev/null +++ b/dsa-nagios-checks/checks/dsa-check-udldap-freshness @@ -0,0 +1,50 @@ +#!/usr/bin/perl -w + +use strict; +my %CODE = ( + 'UNDEF' => -1, + 'OK' => 0, + 'WARNING' => 1, + 'CRITICAL' => 2, + 'UNKNOWN' => 3 +); + +my $f; + +$SIG{__DIE__ } = sub() { + print shift; + exit $CODE{'UNKNOWN'}; +}; + +if ( -e "/var/lib/misc/thishost/passwd.tdb" ) { + $f = "/var/lib/misc/thishost/passwd.tdb"; +} else { + my $hostname = `hostname -f`; + chomp $hostname; + $hostname =~ m/^([a-z]+(?:\.[a-z]+)+)$/; + die "Weird hostname '$hostname'\n" unless defined $1; + $hostname = $1; + if ( -e "/var/lib/misc/$hostname/passwd.tdb" ) { + $f = "/var/lib/misc/$hostname/passwd.tdb"; + }; +}; + +die "Could not find passwd.tdb" unless defined $f; + +my @stat = stat($f) or die ("Cannot stat $f: $!\n"); +my $age = time - $stat[10]; +my $hage; +if ($age > 48 * 3600) { + $hage = sprintf("%.1f days", $age / 24 / 3600); +} elsif ($age > 3600) { + $hage = sprintf("%.1f hours", $age / 3600); +} else { + $hage = sprintf("%d minutes", $age / 60); +}; + +if ($age > 60*60) { + print "WARNING: ud-ldap info is $hage old\n"; + exit $CODE{'WARNING'}; +}; +print "OK: ud-ldap info is $hage old\n"; +exit $CODE{'OK'}; diff --git a/dsa-nagios-checks/debian/changelog b/dsa-nagios-checks/debian/changelog index 0bcbd06..e252ca0 100644 --- a/dsa-nagios-checks/debian/changelog +++ b/dsa-nagios-checks/debian/changelog @@ -4,8 +4,9 @@ dsa-nagios-checks (69) unstable; urgency=low * Replaces/Conflicts dsa-nagios-nrpe-config. * Update description. * No longer install nrpe_dsa.cfg. + * Move files into specific directories in source. - -- Peter Palfrader Tue, 31 Mar 2009 19:15:45 +0200 + -- Peter Palfrader Tue, 31 Mar 2009 19:19:14 +0200 dsa-nagios-nrpe-config (68) unstable; urgency=low diff --git a/dsa-nagios-checks/debian/rules b/dsa-nagios-checks/debian/rules index 269aa3a..179ed1d 100755 --- a/dsa-nagios-checks/debian/rules +++ b/dsa-nagios-checks/debian/rules @@ -13,31 +13,21 @@ install: dh_clean -k dh_installdirs - install -m 755 dsa-check-hpacucli $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-raid-areca $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-raid-dac960 $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-raid-mpt $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-raid-sw $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-raid-3ware $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-running-kernel $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-config $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-dabackup $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-dabackup-server $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-udldap-freshness $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-statusfile $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-samhain $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-mirrorsync $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-soas $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - - install -m 755 dsa-check-puppet $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 755 dsa-check-packages $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins - install -m 644 obsolete-packages-ignore $(CURDIR)/debian/dsa-nagios-nrpe-config/etc/nagios - - install -m 755 apt-status-check $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/share/dsa - install -m 755 weak-ssh-keys-check $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/share/dsa - - install -m 755 dsa-update-apt-status $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/sbin - install -m 755 dsa-update-samhain-status $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/sbin + for f in `ls -1 checks/*`; do \ + install -m 755 $$f $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/lib/nagios/plugins; \ + done + + for f in `ls -1 etc/*`; do \ + install -m 644 $$f $(CURDIR)/debian/dsa-nagios-nrpe-config/etc/nagios; \ + done + + for f in `ls -1 share/*`; do \ + install -m 755 $$f $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/share/dsa; \ + done + + for f in `ls -1 sbin/*`; do \ + install -m 755 $$f $(CURDIR)/debian/dsa-nagios-nrpe-config/usr/sbin; \ + done binary-indep: install diff --git a/dsa-nagios-checks/dsa-check-config b/dsa-nagios-checks/dsa-check-config deleted file mode 100755 index 0d62402..0000000 --- a/dsa-nagios-checks/dsa-check-config +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh - -# Check that debian-admin is in /etc/aliases for root. -# Peter Palfrader, 2008 - -#my %ERRORS = ( OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => -1 ); - -set -e -err=0 - -log() { - if [ "$0" == "ok" ] && [ "$err" == 0 ]; then - err=0 - elif [ "$1" == "warn" ] && [ "$err" -lt 1 ]; then - err=1 - elif [ "$1" == "critical" ] && [ "$err" -lt 2 ]; then - err=2 - elif [ "$1" == "unknown" ] && [ "$err" == 0 ]; then - err=3 - fi - if [ "`eval echo \\$$1`" = "" ]; then - eval $1="\"$2\"" - else - eval $1="\"`eval echo \\$$1`; $2\"" - fi -} - - -check_aliases() { - if ! [ -e /etc/aliases ]; then - log unknown "/etc/aliases not found" - return - fi - - if egrep '^root:.*debian-admin@debian.org' /etc/aliases > /dev/null; then - log ok "debian-admin found in aliases" - return - fi - - log warn "debian-admin not found in root entry in aliases" -} - -check_ldap_conf() { - if ! [ -e /etc/ldap/ldap.conf ]; then - log unknown "/etc/ldap/ldap.conf not found" - return - fi - - if egrep '^URI.*ldap://db.debian.org' /etc/ldap/ldap.conf > /dev/null && - egrep '^BASE.*dc=debian,dc=org' /etc/ldap/ldap.conf > /dev/null && - egrep '^TLS_CACERT.*/etc/ssl/certs/spi-cacert-2008.pem' /etc/ldap/ldap.conf > /dev/null && - egrep '^TLS_REQCERT.*hard' /etc/ldap/ldap.conf > /dev/null ; then - log ok "ldap.conf configured properly" - return - fi - - log warn "ldap.conf does not have URI, BASE, TLS_CACERT, TLS_REQCERT all configured correctly" -} - -check_aliases -check_ldap_conf - -[ "$critical" = "" ] || echo -n "Critical: $critical; " -[ "$warn" = "" ] || echo -n "Warning: $warn; " -[ "$unknown" = "" ] || echo -n "Unknown: $unknown; " -[ "$ok" = "" ] || echo -n "OK: $ok" -echo -exit $err diff --git a/dsa-nagios-checks/dsa-check-dabackup b/dsa-nagios-checks/dsa-check-dabackup deleted file mode 100755 index f400023..0000000 --- a/dsa-nagios-checks/dsa-check-dabackup +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/perl -w - -# Check the status of da-backup backups -# Copyright 2007 Stephen Gran -# Copyright 2008 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -use strict; -use warnings; -use English; -use Getopt::Long; -use Fcntl qw(:seek); - -my $DABACKUP_CONF = '/etc/da-backup.conf'; -my $MAX_AGE = 30*60*60; -my $TOO_FRESH = 5*60; -my %CODE = ( - 'UNDEF' => -1, - 'OK' => 0, - 'WARNING' => 1, - 'CRITICAL' => 2, - 'UNKNOWN' => 3 -); -$SIG{__DIE__ } = sub() { - print shift; - exit $CODE{'UNKNOWN'}; -}; - - -my $EXITCODE = 'UNDEF'; -my %MESSAGE = (); - -sub problem($$$) { - my ($code, $msg, $resource) = @_; - $MESSAGE{$msg} = [] unless defined $MESSAGE{$msg}; - push @{$MESSAGE{$msg}}, $resource; - $EXITCODE = ($CODE{$code} > $CODE{$EXITCODE}) ? $code : $EXITCODE; -}; - - -sub help($$) { - my ($exitcode, $fd) = @_; - version ($fd, 0); - print $fd "Usage: $PROGRAM_NAME --help\n"; - print $fd "Usage: $PROGRAM_NAME"; - exit $exitcode -}; - -my $params = {}; - -Getopt::Long::config('bundling'); -if (!GetOptions ( - 'h|help' => \$params->{'help'}, - )) { - die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [-fwhv]\n"); -}; - -help(0, *STDOUT) if $params->{'help'}; -help(1, *STDERR) if scalar @ARGV > 0; - - -unless (-e $DABACKUP_CONF) { - if (-e '/etc/da-backup') { - print "WARNING: No $DABACKUP_CONF, but we have /etc/da-backup/\n"; - exit $CODE{'WARNING'}; - }; - if (-e '/var/log/da-backup') { - print "WARNING: No $DABACKUP_CONF, but we have /var/log/da-backup/\n"; - exit $CODE{'WARNING'}; - }; - print "OK: da-backup not installed\n"; - exit $CODE{'OK'}; -}; - -my $confdir; -my $logdir; - -open (FH, "< $DABACKUP_CONF") or die ("Cannot open $DABACKUP_CONF: $!\n"); -while () { - if (/confdir=(.*)/) { - $confdir = $1; - } elsif (/logdir=(.*)/) { - $logdir = $1; - }; -}; - -die ("No confdir found in $DABACKUP_CONF") unless defined $confdir; -die ("No logdir found in $DABACKUP_CONF") unless defined $logdir; - -opendir(DIR, $confdir) or die ("Cannot opendir $confdir: $!\n"); -my %conffiles = map {$_ => 1} grep { !/^\./ && !/\.bak$/} readdir(DIR); -closedir(DIR); - -opendir(DIR, $logdir) or die ("Cannot opendir $logdir: $!\n"); -my %logfiles = map {$_ => 1} grep { !/^\./ && !/\.[0-9]+(\.gz)?$/} readdir(DIR); -closedir(DIR); - -if (scalar keys %conffiles == 0) { - print "WARNING: da-backup installed but no backups configured\n"; - exit $CODE{'WARNING'}; -}; - -for my $f (keys %conffiles) { - unless (exists $logfiles{$f}) { - problem('WARNING', 'no log', $f); - } -} - -FILE: -for my $f (sort {$a cmp $b} keys %logfiles) { - unless (exists $conffiles{$f}) { - problem('WARNING', 'no config', $f); - next; - } - - my @stat = stat("$logdir/$f") or die ("Cannot stat $logdir/$f: $!\n"); - my $age = time - $stat[10]; - - if ($age < $TOO_FRESH) { # File is too new, let's use the old one - if (-e "$logdir/$f.0") { - $f .= ".0"; - my @stat = stat("$logdir/$f") or die ("Cannot stat $logdir/$f: $!\n"); - $age = time - $stat[10]; - }; - }; - - if ($age < 0) { - problem('WARNING', 'future timestamp', $f); - next; - } elsif ($age > $MAX_AGE) { - my $hage; - - if ($age > 48 * 3600) { - $hage = sprintf("%d days", $age / 24 / 3600); - } else { - $hage = sprintf("%d hours", $age / 3600); - }; - problem('WARNING', 'old', "$f ($hage)"); - next; - }; - - open(FH, "< $logdir/$f") or die ("Cannot open $logdir/$f: $!\n"); - sysseek(FH, -1024, SEEK_END); # just try it - doesn't matter if it fails - my $last2 = ''; - my $last = ''; - while () { - chomp; - if (/^sent\s+\d+\s+bytes\s+received\s+\d+\s+bytes\s+[\d\.]+\s+bytes\/sec$/) { - problem('OK', 'probably ok', $f); - close(FH); - next FILE; - }; - $last2 = $last; - $last = $_; - }; - problem('CRITICAL', 'FAILED', "$f ($last2 $last)"); -}; - -my $msg = join("; ", map {"$_: ".join(', ', @{$MESSAGE{$_}}) } (sort {$a cmp $b} keys %MESSAGE)); -print $EXITCODE, ": ", $msg, "\n"; -exit $CODE{$EXITCODE}; diff --git a/dsa-nagios-checks/dsa-check-dabackup-server b/dsa-nagios-checks/dsa-check-dabackup-server deleted file mode 100755 index c4e4884..0000000 --- a/dsa-nagios-checks/dsa-check-dabackup-server +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/sh - -# some tests weasel uses to check if da-backup is properly configured: -# Copyright 2008 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -set -e -set -u - -err=0 - -log() { - if [ "$1" == "warn" ] && [ "$err" -lt 1 ]; then - err=1 - elif [ "$1" == "critical" ] && [ "$err" -lt 2 ]; then - err=2 - elif [ "$1" == "unknown" ] && [ "$err" == 0 ]; then - err=3 - fi -} - -cd /etc/da-backup-manager - -# check that the files have proper names -for i in *; do - s=`cat "$i" | awk -F = '$1=="source" {print $2}'` - if [ "$s" = "master.debian.org/debian" ] && [ "$i" = "listarchive" ]; then - # historical exception - continue - fi - if [ "`echo $s | tr / -`" != "$i" ]; then - log warn - echo "Mismatch: Filename $i but backup source $s" - fi -done - -# and that source == destination everywhere -for i in *; do - s=`cat $i | awk -F = '$1=="source"{print $2}'` - d=`cat $i | awk -F = '$1=="destination"{print $2}'` - if [ "$d" != "$s" ]; then - log warn - echo "source != dest in $i. ($s != $d)" - fi -done - -# check that everything that has an entry in authorized_keys has one in /etc/da-backup-manager -rsync_targets=`tempfile` -backup_manager_sources=`tempfile` -trap "rm -f '$rsync_targets' '$backup_manager_sources'" 0 1 2 5 15 -cat /root/.ssh/authorized_keys | - grep '^command=' | - sed -e 's/",no-por.*//' -e 's/.*--ignore-errors . //' -e 's#/org/backup.debian.org/staging/##' | - sort > "$rsync_targets" -grep -h source /etc/da-backup-manager/* | - sed -e 's/source=//' | - sort > "$backup_manager_sources" -if ! diff "$rsync_targets" "$backup_manager_sources" > /dev/null; then - log warn - echo "authorized_keys vs. /etc/da-backup-manage mismatch:" - diff "$rsync_targets" "$backup_manager_sources" -fi - -# check that everything listed as either source or destination by da-backup-manager does exist - if stuff is new it might still be missing tho -for i in `awk -F = '$1=="source" {print $2}' /etc/da-backup-manager/* `; do - if ! [ -d "/org/backup.debian.org/staging/$i" ]; then - log warn - echo "Warning: source $i does not exist" - fi -done -for i in ` awk -F = '$1=="destination"{print $2}' /etc/da-backup-manager/* `; do - if ! [ -d "/org/backup.debian.org/backups/$i" ]; then - log warn - echo "Warning: destination $i does not exist (if it is new, it takes a day)" - fi -done - -# check that everything that does exist has an entry in da-backup-manager -cd /org/backup.debian.org/staging -for i in */*; do - if ! [ -d "$i" ]; then - log warn - echo "WTF: staging/$i is not a dir" - continue - fi - if ! grep "source=$i" /etc/da-backup-manager/* > /dev/null; then - log warn - echo "staging/$i is not listed anywhere in /etc/da-backup-manager" - fi -done -cd /org/backup.debian.org/backups -for i in */*; do - if ! [ -d "$i" ]; then - log warn - echo "WTF: backups/$i is not a dir" - continue - fi - if ! grep "destination=$i" /etc/da-backup-manager/* > /dev/null; then - log warn - echo "backups/$i is not listed anywhere in /etc/da-backup-manager" - fi -done - -if [ "$err" = 0 ]; then - echo "da-backup seems to be properly configured" -fi -exit $err diff --git a/dsa-nagios-checks/dsa-check-hpacucli b/dsa-nagios-checks/dsa-check-hpacucli deleted file mode 100755 index a347388..0000000 --- a/dsa-nagios-checks/dsa-check-hpacucli +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/perl -w - -# check _physical_ disk status of disks on HP smart array controllers -# requires hpacucli -# -# does _not_ check raid status. use arrayprobe for that. - -# Copyright (c) 2008 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -use strict; - -# nagios exit codes -my %CODE = ( - 'OK' => 0, - 'WARNING' => 1, - 'CRITICAL' => 2, - 'UNKNOWN' => 3 -); - -my $EXITCODE = 'OK'; - -$SIG{'__DIE__'} = sub { - print STDERR @_; - exit $CODE{'UNKNOWN'}; -}; - -sub runcmd($) { - my ($cmd) = @_; - $cmd = "sudo hpacucli $cmd"; - open(FH, $cmd."|") or die ("Cannot run $cmd: $!"); - my @lines = ; - close FH; - die ("no results from $cmd\n") if (scalar @lines == 0); - return \@lines; -} - -sub record($) { - my ($newexit) = @_; - die "code $newexit not defined\n" unless defined $CODE{$newexit}; - - if ($CODE{$newexit} > $CODE{$EXITCODE}) { - $EXITCODE = $newexit; - }; -} - - -my $ctrlallshow = runcmd("controller all show"); -my @controllers; -for (@$ctrlallshow) { - chomp; - next if /^$/; - if (/in Slot ([0-9]+) /) { - push @controllers, $1; - next; - }; - die ("Cannot read line '$_' gotten from hpacucli controller all show\n"); -}; - -if (scalar @controllers == 0) { - print "UNKNONW: No smartarray controllers found with hpacucli\n"; - exit $CODE{'UNKNOWN'} -}; - -my @resultstr; - -for my $slot (sort @controllers) { - my $pds = runcmd("controller slot=$slot pd all show"); - my @drives; - my $nodrives = 0; - my %status; - for (@$pds) { - chomp; - next if /^$/; - next if (/^\S.*in Slot $slot/); - next if /^ *array [A-Z]$/; - if (/^ *(array [A-Z]) \(Failed\)$/) { - record('CRITICAL'); - push @{$status{'Failed'}}, $1; - } elsif (/^Error: The specified controller does not have any physical drives on it.$/) { - $nodrives = 1; - } elsif (/^ *physicaldrive (\S+) .* (OK|Predictive Failure|Failed|Rebuilding)(?:, spare)?\)$/) { - my $drive = $1; - my $status = $2; - push @{$status{$status}}, $drive; - if ($status eq 'OK') { - } elsif ($status eq 'Predictive Failure' || - $status eq 'Rebuilding') { - record('WARNING'); - } elsif ($status eq 'Failed') { - record('CRITICAL'); - } else { - record('UNKNOWN'); - }; - push @drives, $drive; - } else { - die ("Cannot read line '$_' gotten from hpacucli controller slot=$slot pd all show\n"); - }; - }; - - # Check that all drives have the proper transfer speed. - # sometimes stuff breaks and they fall back to 10mb/sec. - for my $drive (@drives) { - # skip drives that are known to have failed - next if (exists $status{'Failed'} && grep {$drive eq $_} @{$status{'Failed'}}); - my $type; - if ($drive =~ /^[0-9]+:[0-9]+$/) { # scsi drives - $type = 'SCSI'; - } elsif ($drive =~ /^[0-9]+I:[0-9]+:[0-9]+$/) { # SAS - $type = 'SAS'; - } else { - # I'm not going to run pass arguments of unknown form to the shell.. - warn ("Unknown diskdrive ID $drive\n"); - next; - } - - my $pd = runcmd("controller slot=$slot pd $drive show"); - while (defined $pd->[0] && !($pd->[0] =~ /physicaldrive/)) { - shift @$pd; - }; - shift @$pd; - my %value; - for (@$pd) { - if (m/^\s*(.*?):\s*(.*?)\s*$/) { - $value{$1} = $2; - } - } - - my $key; - my $expected; - if ($type eq 'SCSI') { - $key = 'Transfer Speed'; - if (!defined $value{'Transfer Mode'}) { - record('WARNING'); - push @{$status{'unknown transfer mode'}}, $drive; - next; - } elsif ($value{'Transfer Mode'} eq 'Ultra 3 Wide') { - $expected = '160 MB/Sec'; - } elsif ($value{'Transfer Mode'} eq 'Ultra 320 Wide') { - $expected = '320 MB/Sec'; - } else { - record('WARNING'); - push @{$status{'unknown transfer mode'}}, $drive."(".$value{'Transfer Mode'}.")"; - next; - }; - } elsif ($type eq 'SAS') { - $key = 'PHY Transfer Rate'; - if ($value{'PHY Count'} eq '2') { - $expected = '3.0GBPS, Unknown'; - } else { - $expected = '3.0GBPS'; - } - } else { - warn "Should not be here. Do not know what to do with type '$type'\n"; - next; - } - - if (!defined $value{$key}) { - record('WARNING'); - push @{$status{'unknown transfer speed'}}, $drive; - } elsif ($value{$key} ne $expected) { - record('WARNING'); - push @{$status{'bad transfer speed'}}, $drive."(".$value{$key}.")"; - }; - }; - - if ($nodrives && scalar keys %status > 0) { - push @resultstr, "Slot $slot: have no drives but status results?"; - record('UNKNOWN'); - next; - } elsif ($nodrives) { - push @resultstr, "Slot $slot: no drives"; - next; - }; - - my $cst = runcmd("controller slot=$slot show status"); - for (@$cst) { - chomp; - next if /^$/; - next if (/^\S.*in Slot $slot/); - if (/^ *(.*) Status: (.*)$/) { - my $system = $1; - my $status = $2; - push @{$status{$status}}, $system; - if ($status ne 'OK') { - record('WARNING'); - }; - } else { - die ("Cannot read line '$_' gotten from hpacucli controller slot=$slot show status\n"); - }; - }; - - my $status = join(" - ", (map { $_.": ".join(", ", @{$status{$_}}) } keys %status)); - push @resultstr, "Slot $slot: $status"; -}; - -print "$EXITCODE: ", join(" --- ", @resultstr), "\n"; -exit $CODE{$EXITCODE}; diff --git a/dsa-nagios-checks/dsa-check-mirrorsync b/dsa-nagios-checks/dsa-check-mirrorsync deleted file mode 100755 index 4637cab..0000000 --- a/dsa-nagios-checks/dsa-check-mirrorsync +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/perl -w - -# nagios check for debian security sync checks -# -# Copyright (c) 2008 Alexander Wirt -# Copyright (c) 2009 Peter Palfrader -# -# 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; either version 2 of the License, or -# (at your option) any later version. -# -# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -use LWP::UserAgent; -use Socket; -use strict; -use Date::Parse; -use Getopt::Long; -use Date::Parse; -use Date::Format; -use File::Basename; -use English; -use warnings; - - -sub usage($$) { - my ($fh, $exit) = @_; - my $basename = basename($PROGRAM_NAME); - my $VERSION = '0.1'; - - print $fh "$basename $VERSION\n"; - print $fh "Usage: $basename [--help|--version] [--verbose]\n"; - print $fh "\n"; - print $fh " --help Print this short help.\n"; - print $fh " --version Report version number.\n"; - print $fh " --verbose Be a little verbose.\n"; - print $fh " --host hostname to check.\n"; - print $fh " --path path to tracefile.\n"; - print $fh "\n"; - exit ($exit); -}; - - -$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; -delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; - -my $params; - -$params->{'host'} = 'security.debian.org'; #which host to check -$params->{'path'} = 'project/trace/security-master.debian.org'; - -my $OK = 0; -my $WARNING = 1; -my $CRITICAL = 2; -my $UNKNOWN = 3; - -if (!GetOptions ( - '--help' => \$params->{'help'}, - '--verbose' => \$params->{'verbose'}, - '--version' => \$params->{'version'}, - '--host=s' => \$params->{'host'}, - '--path=s' => \$params->{'path'}, - )) { - usage(*STDERR,1) -}; -usage(*STDOUT,0) if ($params->{'help'}); -usage(*STDERR,1) if (scalar @ARGV); - -my $host = $params->{'host'}; -my $path = $params->{'path'}; -my @slaves; -my $status; -my @exitstatus; -my $exitcode = $OK; - -@slaves = gethostbyname($params->{'host'}) or die "Can't resolve " . $params->{'host'} .": $!\n"; -@slaves = map { inet_ntoa($_) } @slaves[4 .. $#slaves]; -print "Checking the following hosts:\n" . join("\n", @slaves) . "\n" if $params->{'verbose'}; - -my @critical; - -foreach my $slave (@slaves) { - my $ua = LWP::UserAgent->new; - $ua->proxy('http', "http://$slave"); - print "Requesting http://$host/$path from $slave\n" if $params->{'verbose'}; - my $response = $ua->get("http://$host/$path"); - - - if ($response->is_success) { - my $content = $response->content; # or whatever - my ($date, $foo, $bar) = split("\n", $content); - my $synctime = str2time($date);; - print "$slave last synced $synctime\n" if $params->{'verbose'}; - $status->{$slave}->{'synced'} = $synctime; - } - else { - push @exitstatus, "$slave broken: " . $response->status_line; - $status->{$slave}->{'error'} = $response->status_line; - $exitcode = $CRITICAL; - push @critical, $slave; - } -} - - -my %seen; -my $o_sync = scalar(grep !$seen{$_}++, map{$status->{$_}->{'synced'}} keys(%{$status})); -if ($o_sync > 1) { - $exitcode = $CRITICAL; - $o_sync -= 1; - my @mirrors = sort { $status->{$a}->{'synced'} <=> $status->{$b}->{'synced'} } keys %{$status}; - push @exitstatus, "$o_sync mirror(s) not in sync (from oldest to newest): ". - join(",", splice(@mirrors,0,$o_sync)); -} else { - print "All mirrors unique\n" if $params->{'verbose'}; -} - -if ($exitcode == $CRITICAL) { - print "CRITICAL: " . join(',',@exitstatus) . "\n"; -} elsif ($exitcode == $OK) { - print "OK: all mirrors up2date\n"; -} - -foreach my $mirror (keys(%{$status})) { - if ($status->{$mirror}->{'error'}) { - print "$mirror broken: " . $status->{$mirror}->{'error'} . "\n"; - } else { - print "$mirror last synced: " . localtime($status->{$mirror}->{'synced'}) ."\n"; - } -} - -exit $exitcode; diff --git a/dsa-nagios-checks/dsa-check-packages b/dsa-nagios-checks/dsa-check-packages deleted file mode 100755 index 29e7e4d..0000000 --- a/dsa-nagios-checks/dsa-check-packages +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/perl - -# dsa-check-packages - -# checks for obsolete/local and upgradeable packages. -# -# packages for the obsolete/local check can be ignored, by -# listing their full name in /etc/nagios/obsolete-packages-ignore -# or by having a regex (starting a line with "/") that matches -# the packagename in said file. -# -# Takes one optional argument, the location of the ignore file. - - -# Copyright (C) 2008, 2009 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -use strict; -use warnings; -use English; - -my $IGNORE = "/etc/nagios/obsolete-packages-ignore"; - -my %CODE = ( - 'OK' => 0, - 'WARNING' => 1, - 'CRITICAL' => 2, - 'UNKNOWN' => 3 -); -my $EXITCODE = 'OK'; -sub record($) { - my ($newexit) = @_; - die "code $newexit not defined\n" unless defined $CODE{$newexit}; - - if ($CODE{$newexit} > $CODE{$EXITCODE}) { - $EXITCODE = $newexit; - }; -} - - - -sub get_packages { - $ENV{'COLUMNS'} = 1000; - $ENV{'LC_ALL'} = 'C'; - open(F, "dpkg -l|") or die ("Cannot run dpkg: $!\n"); - my @lines = ; - close(F); - chomp(@lines); - - shift @lines while ($lines[0] !~ /\+\+\+/); - shift @lines; - - my %pkgs; - for my $line (@lines) { - my ($state, $pkg, $version, undef) = split(/ */, $line); - $pkgs{$state}{$pkg} = { 'installed' => $version } - } - - my $installed = $pkgs{'ii'}; - delete $pkgs{'ii'}; - - open my $olderr, ">&STDERR" or die "Can't dup STDERR: $!"; - open STDERR, ">/dev/null" or die "Can't dup STDOUT: $!"; - - open (F, "apt-cache policy ".(join(" ", keys(%$installed)))." |") or die ("Cannot run apt-cache policy: $!\n"); - @lines = ; - close(F); - chomp(@lines); - open STDERR, ">&", $olderr or die "Can't dup OLDERR: $!"; - - my $line; - my $pkgname = undef; - while (defined($line = shift @lines)) { - if ($line =~ /^([^ ]*):$/) { - $pkgname = $1; - } elsif ($line =~ /^ +Installed: (.*)$/) { - # etch dpkg -l does not print epochs, so use this info, it's better - $installed->{$pkgname}{'installed'} = $1; - } elsif ($line =~ /^ +Candidate: (.*)$/) { - $installed->{$pkgname}{'candidate'} = $1; - } elsif ($line =~ /^ +\*\*\*/) { - my @l; - @l = split(/ +/, $line); - $line = shift @lines; - @l = split(/ +/, $line); - $installed->{$pkgname}{'origin'} = $l[2]; - } - } - - my (%current, %obsolete, %outofdate); - for my $pkgname (keys %$installed) { - my $pkg = $installed->{$pkgname}; - - unless (defined($pkg->{'candidate'}) && defined($pkg->{'origin'})) { - $obsolete{$pkgname} = $pkg; - next; - } - - if ($pkg->{'candidate'} ne $pkg->{'installed'}) { - $outofdate{$pkgname} = $pkg; - next; - }; - if ($pkg->{'origin'} eq '/var/lib/dpkg/status') { - $obsolete{$pkgname} = $pkg; - next; - } - $current{$pkgname} = $pkg; - } - - $pkgs{'current'} = \%current; - $pkgs{'outofdate'} = \%outofdate; - $pkgs{'obsolete'} = \%obsolete; - return \%pkgs; -} - -sub load_ignores { - my ($ignorefile, $require_file) = @_; - - my @ignores; - if (!$require_file and ! -e $ignorefile) { - return \@ignores; - } - - open (F, "< $ignorefile") or die ("Cannot open $ignorefile: $!\n"); - @ignores = ; - close F; - chomp(@ignores); - return \@ignores; -} - -sub check_ignore { - my ($pkg, $ignores) = @_; - - my $ignore_this = 0; - for my $ignore (@$ignores) { - my $ig = $ignore; - return 1 if ($ig eq $pkg); - if (substr($ig,0,1) eq '/') { - substr($ig, 0, 1, ''); - $ig =~ s,/$,,; - return 1 if ($pkg =~ /$ig/); - } - } - return 0 -} - -sub filter_ignored { - my ($packages, $ignores) = @_; - - my $obs = $packages->{'obsolete'}; - - my (%ignored, %bad); - for my $pkg (keys %$obs) { - if (check_ignore($pkg, $ignores)) { - $ignored{$pkg} = $obs->{$pkg}; - } else { - $bad{$pkg} = $obs->{$pkg}; - }; - } - delete $packages->{'obsolete'}; - $packages->{'obsolete'} = \%bad; - $packages->{'obsolete-ignored'} = \%ignored; -}; - -sub usage { - my ($fd, $exit) = @_; - print $fd "Usage: $PROGRAM_NAME []\n"; - exit $exit; -} - -my $ignorefile = $IGNORE; -my $ignorefile_userset = 0; -usage(\*STDERR, 1) if (@ARGV > 1); -if (@ARGV == 1) { - usage(\*STDOUT, 0) if ($ARGV[0] eq "-h"); - usage(\*STDOUT, 0) if ($ARGV[0] eq "--help"); - $ignorefile = $ARGV[0]; - $ignorefile_userset = 1; -}; - -my $ignores = load_ignores($ignorefile, $ignorefile_userset); -my $packages = get_packages(); - -filter_ignored($packages, $ignores); - - - -my @reportform = ( - { 'key' => 'obsolete', - 'listpackages' => 1, - 'long' => "%d local or obsolete packages: %s", - 'short' => "%d obs", - 'status' => 'WARNING' }, - { 'key' => 'outofdate', - 'listpackages' => 1, - 'long' => "%d out of date packages: %s", - 'short' => "%d updates", - 'status' => 'WARNING' }, - { 'key' => 'current', - 'listpackages' => 0, - 'long' => "%d packages current.", - 'short' => "%d ok", - 'status' => 'OK' }, - { 'key' => 'obsolete-ignored', - 'listpackages' => 1, - 'long' => "%d whitelisted local or obsolete packages: %s", - 'short' => "%d obs(ignored)", - 'status' => 'OK' }, - { 'key' => 'rc', - 'listpackages' => 1, - 'long' => "%d packages removed but not purged: %s", - 'short' => "%d rc", - 'status' => 'OK' }, - { 'key' => 'hi', - 'listpackages' => 1, - 'long' => "%d packages on hold: %s", - 'short' => "%d hi", - 'status' => 'OK' }, - { 'key' => 'pc', - 'listpackages' => 1, - 'long' => "%d packages requested to be purged but conffiles still installed: %s", - 'short' => "%d pc", - 'status' => 'WARNING' }, - ); - -my @longout; -my @shortout; -for my $form (@reportform) { - my $pkgs = $packages->{$form->{'key'}}; - delete $packages->{$form->{'key'}}; - my $num = scalar keys %$pkgs; - next unless ($num > 0); - if ($form->{'listpackages'}) { - my $list = join(", ", keys %$pkgs); - push @longout, sprintf($form->{'long'}, $num, $list); - } else { - push @longout, sprintf($form->{'long'}, $num); - }; - push @shortout, sprintf($form->{'short'}, $num); - record($form->{'status'}); -}; -if (scalar keys %$packages) { - record('WARNING'); - unshift @shortout, "unk: ".join(", ", keys %$packages); - for my $status (sort {$b cmp $a} keys %$packages) { - my $pkgs = $packages->{$status}; - my $list = join(", ", keys %$pkgs); - unshift @longout, "Unknown package status $status: $list"; - }; -} - -my $shortout = $EXITCODE.": ".join(", ", @shortout); -my $longout = join("\n", @longout); - -print $shortout,"\n"; -print $longout,"\n"; - -exit $CODE{$EXITCODE}; diff --git a/dsa-nagios-checks/dsa-check-puppet b/dsa-nagios-checks/dsa-check-puppet deleted file mode 100755 index 332261e..0000000 --- a/dsa-nagios-checks/dsa-check-puppet +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env ruby - -require 'optparse' - -class CheckPuppet - - VERSION = '0.1' - script_name = File.basename($0) - - # default options - OPTIONS = { - :statefile => "/var/lib/puppet/state/state.yaml", - :interval => 60, - } - - o = OptionParser.new do |o| - o.set_summary_indent(' ') - o.banner = "Usage: #{script_name} [OPTIONS]" - o.define_head "The check_puppet Nagios plug-in checks that the specified " + - "puppet state file is no older than specified interval." - o.separator "" - o.separator "Mandatory arguments to long options are mandatory for " + - "short options too." - - o.on("-s", "--statefile=statefile", String, "The state file", - "Default: #{OPTIONS[:statefile]}") { |OPTIONS[:statefile]| } - o.on("-i", "--interval=value", Integer, - "Default: #{OPTIONS[:interval]} minutes") { |OPTIONS[:interval]| } - - o.separator "" - o.on_tail("-h", "--help", "Show this help message.") do - puts o - exit - end - - o.parse!(ARGV) - end - - def check_state - - # Set variables - curt = Time.now - intv = OPTIONS[:interval] * 60 - - # Check file time - @modt = 0 - begin - @modt = File.mtime("#{OPTIONS[:statefile]}") - rescue - @file = 3 - end - - diff = (curt - @modt).to_i - - @file = 2 - @file = 0 if diff <= intv - - end - - def output_status - - case @file - when 0 - state = "state file status okay updated on " + @modt.strftime("%m/%d/%Y at %H:%M:%S") - when 2 - state = "state file is missing or older than #{OPTIONS[:interval]} minutes" - when 3 - state = "state file status unknown" - end - - case @file - when 0 - status = "OK" - exitcode = 0 - when 2 - status = "CRITICAL" - exitcode = 2 - when 3 - status = "UNKNOWN" - exitcide = 3 - end - - puts "PUPPET " + status + ": " + state - exit(exitcode) - end -end - -cp = CheckPuppet.new -cp.check_state -cp.output_status - diff --git a/dsa-nagios-checks/dsa-check-raid-3ware b/dsa-nagios-checks/dsa-check-raid-3ware deleted file mode 100755 index a9887b9..0000000 --- a/dsa-nagios-checks/dsa-check-raid-3ware +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/perl -Tw - -# Copyright (C) 2006 Peter Palfrader - -# Need to allow /usr/local/bin/tw_cli info c0 u0 status in sudoers: -# -# nagios ALL=(ALL) NOPASSWD: /usr/local/bin/tw_cli info c0 u0 status -# - -use strict; -use English; -use Getopt::Long; - -$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; -delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; - -my $TW_CLI = '/usr/local/bin/tw_cli'; -my $SVN_REVISION_STRING = '$Rev: 313 $'; -my ($SVN_REVISION) = ($SVN_REVISION_STRING =~ /([0-9]+)/); - $SVN_REVISION = 'unknown' unless defined $SVN_REVISION; -my $VERSION = '0.0.0.'.$SVN_REVISION; - -# nagios exit codes -my $UNKNOWN = -1; -my $OK = 0; -my $WARNING = 1; -my $CRITICAL = 2; - -my $params = { - 'no-sudo' => 0, - 'controller' => 0, - 'unit' => 0 - }; - -Getopt::Long::config('bundling'); -if (!GetOptions ( - '--help' => \$params->{'help'}, - '--version' => \$params->{'version'}, - '--verbose' => \$params->{'verbose'}, - '--controller=i' => \$params->{'controller'}, - '--unit=i' => \$params->{'unit'}, - '--no-sudo' => \$params->{'no-sudo'}, - )) { - die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--no-sudo] [--controller=] [--unit=]\n"); -}; -if ($params->{'help'}) { - print "$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--no-sudo] [--controller=] [--unit=]\n"; - print "Checks status of 3ware raid arrays.\n"; - exit (0); -}; -if ($params->{'version'}) { - print "nagios-check-raid-3ware $VERSION\n"; - print "nagios check for 3ware raids\n"; - print "Copyright (c) 2006 Peter Palfrader \n"; - exit (0); -}; - -$SIG{'__DIE__'} = sub { - print STDERR @_; - exit $UNKNOWN; -}; - -unless (-e $TW_CLI) { - print "Cannot find '$TW_CLI'.\n"; - exit $UNKNOWN; -}; - -my $sudo = $params->{'no-sudo'} ? '' : 'sudo '; -my $command = "$sudo $TW_CLI info c$params->{'controller'} u$params->{'unit'} status"; -print STDERR "Running $command\n" if $params->{'verbose'}; -open (TW, "$command|") or die ("Cannot run $command: $!\n"); -my @tw=; -close TW; -if ($CHILD_ERROR) { # program failed - die("$command returned with non-zero exit code: ".($CHILD_ERROR / 256)."\n"); -}; - - -my $exit = $UNKNOWN; -my $msg = ''; -for my $line (@tw) { - chomp $line; - next if $line =~ /^$/; - my ($device, $status) = $line =~ m#^(/c[0-9]+/u[0-9]+) status = ([A-Z]+)$#; - unless (defined($device) && defined($status)) { - print "Cannot parse line '$line'\n"; - exit $UNKNOWN; - }; - if ($status eq 'OK' || - $status eq 'VERIFYING') { - $msg .= ($msg eq '' ? '' : '; '). "$device: $status"; - $exit = $exit > $OK ? $exit : $OK; - } elsif ($status eq 'DEGRADED') { - $msg .= ($msg eq '' ? '' : '; '). "$device: $status"; - $exit = $exit > $CRITICAL ? $exit : $CRITICAL; - } elsif ($status eq 'OFFLINE') { - $msg .= ($msg eq '' ? '' : '; '). "$device: $status"; - $exit = $exit > $CRITICAL ? $exit : $CRITICAL; - } else { - $msg .= ($msg eq '' ? '' : '; '). "$device: UNKNOWN STATUS '$status'"; - $exit = $exit > $UNKNOWN ? $exit : $UNKNOWN; - }; -}; - -if ($msg eq '') { - $msg = "No devices found"; - die ("exit is not UNKNOWN but $exit") if ($exit != $UNKNOWN); -} - -print $msg,"\n"; -exit $exit; diff --git a/dsa-nagios-checks/dsa-check-raid-areca b/dsa-nagios-checks/dsa-check-raid-areca deleted file mode 100755 index da97c98..0000000 --- a/dsa-nagios-checks/dsa-check-raid-areca +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/perl - -# downloaded as check_areca from -# http://www.nagiosexchange.org/cgi-bin/page.cgi?g=1486.html;d=1 -# on 20081001 by weasel. -# -# local changes: fix path to areca_cli - -##################################################### -#Program to check the areca RAID controller for the status of the RAID -#Created: 2007-11-27 -#Version: 1.1.0 -#Revised: 2008-07-23 -#Revised by: Erinn Looney-Triggs -#Author: Erinn Looney-Triggs -#Changelog: -#1.1: Fixed issue with newer versions of the Areca CLI > 1.72 and -#fixed a problem where the RAID name contained spaces -#(Reported by Daniel Philipp). Also did a bit of cleanup. -##################################################### - -use Carp; -use English qw( -no_match_vars ); -use Getopt::Long; #Grab command line switches -use Pod::Usage; -use strict; #Do it right -use warnings; - -$ENV{PATH} = '/usr/local/bin:/usr/bin:'; #Safer path -my $areca_cli = '/usr/local/sbin/areca-cli'; -my $timeout = '10'; #Default timeout of 10 seconds -my $VERSION = '1.1.0'; #Version number - -#Nagios plugin return values, in english -my $OK = '0'; -my $WARNING = '1'; -my $CRITICAL = '2'; -my $UNKNOWN = '3'; - -GetOptions( 'areca_cli|A=s' => \$areca_cli, - 'man' => sub { pod2usage(3) }, - 'timeout|t=i' => \$timeout, - 'usage' => sub { pod2usage(1) }, - 'version' => sub { VersionMessage() }, - 'help' => sub { pod2usage(1) }, -); - -sanity_checks(); -parse_areca( check_areca() ); - -sub check_areca{ - my @output; - - #Timer operation. Times out after $timeout seconds. - eval { - - #Set the alarm and set the timeout - local $SIG{ALRM} = sub { die "alarm\n" }; - alarm $timeout; - - #Run the command - @output = `sudo $areca_cli vsf info`; - if ($?){ - print "Command: cli vsf info failed, " - . "$OS_ERROR $CHILD_ERROR, aborting!\n"; - exit $CRITICAL; - } - - #Reset the alarm if successful - alarm 0; - }; - - #Test return value and exit if eval caught the alarm - if ($EVAL_ERROR) { - if ( $EVAL_ERROR eq "alarm\n" ) { - print "Operation timed out after $timeout seconds.\n"; - exit $CRITICAL; - } - else { - print "An unknown error has occured: $EVAL_ERROR \n"; - exit $UNKNOWN; - } - } - - return @output; -} - -sub parse_areca{ - my @output = @_; - - my $abnormal; #Holds count of non-normal returns - - my @pertinent_lines = grep (/\s\d+\s/, @output); - - for my $line (@pertinent_lines){ - #Strip of leading spaces - $line =~ s/^\s+//; - - #Split the line into discrete parts - my ( $number, $level, $capacity, $state, ) - = (split (/\s+/, "$line"))[0,-4,-3,-1]; - - #If the state is normal continue on in loop - if (lc $state eq "normal"){ - print "|Controller number: $number RAID level: $level " - . "Capacity: $capacity State: $state| "; - } - - #If state is abnormal continue on in loop but add 1 to $abnormal - else{ - print "|Controller number: $number RAID level: $level " - . "Capacity: $capacity State: $state| "; - $abnormal++; - } - } - - #If any abnormalities exist ext with a critical error. - if ($abnormal){ - exit $CRITICAL; - } - else { - exit $OK; - } - - return; #This should never be reached -} - -sub sanity_checks{ - if (! -e $areca_cli){ - print "$areca_cli does not exist, aborting!\n"; - exit $CRITICAL; - } - if (! -x $areca_cli){ - print "$areca_cli is not executable by the running user, aborting!\n"; - exit $CRITICAL; - } - - return; #This should never be reached -} - -#Version message information displayed in both --version and --help -sub main::VersionMessage { - - print <<"EOF"; -This is version $VERSION of check_areca. - -Copyright (c) 2007-2008 Erinn Looney-Triggs (erinn.looneytriggs\@gmail.com). -All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License. -See http://www.fsf.org/licensing/licenses/gpl.html - -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. - -EOF - - exit 1; -} - -__END__ - -=head1 NAME - -check_areca - Checks the status of an Areca RAID via the Areca CLI utility. - -=head1 VERSION - -This documentation refers to check_areca version 1.1.0 - -=head1 USAGE - -check_areca.pl - -=head1 REQUIRED ARGUMENTS - -None - -=head1 OPTIONS - - --areca_cli (-A) Set the location of the Areca cli executable. - --help Display usage information. - --man Display the entire POD documentation - --timeout (-t) Sets the timeout, defaults to 10 seconds. - --usage Display usage information (same as --help) - --version Display the version number - - -=head1 DESCRIPTION - -This is a Nagios plugin that runs the Areca CLI to check the status of the -RAID controller. It then parses the resultant exit information and -passes the output to NRPE. - -=head1 DIAGNOSTICS - -=head2 Command: cli vsf info failed, aborting! - -For some reason the command trying to be run failed. Try running it by hand -and seeing if it runs properly. - -=head2 Operation timed out after seconds. - -Running the command failed after a certain amount of time (defaults to 10 -seconds). Try using the --timeout (-t) switch and increasing the timeout -threshold. Also try running the command by hand and see if it is hanging. - -=head2 An unknown error has occurred: - -Just what it says, running the cli command threw an unknown error and the -process died. Run the CLI command by hand and see if you receive proper -output. - -=head2 does not exist, aborting! - -The binary that the script is looking to run does not exist. By default -check_areca looks in /usr/local/areca/bin/ for the cli. However, you can -change this default by setting the --areca_cli (-A) flag from the command -line - -=head2 is not executable by the running user, aborting! - -The cli program was found but it is not executable by the current user, -usually this is the nagios user. - -=head1 CONFIGURATION AND ENVIRONMENT - -The Areca cli program should be available on the system. By default -check_areca looks in /usr/local/areca/bin/cli for the cli. You can set the -location using the --areca_cli (-A) flag from the command line. - -It is helpful to have an Areca RAID controller on the system being checked. - -=head1 DEPENDENCIES - - check_areca depends on the following modules: - POSIX Standard Perl 5.8 module - Getopt::Long Standard Perl 5.8 module - Pod::USAGE Standard Perl 5.8 module - -=head1 INCOMPATIBILITIES - -None known yet. - -=head1 BUGS AND LIMITATIONS - -Bugs, never heard of 'em ;). -If you encounter any bugs let me know. (erinn.looneytriggs@gmail.com) - -=head1 AUTHOR - -Erinn Looney-Triggs (erinn.looneytriggs@gmail.com) - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007-2008 Erinn Looney-Triggs (erinn.looneytriggs@gmail.com). -All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License. -See L. - -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. diff --git a/dsa-nagios-checks/dsa-check-raid-dac960 b/dsa-nagios-checks/dsa-check-raid-dac960 deleted file mode 100755 index 7893365..0000000 --- a/dsa-nagios-checks/dsa-check-raid-dac960 +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# Nagios check for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers -# -# Some background information on the driver is available at -# http://home.germany.net/100-120220/mylex/DAC960.README -# -# Written 2008 Peter Palfrader - -if [ -e /proc/rd/status ]; then - status=`cat /proc/rd/status` - if [ "$status" = "OK" ]; then - echo "OK: all DAC960 controllers operating normally; no (non-standby) failures have occurred" - exit 0; - else - echo "CRITICAL: proc/rd/status is $status" - exit 2; - fi; -else - echo "UNKNOWN: No DAC960 controllers in the system" - exit 3; -fi diff --git a/dsa-nagios-checks/dsa-check-raid-mpt b/dsa-nagios-checks/dsa-check-raid-mpt deleted file mode 100755 index f4f3407..0000000 --- a/dsa-nagios-checks/dsa-check-raid-mpt +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/perl -Tw - -# Copyright (C) 2008 Peter Palfrader - -# Need to allow /usr/local/bin/tw_cli info c0 u0 status in sudoers: -# -# nagios ALL=(ALL) NOPASSWD: /usr/sbin/mpt-status -s -# - -use strict; -use English; -use Getopt::Long; - -$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; -delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; - -my $MPT_STATUS = '/usr/sbin/mpt-status'; - -# nagios exit codes -my $UNKNOWN = -1; -my $OK = 0; -my $WARNING = 1; -my $CRITICAL = 2; - -$SIG{'__DIE__'} = sub { - print STDERR @_; - exit $UNKNOWN; -}; - -unless (-e $MPT_STATUS) { - print "Cannot find '$MPT_STATUS'.\n"; - exit $UNKNOWN; -}; - -my $command = "sudo $MPT_STATUS -s"; -open (MPT, "$command|") or die ("Cannot run $command: $!\n"); -my @tw=; -close MPT; -if ($CHILD_ERROR) { # program failed - die("$command returned with non-zero exit code: ".($CHILD_ERROR / 256)."\n"); -}; - - -my $exit = $UNKNOWN; -my $msg = ''; -for my $line (@tw) { - chomp $line; - next if $line =~ /^$/; - my ($device, $num, $status) = $line =~ m#^(log_id|vol_id|phys_id)\s+([0-9]+)\s+(.*)$#; - unless (defined($device) && defined($num) && defined($status)) { - print "Cannot parse line '$line'\n"; - exit $UNKNOWN; - }; - if ($status eq 'OPTIMAL' || - $status eq 'ONLINE') { - $msg .= ($msg eq '' ? '' : '; '). "$device $num: $status"; - $exit = $exit > $OK ? $exit : $OK; - } else { - $msg .= ($msg eq '' ? '' : '; '). "$device $num: $status"; - $exit = $exit > $CRITICAL ? $exit : $CRITICAL; - }; -}; - -if ($msg eq '') { - $msg = "No devices found"; - die ("exit is not UNKNOWN but $exit") if ($exit != $UNKNOWN); -} - -print $msg,"\n"; -exit $exit; diff --git a/dsa-nagios-checks/dsa-check-raid-sw b/dsa-nagios-checks/dsa-check-raid-sw deleted file mode 100755 index 0297036..0000000 --- a/dsa-nagios-checks/dsa-check-raid-sw +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/perl -w -# ------------------------------------------------------------------------------ -# File Name: chech_raid.pl -# Author: Thomas Nilsen - Norway -# Date: 14/06/2003 -# Version: 0.1 -# Description: This script will check to see if any software raid -# devices are down. -# Email: thomas.nilsen@doc-s.co.uk -# WWW: www.doc-s.co.uk -# ------------------------------------------------------------------------------ -# Copyright 2003 (c) Thomas Nilsen -# Credits go to Ethan Galstad for coding Nagios -# License GPL -# ------------------------------------------------------------------------------ -# Date Author Reason -# ---- ------ ------ -# 2008-03-31 Peter Palfrader Return warning on running resync -# 2007-11-07 Peter Palfrader Return unknown if /proc/mdstat does not exist -# 05/10/2004 Peter Palfrader Make it work without that 'use util (vars)' -# 14/06/2003 TN Initial Release -# - Format of mdstat assumed to be "2 line" per -# device with [??] on the second line. -# ------------------------------------------------------------------------------ - -use strict; -use warnings; -use Getopt::Long;; -use vars qw($opt_V $opt_h $opt_t $opt_F $PROGNAME); -use lib '/usr/local/nagios/libexec/'; -my $TIMEOUT=15; -my %ERRORS = ( OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => -1 ); - - -$PROGNAME="check_raid"; - -sub print_help (); -sub print_usage (); - -$ENV{'PATH'}=''; -$ENV{'BASH_ENV'}=''; -$ENV{'ENV'}=''; -my ( $line, $stat, $state ,@device, $msg, $status, $timeout); - -$stat="/proc/mdstat"; - -#Option checking -Getopt::Long::Configure('bundling'); -$status = GetOptions( - "V" => \$opt_V, "version" => \$opt_V, - "h" => \$opt_h, "help" => \$opt_h, - "F" => \$opt_F, "filename" => \$opt_F, - "t" => \$opt_t, "timeout" => \$opt_t); -# Version -if ($opt_V) { - print($PROGNAME,': $Revision: 0.1 $'); - exit $ERRORS{'OK'}; -} -# Help -if ($opt_h) { - print_help(); - exit $ERRORS{'OK'}; -} -# Filename supplied -if ($opt_F) { - $opt_F = shift; - $stat = $1 if ($opt_F =~ /^(.*)$/); - - if ( ! -r $stat ) { - print "Invalid mdstat file: $opt_F\n"; - exit $ERRORS{'UNKNOWN'}; - } -} - -$timeout = $TIMEOUT; -($opt_t) && ($opt_t =~ /^([0-9]+)$/) && ($timeout = $1); - -# Just in case of problems, let's not hang Nagios -$SIG{'ALRM'} = sub { - print ("ERROR: No response (alarm)\n"); - exit $ERRORS{'UNKNOWN'}; -}; -alarm($timeout); - -# Start checking the file... -open (FH, $stat) or print("UNKNOWN: Cannot open $stat: $!\n"), exit $ERRORS{'UNKNOWN'}; - -my @failed = (); -my @resyncing = (); -my $device = ''; - -# Now check the mdstat file.. -while () { - $line = $_; - if ($line =~ /^(md\S*) /) { - $device = $1; - } elsif( $line =~ / \[_|_\]|U_|_U /) { - push @failed, $device; - } - elsif ( $line =~ / resync /) { - # [==>..................] resync = 10.3% (15216320/146994624) finish=2153.2min speed=1018K/sec - my ($percent) = ($line =~ m# resync = ([0-9.]+%)#); - my ($finish) = ($line =~ m# finish=([0-9.]+min)#); - my ($speed) = ($line =~ m# speed=([0-9.]+K/sec)#); - push @resyncing, "$device ($percent done, finish in $finish at $speed)"; - } -} -close (FH); - -if (scalar @failed > 0) { - if (scalar @failed == 1) { - print "CRITICAL - Device $failed[0] has failed.\n"; - } else { - print "CRITICAL - Devices ".join(", ", @failed)." have failed.\n" - }; - exit $ERRORS{'CRITICAL'}; -} elsif (scalar @resyncing > 0 ) { - print "WARNING: Resyncing: ".(join "; ", @resyncing)."\n"; - exit $ERRORS{'WARNING'}; -} else { - print "OK - All devices are online\n"; - exit $ERRORS{'OK'}; -}; - - -sub print_usage () { - print "Usage: $PROGNAME -t -F \n"; -} - -sub print_help () { - print_revision($PROGNAME,'$Revision: 0.1 $'); - print "Copyright (c) 2003 Thomas Nilsen/Karl DeBisschop\n"; - print "\n"; - print_usage(); - print "Checks the mdstat file for errors on any configured software raid.\n --t ( --timeout=INTEGER) - Seconds before script times out (default: 10)\n --F ( --filename=FILE) - Full path and name to mdstat file (usually '/proc/mdstat') \n\n"; -} diff --git a/dsa-nagios-checks/dsa-check-running-kernel b/dsa-nagios-checks/dsa-check-running-kernel deleted file mode 100755 index 818288f..0000000 --- a/dsa-nagios-checks/dsa-check-running-kernel +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/bash - -# Check if the running kernel has the same version string as the on-disk -# kernel image. - -# Copyright 2008 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -OK=0; -WARNING=1; -CRITICAL=2; -UNKNOWN=3; - -get_offset() { - local file needle - - file="$1" - needle="$2" - perl -e ' - undef $/; - $i = index(<>, "'"$needle"'"); - if ($i < 0) { - exit 1; - }; - print $i,"\n"' < "$file" -} - -get_image() { - local image GZHDR1 GZHDR2 off - - image="$1" - - GZHDR1="\x1f\x8b\x08\x00" - GZHDR2="\x1f\x8b\x08\x08" - - off=`get_offset "$image" $GZHDR1` - [ "$?" != "0" ] && off="-1" - if [ "$off" -eq "-1" ]; then - off=`get_offset "$image" $GZHDR2` - [ "$?" != "0" ] && off="-1" - fi - if [ "$off" -eq "0" ]; then - zcat < "$image" - return - elif [ "$off" -ne "-1" ]; then - (dd ibs="$off" skip=1 count=0 && dd bs=512k) < "$image" 2>/dev/null | zcat 2>/dev/null - return - fi - - echo "ERROR: Unable to extract kernel image." 2>&1 - exit 1 -} - -searched="" -for on_disk in \ - "/boot/vmlinuz-`uname -r`"\ - "/boot/vmlinux-`uname -r`"; do - - if [ -e "$on_disk" ]; then - on_disk_version="`get_image "$on_disk" | strings | grep 'Linux version' | head -n1`" - [ -z "$on_disk_version" ] || break - on_disk_version="`cat "$on_disk" | strings | grep 'Linux version' | head -n1`" - [ -z "$on_disk_version" ] || break - - echo "UNKNOWN: Failed to get a version string from image $on_disk" - exit $UNKNOWN - fi - searched="$searched $on_disk" -done - -if ! [ -e "$on_disk" ]; then - echo "WARNING: Did not find a kernel image (checked$searched) - I have no idea which kernel I am running" - exit $WARNING -fi - - -running_version="`cat /proc/version`" -if [ -z "$running_version" ] ; then - echo "UNKNOWN: Failed to get a version string from running system" - exit $UNKNOWN -fi - -if [ "$running_version" != "$on_disk_version" ]; then - echo "WARNING: Running kernel does not match on-disk kernel image: [$running_version != $on_disk_version]" - exit $WARNING -else - echo "OK: Running kernel matches on disk image: [$running_version]" - exit $OK -fi diff --git a/dsa-nagios-checks/dsa-check-samhain b/dsa-nagios-checks/dsa-check-samhain deleted file mode 100755 index c6b3f4f..0000000 --- a/dsa-nagios-checks/dsa-check-samhain +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/perl -w - -# check_samhain.pl - check to see how many policy violations are reported -# by the samhain file integrity checker. -# -# Copyright Rainer Wichmann (2004) -# Copyright Martin Zobel-Helas (2008) -# -# License Information: -# 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; either version 2 of the License, or -# (at your option) any later version. -# -# 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -############################################################################ - -# -------------------------------------------------------------------[ Uses ]-- - -use strict; -use Getopt::Long; -use vars qw($PROGNAME $SAMHAIN $opt_V $opt_h $opt_v $verbose $opt_w $opt_c $opt_t $status $msg $state $retval); -use lib "/usr/lib/nagios/plugins"; -use utils qw(%ERRORS &print_revision); - -#my $TIMEOUT = 15; -#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); -#sub print_revision ($$); - -# ----------------------------------------------------[ Function Prototypes ]-- - -sub print_help (); -sub print_usage (); -sub process_arguments (); - -# ------------------------------------------------------------[ Environment ]-- - -$ENV{'PATH'}=''; -$ENV{'BASH_ENV'}=''; -$ENV{'ENV'}=''; - -# -----------------------------------------------------------------[ Global ]-- - -$PROGNAME = "dsa-check-samhain"; -$SAMHAIN = "/usr/sbin/samhain"; - -# ----------------------------------------------------------------[ options ]-- - -Getopt::Long::Configure('bundling'); -$status = process_arguments(); -if ($status){ - print "ERROR: processing arguments\n"; - exit $ERRORS{"UNKNOWN"}; -} - -# ----------------------------------------------------------------[ timeout ]-- - -$SIG{'ALRM'} = sub { - print ("ERROR: timed out waiting for $SAMHAIN\n"); - exit $ERRORS{"WARNING"}; -}; -alarm($opt_t); - -# ----------------------------------------------------------[ start samhain ]-- - -if ( defined $SAMHAIN && -x $SAMHAIN ) { - if (! open (SHPIPE, "/usr/bin/sudo $SAMHAIN -t check --foreground -p err -s none -l none -m none 2>&1 | " ) ) { - print "ERROR: could not popen $SAMHAIN \n"; - exit $ERRORS{'UNKNOWN'}; - } -}else{ - print "ERROR: Could not find samhain executable!\n"; - exit $ERRORS{'UNKNOWN'}; -} - -# ---------------------------------------------------------[ read from pipe ]-- - -$status = 0; - -while () { - if (/POLICY/) { - ++$status; - print $_ if $verbose; - } -} - -if ($status < $opt_w) { - $msg = "OK: $status policy violations (threshold $opt_w/$opt_c)"; - $state = $ERRORS{'OK'}; -} elsif ($status >= $opt_w && $status < $opt_c) { - $msg = "WARNING: $status policy violations (threshold w=$opt_w)"; - $state = $ERRORS{'WARNING'}; -} else { - $msg = "CRITICAL: $status policy violations (threshold w=$opt_w)"; - $state = $ERRORS{'CRITICAL'}; -} - -# -------------------------------------------------------------[ close pipe ]-- - -close (SHPIPE); - -# declare an error if we also get a non-zero return code from samhain - -if ( $? ) { - $retval = $? / 256; - if ( $! ) { - print "Error closing $SAMHAIN: $!\n" if $verbose; - } else { - print "$SAMHAIN returned exit status $retval\n" if $verbose; - } - if ($state == $ERRORS{"CRITICAL"}) { - $state = $ERRORS{"CRITICAL"}; - } else { - print "ERROR: $SAMHAIN exit status $retval\n"; - exit $ERRORS{'UNKNOWN'}; - } -} - -# -------------------------------------------------------------------[ exit ]-- - -print "$msg | 'policy violations'=$status;$opt_w;$opt_c\n"; -exit $state; - - -# ------------------------------------------------------------[ Subroutines ]-- - -sub process_arguments(){ - GetOptions - ("V" => \$opt_V, "version" => \$opt_V, - "h" => \$opt_h, "help" => \$opt_h, - "v" => \$opt_v, "verbose" => \$opt_v, - "w=i" => \$opt_w, "warning=i" => \$opt_w, - "c=i" => \$opt_c, "critical=i" => \$opt_c, - "t=i" => \$opt_t, "timeout=i" => \$opt_t - ); - - if ($opt_V) { - print_revision($PROGNAME,'$Revision: 1.0 $ '); - exit $ERRORS{'OK'}; - } - - if ($opt_h) { - print_help(); - exit $ERRORS{'OK'}; - } - - if (defined $opt_v ){ - $verbose = $opt_v; - } - - unless (defined $opt_t) { - $opt_t = $utils::TIMEOUT ; # default timeout - # $opt_t = $TIMEOUT ; - } - - unless (defined $opt_w) { - $opt_w = 1; - } - - unless (defined $opt_c) { - $opt_c = 1; - } - - if ( $opt_w > $opt_c) { - print "Warning cannot be greater than Critical!\n"; - exit $ERRORS{'UNKNOWN'}; - } - - return $ERRORS{'OK'}; -} - -sub print_usage () { - print "Usage: $PROGNAME [-w ] [-c ] [-t ]\n"; -} - -sub print_help () { - print_revision($PROGNAME, '$Revision: 1.0 $'); - print "Copyright (c) 2004 Rainer Wichmann - -This plugin checks the number of policy violations reported by the -samhain file intgrity checker - -"; - print_usage(); - print " --w, --warning=INTEGER - Minimum number of policy violations for which a WARNING status will result --c, --critical=INTEGER - Minimum number of policy violations for which a CRITICAL status will result --t, --timeout=SECONDS - The number of seconds after which a the plugin will timeout --v, --verbose - Verbose output --h, --help - Show this help message --V, --version - Show the version of the plugin - -"; -} - -#sub print_revision ($$) { -# my $commandName = shift; -# my $pluginRevision = shift; -# $pluginRevision =~ s/^\$Revision: //; -# $pluginRevision =~ s/ \$\s*$//; -# print "$commandName (samhain 2.2.3) $pluginRevision\n"; -#} diff --git a/dsa-nagios-checks/dsa-check-soas b/dsa-nagios-checks/dsa-check-soas deleted file mode 100755 index 9d05fff..0000000 --- a/dsa-nagios-checks/dsa-check-soas +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/ruby - -# Copyright 2006 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -require 'resolv' -require 'optparse' -require 'yaml' - -NAGIOS_STATUS = { :OK => 0, :WARNING => 1, :CRITICAL => 2, :UNKNOWN => -1 }; -@verbose = 0; -@additional_nameservers = [] - -def show_help(parser, code=0, io=STDOUT) - program_name = File.basename($0, '.*') - io.puts "Usage: #{program_name} [options] [ ...]" - io.puts parser.summarize - exit(code) -end -ARGV.options do |opts| - opts.on_tail("-h", "--help" , "Display this help screen") { show_help(opts) } - opts.on("-v", "--verbose" , String, "Be verbose") { @verbose += 1 } - opts.on("-a", "--add=HOST" , String, "Also check SOA on ") { |val| @additional_nameservers << val } - opts.parse! -end -show_help(ARGV.options, 1, STDERR) if ARGV.length == 0 - -warnings = [] -oks = [] - -dns = Resolv::DNS.new -ARGV.each{ |domain| - serial = [] - nameservers = dns.getresources(domain, Resolv::DNS::Resource::IN::NS) - nameservernames = nameservers.collect{ |ns| ns.name.to_s } - nameservernames = nameservernames.concat @additional_nameservers - nameservernames.each{ |nameserver| - puts "Testing nameserver #{nameserver} for #{domain}" if @verbose > 0 - arecords = dns.getresources(nameserver, Resolv::DNS::Resource::IN::A) - warnings << "Nameserver #{nameserver} for #{domain} has #{arecords.length} A records" if arecords.length != 1 - arecords.each{ |a| - puts " Nameserver #{nameserver} is at #{a.address}" if @verbose > 0 - begin - resolver = Resolv::DNS.new({:nameserver => a.address.to_s}) - soas = resolver.getresources(domain, Resolv::DNS::Resource::IN::SOA) - rescue SystemCallError => e - warnings << "Could not resolve #{domain} on #{nameserver}: #{e.message}" - else - resolver.close - warnings << "Nameserver #{nameserver} for #{domain} returns #{soas.length} SOAs" if soas.length != 1 - soas.each{ |soa| - puts " Nameserver #{nameserver} returns serial #{soa.serial} for #{domain}" if @verbose > 0 - serial << soa.serial unless serial.include? soa.serial - } - end - } - } - case serial.length - when 0 - warnings << "Found no serials for #{domain}" - when 1 - oks << "#{domain} is at #{serial.first}" - else - warnings << "Nameservers disagree on serials for #{domain}: found #{serial.join(', ')}" if serial.length != 1 - end -} -dns.close - -if warnings.length > 0 - puts warnings.join('; ') - exit NAGIOS_STATUS[:WARNING] -else - puts oks.join('; ') - exit NAGIOS_STATUS[:OK] -end diff --git a/dsa-nagios-checks/dsa-check-statusfile b/dsa-nagios-checks/dsa-check-statusfile deleted file mode 100755 index a69d977..0000000 --- a/dsa-nagios-checks/dsa-check-statusfile +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/ruby - -# Relay the status of a check that was previously run and which stored -# its result in a file to nagios. -# -# Copyright 2008 Peter Palfrader -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -require 'resolv' -require 'optparse' - -NAGIOS_STATUS = { "OK" => 0, "WARNING" => 1, "CRITICAL" => 2, "UNKNOWN" => 3 } -UNITS_TO_SECONDS = { 's' => 1, 'm' => 60, 'h' => 60*60, 'd' => 24*60*60 } - -def show_help(parser, code=0, io=STDOUT) - program_name = File.basename($0, '.*') - io.puts "Usage: #{program_name} [options] " - io.puts parser.summarize - exit(code) -end - -max_age = "26h" -ARGV.options do |opts| - opts.on_tail("-h", "--help" , "Display this help screen") { show_help(opts) } - opts.on("-a", "--age=AGE" , String, "maximum age, in seconds (or use Nm, Nh or Nd) - default is 26h") { |max_age| } - opts.parse! -end -show_help(ARGV.options, 1, STDERR) if ARGV.length != 1 - -statusfile = ARGV.shift - -# find out what the max age is that we accept -unless (m = /^([0-9]+)([smhd])?$/.match max_age) - STDERR.puts "Invalid age #{age}." - show_help(ARGV.options, 1, STDERR) if ARGV.length != 1 -end -max_age = m[1].to_i * UNITS_TO_SECONDS[m[2] ? m[2] : 's'] - -# let's see if it exists -unless File.exists? statusfile - puts "UNKNOWN: #{statusfile} does not exist." - exit NAGIOS_STATUS['UNKNOWN'] -end - - -mtime = File.stat(statusfile).mtime -if mtime + max_age < Time.now - puts "WARNING: #{statusfile} is old: #{mtime}" - exit NAGIOS_STATUS['WARNING'] -end - -status = File.new(statusfile) -returnvalue = status.readline.chomp - -unless NAGIOS_STATUS.has_key? returnvalue - puts "UNKNOWN: #{statusfile} has invalid return value: #{returnvalue}" - exit NAGIOS_STATUS['UNKNOWN'] -end - -status.readlines.each do |line| - print line -end -exit NAGIOS_STATUS[returnvalue] diff --git a/dsa-nagios-checks/dsa-check-udldap-freshness b/dsa-nagios-checks/dsa-check-udldap-freshness deleted file mode 100755 index be2a6da..0000000 --- a/dsa-nagios-checks/dsa-check-udldap-freshness +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/perl -w - -use strict; -my %CODE = ( - 'UNDEF' => -1, - 'OK' => 0, - 'WARNING' => 1, - 'CRITICAL' => 2, - 'UNKNOWN' => 3 -); - -my $f; - -$SIG{__DIE__ } = sub() { - print shift; - exit $CODE{'UNKNOWN'}; -}; - -if ( -e "/var/lib/misc/thishost/passwd.tdb" ) { - $f = "/var/lib/misc/thishost/passwd.tdb"; -} else { - my $hostname = `hostname -f`; - chomp $hostname; - $hostname =~ m/^([a-z]+(?:\.[a-z]+)+)$/; - die "Weird hostname '$hostname'\n" unless defined $1; - $hostname = $1; - if ( -e "/var/lib/misc/$hostname/passwd.tdb" ) { - $f = "/var/lib/misc/$hostname/passwd.tdb"; - }; -}; - -die "Could not find passwd.tdb" unless defined $f; - -my @stat = stat($f) or die ("Cannot stat $f: $!\n"); -my $age = time - $stat[10]; -my $hage; -if ($age > 48 * 3600) { - $hage = sprintf("%.1f days", $age / 24 / 3600); -} elsif ($age > 3600) { - $hage = sprintf("%.1f hours", $age / 3600); -} else { - $hage = sprintf("%d minutes", $age / 60); -}; - -if ($age > 60*60) { - print "WARNING: ud-ldap info is $hage old\n"; - exit $CODE{'WARNING'}; -}; -print "OK: ud-ldap info is $hage old\n"; -exit $CODE{'OK'}; diff --git a/dsa-nagios-checks/dsa-update-apt-status b/dsa-nagios-checks/dsa-update-apt-status deleted file mode 100755 index 3e3acef..0000000 --- a/dsa-nagios-checks/dsa-update-apt-status +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh - -UPDATE_RUNS=3 -STATUS=/var/cache/dsa/nagios/apt -SLEEP_MAX=$(( 15 * 60 )) -MAX_AGE=$(( 23 * 60 * 60 )) - -# we want to run if any of the following things is true -# - we have never run before -# - var/lib/dpkg/status has been touched since the last run -# - var/cache/apt/pkgcache.bin has been touched since the last run -# - our last run ended with 'apt-get update failed' -# - our last run has been more than MAX_AGE (23hrs) ago -run_required() { - local run=0 - local norun=1 - - [ -e "$STATUS" ] || return $run - [ /var/lib/dpkg/status -nt "$STATUS" ] && return $run - [ /var/cache/apt/pkgcache.bin -nt "$STATUS" ] && return $run - grep "apt-get update failed" "$STATUS" > /dev/null && return $run - - local last_mod - last_mod=`stat -c "%Y" "$STATUS"` - now=`date +%s` - age=$(( $now - $last_mod )) - [ "$age" -gt "$MAX_AGE" ] && return $run - - return $norun -} - -# do stuff only when required -run_required || exit - -# sleep if called non-interactively -if [ -z "$TERM" -o "$TERM" = "dumb" ]; then - sleep $(( $RANDOM % $SLEEP_MAX )) -fi - -# run apt-get update, retry a few times if it fails -count=0 -while [ "$count" -lt "$UPDATE_RUNS" ]; do - apt-get update -qq >/dev/null >&2 - if [ "$?" = "0" ]; then break; fi - sleep $(( $RANDOM % 600 )) - count="$(( $count + 1 ))" -done -if [ "$count" -ge "$UPDATE_RUNS" ]; then - (echo "WARNING" - echo "apt-get update failed") > "$STATUS" - exit 1 -fi - -# run the apt check itself -tmp=`tempfile` -trap "rm -f '$tmp'" exit -#/usr/share/dsa/apt-status-check --noupdate --timeout=600 > "$tmp" -/usr/lib/nagios/plugins/dsa-check-packages > "$tmp" -result="$?" -case "$result" in - 0) - st="OK" - ;; - 1) - st="WARNING" - ;; - 2) - st="CRITICAL" - ;; - *) - st="UNKNOWN" - ;; -esac -(echo "$st"; cat "$tmp") > "$STATUS" diff --git a/dsa-nagios-checks/dsa-update-samhain-status b/dsa-nagios-checks/dsa-update-samhain-status deleted file mode 100755 index 22bd1dc..0000000 --- a/dsa-nagios-checks/dsa-update-samhain-status +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -STATUS=/var/cache/dsa/nagios/samhain - -tmp=`tempfile` -trap "rm -f '$tmp'" exit -/usr/lib/nagios/plugins/dsa-check-samhain -t 1800 > "$tmp" -result="$?" -case "$result" in - 0) - st="OK" - ;; - 1) - st="WARNING" - ;; - 2) - st="CRITICAL" - ;; - *) - st="UNKNOWN" - ;; -esac -(echo "$st"; cat "$tmp") > "$STATUS" diff --git a/dsa-nagios-checks/etc/obsolete-packages-ignore b/dsa-nagios-checks/etc/obsolete-packages-ignore new file mode 100644 index 0000000..7dd79e5 --- /dev/null +++ b/dsa-nagios-checks/etc/obsolete-packages-ignore @@ -0,0 +1,4 @@ +/linux-image-.*/ +/kernel-image-.*/ +buildd +sbuild diff --git a/dsa-nagios-checks/obsolete-packages-ignore b/dsa-nagios-checks/obsolete-packages-ignore deleted file mode 100644 index 7dd79e5..0000000 --- a/dsa-nagios-checks/obsolete-packages-ignore +++ /dev/null @@ -1,4 +0,0 @@ -/linux-image-.*/ -/kernel-image-.*/ -buildd -sbuild diff --git a/dsa-nagios-checks/sbin/dsa-update-apt-status b/dsa-nagios-checks/sbin/dsa-update-apt-status new file mode 100755 index 0000000..3e3acef --- /dev/null +++ b/dsa-nagios-checks/sbin/dsa-update-apt-status @@ -0,0 +1,74 @@ +#!/bin/sh + +UPDATE_RUNS=3 +STATUS=/var/cache/dsa/nagios/apt +SLEEP_MAX=$(( 15 * 60 )) +MAX_AGE=$(( 23 * 60 * 60 )) + +# we want to run if any of the following things is true +# - we have never run before +# - var/lib/dpkg/status has been touched since the last run +# - var/cache/apt/pkgcache.bin has been touched since the last run +# - our last run ended with 'apt-get update failed' +# - our last run has been more than MAX_AGE (23hrs) ago +run_required() { + local run=0 + local norun=1 + + [ -e "$STATUS" ] || return $run + [ /var/lib/dpkg/status -nt "$STATUS" ] && return $run + [ /var/cache/apt/pkgcache.bin -nt "$STATUS" ] && return $run + grep "apt-get update failed" "$STATUS" > /dev/null && return $run + + local last_mod + last_mod=`stat -c "%Y" "$STATUS"` + now=`date +%s` + age=$(( $now - $last_mod )) + [ "$age" -gt "$MAX_AGE" ] && return $run + + return $norun +} + +# do stuff only when required +run_required || exit + +# sleep if called non-interactively +if [ -z "$TERM" -o "$TERM" = "dumb" ]; then + sleep $(( $RANDOM % $SLEEP_MAX )) +fi + +# run apt-get update, retry a few times if it fails +count=0 +while [ "$count" -lt "$UPDATE_RUNS" ]; do + apt-get update -qq >/dev/null >&2 + if [ "$?" = "0" ]; then break; fi + sleep $(( $RANDOM % 600 )) + count="$(( $count + 1 ))" +done +if [ "$count" -ge "$UPDATE_RUNS" ]; then + (echo "WARNING" + echo "apt-get update failed") > "$STATUS" + exit 1 +fi + +# run the apt check itself +tmp=`tempfile` +trap "rm -f '$tmp'" exit +#/usr/share/dsa/apt-status-check --noupdate --timeout=600 > "$tmp" +/usr/lib/nagios/plugins/dsa-check-packages > "$tmp" +result="$?" +case "$result" in + 0) + st="OK" + ;; + 1) + st="WARNING" + ;; + 2) + st="CRITICAL" + ;; + *) + st="UNKNOWN" + ;; +esac +(echo "$st"; cat "$tmp") > "$STATUS" diff --git a/dsa-nagios-checks/sbin/dsa-update-samhain-status b/dsa-nagios-checks/sbin/dsa-update-samhain-status new file mode 100755 index 0000000..22bd1dc --- /dev/null +++ b/dsa-nagios-checks/sbin/dsa-update-samhain-status @@ -0,0 +1,23 @@ +#!/bin/sh + +STATUS=/var/cache/dsa/nagios/samhain + +tmp=`tempfile` +trap "rm -f '$tmp'" exit +/usr/lib/nagios/plugins/dsa-check-samhain -t 1800 > "$tmp" +result="$?" +case "$result" in + 0) + st="OK" + ;; + 1) + st="WARNING" + ;; + 2) + st="CRITICAL" + ;; + *) + st="UNKNOWN" + ;; +esac +(echo "$st"; cat "$tmp") > "$STATUS" diff --git a/dsa-nagios-checks/share/apt-status-check b/dsa-nagios-checks/share/apt-status-check new file mode 100755 index 0000000..1d4ac92 --- /dev/null +++ b/dsa-nagios-checks/share/apt-status-check @@ -0,0 +1,231 @@ +#!/usr/bin/perl -Tw + +# $Id: nagios-check-apt-updates 352 2008-05-20 21:36:54Z weasel $ + +# nagios check for debian (security) updates, +# based on net-snmp glue to security updates via apt-get. +# Copyright (C) 2004 SILVER SERVER Gmbh +# Copyright (C) 2004, 2005, 2006, 2007, 2008 Peter Palfrader +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +use strict; +use English; +use Getopt::Long; +use IO::Handle; +use IPC::Open2; +use IPC::Open3; + +$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +my $APT = '/usr/bin/apt-get'; +my $VERBOSE; + +sub do_check($$$$$$) { + my ($pre_command, $timeout, $noupdate, $name, $updates_security, $updates_other) = @_; + my $fh; + my $pid; + my @command; + + unless ($noupdate) { + print STDERR "Running $APT update in $name\n" if $VERBOSE; + @command = ($APT, 'update'); + unshift @command, @$pre_command; + $fh = new IO::Handle; + $pid = open3(\*STDIN, $fh, $fh, @command) or die ("Cannot run $APT update in $name: $!\n"); + local $SIG{ALRM} = sub { die "Timeout for apt-get update.\n" }; + alarm $timeout; + my @ignore=<$fh>; + alarm 0; + close $fh; + waitpid $pid, 0; + if ($CHILD_ERROR) { # program failed + die("$APT update returned with non-zero exit code in $name: ".($CHILD_ERROR / 256)."\n"); + }; + }; + + print STDERR "Running $APT --simulate upgrade in $name\n" if $VERBOSE; + @command = ($APT, qw{--simulate upgrade}); + unshift @command, @$pre_command; + $fh = new IO::Handle; + $pid = open2($fh, \*STDIN, @command) or die ("Cannot run $APT --simulate upgrade | sort -u in $name: $!\n"); + local $SIG{ALRM} = sub { die "Timeout for apt-get --simulate upgrade.\n" }; + alarm $timeout; + my @lines=<$fh>; + close $fh; + alarm 0; + waitpid $pid, 0; + if ($CHILD_ERROR) { # program failed + die("$APT --simulate upgrade | sort -u returned with non-zero exit code in $name: ".($CHILD_ERROR / 256)."\n"); + }; + + @lines = sort {$a cmp $b} @lines; + my %uniq; + @lines = grep {!$uniq{$_}++} @lines; + + print STDERR "Processing information for $name\n" if $VERBOSE; + for my $line (@lines) { + if ($line =~ m/^Inst\s+(\S+)\s+/) { + my $package = $1; + if ($line =~ m/^Inst\s+\S+\s+.*security/i) { + push @$updates_security, $package.($name ne '/' ? "($name)" : ''); + } else { + push @$updates_other, $package.($name ne '/' ? "($name)" : ''); + }; + } + } +} + + + +my $VERSION = '0.0.3 - $Rev: 352 $'; +my $use_sudo = 1; +my $params; + +# nagios exit codes +my $OK = 0; +my $WARNING = 1; +my $CRITICAL = 2; +my $UNKNOWN = 3; + +$params->{'chroots'} = []; +$params->{'vservers'} = []; +$params->{'timeout'} = 20; +Getopt::Long::config('bundling'); +if (!GetOptions ( + '--help' => \$params->{'help'}, + '--version' => \$params->{'version'}, + '--sudo' => \$params->{'sudo'}, + '--noupdate' => \$params->{'noupdate'}, + '--nosudo' => \$params->{'nosudo'}, + '--verbose' => \$params->{'verbose'}, + '--warnifupdates' => \$params->{'warnifupdates'}, + '--timeout=i' => \$params->{'timeout'}, + '--chroot=s' => $params->{'chroots'}, + '--vserver=s' => $params->{'vservers'} + )) { + die ("Usage: $PROGRAM_NAME [--help|--version] [--sudo|--nosudo] [--timeout=] [--verbose]\n"); +}; +if ($params->{'help'}) { + print "nagios-check-apt-updates $VERSION\n"; + print "Usage: $PROGRAM_NAME [--help|--version] [--sudo|--nosudo] [--verbose]\n"; + print "Reports packages to upgrade, updating the list if necessary.\n"; + print "\n"; + print " --help Print this short help.\n"; + print " --version Report version number.\n"; + print " --sudo Use sudo to call apt-get (default).\n"; + print " --noupdate Do not run apt-get update first.\n"; + print " --nosudo Do not use sudo to call apt-get.\n"; + print " --warnifupdates Exit with a WARNING status if any updates are available.\n"; + print " --timeout= Timeout in seconds for each of the two apt-get runs.\n"; + print " --verbose Be a little verbose.\n"; + print " --chroot= Run check in path.\n"; + print " --vserver= Run check in vserver.\n"; + print "\n"; + print "Note that for --sudo (default) you will need entries in /etc/sudoers like these:\n"; + print "nagios ALL=(ALL) NOPASSWD: /usr/bin/apt-get update\n"; + print "nagios ALL=(ALL) NOPASSWD: /usr/bin/apt-get --simulate upgrade\n"; + print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/chroot /chroot-ia32 /usr/bin/apt-get update\n"; + print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/chroot /chroot-ia32 /usr/bin/apt-get --simulate upgrade\n"; + print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/vserver phpserver exec /usr/bin/apt-get update\n"; + print "nagios ALL=(ALL) NOPASSWD: /usr/sbin/vserver phpserver exec /usr/bin/apt-get --simulate upgrade\n"; + print "\n"; + exit (0); +}; +if ($params->{'version'}) { + print "nagios-check-apt-updates $VERSION\n"; + print "nagios check for availability of debian (security) updates\n"; + print "Copyright (c) 2004 SILVER SERVER Gmbh\n"; + print "Copyright (c) 2004,2005 Peter Palfrader \n"; + exit (0); +}; +if ($params->{'sudo'} && $params->{'nosudo'}) { + die ("$PROGRAM_NAME: --sudo and --nosudo are mutually exclusive.\n"); +}; +if ($params->{'sudo'}) { + $use_sudo = 1; +}; +if ($params->{'nosudo'}) { + $use_sudo = 0; +}; +if (scalar @{$params->{'chroots'}} == 0 && scalar @{$params->{'vservers'}} == 0) { + $params->{'chroots'} = ['/']; +}; +$VERBOSE = $params->{'verbose'}; + + +$SIG{'__DIE__'} = sub { + print STDERR @_; + exit $UNKNOWN; +}; + + +my @updates_security; +my @updates_other; + + +# Make sure chroot paths are nice; +my @chroots = (); +for my $root (@{$params->{'chroots'}}) { + if ($root =~ m#^(/[a-zA-Z0-9/.-]*)$#) { + push @chroots, $1; + } else { + die ("Chroot path $root is not nice.\n"); + }; +}; +for my $root (@chroots) { + my @pre_command = (); + unshift @pre_command, 'chroot', $root if ($root ne '/'); + unshift @pre_command, 'sudo' if $use_sudo; + do_check(\@pre_command, $params->{'timeout'}, $params->{'noupdate'}, $root, \@updates_security, \@updates_other); +} + +# Make sure vserver names are nice; +my @vservers = (); +for my $vserver (@{$params->{'vservers'}}) { + if ($vserver =~ m#^([a-zA-Z0-9.-]+)$#) { + push @vservers, $1; + } else { + die ("Vserver name $vserver is not nice.\n"); + }; +}; +for my $vserver (@vservers) { + my @pre_command = (); + unshift @pre_command, '/usr/sbin/vserver', $vserver, 'exec'; + unshift @pre_command, 'sudo' if $use_sudo; + do_check(\@pre_command, $params->{'timeout'}, $params->{'noupdate'}, $vserver, \@updates_security, \@updates_other); +} + + + + +my $exit = $OK; + +my $updateinfo; +if (@updates_security) { + $updateinfo .= 'Security updates ('.(scalar @updates_security).'): '.join(', ', @updates_security)."; "; + $exit = $CRITICAL; +} +if (@updates_other) { + $updateinfo .= 'Other Updates ('.(scalar @updates_other).'): '.join(', ', @updates_other)."; "; + $exit = $WARNING if ($params->{'warnifupdates'} and $exit == $OK); +}; +$updateinfo = 'No updates available' unless defined $updateinfo; + + +print $updateinfo,"\n"; +exit $exit; diff --git a/dsa-nagios-checks/share/weak-ssh-keys-check b/dsa-nagios-checks/share/weak-ssh-keys-check new file mode 100755 index 0000000..e35a8a1 --- /dev/null +++ b/dsa-nagios-checks/share/weak-ssh-keys-check @@ -0,0 +1,340 @@ +#!/usr/bin/perl + +# This cheak is based on code from the Debian/OpenSSL Weak Key Detector +# written by Florian Weimer . +# The code has been modified and enhanced by Alexander Wirt +# to use it as a nagios check. +# +# Copyright (c) 2008, Florian Weimer for the original +# Debian/OpenSSL Weak Key Detector +# (http://security.debian.org/project/extra/dowkd/dowkd.pl.gz) +# +# Copyright (c) 2008, Alexander Wirt for check_weakkeys +# +# Copyright (c) 2008 Peter Palfrader +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +=pod + +=head1 NAME + +B - checks system for weak ssh keys + +=cut + +=head1 SYNOPSIS + +B [options] + +=cut + +=head1 DESCRIPTION + +B checks for all users if there id_rsa, id_dsa or +authorized_key files if they contain weak ssh keys created by a Debian with a +broken libssl (see DSA-1571 for more informations). Optionally +can spit out a warning of there are any DSA keys left in key or authorized_key +files. To work it needs a database of precomputed hashes of known weak keys. +This file is expected as an bdb database with the hash (like +03:a2:f0:46:7f:13:9f:5f:96:71:a9:b8:a0:1c:01:05) as key. See for +such a database generator. outputs his data to STDOUT or to a +file. It meaned to be picked up by an nagios check like B +from Peter Palfrader. + +=cut + +=head1 OPTIONS + +=over 4 + +=item B<-h, --help> + +Prints out a brief help + +=item B<-s, --statusfile> "statusfile" + +Use 'F' instead of 'F'. + +=item B<-f, --fprdb> "database" (default: /var/lib/dsa/ssh-weak-keys.db) + +Use 'F' instead of 'F' +as fingerprint database. + +=item B<-n, --dsa_nowarn> + +Don't warn for DSA keys + +=back + +=cut + +use strict; +use warnings; + +use File::Temp; +use BerkeleyDB; +use Pod::Usage; +use Getopt::Long; +use IPC::Open3; + +my $fprdb_fname = "/var/lib/dsa/ssh-weak-keys.db" ; +my ($outfile, $help); +my $dsa_nowarn = 0; + +GetOptions( 'help|h' => \$help, #Help function + 'statusfile|s=s' => \$outfile, + 'fprdb|f=s' => \$fprdb_fname, + 'n|dsa_nowarn' => \$dsa_nowarn, +); + +pod2usage(1) if $help; + +my $fh; +if ($outfile) { + open ($fh, '>', $outfile) + or die "Could not open statusfile '$outfile' for writing: $!"; +} else { + $fh = *STDOUT; +} + +my %fpr_hash; +tie %fpr_hash, 'BerkeleyDB::Btree', + -Filename => $fprdb_fname, + -Flags => DB_RDONLY + or die "Cannot open fingerprint db $fprdb_fname: $! $BerkeleyDB::Error\n"; + + +my ($weak_keys,$checked_keys) = 0; +my $dsa_keys = 0; +my $weird_keyfiles = 0; +my $text = ''; +my %key_sizes; + + + +#&from_user_all; +&from_debianorg_places; +&from_ssh_host(qw(localhost)); + +my $status="OK"; +if ($weak_keys) { + $status = "CRITICAL"; +} elsif ($dsa_keys && ! $dsa_nowarn || $weird_keyfiles) { + $status = "WARNING"; +} + +print $fh "$status\n"; +print $fh "Checked $checked_keys keys - $weak_keys weak - $dsa_keys dsa keys\n"; +print $fh "Sizes: "; +foreach my $size (sort(keys(%key_sizes))) { + print $fh "$size:$key_sizes{$size} "; +} + +print $fh "\n"; +print $fh "$text" if $text; + + + +sub safe_backtick (@) { + my @args = @_; + + my ($wtr, $fh, $err); + + open3($wtr,$fh,$err, @args) + or die "error: failed to spawn $args[0]: $!\n"; + my @result; + if (wantarray) { + @result = <$fh>; + } else { + local $/; + @result = scalar(<$fh>); + } + close $fh; + $? == 0 or return undef; + if (wantarray) { + return @result; + } else { + return $result[0]; + } +} + +sub ssh_fprint_file ($) { + my $name = shift; + my $data = safe_backtick qw/ssh-keygen -l -f/, $name; + defined $data or return (); + my @data = $data =~ /^(\d+) ([0-9a-f]{2}(?::[0-9a-f]{2}){15})/; + return @data if @data == 2; + return (); +} + +sub ssh_fprint_check ($$$) { + my ($name, $length, $hash) = @_; + if (exists $key_sizes{$length}) { + $key_sizes{$length}++; + } else { + $key_sizes{$length}=1; + } + $checked_keys++; + if (exists $fpr_hash{$hash}) { + $weak_keys++; + $text .= "$name weak ($hash)\n"; + } +} + + +sub from_ssh_key_file ($) { + my $name = shift; + if (open (my $FH, '<', $name)) { + my $key = <$FH>; + if (! defined $key) { + $weird_keyfiles++; + $text .= "cannot read $name properly - empty?\n"; + } elsif ($key =~ m/ssh-dss/) { + $dsa_keys++; + $text .= "$name is a DSA key\n"; + } + } else { + $text .= "Could not open $name: $!"; + } + my ($length, $hash) = ssh_fprint_file $name; + if ($length && $hash) { + ssh_fprint_check "$name:1", $length, $hash; + } else { + $text .= "$name:1: warning: failed to parse SSH key file\n"; + } +} + +sub clear_tmp ($) { + my $tmp = shift; + seek $tmp, 0, 0 or die "seek: $!"; + truncate $tmp, 0 or die "truncate: $!"; +} + +sub from_ssh_auth_file ($) { + my $name = shift; + my $auth; + unless (open $auth, '<', $name) { + warn "$name:0: error: open failed: $!\n"; + return; + } + my $tmp = new File::Temp; + while (my $line = <$auth>) { + chomp $line; + my $lineno = $.; + clear_tmp $tmp; + next if $line =~ m/^$/; # ignore empty lines + next if $line =~ m/^#/; # ignore comments + if ($line =~ m/ssh-dss/) { + $dsa_keys++; + $text .= "$name:$lineno is a DSA key\n"; + } + print $tmp "$line\n" or die "print: $!"; + $tmp->flush; + my ($length, $hash) = ssh_fprint_file "$tmp"; + if ($length && $hash) { + ssh_fprint_check "$name:$lineno", $length, $hash; + } else { + $text .= "$name:$lineno: warning: unparsable line\n"; + } + } +} + +sub from_ssh_host (@) { + my @names = @_; + my @lines; + push @lines, safe_backtick qw|ssh-keyscan -t rsa|, @names; + push @lines, safe_backtick qw|ssh-keyscan -t dsa|, @names; + + my $tmp = new File::Temp; + for my $line (@lines) { + next if $line =~ /^#/; + next if $line =~ /^no hostkey alg/; + my ($host, $data) = $line =~ /^(\S+) (.*)$/; + clear_tmp $tmp; + print $tmp "$data\n" or die "print: $!"; + $tmp->flush; + my ($length, $hash) = ssh_fprint_file "$tmp"; + if ($length && $hash) { + ssh_fprint_check "$host", $length, $hash; + } else { + $text .= "$host: warning: unparsable line\n"; + } + } +} + +sub from_user ($) { + my $user = shift; + my ($name,$passwd,$uid,$gid, + $quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user); + my $file = "$dir/.ssh/authorized_keys"; + from_ssh_auth_file $file if -r $file; + $file = "$dir/.ssh/authorized_keys2"; + from_ssh_auth_file $file if -r $file; + $file = "$dir/.ssh/id_rsa.pub"; + from_ssh_key_file $file if -r $file; + $file = "$dir/.ssh/id_dsa.pub"; + from_ssh_key_file $file if -r $file; +} + +sub from_user_all () { + setpwent; + while (my $name = getpwent) { + from_user $name; + } + endpwent; +} + + +sub from_debianorg_places () { + open(F, "/etc/ssh/sshd_config") or die ("Cannot open /etc/ssh/sshd_config: $!\n"); + my @lines = ; + close(F); + + my @ak = grep { /^AuthorizedKeysFile\s/i } @lines; + my @ak2 = grep { /^AuthorizedKeysFile2\s/i } @lines; + + if (scalar @ak != 1) { + print $fh "UNKNOWN\n"; + print $fh "There is more than one AuthorizedKeysFile definition in sshd_config\n"; + exit + } + if (scalar @ak2 != 1) { + print $fh "UNKNOWN\n"; + print $fh "There is more than one AuthorizedKeysFile2 definition in sshd_config\n"; + exit + } + unless ($ak[0] =~ m#^((?i)AuthorizedKeysFile)\s+/etc/ssh/userkeys/%u$# ) { + print $fh "UNKNOWN\n"; + print $fh "The AuthorizedKeysFile definition has an unexpected value. Should be /etc/ssh/userkeys/%u\n"; + exit + } + unless ($ak2[0] =~ m#^((?i)AuthorizedKeysFile2)\s+/var/lib/misc/userkeys/%u$# ) { + print $fh "UNKNOWN\n"; + print $fh "The AuthorizedKeysFile2 definition has an unexpected value. Should be /var/lib/misc/userkeys/%u\n"; + exit + } + + for my $d (qw{/etc/ssh/userkeys /var/lib/misc/userkeys}) { + next unless (-d $d); + opendir(D, $d) or die "Cannot opendir $d: $!\n"; + for my $file (grep { ! -d $d.'/'.$_ } readdir(D)) { + next if ($file eq 'README-DSA-BUILDD'); + my $f = $d.'/'.$file; + from_ssh_key_file $f if -r $f; + }; + }; +} + + diff --git a/dsa-nagios-checks/weak-ssh-keys-check b/dsa-nagios-checks/weak-ssh-keys-check deleted file mode 100755 index e35a8a1..0000000 --- a/dsa-nagios-checks/weak-ssh-keys-check +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/perl - -# This cheak is based on code from the Debian/OpenSSL Weak Key Detector -# written by Florian Weimer . -# The code has been modified and enhanced by Alexander Wirt -# to use it as a nagios check. -# -# Copyright (c) 2008, Florian Weimer for the original -# Debian/OpenSSL Weak Key Detector -# (http://security.debian.org/project/extra/dowkd/dowkd.pl.gz) -# -# Copyright (c) 2008, Alexander Wirt for check_weakkeys -# -# Copyright (c) 2008 Peter Palfrader -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -=pod - -=head1 NAME - -B - checks system for weak ssh keys - -=cut - -=head1 SYNOPSIS - -B [options] - -=cut - -=head1 DESCRIPTION - -B checks for all users if there id_rsa, id_dsa or -authorized_key files if they contain weak ssh keys created by a Debian with a -broken libssl (see DSA-1571 for more informations). Optionally -can spit out a warning of there are any DSA keys left in key or authorized_key -files. To work it needs a database of precomputed hashes of known weak keys. -This file is expected as an bdb database with the hash (like -03:a2:f0:46:7f:13:9f:5f:96:71:a9:b8:a0:1c:01:05) as key. See for -such a database generator. outputs his data to STDOUT or to a -file. It meaned to be picked up by an nagios check like B -from Peter Palfrader. - -=cut - -=head1 OPTIONS - -=over 4 - -=item B<-h, --help> - -Prints out a brief help - -=item B<-s, --statusfile> "statusfile" - -Use 'F' instead of 'F'. - -=item B<-f, --fprdb> "database" (default: /var/lib/dsa/ssh-weak-keys.db) - -Use 'F' instead of 'F' -as fingerprint database. - -=item B<-n, --dsa_nowarn> - -Don't warn for DSA keys - -=back - -=cut - -use strict; -use warnings; - -use File::Temp; -use BerkeleyDB; -use Pod::Usage; -use Getopt::Long; -use IPC::Open3; - -my $fprdb_fname = "/var/lib/dsa/ssh-weak-keys.db" ; -my ($outfile, $help); -my $dsa_nowarn = 0; - -GetOptions( 'help|h' => \$help, #Help function - 'statusfile|s=s' => \$outfile, - 'fprdb|f=s' => \$fprdb_fname, - 'n|dsa_nowarn' => \$dsa_nowarn, -); - -pod2usage(1) if $help; - -my $fh; -if ($outfile) { - open ($fh, '>', $outfile) - or die "Could not open statusfile '$outfile' for writing: $!"; -} else { - $fh = *STDOUT; -} - -my %fpr_hash; -tie %fpr_hash, 'BerkeleyDB::Btree', - -Filename => $fprdb_fname, - -Flags => DB_RDONLY - or die "Cannot open fingerprint db $fprdb_fname: $! $BerkeleyDB::Error\n"; - - -my ($weak_keys,$checked_keys) = 0; -my $dsa_keys = 0; -my $weird_keyfiles = 0; -my $text = ''; -my %key_sizes; - - - -#&from_user_all; -&from_debianorg_places; -&from_ssh_host(qw(localhost)); - -my $status="OK"; -if ($weak_keys) { - $status = "CRITICAL"; -} elsif ($dsa_keys && ! $dsa_nowarn || $weird_keyfiles) { - $status = "WARNING"; -} - -print $fh "$status\n"; -print $fh "Checked $checked_keys keys - $weak_keys weak - $dsa_keys dsa keys\n"; -print $fh "Sizes: "; -foreach my $size (sort(keys(%key_sizes))) { - print $fh "$size:$key_sizes{$size} "; -} - -print $fh "\n"; -print $fh "$text" if $text; - - - -sub safe_backtick (@) { - my @args = @_; - - my ($wtr, $fh, $err); - - open3($wtr,$fh,$err, @args) - or die "error: failed to spawn $args[0]: $!\n"; - my @result; - if (wantarray) { - @result = <$fh>; - } else { - local $/; - @result = scalar(<$fh>); - } - close $fh; - $? == 0 or return undef; - if (wantarray) { - return @result; - } else { - return $result[0]; - } -} - -sub ssh_fprint_file ($) { - my $name = shift; - my $data = safe_backtick qw/ssh-keygen -l -f/, $name; - defined $data or return (); - my @data = $data =~ /^(\d+) ([0-9a-f]{2}(?::[0-9a-f]{2}){15})/; - return @data if @data == 2; - return (); -} - -sub ssh_fprint_check ($$$) { - my ($name, $length, $hash) = @_; - if (exists $key_sizes{$length}) { - $key_sizes{$length}++; - } else { - $key_sizes{$length}=1; - } - $checked_keys++; - if (exists $fpr_hash{$hash}) { - $weak_keys++; - $text .= "$name weak ($hash)\n"; - } -} - - -sub from_ssh_key_file ($) { - my $name = shift; - if (open (my $FH, '<', $name)) { - my $key = <$FH>; - if (! defined $key) { - $weird_keyfiles++; - $text .= "cannot read $name properly - empty?\n"; - } elsif ($key =~ m/ssh-dss/) { - $dsa_keys++; - $text .= "$name is a DSA key\n"; - } - } else { - $text .= "Could not open $name: $!"; - } - my ($length, $hash) = ssh_fprint_file $name; - if ($length && $hash) { - ssh_fprint_check "$name:1", $length, $hash; - } else { - $text .= "$name:1: warning: failed to parse SSH key file\n"; - } -} - -sub clear_tmp ($) { - my $tmp = shift; - seek $tmp, 0, 0 or die "seek: $!"; - truncate $tmp, 0 or die "truncate: $!"; -} - -sub from_ssh_auth_file ($) { - my $name = shift; - my $auth; - unless (open $auth, '<', $name) { - warn "$name:0: error: open failed: $!\n"; - return; - } - my $tmp = new File::Temp; - while (my $line = <$auth>) { - chomp $line; - my $lineno = $.; - clear_tmp $tmp; - next if $line =~ m/^$/; # ignore empty lines - next if $line =~ m/^#/; # ignore comments - if ($line =~ m/ssh-dss/) { - $dsa_keys++; - $text .= "$name:$lineno is a DSA key\n"; - } - print $tmp "$line\n" or die "print: $!"; - $tmp->flush; - my ($length, $hash) = ssh_fprint_file "$tmp"; - if ($length && $hash) { - ssh_fprint_check "$name:$lineno", $length, $hash; - } else { - $text .= "$name:$lineno: warning: unparsable line\n"; - } - } -} - -sub from_ssh_host (@) { - my @names = @_; - my @lines; - push @lines, safe_backtick qw|ssh-keyscan -t rsa|, @names; - push @lines, safe_backtick qw|ssh-keyscan -t dsa|, @names; - - my $tmp = new File::Temp; - for my $line (@lines) { - next if $line =~ /^#/; - next if $line =~ /^no hostkey alg/; - my ($host, $data) = $line =~ /^(\S+) (.*)$/; - clear_tmp $tmp; - print $tmp "$data\n" or die "print: $!"; - $tmp->flush; - my ($length, $hash) = ssh_fprint_file "$tmp"; - if ($length && $hash) { - ssh_fprint_check "$host", $length, $hash; - } else { - $text .= "$host: warning: unparsable line\n"; - } - } -} - -sub from_user ($) { - my $user = shift; - my ($name,$passwd,$uid,$gid, - $quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user); - my $file = "$dir/.ssh/authorized_keys"; - from_ssh_auth_file $file if -r $file; - $file = "$dir/.ssh/authorized_keys2"; - from_ssh_auth_file $file if -r $file; - $file = "$dir/.ssh/id_rsa.pub"; - from_ssh_key_file $file if -r $file; - $file = "$dir/.ssh/id_dsa.pub"; - from_ssh_key_file $file if -r $file; -} - -sub from_user_all () { - setpwent; - while (my $name = getpwent) { - from_user $name; - } - endpwent; -} - - -sub from_debianorg_places () { - open(F, "/etc/ssh/sshd_config") or die ("Cannot open /etc/ssh/sshd_config: $!\n"); - my @lines = ; - close(F); - - my @ak = grep { /^AuthorizedKeysFile\s/i } @lines; - my @ak2 = grep { /^AuthorizedKeysFile2\s/i } @lines; - - if (scalar @ak != 1) { - print $fh "UNKNOWN\n"; - print $fh "There is more than one AuthorizedKeysFile definition in sshd_config\n"; - exit - } - if (scalar @ak2 != 1) { - print $fh "UNKNOWN\n"; - print $fh "There is more than one AuthorizedKeysFile2 definition in sshd_config\n"; - exit - } - unless ($ak[0] =~ m#^((?i)AuthorizedKeysFile)\s+/etc/ssh/userkeys/%u$# ) { - print $fh "UNKNOWN\n"; - print $fh "The AuthorizedKeysFile definition has an unexpected value. Should be /etc/ssh/userkeys/%u\n"; - exit - } - unless ($ak2[0] =~ m#^((?i)AuthorizedKeysFile2)\s+/var/lib/misc/userkeys/%u$# ) { - print $fh "UNKNOWN\n"; - print $fh "The AuthorizedKeysFile2 definition has an unexpected value. Should be /var/lib/misc/userkeys/%u\n"; - exit - } - - for my $d (qw{/etc/ssh/userkeys /var/lib/misc/userkeys}) { - next unless (-d $d); - opendir(D, $d) or die "Cannot opendir $d: $!\n"; - for my $file (grep { ! -d $d.'/'.$_ } readdir(D)) { - next if ($file eq 'README-DSA-BUILDD'); - my $f = $d.'/'.$file; - from_ssh_key_file $f if -r $f; - }; - }; -} - -