CEL Validation: HTTPRoute Case-Insensitive Header Name Uniqueness
What happened: Unfortunately CEL is not currently capable of validating the case-insensitive uniqueness of header names in header modifier filters. This is the only standard channel validation we are still reliant on the validating webhook for. @gauravkghildiyal already developed a CEL rule for this:
// +kubebuilder:validation:XValidation:message="Must not match the same header (case-insensitive) multiple times in the same rule",rule="self.all(h1, self.exists_one(h2, h1.name.lowerAscii() == h2.name.lowerAscii()))"
Unfortunately there is a problem with CEL cost estimation that prevents this https://github.com/kubernetes/kubernetes/issues/119749, @jpbetz is working on a fix for this.
Anything else we need to know?: Given the Gateway API versioning policy to support the 5 latest minor Kubernetes versions, even when this is fixed upstream, it's going to be a long time before we can adopt this.
/lifecycle frozen
/cc
The Kubernetes project currently lacks enough contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Mark this issue as fresh with
/remove-lifecycle stale - Close this issue with
/close - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
This should definitely be frozen, as it is blocked by upstream.
/remove-lifecycle stale /lifecycle frozen
As the issue on k/k is closed, should we move with the validation here?
@snorwin as you have recently worked on header validations
/assign @snorwin
Unfortunately, the cost-estimation issue related to lowerAscii did not resolve the issue we are facing here. Due to the high level of nesting, even without lowerAscii the validation exceeds the budget by a factor of more than 100.
/unassign @snorwin
@snorwin I am doing the tests here
When you say the costs exceeds 100, can you give me some example on reproducing it? IIUC the problem is like, having multiple headers here will exponentially grow the cost, right?
@rikatz I tested with:
// +kubebuilder:validation:XValidation:message="Must not match the same header (case-insensitive) multiple times in the same rule",rule="self.all(h1, self.exists_one(h2, h1.name.lowerAscii() == h2.name.lowerAscii()))"
The actual issue isn’t the expression itself but the combinatorial explosion caused by the nesting:
- 16 (rules) x 16 (filters) x 16 x 16 (headers) x 3 (set/add/delete)
- 16 (rules) x 16 (backend refs) x 16 (filters) x 16 x 16 (headers) x 3 (set/add/delete)