Automatic certificate expiration check

If you authenticate certain services on your Linux server like your WLAN or webserver towards users for their security you will likely have multiple certificates. These usually have a certain period during which they are valid. This means you have to renew them from time to time.

If you don't track the certificates' expiration times you likely only notice an outdated certificate if a horde of users knocks on your door complaining that a certain service is out of order. Good luck fixing this problem with a mob of people in your back throwing torches and pitchforks at you.

One option is to keep a Post-It with all important dates for each single certificate on your screen. Unfortunately if you do this for other jobs too the notes will either cover your screen or each other. The result is the same. You won't be able to do your work properly any more. The more lazy (i.e. better) way is to let a script automatically warn you in advance before expiration.

The good news is that you don't have to write the script on your own. I already prepared one which you can use under a CC BY license.

It can be executed as cron job or used as Nagios check out of the box. A Zabbix check will need some minor adjustments. I recommend just echoing the remaining days. In that case you can completely drop the existing output part and criticality check including the days input parameters. This is all done in Zabbix

The script calculates the remaining days until a certificate expires. Note that I ignore leap years and that months have a diffent amount of days. This is sufficiently accurate for me. As follows I don't see the point in wasting my time in programming a more detailed solution.

You can give the script the path to any certificate (for which you have read permission). Furthermore it will throw a critical or warning message depending on an adjustable amount of days left. A separate message will be given if the certificate already expired.
# This script is published under a Creative Commons BY license
# Written by XXLRay

Checks whether a certificate expires. The script ignores leap years and that months have a different amount of days.\n
Written by XXLRay
Usage: $(basename $0) [-h] -i -w <warnlevel> -c <critlevel>\n
  file: path and name of certficate to check\n
  warnlevel: warning shall be given when that many days are left\n
  critlevel: critical shall be reported when that many days are left\n
e.g.: ./$(basename $0) -i /etc/raddb/certs/radius.cert.pem -w 30 -c 7\n"

while getopts hi:c:w: OPT
  case "$OPT" in
    h)  echo -e "$USAGE"
        exit 1
    i)  FILE=$OPTARG
  [?])  echo -e "$USAGE" >&2
        exit 1

# check parameters
if [ "$FILE" == "" -o "$WARNLEVEL" == "" -o "$CRITLEVEL" == "" ]
  echo -e "At least one of the arguments was empty!\n"
  echo -e $USAGE
  exit 1
# determine when certificate expires
EXPIRATIONDATE=$(openssl x509 -in $FILE -noout -enddate | sed -e 's/notAfter=//g' -e 's/ *Jan */01;/g' -e 's/ *Feb */03;/g' -e 's/ *Mar */03;/g' -e 's/ *Apr */04;/g' -e 's/ *May */05;/g' -e 's/ *Jun */06;/g' -e 's/ *Jul */07;/g' -e 's/ *Aug */08;/g' -e 's/ *Sep */09;/g' -e 's/ *Oct */10;/g' -e 's/ *Nov */11;/g' -e 's/ *Dec */12;/g' -e 's/ *[0-9][0-9]:[0-9][0-9]:[0-9][0-9] */;/g' -e 's/ *GMT *//g')
EXPIRATIONMONTH=$(echo $EXPIRATIONDATE | cut -f1 -d";" | sed 's/^0*//')
EXPIRATIONDAY=$(echo $EXPIRATIONDATE | cut -f2 -d";" | sed 's/^0*//')
# inspect todays date
CURRENTDATE=$(date +%m\;%d\;%Y)
CURRENTYEAR=$(echo $CURRENTDATE | cut -f3 -d";")
CURRENTMONTH=$(echo $CURRENTDATE | cut -f1 -d";" | sed 's/^0*//')
CURRENTDAY=$(echo $CURRENTDATE | cut -f2 -d";" | sed 's/^0*//')
# calculate how many days are left
REMAININGDAYS=$(($YEARDIST*365)) # ignoring leap years
REMAININGDAYS=$(($REMAININGDAYS + $MONTHDIST*30)) # ignoring different day count per month
# preparing for human readable output
if [ $DAYDIST -lt 0 ]
  DAYDIST=$((30 + $DAYDIST)) # ignoring different day count per month
if [ $MONTHDIST -lt 0 ]
# check criticality
if [ $REMAININGDAYS -lt 1 ]
  echo "Certificate $FILE expired!"
  exit 2
  echo "Certificate $FILE expires in $YEARDIST years $MONTHDIST months $DAYDIST days. This is critical!"
  exit 2
  echo "Warning - Certificate $FILE expires in $YEARDIST years $MONTHDIST months $DAYDIST days."
  exit 1
# remaining time is still fine
exit 0