If I have the actual file and a Bash shell in Mac or Linux, how can I query the cert file for when it will expire? Not a web site, but actually the certificate file itself, assuming I have the csr, key, pem and chain files.
9 Answers
With openssl:
openssl x509 -enddate -noout -in file.pem
The output is on the form:
notAfter=Nov 3 22:23:50 2014 GMT
Also see MikeW's answer for how to easily check whether the certificate has expired or not, or whether it will within a certain time period, without having to parse the date above.
If you just want to know whether the certificate has expired (or will do so within the next N seconds), the -checkend <seconds> option to openssl x509 will tell you:
if openssl x509 -checkend 86400 -noout -in file.pem
then
echo "Certificate is good for another day!"
else
echo "Certificate has expired or will do so within 24 hours!"
echo "(or is invalid/not found)"
fi
This saves having to do date/time comparisons yourself.
openssl will return an exit code of 0 (zero) if the certificate has not expired and will not do so for the next 86400 seconds, in the example above. If the certificate will have expired or has already done so - or some other error like an invalid/nonexistent file - the return code is 1.
(Of course, it assumes the time/date is set correctly)
Be aware that older versions of openssl have a bug which means if the time specified in checkend is too large, 0 will always be returned (https://github.com/openssl/openssl/issues/6180).
Here's my bash command line to list multiple certificates in order of their expiration, most recently expiring first.
for pem in /etc/ssl/certs/*.pem; do
printf '%s: %s\n' \
"$(date --date="$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" --iso-8601)" \
"$pem"
done | sort
Sample output:
2015-12-16: /etc/ssl/certs/Staat_der_Nederlanden_Root_CA.pem
2016-03-22: /etc/ssl/certs/CA_Disig.pem
2016-08-14: /etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_S.pem
Here's a bash function which checks all your servers, assuming you're using DNS round-robin. Note that this requires GNU date and won't work on Mac OS
function check_certs () {
if [ -z "$1" ]
then
echo "domain name missing"
exit 1
fi
name="$1"
shift
now_epoch=$( date +%s )
dig +noall +answer $name | while read _ _ _ _ ip;
do
echo -n "$ip:"
expiry_date=$( echo | openssl s_client -showcerts -servername $name -connect $ip:443 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2 )
echo -n " $expiry_date";
expiry_epoch=$( date -d "$expiry_date" +%s )
expiry_days="$(( ($expiry_epoch - $now_epoch) / (3600 * 24) ))"
echo " $expiry_days days"
done
}
Output example:
$ check_certs stackoverflow.com
151.101.1.69: Aug 14 12:00:00 2019 GMT 603 days
151.101.65.69: Aug 14 12:00:00 2019 GMT 603 days
151.101.129.69: Aug 14 12:00:00 2019 GMT 603 days
151.101.193.69: Aug 14 12:00:00 2019 GMT 603 days
One line checking on true/false if cert of domain will be expired in some time later(ex. 15 days):
openssl x509 -checkend $(( 24*3600*15 )) -noout -in <(openssl s_client -showcerts -connect my.domain.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM)
if [ $? -eq 0 ]; then
echo 'good'
else
echo 'bad'
fi
For MAC OSX (El Capitan) This modification of Nicholas' example worked for me.
for pem in /path/to/certs/*.pem; do
printf '%s: %s\n' \
"$(date -jf "%b %e %H:%M:%S %Y %Z" "$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" +"%Y-%m-%d")" \
"$pem";
done | sort
Sample Output:
2014-12-19: /path/to/certs/MDM_Certificate.pem
2015-11-13: /path/to/certs/MDM_AirWatch_Certificate.pem
macOS didn't like the --date= or --iso-8601 flags on my system.
I have made a bash script related to the same to check if the certificate is expired or not. You can use the same if required.
Script
https://github.com/zeeshanjamal16/usefulScripts/blob/master/sslCertificateExpireCheck.sh
ReadMe
https://github.com/zeeshanjamal16/usefulScripts/blob/master/README.md