Certificates created using OpenSSL usually expire in a year or two, forcing a new certificate signing request. Some certificate vendors, such as cacert.org, provide reminders when certificates are about to expire. Any in-house certificates should also be monitored, to prevent service loss due to certificate expiration. Use the check-expire script to check and report on certificates about to expire.
Proper expiration checking will depend on the site, and must include sufficient time to account for busy operations staff, budget or change control approval, and other unexpected problems. Take advantage of certificate providers offering renewal cycle plus extra weeks to allow for renewal before expiration. Cut an initial ticket (medium importance and low priority) for the renew at least two weeks in advance, and a high importance and priority ticket at least three days if the first ticket has not yet been resolved.
Some sites may benefit from scheduled renewals, for example reviewing and renewing all certificates in the first week of August, to avoid renewal during the busy Holiday months, or when students are in session. Even with a scheduled renewal, run check-expire to ensure nothing slips through the cracks.
Configuration
check-expire requires a preferences file. This file specifies how expired certificates should be handled, and what actions to take should a certificate expire inside a time window. The preferences file is read by Config::General. The following example sends e-mail if the certificate will expire inside three weeks, e-mail and an elevated exit code (for use by SiteScope) if a certificate expires inside a week, and a critical exit code should a certificate be expired.
<class default>
# too late! scream at folks!!
<expired>
stdout "Return Code: 2"
exit_value 2
</expired>
# If within a week, notify and escalate in monitoring software
<window>
inside 3d
stdout "Return Code: 1"
exit_value 1
pipe <<END_PIPE
Certificate expires inside 7 days!
subject=%{extra.subject}
command=%{program.name} %{program.argv}
| /bin/mail -s "Certificate will expire!" root
END_PIPE
</window>
<window>
inside 2w
stdout "Return Code: 0"
pipe <<END_PIPE
Certificate expires soon:
subject=%{extra.subject}
command=%{program.name} %{program.argv}
| /bin/mail -s "Certificate Renewal notice" root
END_PIPE
</window>
</class>
Usage
check-expire can check local certificate files, or run a wrapper script to perform arbitrary application checks. Use the certificate or openssl-x509 modes to check certificates:
$ check-expire -f prefs certificate check-web www.example.org:443
$ check-expire -f prefs openssl-x509 -in /etc/mail/certs/host.cert
Other modes can be written to extend check-expire, for example to audit software licenses for expiration.
check-expire may be run as a plugin under monitoring software such as Nagios or SiteScope. Checks can also be scheduled via cron(8) or CFEngine:
- Sample crontab(5) entries to check a website and a local certificate file:
- Sample CFEngine configuration to do similar, but more scalable, checks:
@weekly check-expire -f /etc/check-expire/prefs↵
certificate check-web example.org:443
@weekly check-expire -f /etc/check-expire/prefs↵
openssl_x509 -in /etc/mail/certs/host.cert
control:
any::
ce_path = ( /usr/bin/check-expire )
ce_prefs = ( /etc/check-expire/prefs )
classes:
any::
role_mail_server = ( mail mx1 mx2 )
role_tls_web_server = ( www )
shellcommands:
role_tls_web_server.Sunday::
"${ce_path} -f ${ce_prefs} certificate check-web ${host}:443"
ifelapsed=1470
role_mail_server.Sunday::
"${ce_path} -f ${ce_prefs} openssl_x509 -in /etc/mail/certs/host.cert"
ifelapsed=1470
Application Wrappers
The check-expire script can either check a local certificate file, or run a wrapper that returns a certificate for use by the certificate mode. Sample application wrappers for use by the certificate mode include the following. These rely on openssl s_client, and know enough about the protocol in question to exit cleanly once connected. The wrappers should be saved somewhere on the system, then used as arguments to check-expire certificate:
$ check-expire -f prefs certificate check-web www.example.org:443
- check-imap - returns Internet Message Access Protocol (IMAP) server certificate.
- check-ldap - returns Lightweight Directory Access Protocol (LDAP) server certificate.
- check-pop3 - returns Post Office Protocol (POP3) server certificate.
- check-smtp - returns Simple Mail Transport Protocol (SMTP) server certificate.
- check-web - returns website certificate.
#!/bin/sh
# Show IMAP server certificate. Usage:
# check-imap -connect mail.example.org:993
echo 00000001 LOGOUT | openssl s_client -connect "$1" 2>&1
#!/bin/sh
# Show LDAP server certificate. Usage:
# check-ldap ldap.example.org:636
echo QUIT | openssl s_client "$1" 2>&1
#!/bin/sh
# Show POP3 server certificate. Usage:
# check-pop3 -connect mail.example.org:995
# check-pop3 -starttls pop3 -connect mail.example.org:110
echo QUIT | openssl s_client $@ 2>&1
Note that older versions of openssl do not have the -starttls option to the s_client mode. Without -starttls support, a connection must be made to the raw Transport Layer Security (TLS) port instead of the standard application port.
#!/bin/sh
# Show SMTP server certificate. Usage:
# check-smtp -connect mail.example.org:465
# check-smtp -starttls smtp -connect mail.example.org:25
# check-smtp -starttls smtp -connect mail.example.org:587
(echo HELO `hostname`; echo QUIT) | openssl s_client $@ 2>&1
#!/bin/sh
# Show website certificate. Usage: check-web www.example.org:443
echo GET / HTTP/1.0 | openssl s_client -connect "$1" 2>&1