Improve check output
[infodrom/icinga-plugins] / check_ssl_certificate
1 #!/usr/bin/perl -w
2 #
3 # check_ssl_certificate
4 #   Nagios script to check ssl certificate expirations
5 #
6 # Copyright (c) 2006-2008 David Alden <alden@math.ohio-state.edu>
7 #
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License
10 # as published by the Free Software Foundation; either version 2
11 # of the License, or (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
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, USA.
21 #
22 #
23 # Changes:
24 #   10/30/2008 dja <alden@math.ohio-state.edu>
25 #      - fixed a bug which caused it to not deal with certs that expire
26 #        on a single digit day (thanks to Christian Sava, Kyle Smith &
27 #        Raphael Berlamont)
28 #
29 #   10/09/2007 dja <alden@math.ohio-state.edu>
30 #      - fixed a bug which caused it to improperly report expired certs
31 #        (thanks to Hassan Alusesi for pointing this out)
32 #      - no longer use temporary files or Date::Manip
33 #        (thanks to tommybobbins on NagiosExchange)
34 #      - added the printing of the Common Name (CN) if verbose is specified
35 #        (thanks to mp72 on NagiosExchange)
36 #
37 #
38 # Description:
39 #   This script will check if an SSL certificate is going to expire.  For
40 # example, to check the IMAP certificate on an imaps port:
41 #
42 # check_ssl_certificate -H 1.1.1.1 -p 993
43 #
44 #
45 # Installation:
46 #   Edit this script, replacing the line:
47 #       use lib "/usr/lib/nagios/plugins";
48 #   with the path to your nagios plugins directory (where utils.pm is
49 #   located).  Also edit the line:
50 #       my $openssl = "/usr/bin/openssl";
51 #   with the path to your openssl binary.  Then copy the script into
52 #   your nagios plugins directory.
53 #
54 #
55 use strict;
56 use Time::Local;
57 use Getopt::Long;
58 use lib "/usr/lib/nagios/plugins";
59 use utils qw(%ERRORS &print_revision &support &usage);
60
61 my $PROGNAME="check_ssl_certificates";
62 my $REVISION="1.2";
63
64 #
65 $ENV{PATH}="/usr/sbin:/usr/bin:/bin";
66
67 #
68 my $openssl = "/usr/bin/openssl";
69
70 my $critical = 7;
71 my $help;
72 my $host;
73 my $port = 443;
74 my $additional = '';
75 my $verbose;
76 my $version;
77 my $warning = 30;
78
79 #
80 my %months = ('Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4,
81               'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9,
82               'Nov' => 10, 'Dec' => 11);
83
84 #
85 Getopt::Long::Configure('bundling');
86 if (GetOptions(
87                "a=s" => \$additional,
88                "c:s" => \$critical,
89                "h"   => \$help,
90                "H:s" => \$host,
91                "o=s" => \$openssl,
92                "p=i" => \$port,
93                "v"   => \$verbose,
94                "V"   => \$version,
95                "w:s" => \$warning,
96               ) == 0) {
97
98   print_usage();
99   exit $ERRORS{'UNKNOWN'}
100 }
101
102 if ($version) {
103   print_revision($PROGNAME, "\$Revision: $REVISION \$");
104   exit $ERRORS{'OK'};
105 }
106
107 if ($help) {
108   print_help();
109   exit $ERRORS{'OK'};
110 }
111
112 if (! utils::is_hostname($host)) {
113   usage("");
114   exit $ERRORS{'UNKNOWN'};
115 }
116
117 open(OPENSSL, "$openssl s_client -connect $host:$port $additional < /dev/null 2>&1 | $openssl x509 -enddate -noout |") ||
118   die "unable to open $openssl: $!";
119
120 my $date;
121 while (<OPENSSL>) {
122   if ($_ =~ /^notAfter=(.*)/) {
123     $date = $1;
124     chomp($date);
125 #    last;
126   }
127 }
128 close(OPENSSL);
129
130 $date =~ s/ +/ /g;
131
132 my ($month, $day, $hour, $min, $sec, $year, $tz) = split(/[\s+|:]/, $date);
133 printf "Expiry date: %d %s %d, %d:%02d:%02d %s\n", $day, $month, $year, $hour, $min, $sec, $tz;
134
135 my $daysLeft = int((timegm($sec, $min, $hour, $day, $months{$month}, $year - 1900) - time()) / 86400);
136
137 my $cn="this certificate";
138 if ($verbose) {
139
140   open(OPENSSL, "$openssl s_client -connect $host:$port $additional < /dev/null 2>&1 |") ||
141     die "unable to open $openssl: $!";
142
143   while (<OPENSSL>) {
144     next unless $_ =~ /Certificate chain/;
145
146     while (<OPENSSL>) {
147       next unless $_ =~ /CN=(.*)/;
148       ($cn) = split(/\//, $1);
149       $cn .= "[$host]" if ($cn ne $host);
150       last;
151     }
152   }
153 }
154
155 if ($daysLeft < 0) {
156   print "$PROGNAME: CRITICAL - $cn expired " . abs($daysLeft) . " day(s) ago.\n";
157 } elsif ($daysLeft <= $critical) {
158   print "$PROGNAME: CRITICAL - only $daysLeft day(s) left for $cn.\n";
159   exit $ERRORS{'CRITICAL'};
160 } elsif ($daysLeft <= $warning) {
161   print "$PROGNAME: WARNING - only $daysLeft day(s) left for $cn.\n";
162   exit $ERRORS{'WARNING'};
163 } elsif ($verbose) {
164   print "$PROGNAME: $daysLeft day(s) left for $cn.\n";
165 }
166
167 exit $ERRORS{'OK'};
168
169 sub print_help {
170   print_revision($PROGNAME, "\$Revision: $REVISION \$");
171   print "Copyright (c) 2006 David Alden
172
173 Check if an SSL certificate is close to expiring
174
175 ";
176
177   print_usage();
178
179   print "
180 -a <add>   add the text to the openssl line, used for checking the smtp ssl
181            certificate with starttls (\"-a '-starttls smtp'\")
182 -c <num>   exit with CRITICAL status if number of days left is less than <num>
183 -h         show this help script
184 -H <host>  check the certificate on the indicated host
185 -o <path>  path to openssl binary
186 -p <port>  check the certificate on the specified port
187 -w <num>   exit with WARNING status if number of days left is less than <num>
188 -v         show the number of days left
189 -V         show version and license information
190 ";
191
192   support();
193 }
194
195
196 sub print_usage {
197   print "Usage: $PROGNAME -H <host> [-p <port>] [-c <low>:<high>] [-w <low>:<high>]\n";
198   return();
199 }