Commit Graph
53 Commits
Author SHA1 Message Date
Thibault VINCENT a25177d096 test(chart): render ratchets for alert overrides, rulePrefix, disableBuiltinAlertGroup guard 2026-06-15 18:12:17 +02:00
Thibault VINCENT d73f3c0c76 feat(chart): per-alert expr and for overrides + render ratchet
Two new value maps under `prometheusRules`:

- `alertExprOverrides` — alertName -> custom Prometheus expression
  that replaces the default `expr:`. Closes #253: multi-cluster setups
  can inject `max by (cluster, …)` aggregations or label filters
  without having to disableBuiltinAlertGroup and reconstruct everything.
- `alertForOverrides` — alertName -> `for:` duration that replaces
  the default. Schema-validated against Prometheus's duration syntax.

Both maps key on bare alert names (no `rulePrefix`). Overrides are
taken whole — no merge with the default. Single-line and multi-line
strings both render correctly: the template now emits each `expr:`
via `| quote` which wraps in a YAML double-quoted scalar (newlines
serialise to \n; Prometheus parses the resulting string identically
to the multi-line form).

Test ratchets added alongside:

- test/schema/valid/prometheusrules-alert-overrides.yaml — valid case
  covering both maps, with a multi-line expr to exercise the quoting
  path.
- test/schema/invalid/prometheusrules-alertforoverrides-bad-duration
  — paired with .expect.txt, ensures the duration regex rejects
  natural-language inputs ("30 minutes").
- test/render/prometheusrules-default-alerts.{yaml,expect-pass.txt} —
  new ratchet under the existing TestHelmRender machinery (extended
  to support "positive substring" checks via .expect-pass.txt). Locks
  in the exact 13 alert names the chart ships by default: any rename
  or accidental removal breaks the test at PR time.

Docs:

- chart/README.md.gotmpl alert table refreshed — was still on the v3
  layout (X509ExporterReadErrors + 3 cert alerts). Now lists all 13.
- values.yaml gets the two new map keys with descriptions and
  commented examples.
2026-05-25 19:18:58 +02:00
Thibault VINCENT 82e96e11a3 refactor(chart)!: rebuild PrometheusRule template, rename v3-era alerts
MAJOR CHANGE: PrometheusRule alert names and chart value keys
renamed. Users with AlertManager routing or silencing rules that
reference the old names must update them on upgrade. Migration map:

  X509ExporterReadErrors     -> SourceErrors (+ SourceErrorsSustained)
  alertOnReadErrors          -> alertOnSourceErrors
  readErrorsSeverity         -> sourceErrorsSeverity (+ ...SustainedSeverity)
  alertOnPassphraseFailures  -> alertOnKeystorePassphraseFailures
  passphraseFailuresSeverity -> keystorePassphraseFailuresSeverity
  alertOnCertificateErrors   -> alertOnCertificateError       (singular)
  certificateErrorsSeverity  -> certificateErrorSeverity      (singular)
  alertOnCertificateCollisions -> alertOnCertificateCollision (singular)
  certificateCollisionsSeverity -> certificateCollisionSeverity
  alertOnCRLs                -> (removed; CRL alerts always-on like Renewal/Expiration)

Substantive changes alongside the renames:

- SourceErrors gets the same two-band shape as KubeTransportErrors
  (warning at >5/15min for 5m, critical for 30m). The previous "fire
  on any single error" expression paged on a single malformed PEM,
  which was indistinguishable from a real outage.
- SourceErrors and KubeTransportErrors both aggregate over
  reason/resource via 'sum without (...)', so the alert routes by
  source. The breakdown stays available on the metric for triage.
- CRLNeedsRefresh and CRLStale no longer require alertOnCRLs — same
  policy as CertificateRenewal/Expiration. The underlying x509_crl_*
  series only exist when a CRL is actually observed, so installs that
  don't watch CRLs get nothing.
- CertificateRenewal expression now anchors to (not_after - now) > 0,
  so it doesn't keep firing alongside CertificateExpiration once a
  cert is past its NotAfter (those two alerts had identical truth
  values in the late-life window).
- CertificateExpiration description distinguishes 'expires in X' from
  'expired X ago' via humanizeDuration's sign, so the message stays
  accurate after the cert is past NotAfter.
- CertificateError, CertificateNotYetValid, CertificateRenewal and
  CertificateExpiration each get inline comments explaining their
  dependency or always-on status — consistent with the recent
  KubeTransportErrors / CertificateCollision additions.

Template hygiene:

- Three helper templates in _helpers.tpl: alertExtraLabels and
  alertExtraAnnotations (replace 12 duplicated if-blocks);
  alertLocationSuffix (replaces the 5 sites that re-emit the
  "{{if $labels.secret_name}}in Kubernetes secret …{{else}}at
  location …{{end}}" literal — when we flipped quotes to backticks
  recently, 5 edits were required; the helper would have made that
  one).
- All alerts stay in a single PrometheusRule group. Groups in
  PrometheusRule only matter for sequential recording-rule ordering,
  per-group evaluation intervals, or execution isolation — none of
  which apply here. AlertManager routes on labels (alertname,
  severity), not on group names, so splitting by domain would
  fragment without buying anything; worse, it would trap users who
  add recording rules via extraAlertGroups into the wrong group.
  Category-based routing on the consumer side is straightforward via
  alertname regex (Source.*, Cert.*, CRL.*, Kube.*).
2026-05-25 19:18:58 +02:00
Thibault VINCENT 0debda6a7b build(goreleaser): use v2.16 post-hook for Tilt retag, label base image digest
- dockers_v2.hooks.post on the tilt entry strips the -<arch> suffix
  dockers_v2 appends in snapshot mode, keeping the workaround colocated
  with the build config instead of in the Tiltfile.
- baseimage/baseimagedigest template variables populate
  org.opencontainers.image.base.name/digest on the busybox variant for
  supply-chain transparency. Scratch is skipped — FROM scratch has no
  parent and the labels would be empty.
- flake.nix grows a dedicated goreleaser derivation (fetchurl pattern,
  mirroring goSizeAnalyzer) so the dev shell ships a version
  independent of nixpkgs. Renovate tracks the pin via a new regex
  manager that uses the same depName as the existing CI pin, so a
  single PR bumps every reference.
2026-05-25 13:43:04 +02:00
Thibault VINCENT 0eed4da25d feat(chart, docs): expose jks.passphraseSecretRef in schema + examples 2026-05-15 16:54:25 +02:00
Thibault VINCENT c6e9aecf02 docs(chart, metrics): document DER format and add a positive schema fixture 2026-05-13 16:57:02 +02:00
Thibault VINCENT 6a55f83cd1 test(e2e): cover x509_crl_* with fresh, stale, and cert+CRL mixed scenarios 2026-05-13 16:57:02 +02:00
Thibault VINCENT 80b44e80f3 test(cabundle): close audit gaps (rotation, cross-kind, validation, fixtures) 2026-05-13 14:24:36 +02:00
Thibault VINCENT 7610ca68fe feat(cabundle): extend source to APIService and CRD conversion webhooks 2026-05-13 14:24:36 +02:00
Thibault VINCENT 86fb1c11b9 test+docs(cabundle): e2e scenarios, README + metrics.md, opt-in example 2026-05-13 14:24:36 +02:00
Thibault VINCENT 830ca14902 feat(chart): expose cluster-scoped cabundle exporter (opt-in) 2026-05-13 14:24:36 +02:00
Thibault VINCENT 2958d64ecd fix(chart): omit registry segment when image.registry is empty
Fix #499
2026-05-12 18:16:22 +02:00
Thibault VINCENT 840e762311 test(chart): assert configmap↔daemonset mount alignment via helm template 2026-05-12 15:08:40 +02:00
Thibault VINCENT 9626e52baf feat(chart): support glob and recursive (**) patterns in watchDirectories
Fix #108
2026-05-12 15:08:40 +02:00
Thibault VINCENT 8554ec5895 test(schema): negative fixture asserting serviceAccountName rejects non-string 2026-05-06 03:43:02 +02:00
Thibault VINCENT 5c82ade682 fix(chart): kube-rbac-proxy deprecation warnings — explicit TLS cert + drop --logtostderr 2026-05-06 03:41:57 +02:00
Thibault VINCENT 01326a0942 test(schema): probeListenPort range fixtures (positive + negative cases) 2026-05-06 02:56:20 +02:00
Thibault VINCENT 9303de785e test(schema): positive fixtures for rbacProxy enabled and webConfiguration inline 2026-05-06 02:45:46 +02:00
Thibault VINCENT 5fe6ffe495 test(e2e): auth-gating tests for webConfiguration (TLS+mTLS+basic_auth) and rbacProxy 2026-05-06 02:45:46 +02:00
Thibault VINCENT 7541605185 fix(chart): tighten values.schema.json (missing enums and nullable defaults) 2026-05-06 01:37:07 +02:00
Thibault VINCENT abbb9b5fa8 feat(chart): values.schema.json with strict mode + helm-side regression tests 2026-05-06 01:21:22 +02:00
Thibault VINCENT e354287f94 test(e2e): assert exposed Secret label values + cover 'right type, no matching key' 2026-05-05 21:18:11 +02:00
Thibault VINCENT b4cecfd4fe test(k8s): add memory smoke tests, ConfigMap delete coverage, and a sync benchmark 2026-05-05 14:43:36 +02:00
Thibault VINCENT 14b17c79dc docs: align comments and documentation with direct LIST+WATCH architecture 2026-05-05 14:34:42 +02:00
Thibault VINCENT d5b3cc1b32 chore(e2e): improve e2e cluster isolation 2026-05-03 12:57:53 +02:00
Thibault VINCENT a93402f86e test(e2e): new scenario for hostpath exporter 2026-05-01 19:19:45 +02:00
Thibault VINCENT b4f3f84086 feat!: rewrite from scratch with new architecture and toolchain
Complete rewrite of the codebase, the build pipeline, the dev loop,
and the release pipeline.

For the exporter itself, refer to the updated README and Helm chart
documentation to discover the new functionality and assess the impact
of the breaking changes on your existing setup.

Build & release:
- QA/CI pipelines now run through a Dagger Module, wrapped by
  Taskfile.yml for the developer interface.
- Releases run through GoReleaser: cross-compiled binaries × OS/arch,
  archives, checksums, multi-arch container images (busybox + scratch
  variants on linux/amd64,arm64,riscv64), pushed to ghcr/quay/docker.io.
- Everything is cosign-signed (binaries, images, Helm chart). Image
  CycloneDX SBOMs are attached as cosign attestations. SLSA-3
  provenance is attached to every GitHub Release.
- The Helm chart is published as a cosign-signed OCI artifact.
- Versioning and changelog are automated by release-please from
  Conventional Commits.

Dev experience:
- Local loop driven by Tilt + k3d + Dagger; one command brings up an
  exporter with seeded fixtures and a Prometheus scraping it.
- End-to-end tests run on a throwaway k3d cluster against the real
  rendered chart.

BREAKING CHANGE: the Helm chart is now published exclusively as an OCI
artifact at oci://quay.io/enix/charts/x509-certificate-exporter. The
legacy Helm repository at https://charts.enix.io is no longer updated;
users must switch to the OCI reference (Helm 3.8+ required).
Installation: `helm install x509-certificate-exporter
oci://quay.io/enix/charts/x509-certificate-exporter --version <vX.Y.Z>`.
BREAKING CHANGE: the Helm chart's values schema may diverge from v3 in
edge cases despite a best-effort to preserve backwards compatibility.
Review your existing values against the updated chart/values.yaml
before upgrading. A JSON schema (chart/values.schema.json) is shipped
with the chart so `helm install` / `helm upgrade` will reject any
values that no longer match the expected shape, surfacing regressions
early instead of at runtime.
BREAKING CHANGE: Alpine-based container images are no longer published.
The release pipeline now ships only the `busybox` and `scratch` variants
on linux/amd64,arm64,riscv64. Users pulling `*-alpine` tags must switch
to one of the new variants — `busybox` is the closest functional
replacement (still has a shell), `scratch` is the minimal distroless
option.
2026-04-30 20:35:54 +02:00
Alex Stockinger 59c3a929b2 Adapt tests 2023-05-22 17:10:46 +02:00
Alex Stockinger 42d7d2315f Make yaml-basic.conf valid 2023-05-22 17:10:46 +02:00
Arthur Chaloin f01ae2c7e9 chore: add missing tests for 100% coverage 2023-03-06 11:43:08 +01:00
Andreas Sommer c550166e11 fix(test): create service account tokens explicitly since Kubernetes 1.24 disables this insecure default 2022-08-19 11:27:15 +02:00
Arthur Chaloin f7a362989b test: fix typo in filename 2022-05-25 15:34:50 +02:00
Arthur Chaloin ad89ec4d6d test: add missing test file 2022-05-25 13:46:48 +02:00
Arthur Chaloin aac1ff511c test: add test with duplicate certificate in different formats 2022-05-25 13:36:18 +02:00
Arthur Chaloin 31789ed19d test: add test for invalid base64 strings in yaml 2022-05-25 13:20:13 +02:00
Arthur Chaloin 67f41d68fd test: add test for duplicate certificates 2022-05-25 13:19:48 +02:00
Arthur Chaloin 3fedef237e fix: don't fail when pem block isn't a certificate 2021-03-02 12:57:48 +01:00
Arthur Chaloin 49017cd6b1 feat: try to resolve symlinks in current directory 2021-03-01 17:15:33 +01:00
Arthur Chaloin d9b973b32a chore(ci): run builds on ubuntu 2021-02-24 11:56:39 +01:00
Arthur Chaloin 2683bc4004 chore(ci): quote release url 2021-02-24 11:33:41 +01:00
Arthur Chaloin 75fdaf8ed5 chore(ci): debug 2021-02-23 17:20:39 +01:00
Arthur Chaloin 9f4908312a chore(ci): fllow github auth redirect 2021-02-23 17:04:12 +01:00
Arthur Chaloin af0f7aafe1 chore(ci): publish binaries as release assets 2021-02-23 16:04:02 +01:00
Arthur Chaloin 650e419224 test: add missing error cases 2021-02-22 17:39:21 +01:00
Arthur Chaloin 99ce1632be test: add tests for new yaml handling 2021-02-22 16:01:54 +01:00
Thibault VINCENT fdee6b2bdc chore: project renamed to x509-certificate-exporter 2021-02-19 14:42:11 +01:00
Arthur Chaloin 075fe532a6 fix: handle absolute paths 2021-01-12 13:52:26 +01:00
Arthur Chaloin 6a57bc254d fix(testing): fix kube api server address lookup 2021-01-05 12:10:36 +01:00
Arthur Chaloin 83f4048a62 feat(ci): setup ci for k8s integration tests
fix(ci): add curl

fix(ci): add dind

fix(ci): try add docker client

fix(ci): delete cluster whatever

fix(ci): fix kind

fix(ci): remove docker

fix(ci): fix path

fix(ci): try fix ip

wip(ci): remove tests

wip(ci): try better net config

fix(ci): dummy mistake

fix(ci): try new ip

wip(ci): try with container name

wip(ci): try with 'docker' host

wip(ci): try with service

wip(ci): try new ip

wip(ci): try new ip

wip(ci): try example from kind ci

wip(ci): typo

wip(ci): try exact example from kind

wip(ci): test docker inspect

wip(ci): cluster name

wip(ci): typo

wip(ci): quotes

wip(ci): debug

wip(ci): try reach container directly

wip(ci): escape chars

wip(ci): fix escaping

wip(ci): fixes

wip(ci): fix

wip(ci): wip

wip(ci): skip tls verify

wip(ci): skip tls in tests

wip(ci): remove ca

wip(ci): fix connection test

fix(ci): increase timeout

wip(ci): fix

wip(ci): fix b64 arg
2020-10-19 16:05:14 +02:00
Arthur Chaloin 27a4c79624 feat(testing): kube integration tests 2020-10-15 16:10:30 +02:00