Skip to Content

Webhooks

webhooks.enabled: true renders a ValidatingWebhookConfiguration/MutatingWebhookConfiguration (built-in admissionregistration.k8s.io/v1 — no capability-registry gate needed) backed by a generated CA and serving certificate. Requires service.enabled: true, since clientConfig.service targets the release Service.

webhooks: enabled: true ca: validityDays: 3650 renewBeforeDays: 30 port: 443 certMountPath: /etc/webhook-tls validating: - name: validate.example.com path: /validate rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"]

Required per entry

Every entry under validating or mutating requires name, path, and rules. The library enforces this at template time with a named error (for example webhooks.validating[0].path is required.) — a malformed entry can never render a broken webhook object. If your chart also ships a values.schema.json copied from the reference schema (the scaffold does this for you), the same requirements plus an FQDN pattern on name are caught even earlier, as a schema validation error. rules is a verbatim admissionregistration.k8s.io RuleWithOperations passthrough — write it the same way you would in a raw Kubernetes manifest.

Defaults applied per entry

FieldDefault when omitted
failurePolicyFail
sideEffectsNone
timeoutSeconds10
matchPolicyEquivalent
admissionReviewVersions[v1]
namespaceSelector / objectSelector{} (no restriction)
reinvocationPolicy (mutating only)Kubernetes API default (Never)

failurePolicy: Fail is cluster-wide blast radius. Both webhook configuration objects are cluster-scoped — a webhook that starts rejecting or timing out with failurePolicy: Fail blocks admission for every resource matching its rules, cluster-wide, not just resources in your namespace. Scope rules, namespaceSelector, and objectSelector as tightly as the webhook’s actual purpose allows, and treat a failurePolicy: Fail webhook with the same review scrutiny as a cluster-admin RBAC grant.

Certificate lifecycle

The CA and serving certificate live in one Secret, <fullname>-webhook-cert, with all four keys (ca.crt, ca.key, tls.crt, tls.key) reused together or regenerated together — never a partial mix, since the serving certificate must always chain to whichever CA is currently live. Reuse continues until the recorded expiry (platform/tls-not-after annotation) is within webhooks.ca.renewBeforeDays, at which point both regenerate. As with every self-signed feature in this library, lookup returns nothing under helm template/client-side --dry-run, so offline renders always regenerate.

The serving certificate is mounted read-only into every container in the pod at certMountPath (default /etc/webhook-tls) — same per-container coverage as the hardening pass and the tlsSelfSigned.mtls mount feature. caBundle on every webhook entry is exactly the Secret’s ca.crt — there’s no separate CA distribution step to manage.

Naming

Both configuration objects are named <namespace>-<fullname> — the namespace prefix exists because these objects are cluster-scoped (ValidatingWebhookConfiguration/MutatingWebhookConfiguration have no namespace of their own), so two releases of the same chart in different namespaces need distinguishable names.

Rotating the certificate

To force rotation immediately (bypassing the reuse-until-near-expiry lifecycle), delete <fullname>-webhook-cert and run helm upgrade — the next render finds no existing Secret and generates a fresh CA and serving certificate.

Last updated on