From 0f00f53aa8a6becfcc875b1decc88b7377d06357 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Thu, 5 Mar 2026 12:51:11 -0800 Subject: [PATCH 1/2] Add ClusterInformation to ValidatingWebhookConfiguration Register the ClusterInformation write-protection webhook in the ValidatingWebhookConfiguration. This routes Create/Update/Delete requests for clusterinformations to the /cluster-info handler on the webhook server, which blocks writes from non-system users. The handler itself is implemented in projectcalico/calico#12010. Ref: CORE-12369 --- pkg/render/webhooks/render.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pkg/render/webhooks/render.go b/pkg/render/webhooks/render.go index a8ad446c37..3b7b5342eb 100644 --- a/pkg/render/webhooks/render.go +++ b/pkg/render/webhooks/render.go @@ -299,6 +299,38 @@ func (c *component) Objects() ([]client.Object, []client.Object) { TimeoutSeconds: ptr.To[int32](5), FailurePolicy: ptr.To(admissionregistrationv1.Fail), }, + { + // This webhook blocks user writes to ClusterInformation, which is a read-only resource managed by + // Calico system components. This mirrors the write protection provided by the aggregated API server. + Name: "cluster-info.api.projectcalico.org", + Rules: []admissionregistrationv1.RuleWithOperations{ + { + Operations: []admissionregistrationv1.OperationType{ + admissionregistrationv1.Create, + admissionregistrationv1.Update, + admissionregistrationv1.Delete, + }, + Rule: admissionregistrationv1.Rule{ + APIGroups: []string{"projectcalico.org"}, + APIVersions: []string{"v3"}, + Resources: []string{"clusterinformations"}, + Scope: ptr.To(admissionregistrationv1.AllScopes), + }, + }, + }, + ClientConfig: admissionregistrationv1.WebhookClientConfig{ + Service: &admissionregistrationv1.ServiceReference{ + Namespace: common.CalicoNamespace, + Name: WebhooksName, + Path: ptr.To("/cluster-info"), + }, + CABundle: c.cfg.KeyPair.GetCertificatePEM(), + }, + AdmissionReviewVersions: []string{"v1"}, + SideEffects: ptr.To(admissionregistrationv1.SideEffectClassNone), + TimeoutSeconds: ptr.To[int32](5), + FailurePolicy: ptr.To(admissionregistrationv1.Fail), + }, { // This webhook is for audit logging. The webhook controller will get events for all relevant Calico API types // and product audit logs for them. From f4608dc9a67c881b22697cbcdb52db8df00e8aa6 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Thu, 5 Mar 2026 13:28:56 -0800 Subject: [PATCH 2/2] Use Ignore failure policy for ClusterInformation webhook --- pkg/render/webhooks/render.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/render/webhooks/render.go b/pkg/render/webhooks/render.go index 3b7b5342eb..cce71d0cd2 100644 --- a/pkg/render/webhooks/render.go +++ b/pkg/render/webhooks/render.go @@ -329,7 +329,7 @@ func (c *component) Objects() ([]client.Object, []client.Object) { AdmissionReviewVersions: []string{"v1"}, SideEffects: ptr.To(admissionregistrationv1.SideEffectClassNone), TimeoutSeconds: ptr.To[int32](5), - FailurePolicy: ptr.To(admissionregistrationv1.Fail), + FailurePolicy: ptr.To(admissionregistrationv1.Ignore), }, { // This webhook is for audit logging. The webhook controller will get events for all relevant Calico API types