Certificate Expiry Checking Script

Here’s a script I wrote a while ago for checking a bunch of domains to see if their certificates have expired using openssl. Just add your domains to the @domains list. At work we have a cronjob that does this every day:

checkcerts -d 31 | mail -e -s"SSL Certificates Expiring Within a Month" systems@...

#!/usr/bin/perl -w

# checkcerts
# Barney Livingston 2008-11-18

use strict;
use Date::Parse;
use Date::Format;
use POSIX qw(floor);
use Getopt::Long;

my $days = 9999999999; #about 27 million years should be enough
my $help;

GetOptions( "days=i" => \$days,
            "help" => \$help );

if ($help) {
  print <<"END";
Usage: checkcerts [options]
  --days -d <days>   Only show certificates due to expire within <days> days.
END
  exit 0;
}

my @domains = ( "example.com" ); # Your list of domains goes here.

my $time = time;

foreach my $domain (@domains) {

  my $tries = 3;
  my $date = "";
  my $cn = "";
  my $expdays = 0;
  my $x509 = "";

  while ($tries > 0) {
    $x509 = `echo Q | openssl s_client -connect $domain:443 2>&1 | openssl x509 -noout -text`;

    $date = "ERROR";
    if ($x509 =~ /Not After : (... .. ..:..:.. .... ...)\n/) {
      $date = str2time($1);
    }
    $x509=~ /Subject:.+CN=(.*?)[\/\n]/;
    $cn = $1;

    if ($date eq "ERROR") {
       $tries--;
    } else {
       $tries = 0;
    }
  }


  if ($date eq "ERROR") {
    print "Failed to get a useful response from $domain\n";
  } else {
    $expdays = floor(($date - $time) / (3600 * 24));
    my $expired = "";
    $expired = " EXPIRED" if ($expdays < 0);
    if ($expdays < $days) {
      print time2str("%Y-%m-%d %T", $date) . " -$expired $expdays days - $cn\n";
    }
  }

}