Created
October 16, 2015 21:53
-
-
Save kareiva/23d80b16433b6f6ed770 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -w | |
# | |
# check_ssl_certificate | |
# Nagios script to check ssl certificate expirations | |
# | |
# Copyright (c) 2006-2008 David Alden <[email protected]> | |
# | |
# 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. | |
# | |
# | |
# Changes: | |
# 2014-03-26 Vladimir Mencl <[email protected]> | |
# - add support for checking a certificate in the file (-f) | |
# - add option for supporting a full DN instead of just CN (-D) | |
# - support both 32-bit and 64-bit platforms with "use lib" path | |
# - move some verbose ouput under DEBUG (-d) | |
# - FIX: add missing exit for expired certificate as per comment on plugin | |
# page | |
# - use POSIX:floor() instead of int() for rounding daysLeft | |
# | |
# 10/30/2008 dja <[email protected]> | |
# - fixed a bug which caused it to not deal with certs that expire | |
# on a single digit day (thanks to Christian Sava, Kyle Smith & | |
# Raphael Berlamont) | |
# | |
# 10/09/2007 dja <[email protected]> | |
# - fixed a bug which caused it to improperly report expired certs | |
# (thanks to Hassan Alusesi for pointing this out) | |
# - no longer use temporary files or Date::Manip | |
# (thanks to tommybobbins on NagiosExchange) | |
# - added the printing of the Common Name (CN) if verbose is specified | |
# (thanks to mp72 on NagiosExchange) | |
# | |
# | |
# Description: | |
# This script will check if an SSL certificate is going to expire. For | |
# example, to check the IMAP certificate on an imaps port: | |
# | |
# check_ssl_certificate -H 1.1.1.1 -p 993 | |
# | |
# | |
# Installation: | |
# Edit this script, replacing the line: | |
# use lib "/usr/lib/nagios/plugins"; | |
# with the path to your nagios plugins directory (where utils.pm is | |
# located). Also edit the line: | |
# my $openssl = "/usr/bin/openssl"; | |
# with the path to your openssl binary. Then copy the script into | |
# your nagios plugins directory. | |
# | |
# | |
use strict; | |
use POSIX; | |
use Time::Local; | |
use Getopt::Long; | |
# support both 32-bit and 64-bit environemnt | |
use lib "/usr/lib/nagios/plugins"; | |
use lib "/usr/lib64/nagios/plugins"; | |
use utils qw(%ERRORS &print_revision &support &usage); | |
my $PROGNAME="check_ssl_certificates"; | |
my $REVISION="1.2"; | |
# | |
$ENV{PATH}="/usr/sbin:/usr/bin:/bin"; | |
# | |
my $openssl = "/usr/bin/openssl"; | |
my $critical = 7; | |
my $help; | |
my $host; | |
my $port = 443; | |
my $certificate_file = ''; | |
my $useDN = 0; | |
my $additional = ''; | |
my $verbose; | |
my $debug = 0; | |
my $version; | |
my $warning = 30; | |
# | |
my %months = ('Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, | |
'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, | |
'Nov' => 10, 'Dec' => 11); | |
# | |
Getopt::Long::Configure('bundling'); | |
if (GetOptions( | |
"a=s" => \$additional, | |
"c:s" => \$critical, | |
"h" => \$help, | |
"H:s" => \$host, | |
"f:s" => \$certificate_file, | |
"D" => \$useDN, | |
"d" => \$debug, | |
"o=s" => \$openssl, | |
"p=i" => \$port, | |
"v" => \$verbose, | |
"V" => \$version, | |
"w:s" => \$warning, | |
) == 0) { | |
print_usage(); | |
exit $ERRORS{'UNKNOWN'} | |
} | |
if ($version) { | |
print_revision($PROGNAME, "\$Revision: $REVISION \$"); | |
exit $ERRORS{'OK'}; | |
} | |
if ($help) { | |
print_help(); | |
exit $ERRORS{'OK'}; | |
} | |
# accept either a hostname or a certificate file - but not both | |
if (! $certificate_file && ! utils::is_hostname($host)) { | |
usage(""); | |
exit $ERRORS{'UNKNOWN'}; | |
} | |
if ($host && $certificate_file) { | |
usage("You cannot specify both host and certificate_file\n"); | |
exit $ERRORS{'UNKNOWN'}; | |
}; | |
my $openssl_cmd = ""; | |
if ($certificate_file ) { | |
$openssl_cmd = "$openssl x509 -enddate -noout -in $certificate_file $additional |" | |
} else { | |
$openssl_cmd = "$openssl s_client -connect $host:$port $additional < /dev/null 2>&1 | $openssl x509 -enddate -noout |" | |
}; | |
open(OPENSSL, "$openssl_cmd" ) || | |
die "unable to open $openssl: $!"; | |
my $date; | |
while (<OPENSSL>) { | |
if ($_ =~ /^notAfter=(.*)/) { | |
$date = $1; | |
chomp($date); | |
# last; | |
} | |
} | |
close(OPENSSL); | |
$date =~ s/ +/ /g; | |
my ($month, $day, $hour, $min, $sec, $year, $tz) = split(/[\s+|:]/, $date); | |
print "m=$month, d=$day, h=$hour, m=$min, s=$sec, y=$year, z=$tz\n" if $debug; | |
my $daysLeft = floor((timegm($sec, $min, $hour, $day, $months{$month}, $year - 1900) - time()) / 86400); | |
print "daysLeft=$daysLeft\n" if $debug; | |
my $cn="this certificate"; | |
# get the certificate name | |
if ($verbose) { | |
# different handling for certificates in a file | |
if ($certificate_file) { | |
open(OPENSSL, "$openssl x509 -subject -noout -in $certificate_file $additional < /dev/null 2>&1 |") || | |
die "unable to open $openssl: $!"; | |
while (<OPENSSL>) { | |
if ( $_ =~ /^subject= (.*)/ ) { | |
# we found the subject line. | |
my $cert_subject = $1; | |
# if we can match a CN field, use that, otherwise the whole DN | |
if ( !$useDN && $cert_subject =~ /CN=([^\/=]*)/ ) { | |
$cn=$1; | |
} else { | |
$cn=$cert_subject; | |
}; | |
$cn .= "[$certificate_file]"; | |
last; | |
} | |
} | |
close(OPENSSL); | |
} else { | |
open(OPENSSL, "$openssl s_client -connect $host:$port $additional < /dev/null 2>&1 |") || | |
die "unable to open $openssl: $!"; | |
while (<OPENSSL>) { | |
next unless $_ =~ /Certificate chain/; | |
while (<OPENSSL>) { | |
next unless $_ =~ /^ 0 s:(.*)/; | |
my $cert_subject = $1; | |
# if we can match a CN field, use that, otherwise the whole DN | |
if ( !$useDN && $cert_subject =~ /CN=([^\/=]*)/ ) { | |
$cn=$1; | |
} else { | |
$cn=$cert_subject; | |
}; | |
$cn .= "[$host]" if ($cn ne $host); | |
last; | |
} | |
} | |
close(OPENSSL); | |
} | |
} | |
if ($daysLeft < 0) { | |
print "$PROGNAME: CRITICAL - $cn expired " . abs($daysLeft) . " day(s) ago.\n"; | |
exit $ERRORS{'CRITICAL'}; | |
} elsif ($daysLeft <= $critical) { | |
print "$PROGNAME: CRITICAL - only $daysLeft day(s) left for $cn.\n"; | |
exit $ERRORS{'CRITICAL'}; | |
} elsif ($daysLeft <= $warning) { | |
print "$PROGNAME: WARNING - only $daysLeft day(s) left for $cn.\n"; | |
exit $ERRORS{'WARNING'}; | |
} elsif ($verbose) { | |
print "$PROGNAME: $daysLeft day(s) left for $cn.\n"; | |
} | |
exit $ERRORS{'OK'}; | |
sub print_help { | |
print_revision($PROGNAME, "\$Revision: $REVISION \$"); | |
print "Copyright (c) 2006 David Alden | |
Check if an SSL certificate is close to expiring | |
"; | |
print_usage(); | |
print " | |
-a <add> add the text to the openssl line, used for checking the smtp ssl | |
certificate with starttls (\"-a '-starttls smtp'\") | |
-c <num> exit with CRITICAL status if number of days left is less than <num> | |
-h show this help script | |
-H <host> check the certificate on the indicated host | |
-o <path> path to openssl binary | |
-p <port> check the certificate on the specified port | |
-f <file> check instead a certificate in a specific file | |
-D use full DN instead of just CN in verbose output | |
-w <num> exit with WARNING status if number of days left is less than <num> | |
-v show the number of days left | |
-d show debug output | |
-V show version and license information | |
"; | |
support(); | |
} | |
sub print_usage { | |
print "Usage: $PROGNAME -H <host> [-p <port>] [-c <low>:<high>] [-w <low>:<high>]\n"; | |
return(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment