Search code examples
clojureopenssl

How to check TLS certificate expiration date with Clojure?


Normally I check a server's certificate expiration using the openssl command, but I'm learning Clojure and would really like to figure out how to do this without calling a shell command if possible.

How would I replicate this functionality?

$ openssl s_client -connect google.com:443 < /dev/null ^ /dev/null | openssl x509 -noout -enddate | awk -F'=' '{print $2}'
Apr 17 09:15:00 2019 GMT

Solution

  • It is possible to obtain and inspect server certificates in Clojure using Java APIs via interop.

    Assuming the server speaks HTTPS, the certificates can be retrieved from a javax.net.ssl.HttpsURLConnection instance once it is in the connected state. The connection is established by calling the getInputStream method and the getServerCertifcates method returns the server certificates as an array of java.security.cert.X509Certificate. To get an HttpsURLConnection instance, we have to call the openConnection method on a java.net.URL. The method getNotAfter of X509Certificate returns the certificate expiration date.

    In Clojure, it would look like this:

    (ns foo.core
      (:require [clojure.java.io :as io]))
    
    (defn get-server-certs [from]
      (let [url (io/as-url from)
            conn (.openConnection url)]
        (with-open [_ (.getInputStream conn)]
          (.getServerCertificates conn))))
    
    (.getNotAfter (first (get-server-certs "https://www.google.com")))
    ;;=> #inst "2019-04-17T09:15:00.000-00:00"