⚠️ Breaking Changes
While not a new major version, this release ships significant changes that close issues inherited from the v3 → v4 jump. Please review your alerting chains after upgrading — silent regressions are possible, particularly around exporter health reporting.
- Helm chart built-in Prometheus rules
- The
X509ExporterReadErrorsalert has been broken since 4.0.0: the underlying metric was renamed fromx509_read_errorstox509_source_errors_total, but the chart kept pointing at the old name. It is now replaced bySourceErrorsandSourceErrorsSustained. See What's New. - Several keys under
prometheusRules.*have been renamed. Affected users will see schema validation errors at upgrade time pointing to the keys that need adjustment.
- The
- [HELD BACK FROM 4.2.0-rc.1] The chart's JSON schema is now strict end-to-end: every key under
values.yamlis explicitly declared and typed, and anything else — typos, removed fields, unexpected nested keys, wrong-type values like a string where a boolean is expected — is rejected byhelm install/helm upgradeinstead of silently ignored. Configurations that worked by accident in 4.0.x and 4.1.x will surface precise JSON-path errors at upgrade time and need cleaning up.
✨ What's New
This release closes implementation gaps in the supported certificate formats and broadens the surface of what can be observed inside a Kubernetes cluster.
- DER format for single-blob certs and CRLs. Format detection is opt-in — declare
format: derexplicitly; the exporter will never probe formats automatically. - CRL monitoring from PEM blocks/bundles or single-blob DER sources, with a new
x509_crl_*metric family (next_update,this_update,stale, etc.) and chart-shipped alertsCRLNeedsRefreshandCRLStale. - Kubernetes CABundle monitoring — a long-overdue source for the inline
caBundlefield ofMutatingWebhookConfiguration,
ValidatingWebhookConfiguration,APIService, and CRD conversion webhooks. Closes a frequent blind spot for control-plane operators. - Cross-Secret passphrase references for PKCS#12 and JKS/JCEKS via
passphraseSecretRef. A promised but broken feature of 4.0.0, now with schema and end-to-end tests coverage. - JKS and JCEKS
- JCEKS truststore/keystore support via a native parser (
keystore-gorejected the JCEKS magic byte). - New metric
x509_jks_passphrase_failures_total, and a chart alertKeystorePassphraseFailuresthat covers PKCS#12 too. It fires onbad_passphraseevents from eitherx509_pkcs12_passphrase_failures_total(pre-existing) orx509_jks_passphrase_failures_total(new).
- JCEKS truststore/keystore support via a native parser (
- Glob patterns everywhere
- Shell-style globs in
include/excludedirectives (namespaces, Secret names, ConfigMap names). - Glob and recursive
**patterns inhostPathsExporter.watchDirectories.
- Shell-style globs in
- New observability metrics
x509_cert_collision_totalkeeps its existing "any collision detected" semantics; a siblingx509_cert_collision_dropped_totalonly increments under theCollision=Neverpolicy and is the actual data-loss signal the chart now alerts on.x509_kube_transport_errors_totalwith 5 reasons (list_failed,watch_start_failed,watch_error_event,watch_flapped,namespace_sync_failed). Closes the blind spot where the exporter could silently degrade on Kubernetes API issues with no metric to alert on.
- New chart-shipped PrometheusRule alerts with opt-out toggles and sensible defaults.
SourceDown: source failed initial sync or stopped reporting (x509_source_up == 0) — common cause of silently expired certs.KeystorePassphraseFailures: PKCS#12 or JKS/JCEKS decode failed withbad_passphrase— flags a misconfiguredpassphraseKeyorpassphraseSecretRef.CertificateNotYetValid:notBeforeis in the future — clock drift, misdated issuance, or a planned-future cert that shipped early.CertificateCollision: at least one certificate was dropped because of a label collision under theCollision=Neverpolicy.KubeTransportErrors[Sustained]: two-band alert onx509_kube_transport_errors_total— warning at >5 transport errors in 15 minutes, critical once that condition has held for 30+ minutes.SourceErrors[Sustained]: same two-band shape onx509_source_errors_total— catches sustained decode or transport failures aggregated across reasons.
- Per-alert overrides for advanced setups.
alertExprOverrides: replace the defaultexpr:of any built-in alert. Useful for multi-cluster deployments that needmax by (cluster, …)aggregations or extra label filters without disabling the whole built-in group.alertForOverrides: replace the defaultfor:duration of any built-in alert. Validated against Prometheus's duration syntax.
- Supply-chain transparency on container images — every published image now carries
org.opencontainers.image.base.nameandorg.opencontainers.image.base.digestlabels, surfacing the exact base image identity for downstream scanners. - Empty
image.registryis now honoured properly — setting it to""omits the registry segment from the rendered image reference, letting the container runtime fall back to its configured default (typicallydocker.io). Previously rendered an empty leading slash.
Changelog
Security Updates
- 50ee4ab: security: update module golang.org/x/net to v0.55.0 [security] (@enix-renovate[bot])
- 3c016bf: security: update module golang.org/x/crypto to v0.52.0 [security] (@enix-renovate[bot])
Features
- 5291d5a: feat: split collision counter metric into total + dropped (@npdgm)
- 52e9c2e: feat: emit x509_kube_transport_errors_total for LIST/WATCH/informer failures (@npdgm)
- d73f3c0: feat(chart): per-alert expr and for overrides + render ratchet (@npdgm)
- ee273b4: feat(chart): add SourceDown, PassphraseFailures, NotYetValid, Collision alerts (@npdgm)
Bug Fixes
- e95dfcb: fix(log): drop source_kind from k8s base logger to avoid collision with SourceRef.Kind (@npdgm)
- e24b0e7: fix(log): debug log when passphraseKey is absent from secret data (@npdgm)
- efe153a: fix(k8s,jks): preserve passphrase resolution cause, sort JKS aliases (@npdgm)
- 17fb83c: fix(k8s): skip parse when passphraseKey absent and tryEmptyPassphrase false (@npdgm)
- cdf7ce8: fix(k8s): skip parse on passphraseSecretRef failure when tryEmptyPassphrase false (@npdgm)
- 305a284: fix(e2e): clean up Docker network leak from k3d teardown (@npdgm)
- 9d32abf: fix(chart): use backticks instead of double quotes in alert descriptions (@npdgm)
- a782c9b: fix(chart): rename x509_read_errors to x509_source_errors_total and use increase() (@npdgm)