diff --git a/api/v1beta2/route_selectors.go b/api/v1beta2/route_selectors.go index 9689391e6..ef494effa 100644 --- a/api/v1beta2/route_selectors.go +++ b/api/v1beta2/route_selectors.go @@ -1,11 +1,73 @@ package v1beta2 import ( - kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" + "github.com/elliotchance/orderedmap/v2" + gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" + + "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" + "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) -// +kubebuilder:object:generate=false -type RouteSelector = kuadrantv1beta3.RouteSelector +// RouteSelector defines semantics for matching an HTTP request based on conditions +// https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec +type RouteSelector struct { + // Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request + // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec + // +optional + Hostnames []gatewayapiv1.Hostname `json:"hostnames,omitempty"` + + // Matches define conditions used for matching the rule against incoming HTTP requests. + // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec + // +optional + // +kubebuilder:validation:MaxItems=8 + Matches []gatewayapiv1.HTTPRouteMatch `json:"matches,omitempty"` +} + +// SelectRules returns, from a HTTPRoute, all HTTPRouteRules that either specify no HTTRouteMatches or that contain at +// least one HTTRouteMatch whose statements expressly include (partially or totally) the statements of at least one of +// the matches of the selector. If the selector does not specify any matches, then all HTTPRouteRules are selected. +// +// Additionally, if the selector specifies a non-empty list of hostnames, a non-empty intersection between the literal +// hostnames of the selector and set of hostnames specified in the HTTPRoute must exist. Otherwise, the function +// returns nil. +func (s *RouteSelector) SelectRules(route *gatewayapiv1.HTTPRoute) (rules []gatewayapiv1.HTTPRouteRule) { + rulesIndices := orderedmap.NewOrderedMap[int, gatewayapiv1.HTTPRouteRule]() + if len(s.Hostnames) > 0 && !utils.Intersect(s.Hostnames, route.Spec.Hostnames) { + return nil + } + if len(s.Matches) == 0 { + return route.Spec.Rules + } + for idx := range s.Matches { + routeSelectorMatch := s.Matches[idx] + for idx, rule := range route.Spec.Rules { + rs := kuadrant.HTTPRouteRuleSelector{HTTPRouteMatch: &routeSelectorMatch} + if rs.Selects(rule) { + rulesIndices.Set(idx, rule) + } + } + } + for el := rulesIndices.Front(); el != nil; el = el.Next() { + rules = append(rules, el.Value) + } + return +} + +// HostnamesForConditions allows avoiding building conditions for hostnames that are excluded by the selector +// or when the hostname is irrelevant (i.e. matches all hostnames) +func (s *RouteSelector) HostnamesForConditions(route *gatewayapiv1.HTTPRoute) []gatewayapiv1.Hostname { + hostnames := route.Spec.Hostnames + + if len(s.Hostnames) > 0 { + hostnames = utils.Intersection(s.Hostnames, hostnames) + } + + if utils.SameElements(hostnames, route.Spec.Hostnames) { + return []gatewayapiv1.Hostname{"*"} + } + + return hostnames +} // +kubebuilder:object:generate=false type RouteSelectorsGetter interface { diff --git a/api/v1beta3/route_selectors_test.go b/api/v1beta2/route_selectors_test.go similarity index 99% rename from api/v1beta3/route_selectors_test.go rename to api/v1beta2/route_selectors_test.go index 0b5e48054..c3934b86f 100644 --- a/api/v1beta3/route_selectors_test.go +++ b/api/v1beta2/route_selectors_test.go @@ -1,6 +1,6 @@ //go:build unit -package v1beta3 +package v1beta2 import ( "fmt" diff --git a/api/v1beta2/topology.go b/api/v1beta2/topology.go index dd6033a04..2b6efe9bd 100644 --- a/api/v1beta2/topology.go +++ b/api/v1beta2/topology.go @@ -8,8 +8,8 @@ import ( ) var ( - AuthPoliciesResource = GroupVersion.WithResource("authpolicies") - AuthPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "AuthPolicy"} + AuthPoliciesResource = GroupVersion.WithResource("authpolicies") + AuthPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "AuthPolicy"} ) var _ machinery.Policy = &AuthPolicy{} diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 3f58b7306..bcdb917cb 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -22,9 +22,9 @@ package v1beta2 import ( apiv1beta2 "github.com/kuadrant/authorino/api/v1beta2" - "github.com/kuadrant/kuadrant-operator/api/v1beta3" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -59,7 +59,7 @@ func (in *AuthPolicyCommonSpec) DeepCopyInto(out *AuthPolicyCommonSpec) { *out = *in if in.RouteSelectors != nil { in, out := &in.RouteSelectors, &out.RouteSelectors - *out = make([]v1beta3.RouteSelector, len(*in)) + *out = make([]RouteSelector, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -289,7 +289,7 @@ func (in *CommonAuthRuleSpec) DeepCopyInto(out *CommonAuthRuleSpec) { *out = *in if in.RouteSelectors != nil { in, out := &in.RouteSelectors, &out.RouteSelectors - *out = make([]v1beta3.RouteSelector, len(*in)) + *out = make([]RouteSelector, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -365,6 +365,33 @@ func (in *ResponseSpec) DeepCopy() *ResponseSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteSelector) DeepCopyInto(out *RouteSelector) { + *out = *in + if in.Hostnames != nil { + in, out := &in.Hostnames, &out.Hostnames + *out = make([]apisv1.Hostname, len(*in)) + copy(*out, *in) + } + if in.Matches != nil { + in, out := &in.Matches, &out.Matches + *out = make([]apisv1.HTTPRouteMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSelector. +func (in *RouteSelector) DeepCopy() *RouteSelector { + if in == nil { + return nil + } + out := new(RouteSelector) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SuccessResponseSpec) DeepCopyInto(out *SuccessResponseSpec) { *out = *in diff --git a/api/v1beta3/ratelimitpolicy_types.go b/api/v1beta3/ratelimitpolicy_types.go index d5dd195c4..587ae0dbf 100644 --- a/api/v1beta3/ratelimitpolicy_types.go +++ b/api/v1beta3/ratelimitpolicy_types.go @@ -87,7 +87,7 @@ type Rate struct { Unit TimeUnit `json:"unit"` } -// RouteSelector defines semantics for matching an HTTP request based on conditions +// WhenCondition defines semantics for matching an HTTP request based on conditions // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec type WhenCondition struct { // Selector defines one item from the well known selectors @@ -104,11 +104,6 @@ type WhenCondition struct { // Limit represents a complete rate limit configuration type Limit struct { - // RouteSelectors defines semantics for matching an HTTP request based on conditions - // +optional - // +kubebuilder:validation:MaxItems=15 - RouteSelectors []RouteSelector `json:"routeSelectors,omitempty"` - // When holds the list of conditions for the policy to be enforced. // Called also "soft" conditions as route selectors must also match // +optional @@ -132,7 +127,6 @@ func (l Limit) CountersAsStringList() []string { } // RateLimitPolicySpec defines the desired state of RateLimitPolicy -// +kubebuilder:validation:XValidation:rule="self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, has(self.limits[x].routeSelectors))",message="route selectors not supported when targeting a Gateway" // +kubebuilder:validation:XValidation:rule="!(has(self.defaults) && has(self.limits))",message="Implicit and explicit defaults are mutually exclusive" // +kubebuilder:validation:XValidation:rule="!(has(self.defaults) && has(self.overrides))",message="Overrides and explicit defaults are mutually exclusive" // +kubebuilder:validation:XValidation:rule="!(has(self.overrides) && has(self.limits))",message="Overrides and implicit defaults are mutually exclusive" @@ -266,18 +260,6 @@ func (r *RateLimitPolicy) GetWrappedNamespace() gatewayapiv1.Namespace { func (r *RateLimitPolicy) GetRulesHostnames() (ruleHosts []string) { ruleHosts = make([]string, 0) - for _, limit := range r.Spec.CommonSpec().Limits { - for _, routeSelector := range limit.RouteSelectors { - convertHostnamesToString := func(gwHostnames []gatewayapiv1.Hostname) []string { - hostnames := make([]string, 0, len(gwHostnames)) - for _, gwHostName := range gwHostnames { - hostnames = append(hostnames, string(gwHostName)) - } - return hostnames - } - ruleHosts = append(ruleHosts, convertHostnamesToString(routeSelector.Hostnames)...) - } - } return } diff --git a/api/v1beta3/route_selectors.go b/api/v1beta3/route_selectors.go deleted file mode 100644 index 24d3c2044..000000000 --- a/api/v1beta3/route_selectors.go +++ /dev/null @@ -1,75 +0,0 @@ -package v1beta3 - -import ( - "github.com/elliotchance/orderedmap/v2" - gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - - "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" - "github.com/kuadrant/kuadrant-operator/pkg/library/utils" -) - -// RouteSelector defines semantics for matching an HTTP request based on conditions -// https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec -type RouteSelector struct { - // Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - // +optional - Hostnames []gatewayapiv1.Hostname `json:"hostnames,omitempty"` - - // Matches define conditions used for matching the rule against incoming HTTP requests. - // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - // +optional - // +kubebuilder:validation:MaxItems=8 - Matches []gatewayapiv1.HTTPRouteMatch `json:"matches,omitempty"` -} - -// SelectRules returns, from a HTTPRoute, all HTTPRouteRules that either specify no HTTRouteMatches or that contain at -// least one HTTRouteMatch whose statements expressly include (partially or totally) the statements of at least one of -// the matches of the selector. If the selector does not specify any matches, then all HTTPRouteRules are selected. -// -// Additionally, if the selector specifies a non-empty list of hostnames, a non-empty intersection between the literal -// hostnames of the selector and set of hostnames specified in the HTTPRoute must exist. Otherwise, the function -// returns nil. -func (s *RouteSelector) SelectRules(route *gatewayapiv1.HTTPRoute) (rules []gatewayapiv1.HTTPRouteRule) { - rulesIndices := orderedmap.NewOrderedMap[int, gatewayapiv1.HTTPRouteRule]() - if len(s.Hostnames) > 0 && !utils.Intersect(s.Hostnames, route.Spec.Hostnames) { - return nil - } - if len(s.Matches) == 0 { - return route.Spec.Rules - } - for idx := range s.Matches { - routeSelectorMatch := s.Matches[idx] - for idx, rule := range route.Spec.Rules { - rs := kuadrant.HTTPRouteRuleSelector{HTTPRouteMatch: &routeSelectorMatch} - if rs.Selects(rule) { - rulesIndices.Set(idx, rule) - } - } - } - for el := rulesIndices.Front(); el != nil; el = el.Next() { - rules = append(rules, el.Value) - } - return -} - -// HostnamesForConditions allows avoiding building conditions for hostnames that are excluded by the selector -// or when the hostname is irrelevant (i.e. matches all hostnames) -func (s *RouteSelector) HostnamesForConditions(route *gatewayapiv1.HTTPRoute) []gatewayapiv1.Hostname { - hostnames := route.Spec.Hostnames - - if len(s.Hostnames) > 0 { - hostnames = utils.Intersection(s.Hostnames, hostnames) - } - - if utils.SameElements(hostnames, route.Spec.Hostnames) { - return []gatewayapiv1.Hostname{"*"} - } - - return hostnames -} - -// +kubebuilder:object:generate=false -type RouteSelectorsGetter interface { - GetRouteSelectors() []RouteSelector -} diff --git a/api/v1beta3/topology.go b/api/v1beta3/topology.go index df9f6bb5e..aa6672910 100644 --- a/api/v1beta3/topology.go +++ b/api/v1beta3/topology.go @@ -9,7 +9,7 @@ import ( var ( RateLimitPoliciesResource = GroupVersion.WithResource("ratelimitpolicies") - RateLimitPolicyKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "RateLimitPolicy"} + RateLimitPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "RateLimitPolicy"} ) var _ machinery.Policy = &RateLimitPolicy{} diff --git a/api/v1beta3/zz_generated.deepcopy.go b/api/v1beta3/zz_generated.deepcopy.go index 0c19fe0a0..1af900e7b 100644 --- a/api/v1beta3/zz_generated.deepcopy.go +++ b/api/v1beta3/zz_generated.deepcopy.go @@ -23,19 +23,11 @@ package v1beta3 import ( "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" - apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Limit) DeepCopyInto(out *Limit) { *out = *in - if in.RouteSelectors != nil { - in, out := &in.RouteSelectors, &out.RouteSelectors - *out = make([]RouteSelector, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.When != nil { in, out := &in.When, &out.When *out = make([]WhenCondition, len(*in)) @@ -209,33 +201,6 @@ func (in *RateLimitPolicyStatus) DeepCopy() *RateLimitPolicyStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteSelector) DeepCopyInto(out *RouteSelector) { - *out = *in - if in.Hostnames != nil { - in, out := &in.Hostnames, &out.Hostnames - *out = make([]apisv1.Hostname, len(*in)) - copy(*out, *in) - } - if in.Matches != nil { - in, out := &in.Matches, &out.Matches - *out = make([]apisv1.HTTPRouteMatch, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSelector. -func (in *RouteSelector) DeepCopy() *RouteSelector { - if in == nil { - return nil - } - out := new(RouteSelector) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WhenCondition) DeepCopyInto(out *WhenCondition) { *out = *in diff --git a/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml b/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml index 089ea0d7b..25b2b124d 100644 --- a/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml +++ b/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml @@ -106,7 +106,7 @@ metadata: capabilities: Basic Install categories: Integration & Delivery containerImage: quay.io/kuadrant/kuadrant-operator:latest - createdAt: "2024-10-04T07:47:31Z" + createdAt: "2024-10-04T10:37:57Z" description: A Kubernetes Operator to manage the lifecycle of the Kuadrant system operators.operatorframework.io/builder: operator-sdk-v1.32.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 diff --git a/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml b/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml index 00aae5aaa..043dec0fa 100644 --- a/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml +++ b/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml @@ -121,309 +121,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -510,307 +214,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching an - HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate used - to match requests to a given\naction. Multiple match - types are ANDed together, i.e. the match will\nevaluate - to true only if all conditions are satisfied.\n\n\nFor - example, the match below will match a HTTP request - only if its path\nstarts with `/foo` AND it contains - the `version: v1` header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t - \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and start - with '/' when type one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] || self.type - == 'RegularExpression' - - message: must only contain valid characters (matching - ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP query - param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -901,309 +311,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -1275,9 +389,6 @@ spec: - targetRef type: object x-kubernetes-validations: - - message: route selectors not supported when targeting a Gateway - rule: self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, - has(self.limits[x].routeSelectors)) - message: Implicit and explicit defaults are mutually exclusive rule: '!(has(self.defaults) && has(self.limits))' - message: Overrides and explicit defaults are mutually exclusive diff --git a/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml b/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml index 77de10a83..88b591b84 100644 --- a/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml +++ b/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml @@ -120,309 +120,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -509,307 +213,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching an - HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate used - to match requests to a given\naction. Multiple match - types are ANDed together, i.e. the match will\nevaluate - to true only if all conditions are satisfied.\n\n\nFor - example, the match below will match a HTTP request - only if its path\nstarts with `/foo` AND it contains - the `version: v1` header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t - \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and start - with '/' when type one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] || self.type - == 'RegularExpression' - - message: must only contain valid characters (matching - ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP query - param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -900,309 +310,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -1274,9 +388,6 @@ spec: - targetRef type: object x-kubernetes-validations: - - message: route selectors not supported when targeting a Gateway - rule: self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, - has(self.limits[x].routeSelectors)) - message: Implicit and explicit defaults are mutually exclusive rule: '!(has(self.defaults) && has(self.limits))' - message: Overrides and explicit defaults are mutually exclusive diff --git a/doc/rate-limiting.md b/doc/rate-limiting.md index 8398a982b..40dc06afc 100644 --- a/doc/rate-limiting.md +++ b/doc/rate-limiting.md @@ -30,7 +30,6 @@ The `RateLimitPolicy` spec includes, basically, two parts: Each limit definition includes: * A set of rate limits (`spec.limits..rates[]`) * (Optional) A set of dynamic counter qualifiers (`spec.limits..counters[]`) -* (Optional) A set of route selectors, to further qualify the specific routing rules when to activate the limit (`spec.limits..routeSelectors[]`) * (Optional) A set of additional dynamic conditions to activate the limit (`spec.limits..when[]`) The limit definitions (`limits`) can be declared at the top-level level of the spec (with the semantics of _defaults_) or alternatively within explicit `defaults` or `overrides` blocks. @@ -73,12 +72,6 @@ spec: # Check out Kuadrant RFC 0002 (https://github.com/Kuadrant/architecture/blob/main/rfcs/0002-well-known-attributes.md) to learn more about the Well-known Attributes that can be used in this field. counters: […] - # Further qualification of the scpecific HTTPRouteRules within the targeted HTTPRoute that should trigger the limit. - # Each element contains a HTTPRouteMatch object that will be used to select HTTPRouteRules that include at least one identical HTTPRouteMatch. - # The HTTPRouteMatch part does not have to be fully identical, but the what's stated in the selector must be identically stated in the HTTPRouteRule. - # Do not use it on RateLimitPolicies that target a Gateway. - routeSelectors: […] - # Additional dynamic conditions to trigger the limit. # Use it for filtering attributes not supported by HTTPRouteRule or with RateLimitPolicies that target a Gateway. # Check out Kuadrant RFC 0002 (https://github.com/Kuadrant/architecture/blob/main/rfcs/0002-well-known-attributes.md) to learn more about the Well-known Attributes that can be used in this field. @@ -103,8 +96,6 @@ spec: When a RateLimitPolicy targets a HTTPRoute, the policy is enforced to all traffic routed according to the rules and hostnames specified in the HTTPRoute, across all Gateways referenced in the `spec.parentRefs` field of the HTTPRoute. -The targeted HTTPRoute's rules and/or hostnames to which the policy must be enforced can be filtered to specific subsets, by specifying the [`routeSelectors`](reference/route-selectors.md#the-routeselectors-field) field of the limit definition. - Target a HTTPRoute by setting the `spec.targetRef` field of the RateLimitPolicy as follows: ```yaml @@ -195,7 +186,6 @@ Expected behavior: ### Limit definition A limit will be activated whenever a request comes in and the request matches: -- any of the route rules selected by the limit (via [`routeSelectors`](reference/route-selectors.md#the-routeselectors-field) or implicit "catch-all" selector), and - all of the `when` conditions specified in the limit. A limit can define: @@ -225,19 +215,20 @@ spec: unit: minute counters: - auth.identity.username - routeSelectors: - hostnames: - - api.toystore.com + when: + - selector: request.host + operator: eq + value: "api.toystore.com" "toystore-admin-unverified-users": rates: - limit: 250 duration: 1 unit: second - routeSelectors: - hostnames: - - admin.toystore.com when: + - selector: request.host + operator: eq + value: "admin.toystore.com" - selector: auth.identity.email_verified operator: eq value: "false" @@ -249,15 +240,9 @@ spec: | `admin.toystore.com` | 250rps | | `other.toystore.com` | 5000rps | -### Route selectors - -Route selectors allow targeting sections of a HTTPRoute, by specifying sets of HTTPRouteMatches and/or hostnames that make the policy controller look up within the HTTPRoute spec for compatible declarations, and select the corresponding HTTPRouteRules and hostnames, to then build conditions that activate the policy or policy rule. - -Check out [Route selectors](reference/route-selectors.md) for a full description, semantics and API reference. - #### `when` conditions -`when` conditions can be used to scope a limit (i.e. to filter the traffic to which a limit definition applies) without any coupling to the underlying network topology, i.e. without making direct references to HTTPRouteRules via [`routeSelectors`](reference/route-selectors.md#the-routeselectors-field). +`when` conditions can be used to scope a limit (i.e. to filter the traffic to which a limit definition applies) without any coupling to the underlying network topology, i.e. without making direct references to HTTPRouteRules. Use `when` conditions to conditionally activate limits based on attributes that cannot be expressed in the HTTPRoutes' `spec.hostnames` and `spec.rules.matches` fields, or in general in RateLimitPolicies that target a Gateway. diff --git a/doc/reference/ratelimitpolicy.md b/doc/reference/ratelimitpolicy.md index 6a6c98744..3b31c0d4c 100644 --- a/doc/reference/ratelimitpolicy.md +++ b/doc/reference/ratelimitpolicy.md @@ -37,7 +37,6 @@ |------------------|-----------------------------------------------------|:------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `rates` | [][RateLimit](#ratelimit) | No | List of rate limits associated with the limit definition | | `counters` | []String | No | List of rate limit counter qualifiers. Items must be a valid [Well-known attribute](https://github.com/Kuadrant/architecture/blob/main/rfcs/0002-well-known-attributes.md). Each distinct value resolved in the data plane starts a separate counter for each rate limit. | -| `routeSelectors` | [][RouteSelector](route-selectors.md#routeselector) | No | List of selectors of HTTPRouteRules whose matching rules activate the limit. At least one HTTPRouteRule must be selected to activate the limit. If omitted, all HTTPRouteRules of the targeted HTTPRoute activate the limit. Do not use it in policies targeting a Gateway. | | `when` | [][WhenCondition](#whencondition) | No | List of additional dynamic conditions (expressions) to activate the limit. All expression must evaluate to true for the limit to be applied. Use it for filtering attributes that cannot be expressed in the targeted HTTPRoute's `spec.hostnames` and `spec.rules.matches` fields, or when targeting a Gateway. | #### RateLimit diff --git a/doc/user-guides/simple-rl-for-app-developers.md b/doc/user-guides/simple-rl-for-app-developers.md index a978320fb..aaa7e862a 100644 --- a/doc/user-guides/simple-rl-for-app-developers.md +++ b/doc/user-guides/simple-rl-for-app-developers.md @@ -136,12 +136,10 @@ spec: - limit: 5 duration: 10 unit: second - routeSelectors: - - matches: # selects the 2nd HTTPRouteRule of the targeted route - - method: POST - path: - type: Exact - value: "/toys" + when: + - selector: request.method + operator: eq + value: "POST" EOF ``` diff --git a/examples/toystore/ratelimitpolicy_httproute.yaml b/examples/toystore/ratelimitpolicy_httproute.yaml index de10f7143..c11ac81f6 100644 --- a/examples/toystore/ratelimitpolicy_httproute.yaml +++ b/examples/toystore/ratelimitpolicy_httproute.yaml @@ -19,12 +19,6 @@ spec: - limit: 5 duration: 30 unit: second - routeSelectors: - - matches: - - path: - type: Exact - value: "/toy" - method: GET "admin-post-or-delete-toy-per-user": rates: diff --git a/pkg/rlptools/wasm/utils.go b/pkg/rlptools/wasm/utils.go index 85b7dec53..6192699e1 100644 --- a/pkg/rlptools/wasm/utils.go +++ b/pkg/rlptools/wasm/utils.go @@ -115,24 +115,10 @@ func conditionsFromLimit(limit *kuadrantv1beta3.Limit, route *gatewayapiv1.HTTPR routeConditions := make([]Condition, 0) - if len(limit.RouteSelectors) > 0 { - // build conditions from the rules selected by the route selectors - for idx := range limit.RouteSelectors { - routeSelector := limit.RouteSelectors[idx] - hostnamesForConditions := routeSelector.HostnamesForConditions(route) - for _, rule := range routeSelector.SelectRules(route) { - routeConditions = append(routeConditions, conditionsFromRule(rule, hostnamesForConditions)...) - } - } - if len(routeConditions) == 0 { - return nil, errors.New("cannot match any route rules, check for invalid route selectors in the policy") - } - } else { - // build conditions from all rules if no route selectors are defined - hostnamesForConditions := (&kuadrantv1beta3.RouteSelector{}).HostnamesForConditions(route) - for _, rule := range route.Spec.Rules { - routeConditions = append(routeConditions, conditionsFromRule(rule, hostnamesForConditions)...) - } + // build conditions from all rules + hostnamesForConditions := route.Spec.Hostnames + for _, rule := range route.Spec.Rules { + routeConditions = append(routeConditions, conditionsFromRule(rule, hostnamesForConditions)...) } if len(limit.When) == 0 { diff --git a/pkg/rlptools/wasm/utils_test.go b/pkg/rlptools/wasm/utils_test.go index 94222a514..933adaa97 100644 --- a/pkg/rlptools/wasm/utils_test.go +++ b/pkg/rlptools/wasm/utils_test.go @@ -118,198 +118,6 @@ func TestRules(t *testing.T) { }, }, }, - { - name: "RLP with route selector based on hostname", - rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ - "50rps-for-selected-hostnames": { - Rates: []kuadrantv1beta3.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { - Hostnames: []gatewayapiv1.Hostname{ - "*.example.com", - "myapp.apps.example.com", // ignored - }, - }, - }, - }, - }), - route: httpRoute, - expectedRules: []Rule{ - { - Conditions: []Condition{ - { - AllOf: []PatternExpression{ - { - Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), - Value: "/toy", - }, - { - Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta3.EqualOperator), - Value: "GET", - }, - { - Selector: "request.host", - Operator: PatternOperator(kuadrantv1beta3.EndsWithOperator), - Value: ".example.com", - }, - }, - }, - }, - Actions: []Action{ - { - Scope: "my-app/my-rlp", - ExtensionName: RateLimitPolicyExtensionName, - Data: []DataType{ - { - Value: &Static{ - Static: StaticSpec{ - Key: "limit.50rps_for_selected_hostnames__ac4044ab", - Value: "1", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "RLP with route selector based on http route matches (full match)", - rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ - "50rps-for-selected-route": { - Rates: []kuadrantv1beta3.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: &[]gatewayapiv1.PathMatchType{gatewayapiv1.PathMatchPathPrefix}[0], - Value: &[]string{"/toy"}[0], - }, - Method: &[]gatewayapiv1.HTTPMethod{"GET"}[0], - }, - }, - }, - }, - }, - }), - route: httpRoute, - expectedRules: []Rule{ - { - Conditions: []Condition{ - { - AllOf: []PatternExpression{ - { - Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), - Value: "/toy", - }, - { - Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta3.EqualOperator), - Value: "GET", - }, - }, - }, - }, - Actions: []Action{ - { - Scope: "my-app/my-rlp", - ExtensionName: RateLimitPolicyExtensionName, - Data: []DataType{ - { - Value: &Static{ - Static: StaticSpec{ - Key: "limit.50rps_for_selected_route__db289136", - Value: "1", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "RLP with route selector based on http route matches (partial match)", - rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ - "50rps-for-selected-path": { - Rates: []kuadrantv1beta3.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: &[]gatewayapiv1.PathMatchType{gatewayapiv1.PathMatchPathPrefix}[0], - Value: &[]string{"/toy"}[0], - }, - }, - }, - }, - }, - }, - }), - route: httpRoute, - expectedRules: []Rule{ - { - Conditions: []Condition{ - { - AllOf: []PatternExpression{ - { - Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), - Value: "/toy", - }, - { - Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta3.EqualOperator), - Value: "GET", - }, - }, - }, - }, - Actions: []Action{ - { - Scope: "my-app/my-rlp", - ExtensionName: RateLimitPolicyExtensionName, - Data: []DataType{ - { - Value: &Static{ - Static: StaticSpec{ - Key: "limit.50rps_for_selected_path__38eb97a4", - Value: "1", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "RLP with mismatching route selectors", - rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ - "50rps-for-non-existent-route": { - Rates: []kuadrantv1beta3.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Method: &[]gatewayapiv1.HTTPMethod{"POST"}[0], - }, - }, - }, - }, - }, - }), - route: httpRoute, - expectedRules: []Rule{}, - }, { name: "HTTPRouteRules without rule matches", rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ diff --git a/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go b/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go index 39497b3c5..4ffb86ce9 100644 --- a/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go +++ b/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go @@ -1594,44 +1594,4 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { Expect(k8sClient.Create(ctx, policy)).To(Succeed()) }, testTimeOut) }) - - Context("Route Selector Validation", func() { - const ( - gateWayRouteSelectorErrorMessage = "route selectors not supported when targeting a Gateway" - ) - - It("invalid usage of limit route selectors with a gateway targetRef", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { - policy.Spec.TargetRef.Kind = "Gateway" - policy.Spec.TargetRef.Name = "my-gw" - policy.Spec.RateLimitPolicyCommonSpec = kuadrantv1beta3.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta3.Limit{ - "l1": { - Rates: []kuadrantv1beta3.Rate{ - { - Limit: 1, Duration: 3, Unit: "minute", - }, - }, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { - Hostnames: []gatewayapiv1.Hostname{"*.foo.io"}, - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Value: ptr.To("/foo"), - }, - }, - }, - }, - }, - }, - }, - } - }) - - err := k8sClient.Create(ctx, policy) - Expect(err).To(Not(BeNil())) - Expect(strings.Contains(err.Error(), gateWayRouteSelectorErrorMessage)).To(BeTrue()) - }, testTimeOut) - }) }) diff --git a/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go b/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go index c1f8e639a..eefbd428b 100644 --- a/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go +++ b/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go @@ -239,19 +239,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { {Limit: 50, Duration: 1, Unit: kuadrantv1beta3.TimeUnit("minute")}, }, Counters: []kuadrantv1beta3.ContextSelector{"auth.identity.username"}, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { // selects the 1st HTTPRouteRule (i.e. get|post /toys*) for one of the hostnames - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/toys"), - }, - }, - }, - Hostnames: []gatewayapiv1.Hostname{"*.toystore.acme.com"}, - }, - }, When: []kuadrantv1beta3.WhenCondition{ { Selector: "auth.identity.group", @@ -265,18 +252,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { {Limit: 5, Duration: 1, Unit: kuadrantv1beta3.TimeUnit("minute")}, {Limit: 100, Duration: 12, Unit: kuadrantv1beta3.TimeUnit("hour")}, }, - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { // selects the 2nd HTTPRouteRule (i.e. /assets*) for all hostnames - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/assets"), - }, - }, - }, - }, - }, }, }, }, @@ -321,11 +296,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, - { - Selector: "request.host", - Operator: wasm.PatternOperator(kuadrantv1beta3.EndsWithOperator), - Value: ".toystore.acme.com", - }, { Selector: "auth.identity.group", Operator: wasm.PatternOperator(kuadrantv1beta3.NotEqualOperator), @@ -345,11 +315,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "POST", }, - { - Selector: "request.host", - Operator: wasm.PatternOperator(kuadrantv1beta3.EndsWithOperator), - Value: ".toystore.acme.com", - }, { Selector: "auth.identity.group", Operator: wasm.PatternOperator(kuadrantv1beta3.NotEqualOperator), @@ -615,18 +580,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { // does no select any HTTPRouteRule (i.e. GET /toys*) - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/other"), - }, - }, - }, - }, - }, Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), @@ -741,18 +694,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { // does no select any HTTPRouteRule (i.e. GET /otherPathRouteC*) - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/notmatchingpath"), - }, - }, - }, - }, - }, Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), @@ -2305,14 +2246,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - RouteSelectors: []kuadrantv1beta3.RouteSelector{ - { - // Route does not specify any hostname - // gateway's listener specifies *.gw.example.com - Hostnames: []gatewayapiv1.Hostname{"*.gw.example.com"}, - }, - }, - Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"),