|
1 #!/usr/bin/perl -w |
|
2 |
|
3 use strict; |
|
4 use warnings; |
|
5 use File::Basename; |
|
6 use Getopt::Long; |
|
7 use Date::Manip; |
|
8 use IPC::Open2; |
|
9 use lib "/usr/lib/nagios/plugins"; |
|
10 use utils qw (%ERRORS &print_revision &support); |
|
11 |
|
12 sub print_help(); |
|
13 sub print_usage(); |
|
14 |
|
15 my $ME = basename $0; |
|
16 my ($opt_w, $opt_c, $opt_V, $opt_h, $opt_b, @opt_certfiles); |
|
17 my ($w_time, $c_time, $result, $message, %certs); |
|
18 my (@critical, @warning); |
|
19 |
|
20 $opt_w = "1month"; |
|
21 $opt_c = "1week"; |
|
22 $opt_b = "/usr/bin/openssl"; |
|
23 |
|
24 Getopt::Long::Configure('bundling'); |
|
25 GetOptions( |
|
26 "V" => \$opt_V, "version" => \$opt_V, |
|
27 "h" => \$opt_h, "help" => \$opt_h, |
|
28 "b=s" => \$opt_b, "binary" => \$opt_b, |
|
29 "w=s" => \$opt_w, "warning=s" => \$opt_w, |
|
30 "c=s" => \$opt_c, "critical=s" => \$opt_c, |
|
31 "f=s" => \@opt_certfiles, "certfile=s" => \@opt_certfiles); |
|
32 |
|
33 if ($opt_V) { |
|
34 print_revision($ME, "0.1"); |
|
35 exit $ERRORS{"OK"}; |
|
36 } |
|
37 |
|
38 if ($opt_h) { |
|
39 print_help(); |
|
40 exit $ERRORS{"OK"}; |
|
41 } |
|
42 |
|
43 # check openssl binary |
|
44 unless (-x $opt_b) { |
|
45 print "CERT CRITICAL: OpenSSL not found or not executable - $opt_b\n"; |
|
46 exit $ERRORS{"CRITICAL"}; |
|
47 } |
|
48 |
|
49 unless(@opt_certfiles) { |
|
50 print "CERT WARNING: Not defined any certificate files\n"; |
|
51 exit $ERRORS{"WARNING"}; |
|
52 } |
|
53 |
|
54 @opt_certfiles = split(/,/, join(',', @opt_certfiles)); |
|
55 |
|
56 # extract certificate data |
|
57 foreach my $file (@opt_certfiles) { |
|
58 unless (-r $file) { |
|
59 print "CERT CRITICAL: $file - not exists or not read permission is granted\n"; |
|
60 exit $ERRORS{"CRITICAL"}; |
|
61 } |
|
62 my @cmd_x509 = ($opt_b, "x509", "-in", $file, "-noout", "-subject", "-enddate"); |
|
63 my @cmd_pkcs12 = ($opt_b, "pkcs12", "-in", $file, "-clcerts", "-nokeys", "-nomacver", "-passin", "pass:"); |
|
64 my @cmd_pipe = ($opt_b, "x509", "-noout", "-subject", "-enddate"); |
|
65 my ($temp, $cn, $enddate, $rc); |
|
66 open(CERT, "-|") or do { |
|
67 open(STDERR, ">&STDOUT"); |
|
68 exec(@cmd_x509); |
|
69 }; |
|
70 |
|
71 # check x509 certificates |
|
72 while(<CERT>) { |
|
73 /unable to load certificate/ and $rc = 1 and last; |
|
74 /^subject=\s.*CN=(.*)\s+$/ and $cn = $1; |
|
75 /^notAfter=(.*)\s+$/ and $enddate = $1; |
|
76 } |
|
77 close(CERT); |
|
78 |
|
79 # check pkcs12 certificates |
|
80 if ($rc) { |
|
81 open(PKCS12, "@cmd_pkcs12 |"); |
|
82 |
|
83 while(<PKCS12>) { |
|
84 $temp .= $_; |
|
85 } |
|
86 close(PKCS12); |
|
87 |
|
88 local (*READ, *WRITE); |
|
89 open2(\*READ, \*WRITE, @cmd_pipe) or die "Can't fork: $!\n"; |
|
90 print WRITE $temp; |
|
91 close(WRITE); |
|
92 |
|
93 while(<READ>) { |
|
94 /unable to load certificate/ and print "CERT CRITICAL: unable to load certificate\n" and exit $ERRORS{"CRITICAL"}; |
|
95 /^subject=\s.*CN=(.*)\s+$/ and $cn = $1; |
|
96 /^notAfter=(.*)\s+$/ and $enddate = $1; |
|
97 } |
|
98 close(READ); |
|
99 } |
|
100 # fill the hash |
|
101 push ( @{$certs{$file}}, ($cn, $enddate) ); |
|
102 } |
|
103 |
|
104 # calculate the time |
|
105 $w_time = DateCalc("today", "+ $opt_w"); |
|
106 $c_time = DateCalc("today", "+ $opt_c"); |
|
107 |
|
108 # check expire date |
|
109 foreach (sort keys %certs) { |
|
110 my $enddate; |
|
111 if (@{$certs{$_}}[1] =~ /(\w+\s+\d+\s+\d+:\d+:\d+\s+\d+)/) { $enddate = $1; } |
|
112 $enddate = ParseDate($enddate); |
|
113 unless ($enddate) { |
|
114 print "CERT CRITICAL: Can't parse enddate\n"; |
|
115 exit $ERRORS{"CRITICAL"}; |
|
116 } |
|
117 |
|
118 &Date_Cmp($enddate, $w_time) > 0 and push (@{$certs{$_}}, "OK"), next; |
|
119 &Date_Cmp($enddate, $c_time) > 0 and push (@{$certs{$_}}, "WARNING"), next; |
|
120 push (@{$certs{$_}}, "CRITICAL"); |
|
121 } |
|
122 |
|
123 # looking for stats |
|
124 foreach (sort keys %certs) { |
|
125 if (@{$certs{$_}}[2] eq "WARNING") { |
|
126 push (@warning, "file: $_, CN=@{$certs{$_}}[0] expires @{$certs{$_}}[1]"); |
|
127 } elsif (@{$certs{$_}}[2] eq "CRITICAL") { |
|
128 push (@critical, "file: $_, CN=@{$certs{$_}}[0] expires @{$certs{$_}}[1]"); |
|
129 } |
|
130 } |
|
131 |
|
132 # return the state |
|
133 if (@critical) { |
|
134 print "CERT CRITICAL: @critical\n"; |
|
135 exit $ERRORS{"CRITICAL"}; |
|
136 } elsif (@warning) { |
|
137 print "CERT WARNING: @warning\n"; |
|
138 exit $ERRORS{"WARNING"}; |
|
139 } else { |
|
140 print "CERT OK: all certificates in limit\n"; |
|
141 exit $ERRORS{"OK"}; |
|
142 } |
|
143 |
|
144 sub print_usage() { |
|
145 print "Usage:\n"; |
|
146 print " $ME [-b <binary>] [-w <time>] [-c <time>] [-f <file,file,file,...>]\n"; |
|
147 print " $ME [-h | --help]\n"; |
|
148 print " $ME [-V | --version]\n"; |
|
149 } |
|
150 |
|
151 sub print_help() { |
|
152 print_revision($ME, "0.1"); |
|
153 print "Copyright (c) 2008 Christian Arnold\n\n"; |
|
154 print "This plugin checks the expire date for openssl certificates.\n\n"; |
|
155 print_usage(); |
|
156 print "\n"; |
|
157 print " -b, --binary <binary>\n"; |
|
158 print " Path of openssl binary (default: /usr/bin/openssl)\n"; |
|
159 print " -w, --warning <time>\n"; |
|
160 print " Certificat should not be more than this time older (default: 1month)\n"; |
|
161 print " For time can be used year, month, day, hour, minute, second and weeks.\n"; |
|
162 print " -c, --critical <time>\n"; |
|
163 print " Certificat should not be more than this time older (default: 1week)\n"; |
|
164 print " For time can be used year, month, day, hour, minute, second and weeks.\n"; |
|
165 print " -f, --certfile <file,file,file, ...>\n"; |
|
166 print " Absolute path of x509 or pkcs12 openssl certificate files, use comma-separated lists for multiple files.\n"; |
|
167 print " -h, --help\n"; |
|
168 print " Print detailed help screen\n"; |
|
169 print " -V, --version\n"; |
|
170 print " Print version information\n"; |
|
171 print "\n"; |
|
172 support(); |
|
173 } |
|
174 |
|
175 |
|
176 exit; |
|
177 |
|
178 # vim:sts=4 sw=4 aw ai sm: |