Automated certificate expiration checks on CentOS
December 20, 2009,
It is essential to keep track of the expiration dates of SSL certificates, and so it's useful to have a periodic check on all certificates in use on a system, that will alert systems administrators when a certificate is about to expire. This article shows one way of setting up such a procedure for CentOS and other RHEL derivatives.
Just like many other hosting providers, we use secure sockets layer (SSL) not only for HTTP, but for most other internet protocols we provide services for. One important part of using SSL is to keep track of expiration dates on certificates. Most client software will rightfully refuse to connect to a server that presents an expired certificate, resulting in interupted services. For CentOS and other RHEL based distributions, the crypto-utils package contains a very useful utility called certwatch, whitch can be used to detect whether a certificate will expire in the near future. This is supplemented by a cron script in /etc/cron.daily with the same name, which will send out warnings when SSL certificates used by the Apache web server are about to expire.
Having your systems report when certificates for websites expire is already useful, but what about the other certificates that are in use? We also use SSL certificates to secure POP3 and IMAP, and for stunnel connections. The cron script provided with certwatch determines which certificates to check by asking Apache which certificates are in use. To have certwatch also check certificates used by other systems, we need a modified version of the cron script:
#!/bin/bash # # Issue warning e-mails if SSL certificates expire, using certwatch(1). # Based on the certwatch cron script from the CentOS crypto-tools package # [ -r /etc/sysconfig/httpd ] && . /etc/sysconfig/httpd INCLUDE_CERTS='/etc/stunnel/*.pem /usr/share/ssl/certs/*.pem /usr/share/ssl/certs/*.crt' certs=`ls $INCLUDE_CERTS 2>/dev/null` RETVAL=$? test $RETVAL -eq 0 || exit 0 for c in $certs; do # Check whether a warning message is needed, then issue one if so. if [[ ! "$c" =~ ca-bundle ]]; then /usr/bin/certwatch $CERTWATCH_OPTS -q "$c" && /usr/bin/certwatch $CERTWATCH_OPTS "$c" | /usr/sbin/sendmail -oem -oi -t 2>/dev/null fi done
The script above is fairly simplistic, in the sense that it needs to be modified to indicate where the certificates that need to be looked at are located. Those are specified in the INCLUDE_CERTS variable, which is fed to ls. For the rest we hitchhike along with the settings that the regular certwatch cron script uses, which are defined in /etc/sysconfig/httpd. In the loop over all certificates we explicitly exclude files with ca-bundle in the name. These contain large collections of certificates from certificate authorities (CA's), many of which have expired already. These will always generate an alert, and since these need to be maintained by the CA's themselves, there is no need to check them.