That was incredibly helpful. Thank you. This is not my cleanest work and needs better error checking. It does, however, work as expected.
#!/usr/bin/env perl
#------------------------------------------------
use strict;
use warnings;
#------------------------------------------------
# extras
my $DEBUG = 1;
use LWP::UserAgent;
use Time::HiRes qw(gettimeofday tv_interval);
use Date::Parse;
my $XYMON_SVR = "127.0.0.1";
my $XYMON_PORT = 1984;
my $WARN_DAYS = 30;
my @MONTH = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
#------------------------------------------------
# output formats
# month day, year hh:mm:ss zone
my $TIME_FMT = "%s %s, %s %s:%s:%s %s";
# output for http
my $HTTPFMT="status %s.%s %s %s
%s
%s
%s
%s seconds\n";
# output fro sslcert
my $SSLCERTFMT="status %s.%s %s %s
Certificate for %s expires in %d days
Expiration Date: %s\n";
#------------------------------------------------
# globals
## certificate info
my %g_certinfo = ();
#------------------------------------------------
# main
#------------------------------------------------
sub main {
# get the site name
my $site = $ARGV[0];
return 1 unless $site;
my $resp_line = "";
my $resp_headers = "";
# always start as green
my $status_color = "green";
# start the timer
my $t0 = [gettimeofday];
#----------------------------------------------
# get site headers if it is reachable
# create the agent
my $ua = LWP::UserAgent->new (
ssl_opts => {SSL_verify_callback => \&xtract_cert }
);
# define teh url
my $url = "https://" . $site;
# try to connect
my $resp = $ua->get($url);
# we don't care if the response code is a 200, 300, or 400 but 500 i
+s still a
# bad thing
if ($resp->code >= 500) {
$resp_line = $resp->status_line ? $resp->status_line : "Unable to
+connect to " . $site;
$resp_headers = "";
$status_color = "red";
} else {
$resp_line = $resp->protocol . " " . $resp->status_line;
$resp_headers = $resp->headers_as_string;
chomp($resp_headers);
}
# calculate Elapsed Time
my $et = tv_interval ($t0);
# time for status line
my $time = localtime();
# send https status to xymon
my $httpout = sprintf $HTTPFMT, $site, "http", $status_color, $time,
+ $url, $resp_line, $resp_headers, $et;
send_2_xymon($XYMON_SVR, $XYMON_PORT, $httpout);
# convert time from LWP to seconds since epoch
my $epoch_xpire = str2time( $g_certinfo{EndDate} );
# if no epoch_xpire then there is a problem.
return 1 unless ($epoch_xpire);
# convert expiration time to human readable format
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
+localtime($epoch_xpire);
$year += 1900;
my $tz = $isdst > 0 ? "PDT" : "PST";
my $expire_date = sprintf $TIME_FMT, $MONTH[$mon], $mday, $year, $ho
+ur, $min, $sec, $tz;
# current time since epoch
my $epoch_now = time();
# how much time is left on cert
my $remain_sec = $epoch_xpire - $epoch_now;
my $remain_day = int($remain_sec / 86400 + 0.5);
if ($remain_sec > $WARN_DAYS * 86400) {
$status_color = "green";
} elsif ($remain_sec < 0) {
$status_color = "red";
} else {
$status_color = "yellow";
}
my $sslcertout = sprintf $SSLCERTFMT, $site, "sslcert", $status_colo
+r, $time, $url, $remain_day, $expire_date;
send_2_xymon($XYMON_SVR, $XYMON_PORT, $sslcertout);
return 0;
}
#------------------------------------------------
# extract some certificate information
#------------------------------------------------
sub xtract_cert {
my ($ok, $ctx_store) = @_;
my $cert = Net::SSLeay::X509_STORE_CTX_get_current_cert($ctx_store);
$g_certinfo{EndDate} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSL
+eay::X509_get_notAfter($cert));
return $ok;
}
#------------------------------------------------
# send the data to xymon
#------------------------------------------------
sub send_2_xymon {
use IO::Socket;
my ($server,$port,$output) = @_;
if ($DEBUG) {
print $output, "\n";
return "";
}
# open a socket
my $socket = new IO::Socket::INET (
PeerAddr => $server,
PeerPort => $port,
Proto => 'tcp',
);
return "Could not create socket: $!n" unless $socket;
# send data over socket
print $socket $output;
# close socket
close($socket);
# return empty string on success
return "";
}
exit main();
|