Monitoring certificate transparency logs with the certspotter API
If you manage your DNS using Cloudflare, you can benefit from their Certificate Transparency Monitoring service, currently in beta, which alerts you via email whenever a new certificate appears in CT logs for your domain. This however requires your domain to be hosted on Cloudflare, which is unfortunate as it is a great service. Perhaps once the beta is over they would extend the service to non-Cloudflare domains.
Other alternatives are the Facebook Certificate Transparency Monitoring tool and SSLMate Cert Spotter. Facebook’s offering is free, but requires a Facebook account and email notifications enabled (which may or may not enable other email notifications). This leaves Cert Spotter, which isn’t free and $15/month can be a lot if you only need to monitor a couple of domains.
Luckily, Cert Spotter has a free API offering that is enough for light use. I have created a small utility using the Cert Spotter API: ct-monitor. What it does is pretty simple: for a given domain, get the ID of the last discovered issuance from the positions file if it exists, then query the Cert Spotter API for any new issuances, send a notification, and save the last discovered issuance to the positions file. Queries for all issuances are only done during the first run where there are no positions file.
The tool can be run standalone or wrapped into a systemd file, or it can be run as a
CronJob in Kubernetes, which is what I intended to use it for.
Using it is as simple as copying over the sample manifests and editing it as necessary, especially for the
In order to stay within the Cert Spotter API limits, it is recommended to run the
CronJob once per hour.
apiVersion: batch/v1beta1 kind: CronJob metadata: name: ct-monitor labels: app.kubernetes.io/name: ct-monitor spec: schedule: "0 * * * *" concurrencyPolicy: Forbid startingDeadlineSeconds: 60 jobTemplate: spec: template: spec: containers: - name: ct-monitor image: quay.io/hsn723/ct-monitor:0.1 volumeMounts: - name: config-volume mountPath: /etc/ct-monitor/config.toml subPath: config.toml - name: positions-volume mountPath: /var/log/ct-monitor envFrom: - secretRef: name: ct-monitor-secrets volumes: - name: positions-volume persistentVolumeClaim: claimName: ct-monitor-position - name: config-volume configMap: name: ct-monitor-config restartPolicy: OnFailure
Pod created for the
Job gets deleted every
CronJob run, we want to keep state (the positions file) using a small
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ct-monitor-position spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Mi
ct-monitor expects a token for the Cert Spotter API provided in the
config.toml, as a command-line argument, or using the environment variable
CERTSPOTTER_TOKEN (recommended). Is is recommended to place such
Secrets in another repository, or make use of
Other environment variables that may be required depending on the chosen way to send report emails. For instance, Sendgrid expects a
SENDGRID_TOKEN environment variable and Amazon SES expects an access key ID and secret access key as environment variables:
- Access Key ID:
- Secret Access Key:
Once everything is set up and applied, we will start receiving emails like the following:
ct-monitor has observed the issuance of the following certificate(s) for the festivaljapon.com domain: Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3 DNS Names: [monitor-2.festivaljapon.com] Validity: 2020-07-28T18:07:30-00:00 - 2020-10-26T18:07:30-00:00 SHA256: 946881b2cd9e7fbc55c0172070a7dcb872ade10a374a5b5120aaf74f6081d0c6 Issuance type: cert Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3 DNS Names: [status.festivaljapon.com] Validity: 2020-07-29T14:36:27-00:00 - 2020-10-27T14:36:27-00:00 SHA256: f0bc7da52ce02856bfadf79bae599a87fe37672f939a5d6fd29d05867d03d294 Issuance type: cert Issuer: C=US, O="Cloudflare, Inc.", CN=Cloudflare Inc ECC CA-3 DNS Names: [*.festivaljapon.com festivaljapon.com sni.cloudflaressl.com] Validity: 2020-08-10T00:00:00-00:00 - 2021-08-10T12:00:00-00:00 SHA256: 3b62cdaaf584d39e7844cdccac9c0bd5fe46eb9fe65b4df72c38165d149b2f58 Issuance type: cert