We recently started using Let’s Encrypt SSL certificates. These certificates have a validity of only 90 days, and we wanted a way to easily check the expiry dates of all our certificates.
Turns out, it’s really easy to do this with Go.
The crypto/tls Package
The crypto/tls
package provides a TLS 1.2 implementation. Among other things,
you can use it to establish a TLS connection and examine certificates. Connect
to a host, like google.com
, is as simple as:
conn, err := tls.Dial("tcp", "google.com:443", nil)
The Dial
succeeds only if the server presents a valid certificate (self-signed
certificates will not work). Verifying that the name matches is another step,
which can be done like this:
err := conn.VerifyHostname("google.com")
This checks if the given name matches the Common Name or the Subject Alt Names
specified in the certificate. And finally, the certificate chain itself is
available as conn.ConnectionState().PeerCertificates
. The server’s certificate
contains the expiry date we are interested in.
Here is a snippet (sans error checking) which can be used to get the expiry date of the certificate of an https site:
conn, _ := tls.Dial("tcp", "google.com:443", nil)
err := conn.VerifyHostname("google.com")
expiry := conn.ConnectionState().PeerCertificates[0].NotAfter
Not bad for 3 lines of code!
Rolling it into a command-line tool
We threw in error checking, timeouts and a couple of useful tidbits:
- Read the list of server names to check for from a file and as command-line arguments
- “Humanize” the expiry date with the nifty go-humanize
- ASCII art table
and rolled this into a command-line tool we named certchk
. Here’s certchk
in action:
$ go get github.com/rapidloop/certchk
$ certchk
Usage: certchk [-f file] servername ...
-f file
read server names from file
$ certchk mail.google.com facebook.com
Server | Certificate status
----------------+----------------------------------------------------------------
mail.google.com | valid, expires on 2016-05-31 (2 months from now)
facebook.com | valid, expires on 2016-12-30 (9 months from now)
$ cat /tmp/names
# this is a comment
www.netlanders.net
www.facebook.com
ttybuy.com
$ certchk -f /tmp/names mail.google.com
Server | Certificate status
-------------------+-------------------------------------------------------------
www.netlanders.net | x509: certificate signed by unknown authority
www.facebook.com | valid, expires on 2016-12-30 (9 months from now)
ttybuy.com | x509: certificate is valid for SV100, not ttybuy.com
mail.google.com | valid, expires on 2016-05-31 (2 months from now)
That’s it! The code is available on GitHub, and you can go get it with:
$ go get github.com/rapidloop/certchk
Feel free to send us your feedback, suggestions and PRs!