Verifying a letsencrypt certificate

I generate two certificates using commands:

sudo letsencrypt certonly --standalone --email test@test.com --text --renew-by-default --agree-tos -d test.com
sudo letsencrypt certonly --standalone --email test@test.com --text --renew-by-default --agree-tos -d api.test.com

Commands complete and certificates are created in /etc/letsencrypt/live:

lrwxrwxrwx 1 root root 43 Apr 3 12:38 cert.pem -> …/…/archive/test.com/cert1.pem
lrwxrwxrwx 1 root root 44 Apr 3 12:38 chain.pem -> …/…/archive/test.com/chain1.pem
lrwxrwxrwx 1 root root 48 Apr 3 12:38 fullchain.pem -> …/…/archive/test.com/fullchain1.pem
lrwxrwxrwx 1 root root 46 Apr 3 12:38 privkey.pem -> …/…/archive/test.com/privkey1.pem

lrwxrwxrwx 1 root root 43 Apr 3 12:38 cert.pem -> …/…/archive/api.test.com/cert1.pem
lrwxrwxrwx 1 root root 44 Apr 3 12:38 chain.pem -> …/…/archive/api.test.com/chain1.pem
lrwxrwxrwx 1 root root 48 Apr 3 12:38 fullchain.pem -> …/…/archive/api.test.com/fullchain1.pem
lrwxrwxrwx 1 root root 46 Apr 3 12:38 privkey.pem -> …/…/archive/api.test.com/privkey1.pem

Is there a linux command I can run to verify the certificates? I am most interested in their expiry status.

@fegoze, you can try

openssl verify chain.pem (hopefully this will work on the basis of an IdenTrust cert you should already have within /etc/ssl/certs)

followed by

openssl verify -CApath chain.pem cert.pem

If you’re just interested in the expiry information, the best way is

openssl x509 -text -noout -in cert.pem

If you have a recent enough version of Certbot (which is questionable here since you’re using the form sudo letsencrypt, possibly a sign of a much older version from an OS package), you can also run certbot certificates to see a summary of details of all currently-managed certificates in /etc/letsencrypt.

I’ve got the apt-get version installed, so I might try the more recent certbot you recommended. The cerbot certificates command sounds interesting.

As far as the other commands:

fegoze@localhost:~$ sudo openssl verify /etc/letsencrypt/live/api.test.com/chain.pem
/etc/letsencrypt/live/api.test.com/chain.pem: CN = Fake LE Intermediate X1
error 20 at 0 depth lookup:unable to get local issuer certificate

fegoze@localhost:~$ sudo openssl verify -CApath /etc/letsencrypt/live/api.test.com/chain.pem /etc/letsencrypt/live/api.test.com/cert.pem
/etc/letsencrypt/live/api.test.com/cert.pem: CN = api.test.com
error 20 at 0 depth lookup:unable to get local issuer certificate

The certs were issued from the staging environment. I hit the rate limit on the production environment.
I guess the commands would succeed for real certs?

I’m running commands with a bash shell. $? is 2 after both of those commands.
Would a successful command have $? of 0, and would a command failed due to an expired cert have $? of 2?

It's actually -CAfile when used like this. -CApath is used for directories. -CAfile for a single file.

See the difference:

osiris@server ~ $ openssl verify -CApath /etc/letsencrypt/live/example.com-ecdsa/chain.pem /etc/letsencrypt/live/example.com-ecdsa/cert.pem 
/etc/letsencrypt/live/example.com-ecdsa/cert.pem: CN = example.com
error 20 at 0 depth lookup:unable to get local issuer certificate
osiris@server ~ $ openssl verify -CAfile /etc/letsencrypt/live/example.com-ecdsa/chain.pem /etc/letsencrypt/live/example.com-ecdsa/cert.pem 
/etc/letsencrypt/live/example.com-ecdsa/cert.pem: OK
osiris@server ~ $

That should also work for the staging environment, as the staging end leaf certs are actually signed by the staging intermediate.

Thanks Seth, the certs are verifying using -CAfile.

In the event of an expired cert, will the verify command return a non-zero exit code?

I have a cron setup to check weekly for renewing, but I want the machine to check on boot as well. Is a boot script the best way?

If you use a fairly recent version of certbot, you can just run ‘certbot renew’ as a daily cron job (and on boot as well, if you like). It will check your certs for validity, and renew them if they have less than 30 days remaining.

Whoops, thanks for the correction, @Osiris!

I think I typed -CAfile when testing and then -CApath when documenting. :slight_smile:

I just tested this with an expired cert, and I saw

$ openssl verify -CAfile chain.pem cert.pem 
cert.pem: CN = tomarbanhoeruim.loyalty.org
error 10 at 0 depth lookup:certificate has expired
OK
$ echo $?
0

That is, you get an "error 10" mentioned on stdout, but the return code is apparently based on whether the certificate was ever valid, so there is no error returned from this command for an expired cert.

As @danb35 mentioned, we have a feature called certbot renew which is supposed to handle this for you (I originally implemented it myself!). It checks whether any certificates are going to expire and attempts to renew those that are, and is meant to be run frequently. If certbot renew could work for you, we would recommend not doing extensive shell scripting of alternatives, especially because this feature might get better over time with bug fixes in new versions of Certbot.

I’ve been refactoring a lot of scripts the past few days and everything was starting to look like a script. If I’d paused and asked myself if this really required a script, I probably would have noticed the rather obvious fact that cerbot renew also does an expiry check.

schoen, Osiris, danb35 Thanks for your helpful responses.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.