Converting X509 certificates to JSON objects


Years ago when I wrote ssl-cert-check I looked far and wide for an easy way to parse X509 certificates. I wasn’t able to find a utility so I ended up using a combination of sed and awk to extract various fields from the certificate. That worked, but over the years it’s proven to be an unmaintable solution due to diferences in formatting between the issuers.

I was recently converting some certificate management scripts to Ansible roles when I came across Cloudflare’s certinfo utility. This amazing utility can be used to display a local or remote X509 certificate as a JSON object. Oh boy, I wish this would have been around when I was writing ssl-cert-check!!! In its basic form, certinfo will print the X509 certificate as a pretty printed JSON object:

$ certinfo -domain prefetch.net

{
  "subject": {
    "common_name": "prefetch.net",
    "names": [
      "prefetch.net"
    ]
  },
  "issuer": {
    "common_name": "Let's Encrypt Authority X3",
    "country": "US",
    "organization": "Let's Encrypt",
    "names": [
      "US",
      "Let's Encrypt",
      "Let's Encrypt Authority X3"
    ]
  },
  "serial_number": "285297399086406852295104706694661139012324",
  "sans": [
    "prefetch.net"
  ],
  "not_before": "2019-11-15T23:02:52Z",
  "not_after": "2020-02-13T23:02:52Z",
  "sigalg": "SHA256WithRSA",
  "authority_key_id": "A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1",
  "subject_key_id": "B9:1A:41:B8:64:AE:D7:62:16:B7:27:5E:3B:FE:36:C9:8E:7D:2B:35",
  "pem": "..."
}

In the example above, certinfo is establishing a TLS connection to prefetch.net, extracting the X509 certificate and displaying it as a JSON object. Since the certificate is formatted as JSON we can use everybody’s favorite JSON processing utlity jq (you can learn more about using jq from Scott Lowe) to slice and dice the output. To get the not_after property (this contains the expiration date) as a DateTime string you can run the following command:

$ certinfo -domain prefetch.net | jq '(.not_after)'

"2020-02-13T23:02:52Z"

To extract all of the subject alternate names from a certificate you can dump the sans array:

$ certinfo -domain prefetch.net | jq '(.sans[])'

"prefetch.net"

And as a final example (and one I wish would have existed eons ago), you can get the issuer:

$ certinfo -domain prefetch.net | jq '(.issuer.common_name)'

"Let's Encrypt Authority X3"

Amazing utility, and if the Prometheus blackbox exporter didn’t support monitoring certificate expiration I would consider revamping ssl-cert-check to use it. JSON makes life so much easier.

This article was posted by on 2019-12-10 10:05:16 -0500 -0500