- How to determine SSL cert expiration date from a PEM encoded certificate?
- 11 Answers 11
- Into bash variables
- More complete bash x509 reading:
- Full bash script
- How to Check a TLS/SSL Certificate Expiration Date on Ubuntu
- Checking the TLS/SSL Certificate Expiration Date on Ubuntu
- Step # 1: Check if OpenSSL is Installed on your System or not:
- Step # 2: Define and Export the URL Variable:
- Step # 3: Define and Export the Port Variable:
- Step # 4: Check the TLS/SSL Certificate Expiration Date:
- Conclusion:
- Search
- About This Site
- Latest Tutorials
How to determine SSL cert expiration date from a PEM encoded certificate?
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.
11 Answers 11
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.
You also have the -startdate and -enddate options built into the x509 utility. They will save you the grep .
If you just want to know whether the certificate has expired (or will do so within the next N seconds), the -checkend 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).
To determine whether a certificate is currently expired, use a duration of zero seconds. Omit the -noout option to see a helpful message using a single command without extra logic. E.g., openssl x509 -checkend 0 -in file.pem will give the output «Certificate will expire» or «Certificate will not expire» indicating whether the certificate will expire in zero seconds.
Providing values > 30 years (922752000) to -checkend causes the option to behave unexpectedly (returns 0 even though certificate would expire during this timeframe).
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
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
Very nice! This is what I was after. Now I have an overview of the certificiates that I have to renew soon. Saved it as checkcerts.sh in my home folder so I can check it regularly. Next thing would be to have a CRON job to check every month and email the certificates that need renewal.
# cat | openssl x509 -noout -enddate Example: # cat tower.cert | openssl x509 -noout -enddate
notAfter=Dec 7 04:03:32 2023 GMT
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 >
$ 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
surprisingly osx 10.13.4 runs your shell OK ( don’t judge me I am only on osx today to push an app to app store . booting back to linux shortly 😉
Thank you very much for that code snippit! What an annoying task :), I wish there was a unixtime timestamp flag for openssl.
For those of you on an alpine linux container, your expiry_date value will need to have the timezone name removed from the end of it. Add an additional cut to the end of the pipe to do this: | cut -d ‘ ‘ -f 1-4
Same as accepted answer, But note that it works even with .crt file and not just .pem file, just in case if you are not able to find .pem file location.
openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt
notAfter=Mar 29 06:15:00 2020 GMT
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 | 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
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.
How would you do this if you didn’t have make the .pem files, but just had .cer certs you just made and downloaded from the Apple Dev site?
Into bash variables
As this question is tagged bash, I often use UNIX EPOCH to store dates, this is useful for compute time left with $EPOCHSECONDS and format output via printf ‘%(dateFmt)T bashism:
printf '%-6s %(%a %d %b %Y, %H %Z)T\n' start $certStart end $certEnd
start Mon 01 Nov 2004, 17 UTC end Mon 01 Jan 2035, 05 UTC
Sample, listing content of /etc/ssl/certs and compute days left:
for file in /etc/ssl/certs/*pem;do < read -r certStart;read -r certEnd;> < <( date -f <(cut -d = -f 2 <( openssl x509 -dates -noout -in "$file")) +%s) printf "%(%d %b %Y %T)T - %(%d %b %Y %T)T: %6d %s\n" \ $certStart $certEnd $(( (certEnd - EPOCHSECONDS)/86400 )) $ done
05 May 2011 09:37:37 - 31 Dec 2030 09:37:37: 3034 ACCVRAIZ1.pem 26 Oct 2010 08:38:03 - 26 Oct 2040 08:38:03: 6620 Buypass_Class_2_Root_CA.pem 19 Jan 2010 00:00:00 - 18 Jan 2038 23:59:59: 5609 COMODO_RSA_Certification_Authority.pem 13 Nov 2012 00:00:00 - 19 Jan 2038 03:14:07: 5609 GlobalSign_ECC_Root_CA_-_R4.pem 06 Apr 2001 07:29:40 - 06 Apr 2021 07:29:40: -522 Sonera_Class_2_Root_CA.pem 29 Jun 2004 17:39:16 - 29 Jun 2034 17:39:16: 4310 Starfield_Class_2_CA.pem 04 Feb 2016 12:32:16 - 31 Dec 2029 17:23:16: 2669 TrustCor_RootCert_CA-1.pem 01 Nov 2004 17:14:04 - 01 Jan 2035 05:37:19: 4495 XRamp_Global_CA_Root.pem .
More complete bash x509 reading:
for file in /etc/ssl/certs/*pem;do mapfile -t x509 < <(openssl x509 -noout -dates -subject -in "$file") x509=("$") mapfile -t dates < <(IFS=$'\n';date -f - <<<"$" +%s) str="$" declare -A Subj='([CN]="$")' while [[ "$str" ]] ;do lhs=$ rhs=$ rhs=$ rhs=$ Subj[$]="$rhs" str=$ str=$ done printf "%(%d %b %Y %T)T - %(%d %b %Y %T)T: %s\n" \ $ "$" done
05 May 2011 09:37:37 - 31 Dec 2030 09:37:37: 3034 ACCVRAIZ1 26 Oct 2010 08:38:03 - 26 Oct 2040 08:38:03: 6620 Buypass Class 2 Root CA 19 Jan 2010 00:00:00 - 18 Jan 2038 23:59:59: 5609 COMODO RSA Certification Authority 13 Nov 2012 00:00:00 - 19 Jan 2038 03:14:07: 5609 GlobalSign 06 Apr 2001 07:29:40 - 06 Apr 2021 07:29:40: -522 Sonera Class2 CA 29 Jun 2004 17:39:16 - 29 Jun 2034 17:39:16: 4310 Starfield_Class_2_CA.pem 04 Feb 2016 12:32:16 - 31 Dec 2029 17:23:16: 2669 TrustCor RootCert CA-1 01 Nov 2004 17:14:04 - 01 Jan 2035 05:37:19: 4495 XRamp Global Certification Authority .
Note: Some certs don’t have CN field in subject. For this I’ve initialized $Subj array by setting CN field to filename: declare -A Subj='([CN]=»$»)’
Full bash script
Sharing here a full bash script, showing all certificates from command line arguments, which could by file , domain name or IPv4 address . Will ouput past days, days left, number of alternative domain, and all alts in one (long) line:
#!/bin/bash showCert() < local x509 dates lhs rhs str alts mapfile -t x509 < <( openssl x509 -noout -dates -subject -ext subjectAltName -in "$1") x509=("$") mapfile -t dates < <(IFS=$'\n';date -f - <<<"$" +%s) str="$" local -A Subj;Subj[CN]="$" while [[ -n "$str" ]]; do lhs=$ rhs=$ rhs=$ rhs=$ Subj[$]="$rhs" str=$ str=$ done read -ra alts " alts=("$") printf " %(%d %b %Y %H:%M)T %(%d %b %Y %H:%M)T %6d %6d %-30s %3d %s\n" \ "$" $(((dates[1]-EPOCHSECONDS)/86400)) $(((EPOCHSECONDS- dates[0])/86400)) "$" "$" "$" >
checkIsIpv4() < # throw an error if not valid IPv4 local _iPointer _i _a _vareq=() for _i ;do case $_i in *[^0-9.]* ) return 1 ;; esac read -ra _a " [ $ -eq 4 ] || return 1 for _iPointer in "$" ;do (( _iPointer == ( _iPointer & 255 ) )) || return 2 done done > checkIsLabel() < (($<4 || $>253)) && return 1 [[ -z $ ]] || return 2 [[ -z $ ]] && return 3 set -- $ (($#
printf ' %-17s %-17s %6s %6s %-30s %2s\n' Not\ before Not\ after left \ past Common\ Name Alt for arg ;do if [ -f "$arg" ] ;then showCert "$arg" elif checkIsLabel "$arg" || checkIsIpv4 "$arg" ;then showCert <(openssl s_client -ign_eof -connect "$arg:443" \ <<<$'HEAD / HTTP/1.0\r\n\r' 2>/dev/null) else echo "Unknown argument: '$arg'." fi done
./certShow.sh /etc/ssl/certs/ssl-cert-snakeoil.pem www.example.com Not before Not after left past Common Name Alt 08 Sep 2021 16:49 06 Sep 2031 16:49 3277 372 hostname.local 1 hostname.local 14 Mar 2022 00:00 14 Mar 2023 23:59 179 186 www.example.org 8 www.example.org example.net example.edu example.com example.org www.example.com www.example.edu www.example.net
How to Check a TLS/SSL Certificate Expiration Date on Ubuntu
The purpose of using TLS/SSL certificates on web servers is to encrypt the connection between the web browser and server. However, these certificates are not valid for a whole life rather they also have a finite expiration date after which the web browser will show an error message when connecting to the website. Today, I will show you how you can check the TLS/SSL certificate expiration date of an SSL certificate of a website using OpenSSL on Ubuntu 20.04.
Checking the TLS/SSL Certificate Expiration Date on Ubuntu
To check the TLS/SSL certificate expiration date of an SSL certificate on the Linux shell, follow these steps:
Step # 1: Check if OpenSSL is Installed on your System or not:
First of all, you must ensure that OpenSSL is installed on your system. On most of the latest Linux distributions, OpenSSL is installed by default but we still need to confirm it. If it is not there, then we will have to install it before proceeding further. The existence of OpenSSL on our Ubuntu system can be verified by checking its version with the command shown below:
As you can see the OpenSSL version in the following image, means that OpenSSL is installed on our Ubuntu system so, we are good to go.
Step # 2: Define and Export the URL Variable:
Now, we need to define and export a URL variable that will correspond to the URL of the website whose certificate expiration date we want to check. Whenever we want to check the TLS/SSL certificate expiration date of a new website, we will have to define and export its particular URL variable in the manner shown below:
$ export SITE_URL= "WebsiteURL"
You can replace WebsiteURL with the URL of the website whose TLS/SSL certificate expiration date you want to check out. We have used google.com over here. This command will not produce any output as shown in the following image:
Step # 3: Define and Export the Port Variable:
After that, we need to define and export a Port variable. Now, since we all know that TLS/SSL always uses port number 443 to work that is why this variable will remain the same no matter which website URL you have used in the previous step. To define and export the port variable, we will execute the command shown below:
Again, this command will not produce any output as shown in the following image:
Step # 4: Check the TLS/SSL Certificate Expiration Date:
Finally, we can check the TLS/SSL certificate expiration date of our desired website by executing the command shown below:
$ openssl s_client -connect $:$ -servername $ 2> /dev/null | openssl x509 -noout -dates
After executing this command, you will be presented with two different dates in the output. The date highlighted in the following image is the TLS/SSL certificate expiration date for the specified website.
Conclusion:
This is how you can easily find the TLS/SSL certificate expiration date of any website out there, by making use of OpenSSL. Once you have OpenSSL installed on your system, you can perform this procedure without any worries and it works as smoothly as we have shown you in this article.
Search
About This Site
Vitux.com aims to become a Linux compendium with lots of unique and up to date tutorials.