#!/usr/bin/perl -w

=head1 NAME

check_dns_rrsig.pl - Verify RRSIG expiration for a zone.

=head1 SYNOPSIS

check_dns_rrsig.pl -H host -z zone [ options ]

	host:   The server to query 
	zone:	The DNS zone to monitor.

=head1 OPTIONS

=over 8

=item B<-z|--zone> zone

The DNS zone to monitor.

=item B<-H|--host> host

The nameserver to query.

=item B<-t> timeout

Specify the plugin timeout. Defaults to 15 seconds.

=item B<-c|--critical> critical threshold in days

Specify the number of days remaining before raising a critical alert.
Defaults to 14 days.

=item B<-w|--warning> warning threshold in days

Specify the number of days remaining before raising warning alert.
Defaults to 3 days.

=item B<-V|--version>

Print the version number and exit

=item B<-v|verbose>

Increase verbosity.

=back

=head1 DESCRIPTION

This checks to make sure the nameserver (-H) has RRSIG records for the
zone specified with more than WARNING or CRITICAL days before
expiration.

=head1 AUTHOR

Copyright (c) 2010 Chan Wilson <cwilson at confusedhacker.com>

=cut

use strict;
use Net::DNS;
use Net::DNS::SEC;
use Nagios::Plugin;
use Date::Piece qw(date today);
use Pod::Usage;
require 5.008;
my $VERSION = '1.0';

my ($full_usage, $usage_fh);
open($usage_fh, '>', \$full_usage);
pod2usage(-verbose=>2, -output => $usage_fh, -exitval=>'NOEXIT');


my $plugin = Nagios::Plugin->new(
    usage => "Usage: %s [ -v|--verbose ] -H <host> -z <zone> [-t <timeout>]
    [ -c|--critical=<critical threshold in days> ] [ -w|--warning=<warning threshold in days> ]  ",
    version => $VERSION,
    extra => $full_usage,
    );

$plugin->add_arg( spec => 'host|H=s',    required => 1,
		  help => 'Host (nameserver) to run query against');
$plugin->add_arg( spec => 'zone|z=s',    required => 1,
		  help => 'Zone (domain) to query');
$plugin->add_arg( spec => 'warning|w=i',required => 0, default => 14,
		  help => 'Warning threshold in days, default 14');
$plugin->add_arg( spec => 'critical|c=i',required => 0, default => 3,
		  help => 'Critical threshold in days, default 3');

$plugin->getopts;

#my ($host,$domain,$timeout,$verbose,$wlevel,$clevel);

alarm($plugin->opts->timeout);
$SIG{ALRM} = sub {print "$0 timed out.\n"; exit 2;};

my $resolver = Net::DNS::Resolver->new(nameservers => [ $plugin->opts->host ]);
my $q = $resolver->query( $plugin->opts->zone, 'RRSIG' );

if ($q) {
    alarm(0);
    foreach my $rr ($q->answer) {
	# die unless $rr->type eq 'RRSIG';
	my $sigExpire = date(substr($rr->sigexpiration,0,8));
	if ($sigExpire - $plugin->opts->critical < today) {
	    $plugin->add_message(CRITICAL, rrsig_print($rr, $sigExpire));
	    next;
	}
	if ($sigExpire - $plugin->opts->warning < today) {
	    $plugin->add_message(WARNING, rrsig_print($rr, $sigExpire));
	    next;
	}
	else {
	    $plugin->add_message(OK, rrsig_print($rr, $sigExpire));
	}
    }
}
else {
    $plugin->add_message(CRITICAL, "Could not retrieve RRSIG for " 
			 . $plugin->opts->zone);
}

$plugin->nagios_exit($plugin->check_messages);

sub rrsig_print {
    my ($rr, $expire) = @_;
    sprintf("RRSIG: %s\t%s\tKey:%s\tExpires:%s\tDays left:%d\n",
	    $rr->name, $rr->typecovered, $rr->keytag, $expire,
	    $expire - today);
}
