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].NotAfterNot 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/certchkFeel free to send us your feedback, suggestions and PRs!