Monitor certificate expiration (hosts)

In another Blog Post (Monitor certificate expiration) I showed a small script which checks local certificates for their expiration date and warns when it is near. This due to the fact that lets-encrypt does not send out warning mails anymore.

Checking a remote host is also something that a small bash script can do.

Below a small script which checks the hosts specified in HOSTS for the expiration of their certificate. It will warn whenever it will expire within DAYS_TO_WARN days.

#!/bin/bash
#
# Check certification expiration of a host
#

HOSTS="www.google.com www.yahoo.com"

MAIL_NAME=root
MAIL_SUBJECT='Certificate %cert% is expiring at %certdate%'

NOW=$(date +%s)
DAYS_TO_WARN=30
WARN_DATE=$(( ${NOW} + ( ${DAYS_TO_WARN} * (3600*24) ) ))

send_mail() {

  REPLACEMENT=$(echo ${1}|sed -e 's/\//\\\//g')
  SUBJECT=$(echo ${MAIL_SUBJECT} | sed -e "s/%cert%/${REPLACEMENT}/" | sed -e "s/%certdate%/$2/")

  mail -s "${SUBJECT}" ${MAIL_NAME} <<HERE
Hi!

This is your friendly certificate expiry check script. I've found a certificate that is going
to expire in less than ${DAYS_TO_WARN} days.

Certificate file: $1
Certificate end date: $2
Current date: $(date --date=@${NOW})
Warning date:  $(date --date=@${WARN_DATE})

Please take appropriate action

HERE
}

for host in ${HOSTS}; do
  CERT_TO_DATE=$(openssl s_client -connect ${host}:443 -showcerts 2>&1 < /dev/null|sed -n '/-----BEGIN/,/-----END/p'|openssl x509 -noout -enddate|sed -e 's/^notAfter=//')
  CERT_TO_DATE_FM=$(date --date="${CERT_TO_DATE}" +%s)

  if [ ${WARN_DATE}  -gt ${CERT_TO_DATE_FM} ]; then
    send_mail "${host}" "${CERT_TO_DATE}"
  fi
done;

The script will connect to the HTTPS port for the requested host and fetches the certificate, decodes it and checks if it is going to expire soon. When it does, it sends out an e-mail.