From cbf0c67c16b664d2e8281ce506d66822e72f49d1 Mon Sep 17 00:00:00 2001
From: Alan Premselaar <alien@12inch.com>
Date: Thu, 2 Mar 2006 05:38:09 +0000
Subject: [PATCH] Module to check expiration date of SSL certificate for $HOST
 currently dependant on 'curl' being installed.

at some point I'd like to re-write it to do connections directly,
but haven't figured out yet how to get more than just the certificate
issuer and name.
---
 src/lib/Spong/Network/plugins/check_ssl | 150 ++++++++++++++++++++++++
 1 file changed, 150 insertions(+)
 create mode 100755 src/lib/Spong/Network/plugins/check_ssl

diff --git a/src/lib/Spong/Network/plugins/check_ssl b/src/lib/Spong/Network/plugins/check_ssl
new file mode 100755
index 0000000..5cf5a4c
--- /dev/null
+++ b/src/lib/Spong/Network/plugins/check_ssl
@@ -0,0 +1,150 @@
+# SPONG Network plugin module
+#
+# This plugin will use curl in verbose mode to connect to an SSL server and extract the
+# SSL certificate expiry date and send a warning notification based on the approprate grace
+# period settings.
+#
+# Author: Alan Premselaar <alien@12inch.com>
+#
+# $Id: check_ssl,v 1.1 2006/03/02 05:38:09 apremselaar Exp $
+#
+# Synopsis:
+#
+#	The following variables can be set in the spong.conf file:
+#
+#		$SSLTIMEOUT	- set the timeout in seconds for curl to connect to the URL
+#					this can also be set per host with ssl_timeout => seconds directive
+#		$SSLRETRY	- set the number of retries, in case of timeout
+#		$SSLGRACE	- set the number of seconds before expiry to start warning
+#					($expire - time()) <= $SSLGRACE > $SSLGRACE /2 = yellow
+#					($expire - time()) <= $SSLGRACE /2 = red
+#		$SSLCURLCMD	- the command to use to call curl (installation dependant)
+#					this command should have the tags <TIMEOUT> and <HOSTNAME>
+#					in it as appropriate. Please see the code for an example.
+#					some newer versions of curl require the -k option to connect
+#					to SSL servers w/o requiring a cert.
+#		
+# Register function with the plugin registry
+$PLUGINS{'ssl'} = \&check_ssl;
+
+sub check_ssl {
+
+	use constant SECOND => 1;
+	use constant MINUTE => SECOND * 60;
+	use constant HOUR => MINUTE * 60;
+	use constant DAY => HOUR * 24;
+	use constant WEEK => DAY * 7;
+	use constant MONTH => WEEK * 4;
+
+	use constant TRUE => 1;
+	use constant FALSE => 0;
+
+	use POSIX;
+	use Time::Local;
+
+	our $_TIMEOUT = $SSLTIMEOUT || 5;
+	our $_TO_RETRY = $SSLRETRY || 5;
+
+	our $_CURL_CMD = "/usr/bin/curl -v -m <TIMEOUT>  https://<HOSTNAME> 2>&1";
+	our $_EXPIRE_MATCH = '^\*\s+expire date: (\d{4})-(\d{1,2})-(\d{1,2})\s(\d{1,2}):(\d{1,2}):(\d{1,2})\s+([A-Z]{3})';
+	our $_GRACE = $SSLGRACE || MONTH * 2;		# 2 month grace period: start warning $_GRACE time before date of expiry
+
+	our $retry = 0;
+
+	sub open_https {
+		my $host = shift;
+
+		my $curl = $SSLCURLCMD || $_CURL_CMD;
+		my $host_timeout = $HOSTS{$host}->{ssl_timeout} || $_TIMEOUT;
+
+
+		info(">> [$host] retry = $retry, max = $_TO_RETRY , host_timeout = $host_timeout");
+		my ($year,$month,$day,$hour,$min,$sec,$tz,$timeout);
+
+		$curl =~ s/<HOSTNAME>/$host/g;
+		$curl =~ s/<TIMEOUT>/$host_timeout/g;
+
+		if (! open(CURL, " $curl |")) {
+			error("Cannot pipe to $curl");
+			return(0);
+		}
+
+		while ($line = <CURL>) {
+			if ($line =~ /timeout/i || $line =~ /timed out/i) {
+				if ($retry >= $_TO_RETRY) {
+					info(" [$host] retry = $retry, max = $_TO_RETRY , host_timeout = $host_timeout");
+					return(0,0,0,1,0,1970,"GMT","timeout");
+				}
+				$retry++;
+				debug("  [$host] TIMEOUT: recursing ($retry)");
+#				info("  [$host] TIMEOUT: recursing ($retry)");
+				($sec,$min,$hour,$day,$month,$year,$tz,$timeout) = open_https($host);
+				return($sec,$min,$hour,$day,$month,$year,$tz,$timeout);
+			}
+			next unless ($line =~ /$_EXPIRE_MATCH/);
+			($year,$month,$day,$hour,$min,$sec,$tz) = ($1,$2,$3,$4,$5,$6,$7);
+			last;
+		}
+
+		close(CURL);
+#		info("[$host] $hour:$min:$sec $month/$day/$year");
+		$month -= 1 if ($month > 0);
+		return($sec,$min,$hour,$day,$month,$year,$tz,$timeout);
+	}
+
+	sub will_expire_soon {
+		my $expire = shift;
+		my $currtime = shift;
+		my $grace = shift;
+	
+		my $diff = ($expire - $currtime);
+	
+		if ( $diff <= $grace ) {
+			return(TRUE);
+		} else {
+			return(FALSE);
+		}
+	}
+
+	my ($host) = @_;
+	my ($color,$summary) = ("green","OK");
+
+	my @retval = open_https($host);
+
+	if ($retval[7] eq "timeout") {
+		$color = "yellow";
+		$summary = "Connection timeout: no more retries";
+
+		debug("ssl - $host - $color, $summary");
+		return($color,$summary);
+	}
+
+	my $timeg = timegm(@retval);
+	my $timel = time();
+
+	my $stimeg = strftime("%m-%d-%Y %H:%M:%S %Z", localtime($timeg));
+	my $stimel = strftime("%m-%d-%Y %H:%M:%S %Z", localtime($timel));
+
+	my $yellow = will_expire_soon($timeg,$timel,$_GRACE);
+	my $red = will_expire_soon($timeg,$timel,$_GRACE/2);
+
+	if ($yellow) {
+		$color = "yellow";
+		$summary = "SSL certificate will expire on $stimeg";
+
+	}
+
+	if ($red) {
+		$color = "red";
+		$summary = "WARNING: SSL certificate will expire on $stimeg!";
+	}
+
+	if ($color eq "green") {
+		$summary = "OK - SSL certificate valid until $stimeg";
+	}
+
+	debug( "ssl - $host - $color, $summary" );
+	return( $color, $summary );
+}
+
+1;
-- 
2.30.2