3 # nagios check for debian security sync checks
5 # Copyright (c) 2008 Alexander Wirt <formorer@debian.org>
6 # Copyright (c) 2009, 2010 Peter Palfrader <peter@palfrader.org>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
37 my $basename = basename($PROGRAM_NAME);
40 print $fh "$basename $VERSION\n";
41 print $fh "Usage: $basename [--help|--version] [--verbose]\n";
43 print $fh " --help Print this short help.\n";
44 print $fh " --version Report version number.\n";
45 print $fh " --verbose Be a little verbose.\n";
46 print $fh " --host hostname to check.\n";
47 print $fh " --path path to tracefile.\n";
48 print $fh " --allow-skew=<foo>:<bar> if the newest timestamp is newer than <foo>secs\n";
49 print $fh " then the mirror sync is still ok, assuming the oldest\n";
50 print $fh " trace file is no older than <bar>\n";
55 # Work around LWP not being able to verify service certs directly
56 my $ca_dir = '/etc/ssl/ca-debian';
57 $ENV{'HTTPS_CA_DIR'} = $ca_dir if -d $ca_dir;
59 $ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin';
60 delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
64 $params->{'host'} = 'security.debian.org'; #which host to check
65 $params->{'path'} = 'project/trace/security-master.debian.org';
73 '--help' => \$params->{'help'},
74 '--verbose' => \$params->{'verbose'},
75 '--version' => \$params->{'version'},
76 '--host=s' => \$params->{'host'},
77 '--path=s' => \$params->{'path'},
78 '--allow-skew=s' => \$params->{'skew'},
82 usage(*STDOUT,0) if ($params->{'help'});
83 usage(*STDERR,1) if (scalar @ARGV);
85 if (defined $params->{'skew'}) {
86 if (not $params->{'skew'} =~ /^([0-9]+):([0-9]+)$/) {
87 print STDERR "Invalid allow-skew format\n";
90 $params->{'skew-new'} = $1;
91 $params->{'skew-old'} = $2;
94 my $host = $params->{'host'};
95 my $path = $params->{'path'};
101 @slaves = gethostbyname($params->{'host'}) or die "Can't resolve " . $params->{'host'} .": $!\n";
102 @slaves = map { inet_ntoa($_) } @slaves[4 .. $#slaves];
103 print "Checking the following hosts:\n" . join("\n", @slaves) . "\n" if $params->{'verbose'};
107 foreach my $slave (@slaves) {
108 my $ua = LWP::UserAgent->new;
109 $ua->proxy('http', "http://$slave");
110 print "Requesting http://$host/$path from $slave\n" if $params->{'verbose'};
111 my $response = $ua->get("http://$host/$path");
114 if ($response->is_success) {
115 my $content = $response->content; # or whatever
116 my ($date, $foo, $bar) = split("\n", $content);
117 my $synctime = str2time($date);;
118 if (! defined $synctime) {
120 $exitcode = $UNKNOWN;
121 push @exitstatus, "Cannot parse tracefile on $slave";
123 print "$slave last synced $synctime\n" if $params->{'verbose'};
124 $status->{$slave}->{'synced'} = $synctime;
127 push @exitstatus, "$slave broken: " . $response->status_line;
128 $status->{$slave}->{'error'} = $response->status_line;
129 $status->{$slave}->{'synced'} = 0;
130 $exitcode = $CRITICAL;
131 push @critical, $slave;
137 my $o_sync = scalar(grep !$seen{$_}++, map{$status->{$_}->{'synced'}} keys(%{$status}));
139 my @mirrors = sort { $status->{$a}->{'synced'} <=> $status->{$b}->{'synced'} } keys %{$status};
140 my @not_most_recent = grep { $status->{$_}->{'synced'} <=> $status->{$mirrors[-1]}->{'synced'} } @mirrors;
141 $o_sync = scalar @not_most_recent;
143 my $newest = time - $status->{$mirrors[-1]}->{'synced'};
144 my $oldest = time - $status->{$mirrors[0]}->{'synced'};
145 my $skew_ok = ( defined $params->{'skew-new'} &&
146 defined $params->{'skew-old'} &&
147 $newest <= $params->{'skew-new'} &&
148 $oldest <= $params->{'skew-old'});
153 $msg = "$o_sync mirror(s) not in sync (from oldest to newest), but still within acceptable skew: ";
155 $exitcode = $CRITICAL;
156 $msg = "$o_sync mirror(s) not in sync (from oldest to newest): ";
158 push @exitstatus, $msg . join(", ", @not_most_recent);
160 print "All mirrors unique\n" if $params->{'verbose'};
163 if ($exitcode == $CRITICAL) {
164 print "CRITICAL: " . join(',',@exitstatus) . "\n";
165 } elsif ($exitcode == $OK) {
166 if (scalar @exitstatus > 0) {
167 print "OK: " . join(',',@exitstatus) . "\n";
169 print "OK: all mirrors up2date\n";
172 print join(',',@exitstatus) . "\n";
175 foreach my $mirror (keys(%{$status})) {
176 if ($status->{$mirror}->{'error'}) {
177 print "$mirror broken: " . $status->{$mirror}->{'error'} . "\n";
179 print "$mirror last synced: " . localtime($status->{$mirror}->{'synced'}) ."\n";