{"id":13574164,"url":"https://github.com/enix/x509-certificate-exporter","last_synced_at":"2025-12-30T17:07:37.589Z","repository":{"id":36959844,"uuid":"195274129","full_name":"enix/x509-certificate-exporter","owner":"enix","description":"A Prometheus exporter to monitor x509 certificates expiration in Kubernetes clusters or standalone","archived":false,"fork":false,"pushed_at":"2025-03-20T08:34:05.000Z","size":1194,"stargazers_count":695,"open_issues_count":49,"forks_count":72,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-03-27T01:41:53.238Z","etag":null,"topics":["alert","certificates","certificates-focusing","dashboard","expiration-monitoring","grafana-dashboard","kubernetes","monitoring-tool","prometheus-exporter"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-04T16:36:29.000Z","updated_at":"2025-03-20T20:03:54.000Z","dependencies_parsed_at":"2025-03-19T15:29:32.909Z","dependency_job_id":"49747bdc-bfa8-4410-bf1f-c2fac2191aa6","html_url":"https://github.com/enix/x509-certificate-exporter","commit_stats":null,"previous_names":["enix/x509-exporter"],"tags_count":103,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enix%2Fx509-certificate-exporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enix%2Fx509-certificate-exporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enix%2Fx509-certificate-exporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enix%2Fx509-certificate-exporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enix","download_url":"https://codeload.github.com/enix/x509-certificate-exporter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247194164,"owners_count":20899438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alert","certificates","certificates-focusing","dashboard","expiration-monitoring","grafana-dashboard","kubernetes","monitoring-tool","prometheus-exporter"],"created_at":"2024-08-01T15:00:47.439Z","updated_at":"2025-12-15T19:38:16.650Z","avatar_url":"https://github.com/enix.png","language":"Go","funding_links":[],"categories":["Go","kubernetes","Prometheus-Exporter"],"sub_categories":[],"readme":"# 🔏 X.509 Certificate Exporter\n\n[![Build status](https://gitlab.com/enix.io/x509-certificate-exporter/badges/master/pipeline.svg)](https://gitlab.com/enix.io/x509-certificate-exporter/-/pipelines)\n[![Code coverage](https://gitlab.com/enix.io/x509-certificate-exporter/badges/master/coverage.svg)](https://gitlab.com/enix.io/x509-certificate-exporter/-/pipelines)\n[![Go Report](https://goreportcard.com/badge/github.com/enix/x509-certificate-exporter)](https://goreportcard.com/report/github.com/enix/x509-certificate-exporter)\n[![License MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![Brought by Enix](https://img.shields.io/badge/Brought%20to%20you%20by-ENIX-%23377dff?labelColor=888\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAQAAAC1QeVaAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkBAkQIg/iouK/AAABZ0lEQVQY0yXBPU8TYQDA8f/zcu1RSDltKliD0BKNECYZmpjgIAOLiYtubn4EJxI/AImzg3E1+AGcYDIMJA7lxQQQQRAiSSFG2l457+655x4Gfz8B45zwipWJ8rPCQ0g3+p9Pj+AlHxHjnLHAbvPW2+GmLoBN+9/+vNlfGeU2Auokd8Y+VeYk/zk6O2fP9fcO8hGpN/TUbxpiUhJiEorTgy+6hUlU5N1flK+9oIJHiKNCkb5wMyOFw3V9o+zN69o0Exg6ePh4/GKr6s0H72Tc67YsdXbZ5gENNjmigaXbMj0tzEWrZNtqigva5NxjhFP6Wfw1N1pjqpFaZQ7FAY6An6zxTzHs0BGqY/NQSnxSBD6WkDRTf3O0wG2Ztl/7jaQEnGNxZMdy2yET/B2xfGlDagQE1OgRRvL93UOHqhLnesPKqJ4NxLLn2unJgVka/HBpbiIARlHFq1n/cWlMZMne1ZfyD5M/Aa4BiyGSwP4Jl3UAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDQtMDlUMTQ6MzQ6MTUrMDI6MDDBq8/nAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTA0LTA5VDE0OjM0OjE1KzAyOjAwsPZ3WwAAAABJRU5ErkJggg==)](https://enix.io)\n\nA Prometheus exporter for certificates focusing on expiration monitoring, written in Go. Designed to monitor Kubernetes clusters from inside, it can also be used as a standalone exporter.\n\nGet notified before they expire:\n\n- PEM encoded files, by path or scanning directories\n- Kubeconfigs with embedded certificates or file references\n- TLS Secrets from a Kubernetes cluster\n\n![Grafana Dashboard](./docs/grafana-dashboard.jpg)\n\n## Installation\n\n### 🏃 TL; DR\n\nThe [Helm chart](https://github.com/enix/x509-certificate-exporter/tree/master/deploy/charts/x509-certificate-exporter#-tldr) is the most straightforward way to get a fully-featured exporter running on your cluster.\nThe chart is also highly-customizable if you wish to. See the [chart documentation](https://github.com/enix/x509-certificate-exporter/tree/master/deploy/charts/x509-certificate-exporter) to learn more.\n\nThe provided [Grafana Dashboard](https://grafana.com/grafana/dashboards/13922) can also be used to display the exporter's metrics on your Grafana instance.\n\n### Using Docker\n\nA docker image is available at [enix/x509-certificate-exporter](https://hub.docker.com/r/enix/x509-certificate-exporter).\n\n### Using the pre-built binaries\n\nEvery [release](https://github.com/enix/x509-certificate-exporter/releases) comes with pre-built binaries for many supported platforms.\n\n### Using the source\n\nThe project's entry point is `./cmd/x509-certificate-exporter`.\nYou can run \u0026 build it as any other Go program:\n\n```bash\ngo build ./cmd/x509-certificate-exporter\n```\n\n## Usage\n\nThe following metrics are available:\n\n- `x509_cert_not_before`\n- `x509_cert_not_after`\n- `x509_cert_expired`\n- `x509_cert_expires_in_seconds` (optional)\n- `x509_cert_valid_since_seconds` (optional)\n- `x509_cert_error` (optional)\n- `x509_read_errors`\n- `x509_exporter_build_info`\n\n### Prometheus Alerts\n\nWhen installation is not performed with Helm, the following Prometheus alerting\nrules may be deployed manually:\n\n```\nrules:\n    - alert: X509ExporterReadErrors\n        annotations:\n            description: Over the last 15 minutes, this x509-certificate-exporter instance\n                has experienced errors reading certificate files or querying the Kubernetes\n                API. This could be caused by a misconfiguration if triggered when the exporter\n                starts.\n            summary: Increasing read errors for x509-certificate-exporter\n        expr: delta(x509_read_errors[15m]) \u003e 0\n        for: 5m\n        labels:\n            severity: warning\n    - alert: CertificateRenewal\n        annotations:\n            description: Certificate for \"{{ $labels.subject_CN }}\" should be renewed\n                {{if $labels.secret_name }}in Kubernetes secret \"{{ $labels.secret_namespace\n                }}/{{ $labels.secret_name }}\"{{else}}at location \"{{ $labels.filepath }}\"{{end}}\n            summary: Certificate should be renewed\n        expr: ((x509_cert_not_after - time()) / 86400) \u003c 28\n        for: 15m\n        labels:\n            severity: warning\n    - alert: CertificateExpiration\n        annotations:\n            description: Certificate for \"{{ $labels.subject_CN }}\" is about to expire\n                {{if $labels.secret_name }}in Kubernetes secret \"{{ $labels.secret_namespace\n                }}/{{ $labels.secret_name }}\"{{else}}at location \"{{ $labels.filepath }}\"{{end}}\n            summary: Certificate is about to expire\n        expr: ((x509_cert_not_after - time()) / 86400) \u003c 14\n        for: 15m\n        labels:\n            severity: critical\n```\n\n### Advanced usage\n\nFor advanced configuration, see the program's `--help`:\n\n```\nUsage: x509-certificate-exporter [-hv] [-b value] [--debug] [-d value] [--exclude-label value] [--exclude-namespace value] [--expose-per-cert-error-metrics] [--expose-relative-metrics] [-f value] [--include-label value] [--include-namespace value] [--kubeconfig path] [-k value] [-l value] [--max-cache-duration value] [--profile] [-s value] [--trim-path-components value] [--watch-kube-secrets] [--web.config.file value] [--web.systemd-socket] [parameters ...]\n -b, --listen-address=value\n                address on which to bind and expose metrics [:9793]\n     --debug    enable debug mode\n -d, --watch-dir=value\n                watch one or more directory which contains x509 certificate\n                files (not recursive)\n     --exclude-label=value\n                removes the kube secrets with the given label (or label\n                value if specified) from the watch list (applied after\n                --include-label)\n     --exclude-namespace=value\n                removes the given kube namespace from the watch list\n                (applied after --include-namespace)\n     --expose-per-cert-error-metrics\n                expose additionnal error metric for each certificate\n                indicating wether it has failure(s)\n     --expose-relative-metrics\n                expose additionnal metrics with relative durations instead\n                of absolute timestamps\n -f, --watch-file=value\n                watch one or more x509 certificate file\n -h, --help     show this help message and exit\n     --include-label=value\n                add the kube secrets with the given label (or label value if\n                specified) to the watch list (when used, all secrets are\n                excluded by default)\n     --include-namespace=value\n                add the given kube namespace to the watch list (when used,\n                all namespaces are excluded by default)\n     --kubeconfig=path\n                Path to the kubeconfig file to use for requests. Takes\n                precedence over the KUBECONFIG environment variable, and\n                default path (~/.kube/config).\n -k, --watch-kubeconf=value\n                watch one or more Kubernetes client configuration (kind\n                Config) which contains embedded x509 certificates or PEM\n                file paths\n -l, --expose-labels=value\n     --max-cache-duration=value\n                maximum cache duration for kube secrets. cache is per\n                namespace and randomized to avoid massive requests.\n     --profile  optionally enable a pprof server to monitor cpu and memory\n                usage at runtime\n -s, --secret-type=value\n                one or more kubernetes secret type \u0026 key to watch (e.g.\n                \"kubernetes.io/tls:tls.crt\"\n     --trim-path-components=value\n                remove \u003cn\u003e leading component(s) from path(s) in label(s)\n -v, --version  show version info and exit\n     --watch-kube-secrets\n                scrape kubernetes secrets and monitor them\n     --web.config.file=value\n                [EXPERIMENTAL] path to configuration file that can enable\n                TLS or authentication\n     --web.systemd-socket\n                use systemd socket activation listeners instead of port\n                listeners (Linux only)\n```\n\n## Development\n\nSome snippets to get started with development and testing:\n\n```sh\n# Run server, watch test input files, only listen on localhost to\n# avoid firewall popup dialogs\ngo run ./cmd/x509-certificate-exporter --debug -b localhost:9793 -d test/\n\n# Once the server is running, you can check the exported metrics\ncurl -Ss localhost:9793/metrics | grep \"^x509_cert_not_after\"\n\n# Automated tests do not need a Kubernetes cluster, since we use a fake clientset that simulate a cluster (k8s.io/client-go/kubernetes/fake)\ngo test -v ./internal\nkind delete cluster\n\n# Docker build (does not run tests)\ndocker buildx build .\n```\n\n## FAQ\n\n### Why are you using the `not after` timestamp rather than a remaining number of seconds?\n\nFor two reasons.\n\nFirst, Prometheus tends to do better storage consumption when a value stays identical over checks.\n\nThen, it is better to compute the remaining time through a prometheus query as some latency (seconds) can exist\nbetween this exporter check and your alert or query being run.\n\nHere is an example:\n\n```\nx509_cert_not_after - time()\n```\n\nWhen collecting metrics from tools like Datadog that does not have timestamp functions,\nthe exporter can be run with the `--expose-relative-metrics` flag in order to add the following optional metrics:\n\n- `x509_cert_valid_since_seconds`\n- `x509_cert_expires_in_seconds`\n\n### How to ensure it keeps working over time?\n\nChanges in paths or deleted files may silently break the ability to watch critical certificates.\n\nBecause it's never convenient to alert on disapearing metrics, the exporter will publish on `x509_read_errors` how many\npaths could not be read. It will also count Kubernetes API responses failures, but won't count deleted secrets.\n\nA basic alert would be:\n\n```\nx509_read_errors \u003e 0\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenix%2Fx509-certificate-exporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenix%2Fx509-certificate-exporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenix%2Fx509-certificate-exporter/lists"}