X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=dsa-nagios-checks%2Fchecks%2Fdsa-check-zone-rrsig-expiration-many;h=674dd1c2b000ead32e1f17a4effd2939b06f7182;hb=HEAD;hp=8f7ac4771c8405612b1c602d03faa0e58b792d86;hpb=87983c60272f1a65e0fe42f9933e8984191cabb8;p=mirror%2Fdsa-nagios.git diff --git a/dsa-nagios-checks/checks/dsa-check-zone-rrsig-expiration-many b/dsa-nagios-checks/checks/dsa-check-zone-rrsig-expiration-many index 8f7ac47..674dd1c 100755 --- a/dsa-nagios-checks/checks/dsa-check-zone-rrsig-expiration-many +++ b/dsa-nagios-checks/checks/dsa-check-zone-rrsig-expiration-many @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2010 Peter Palfrader +# Copyright (c) 2010,2012 Peter Palfrader # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,9 +23,13 @@ use strict; use warnings; +use threads; + use English; use Getopt::Long; use FindBin qw($Bin); +use YAML; +use File::Basename; my $CHECK = $Bin.'/dsa-check-zone-rrsig-expiration'; @@ -57,88 +61,157 @@ sub convert_time { return $ticks; } -my $USAGE = "Usage: $PROGRAM_NAME [--help] | [--warn=] [--critical=] \n"; -my $params = { 'warn' => '14d', 'critical' => '7d' }; +sub check_one { + $SIG{'KILL'} = sub { threads->exit(); }; + + my $zone = shift; + my $check = shift; + my $extra = shift; + my $params = shift; + + my @cmd = ($check, '-w', $params->{'warn'}, '-c', $params->{'critical'}); + push(@cmd, '-r', $extra->{'initial_refs'}) if exists $extra->{'initial_refs'}; + push(@cmd, '-d') if $params->{'debug'}; + push(@cmd, $zone); + open(P, '-|', @cmd) or die ("Cannot run $CHECK for $zone\n"); + my @p =

; + close P; + $p[0] = $zone.': '. $p[0] if (scalar @p > 0); + + my $res = $CHILD_ERROR >> 8; + + return ($res, \@p); +} + +my $USAGE = "Usage: $PROGRAM_NAME [--help] | [--debug] [--timeout=] [--warn=] [--critical=] [--geozonedir=] \n"; +my $params = { 'timeout' => 45, 'warn' => '14d', 'critical' => '7d' }; Getopt::Long::config('bundling'); GetOptions ( '--help' => \$params->{'help'}, + '--timeout=i' => \$params->{'timeout'}, '--warn=s' => \$params->{'warn'}, + '--debug' => \$params->{'debug'}, '--critical=s' => \$params->{'critical'}, + '--geozonedir=s' => \$params->{'geozonedir'}, ) or die ($USAGE); if ($params->{'help'}) { - print $USAGE; - exit(0); + print $USAGE; + exit(0); }; die ($USAGE) unless (scalar @ARGV == 1); my $INDIR = shift; -my @zones; +my $states = [qw{critical warn unknown ok unsigned}]; +my $count = { map { $_ => [] } @$states }; +my $details = { map { $_ => [] } @$states }; + + +my %dnsseczones; +# load list of classic zones that will do DNSSEC chdir $INDIR or die "chdir $INDIR failed? $!\n"; -opendir INDIR, $INDIR or die ("Cannot opendir $INDIR\n"); -for my $file (readdir INDIR) { +opendir INDIR, '.' or die ("Cannot opendir $INDIR\n"); +for my $file (sort {$a cmp $b} (readdir INDIR)) { next if ( -l "$file" ); next unless ( -f "$file" ); - next if $file =~ /^(dsset|keyset)-/; - push @zones, $file; + my $do_dnssec = 1; + my $delegated = 1; + my $initial_refs = undef; + open(F, '<', $file) or die ("Cannot open $file: $!\n"); + for () { + if (/^; wzf:\s*dnssec\s*=\s*0\s*$/) { $do_dnssec = 0; } + if (/^; delegated\s*=\s*no\s*$/) { $delegated = 0; } + if (/^; check-initial-refs\s*=\s*(.*?)\s*$/) { $initial_refs = $1; } + }; + close F; + + if ($do_dnssec && $delegated) { + die "Duplicate zone $file?\n" if exists $dnsseczones{$file}; + $dnsseczones{$file} = {}; + $dnsseczones{$file}->{'initial_refs'} = $initial_refs if defined $initial_refs; + } else { + push @{$count ->{'unsigned'}}, $file; + push @{$details->{'unsigned'}}, "$file: marked unsigned or undelegated.\n"; + }; } closedir(INDIR); +# load list of geodns zones that will do DNSSEC +if (defined $params->{'geozonedir'}) { + chdir $params->{'geozonedir'} or die "chdir $params->{'geozonedir'} failed? $!\n"; + opendir INDIR, '.' or die ("Cannot opendir $params->{'geozonedir'}\n"); + for my $file (sort {$a cmp $b} (readdir INDIR)) { + next unless $file =~ /\.zone$/; -my $count = - { 'ok' => [], - 'warn' => [], - 'critical' => [], - 'unknown' => [], - 'unsigned' => [], - }; - -my @details; + my $zone = basename($file, '.zone'); + die "Duplicate zone $zone?\n" if exists $dnsseczones{$zone}; + $dnsseczones{$zone} = {}; + } + closedir(INDIR); +} -for my $zone (sort {$a cmp $b} @zones) { - my $do_dnssec = 0; - open(F, '<', $zone) or die ("Cannot open $zone: $!\n"); - for () { - if (/^; wzf:\s*dnssec\s*=\s*1\s*$/) { $do_dnssec = 1; } - }; - close F; +my %threads; +for my $zone (sort {$a cmp $b} keys %dnsseczones) { + die "Duplicate zone $zone?\n" if defined $threads{$zone}; + my $thr = threads->create({'context' => 'list'}, + \&check_one, $zone, $CHECK, $dnsseczones{$zone}, $params); + $threads{$zone} = $thr; +} - unless ($do_dnssec) { - push @{$count->{'unsigned'}}, $zone; - next; - }; +my $begin = time; +while (time - $begin <= $params->{timeout}) { + for my $zone (sort {$a cmp $b} keys %threads) { + next unless $threads{$zone}->is_joinable(); + my ($res, $det) = $threads{$zone}->join(); - open(P, '-|', ($CHECK, '-w', $params->{'warn'}, '-c', $params->{'critical'}, $zone)) or die ("Cannot run $CHECK for $zone\n"); - push @details,

; - close P; + my $type = ($res == 0) ? 'ok' : + ($res == 1) ? 'warn' : + ($res == 2) ? 'critical' : + 'unknown'; - my $res = $CHILD_ERROR >> 8; - if ($res == 0) { push @{$count->{'ok'}}, $zone; } - elsif ($res == 1) { push @{$count->{'warn'}}, $zone; } - elsif ($res == 2) { push @{$count->{'critical'}}, $zone; } - else { push @{$count->{'unknown'}}, $zone; }; -}; + push @{$details->{$type}}, @$det; + push @{$count ->{$type}}, $zone; + delete $threads{$zone}; + } + last if scalar keys %threads == 0; + print STDERR (scalar keys %threads), " threads left: ", join(" ", keys %threads), "\n" if $params->{'debug'}; + sleep 1; +} +for my $zone (sort {$a cmp $b} keys %threads) { + push @{$count ->{'warn'}}, $zone; + push @{$details->{'warn'}}, "$zone: timeout during check\n"; + $threads{$zone}->kill('KILL')->detach(); +} -my $exit; +my $exit = 0; my %state_mapping = ( 'unknown' => 255, 'critical' => 2, 'warn' => 1, + 'unsigned' => 0, 'ok' => 0 ); -for my $state (sort {$state_mapping{$b} <=> $state_mapping{$a}} keys %state_mapping) { +for my $state (@$states) { + @{$count->{$state}} = sort {$a cmp $b} @{$count->{$state}}; + @{$details->{$state}} = sort {$a cmp $b} @{$details->{$state}}; + if (scalar @{$count->{$state}}) { printf "%s: %d", uc($state), scalar @{$count->{$state}}; if ($state_mapping{$state} > 0) { print ": ", join(', ', @{$count->{$state}}); }; print "; "; - $exit = $state_mapping{$state} unless defined $exit; + $exit = $state_mapping{$state} if ($state_mapping{$state} > $exit); }; }; printf "unsigned: %d", scalar @{$count->{'unsigned'}}; print "\n"; -print $_ for (@details); +for my $state (@$states) { + for (@{$details->{$state}}) { + s/\|/;/g; + print $_; + } +} exit $exit;