feat: CEL-based mutating admission webhook for v1alpha2 Silences#660
feat: CEL-based mutating admission webhook for v1alpha2 Silences#660QuentinBisson wants to merge 8 commits into
Conversation
Introduces a mutating webhook that injects matchers, labels, and annotations into v1alpha2 Silence resources on CREATE/UPDATE, replacing the Kyverno policy in kyverno-policies-observability. Rules are expressed in CEL: an empty condition applies unconditionally (Kyverno parity), while a non-empty condition gates injection to matching objects. Webhook is disabled by default; enabled via webhook.enabled=true and webhook.celRules in Helm values. Helm supports both cert-manager-managed TLS (configurable issuer name and kind) and BYO TLS secret. Adds unit tests, controller integration tests, and e2e tests.
- Add required guard for webhook.caBundle when certManager is disabled; previously an empty CA bundle would silently deploy an unusable webhook - Clarify e2e conditional rule test comment (test validates always-apply rules; extend comment explains how to test conditional rules manually) - Expand CHANGELOG entry with TLS options and failurePolicy warning
- Replace github.com/pkg/errors with fmt.Errorf for consistency with the rest of the codebase
- Replace interface{} with any (Go 1.18+ alias)
- Add TestCELRuntimeError_MissingField: confirms that accessing an absent field (labels) propagates as an error instead of silently skipping
- Add TestCELRuntimeError_SafeGuardWithHas: documents the safe pattern (has() macro) for optional-field conditions
- Add TestMultipleRules_AppliedInOrder: verifies rules fire in declaration order and matchers are appended deterministically
b545ef1 to
c32a956
Compare
- Remove | b64enc from caBundle in MutatingWebhookConfiguration: users provide the value already base64-encoded (as kubectl outputs it), so encoding again would corrupt it; update comment accordingly - Add webhook section to values.schema.json so Helm validates webhook configuration including celRules structure and failurePolicy enum - Add TestLabelOverwrite / TestAnnotationOverwrite: document and verify that labels/annotations are always overwritten (unlike matchers which are deduplicated) - Add TestRegexMatcherInjection: verify =~ match type passes through correctly Signed-off-by: QuentinBisson <quentin@giantswarm.io>
bf190e8 to
d40387c
Compare
Two root causes: 1. Tests timed out when webhook wasn't deployed because there was no skip mechanism despite the comment saying "skip automatically". Now checks for the MutatingWebhookConfiguration by name at BeforeEach and calls Skip() if absent, so the suite gracefully skips when webhook.enabled=false. 2. Tests 2 and 3 failed with "namespace is terminating" because all three tests share the namespace "test-webhook" and BeforeEach was calling createNamespace without waiting for the previous test's AfterEach deletion to complete. Added an Eventually wait in BeforeEach that polls until the namespace no longer exists before recreating it.
647bd04 to
77ec748
Compare
|
This was tested with #661 on graveler |
The current code seems to use |
Could we automate it? Or test it? |
|
You're right, it is done here #661 but I would rather we release the 2 together |
|
I think it might be easier to just delete it via a script on all MCs manually as it is a one time migration |
Is there any chance someone out of giantswarm needs to do this migration? Or is it specific to our internal config? |
|
We are the only one that I know that currently uses kyverno policy for silences but this is tightly coupled with our delivery |
Fine then, we're the only ones impacted. 👍
You're making reference to this message saying we should run a script at release time?
So, "a script" would be the |
|
No this script disables the policy, the safest bet would be to remove the policy from the kyverno-observability-policies and then merge and release the operator, then update the config with the kyverno parity config |
I'm not comfortable with having to do "the safest bet"; I'd prefer we don't bet on whatever during upgrades, and rather rely on tested procedures with a fallback/rollback plan as well 😅 Could you write and append a proper deployment/upgrade procedure to the PR description? |
|
Tested PR #661 (mutating + validating webhooks) on graveler. Works as expected — config is already in place via konfigure, no additional changes needed to deploy. Upgrade plan:
Rollback plan:
|
Summary
v1alpha2Silence resources on CREATE/UPDATE, replacing the Kyverno policy inkyverno-policies-observabilitycondition= always apply (Kyverno parity); non-emptyconditiongates the rule to matching objects (e.g.object.metadata.namespace == "prod")webhook.enabled=trueandwebhook.mutating.celRulesin Helm valuesKyverno parity config
The mutating webhook and the Kyverno
always-allow-heartbeats-and-all-pipelines-alertsClusterPolicy cannot coexist on UPDATE operations.Why: Kyverno's policy uses
patchesJson6902withop: addandpath: /spec/matchers/-, which unconditionally appends matchers on every admission request — including UPDATEs where the matchers are already present. This creates duplicate matchers. The validating webhook (PR #661) then correctly rejects the object.The webhook itself is idempotent (it checks before adding), but Kyverno bypasses that guarantee by appending after the mutating webhook has already run.
Required action before enabling the webhook: suspend or remove the Kyverno policy. In Kyverno v1.17+ this can be done via a never-true precondition: