Keeping Track of Certificate Expiry with a JWKS to iCalendar Converter
This post's featured URL for sharing metadata is https://www.jvt.me/img/profile.jpg.
I work with a number of certificates, and probably the thing I like about them most (but also least!) is how they have a built-in requirement for regular rotation.
Because I work with a number of certificates, I want to make sure that I know ahead of time when I need to plan to rotate them, instead of leaving it until it's last minute (at least for cases where I'm not using Let's Encrypt).
The best way I've found this works is by tracking their expiries in my calendar, so as I'm looking week(s) into the future, I can see what needs to be rotated soon.
I've looked at writing one-off scripts to set these alerts up, but wasn't as much of a fan, as I'd need to keep re-running the scripts.
Because the certs I'm using are generally exposed on a JSON Web Key Set (JWKS) endpoint, I decided to build on the idea of these scripts to generate calendar entries, and have created a lightweight API that can take a given JWKS, parse the X509 certificate from the
x5c field, and return an iCalendar feed.
You can interact with the API by performing a GET request on the below URL:
jwks_uri is a URI for a given JWKS endpoint, such as
(Aside: if you're interested in what the certs look like, check out Extracting
x5cs from a JSON Web Key Set (JWKS) to PEM files with Ruby).
By running this JWKS URI through the jwks-ical API, you will be returned with the following iCalendar representation:
BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Michael Angstadt//biweekly 0.6.3//EN BEGIN:VEVENT UID:76becdc5-a56f-4c6b-ab92-c69ef2f52640 DTSTAMP:20200614T191639Z DTSTART:20320621T080000Z DTEND:20320621T200000Z DESCRIPTION:The certificate for kid ODg2MzE1Qzg5Q0Y3ODdCNjcxNUU1RURERkMzMzU xQzc5MUY0MjI2Nw (with use: `sig` and subject: `CN=jamietanna.eu.auth0.com` ) is expiring on Mon Jun 21 12:01:32 UTC 2032 SUMMARY: Certificate expiry for ODg2MzE1Qzg5Q0Y3ODdCNjcxNUU1RURERkMzMzUxQzc 5MUY0MjI2Nw END:VEVENT BEGIN:VEVENT UID:5074509f-9fbe-4021-bd20-810d1e9d7c0a DTSTAMP:20200614T191639Z DTSTART:20331120T080000Z DTEND:20331120T200000Z DESCRIPTION:The certificate for kid wWbdWIDy-Op5zSH4u53PM (with use: `sig` and subject: `CN=jamietanna.eu.auth0.com`) is expiring on Sun Nov 20 11:58 :57 UTC 2033 SUMMARY: Certificate expiry for wWbdWIDy-Op5zSH4u53PM END:VEVENT END:VCALENDAR
Which you can feed into your calendar reader of choice, and keep an eye on when your certificates are expiring.
Providing more event context
If you've got lots of certs you're keeping an eye of, or if you want to make it more obvious when you've got a production certificate expiring, you can provide a value for the querystring parameter
https://europe-west1-jwksical-jvt-me.cloudfunctions.net/jwks-ical ?jwks_uri=$jwks_uri &prefix=Auth0+Production
Which generates a slightly different event description, to make it a little more obvious:
DESCRIPTION:The certificate for kid ODg2MzE1Qzg5Q0Y3ODdCNjcxNUU1RURERkMzMzU xQzc5MUY0MjI2Nw (with use: `sig` and subject: `CN=jamietanna.eu.auth0.com` ) is expiring on Mon Jun 21 12:01:32 UTC 2032 -SUMMARY: Certificate expiry for ODg2MzE1Qzg5Q0Y3ODdCNjcxNUU1RURERkMzMzUxQzc +SUMMARY: Auth0 Production Certificate expiry for ODg2MzE1Qzg5Q0Y3ODdCNjcxNUU1RURERkMzMzUxQzc 5MUY0MjI2Nw END:VEVENT
Insecure SSL/TLS configuration
Because I want to use this with Open Banking's certificates, I needed to disable the SSL/TLS validation, as
https://keystore.openbanking.org.uk/ uses a self-signed certificate.
Is this a dealbreaker for your own use cases? Let me know, and I can move to a per-JWKS configuration for insecure connections.
This is a Java function, so note that performance isn't exactly going to be perfect. But a) I wanted to write it in Java and b) the performance doesn't need to be perfect, as it doesn't need to be realtime.
This is my first experience with Google Cloud Functions, and I've found it pretty fun to work with. Unfortunately I couldn't get a custom domain working properly with Google Cloud Functions, even using Firebase, so for now you can use
If that's a bit of a mouthful, you can use
https://u.jvt.me/jwks-ical to remember it.
The source code for this can be found at jamietanna/jwks-ical, and is licensed under the AGPL3.
Feedback is always welcome - please feel free to raise an issue on jamietanna/jwks-ical, or contact me with one of the methods below.