diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 202a6954a8..cae9efbbf0 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -6,6 +6,7 @@ package v1alpha1 import ( + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -188,6 +189,21 @@ type HeaderSettings struct { // // +optional Host *HostSettings `json:"host,omitempty"` + + // MaxRequestHeaderLimit provides configuration for the maximum size of the + // request headers allowed for incoming connections, mapping to the Envoy + // `max_request_headers_kb` HTTP connection manager setting. Requests whose + // headers exceed this limit receive a 431 (Request Header Fields Too Large) + // response. The value is rounded up to the nearest KiB, must be at least 1Ki, + // and cannot exceed 8192Ki (the maximum Envoy supports). + // For example, 60Ki, 96Ki, 128Ki etc. + // Note that when the suffix is not provided, the value is interpreted as bytes. + // Default: 60Ki bytes. + // + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" + // +optional + MaxRequestHeaderLimit *resource.Quantity `json:"maxRequestHeaderLimit,omitempty"` } // WithUnderscoresAction configures the action to take when an HTTP header with underscores diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index b966f945df..6ab6ee2ef3 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -4977,6 +4977,11 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = new(HostSettings) (*in).DeepCopyInto(*out) } + if in.MaxRequestHeaderLimit != nil { + in, out := &in.MaxRequestHeaderLimit, &out.MaxRequestHeaderLimit + x := (*in).DeepCopy() + *out = &x + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index b873c582aa..0b56f3e259 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -748,6 +748,24 @@ spec: - name x-kubernetes-list-type: map type: object + maxRequestHeaderLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + MaxRequestHeaderLimit provides configuration for the maximum size of the + request headers allowed for incoming connections, mapping to the Envoy + `max_request_headers_kb` HTTP connection manager setting. Requests whose + headers exceed this limit receive a 431 (Request Header Fields Too Large) + response. The value is rounded up to the nearest KiB, must be at least 1Ki, + and cannot exceed 8192Ki (the maximum Envoy supports). + For example, 60Ki, 96Ki, 128Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + Default: 60Ki bytes. + x-kubernetes-int-or-string: true preserveXRequestID: description: |- PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 5b73c4161a..f6ed8c44a5 100644 --- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -747,6 +747,24 @@ spec: - name x-kubernetes-list-type: map type: object + maxRequestHeaderLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + MaxRequestHeaderLimit provides configuration for the maximum size of the + request headers allowed for incoming connections, mapping to the Envoy + `max_request_headers_kb` HTTP connection manager setting. Requests whose + headers exceed this limit receive a 431 (Request Header Fields Too Large) + response. The value is rounded up to the nearest KiB, must be at least 1Ki, + and cannot exceed 8192Ki (the maximum Envoy supports). + For example, 60Ki, 96Ki, 128Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + Default: 60Ki bytes. + x-kubernetes-int-or-string: true preserveXRequestID: description: |- PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index f6daf2a3ae..697ba63ec7 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -1001,6 +1001,10 @@ func translateClientIPDetection(clientIPDetection *egv1a1.ClientIPDetectionSetti httpIR.ClientIPDetection = (*ir.ClientIPDetectionSettings)(clientIPDetection) } +// maxRequestHeaderLimitKB is the maximum value (in KiB) that Envoy supports for +// the HTTP connection manager max_request_headers_kb setting. +const maxRequestHeaderLimitKB = 8192 + func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, httpIR *ir.HTTPListener) error { if headerSettings == nil { return nil @@ -1035,6 +1039,23 @@ func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, http var errs error + if headerSettings.MaxRequestHeaderLimit != nil { + // Envoy's max_request_headers_kb is expressed in KiB, so convert the + // byte quantity and round up to the nearest KiB. + bytes, ok := headerSettings.MaxRequestHeaderLimit.AsInt64() + switch { + case !ok || bytes < 1024: + errs = errors.Join(errs, fmt.Errorf("MaxRequestHeaderLimit value %s must be at least 1Ki", headerSettings.MaxRequestHeaderLimit.String())) + default: + kb := (bytes + 1023) / 1024 + if kb > maxRequestHeaderLimitKB { + errs = errors.Join(errs, fmt.Errorf("MaxRequestHeaderLimit value %s exceeds the maximum of %dKi", headerSettings.MaxRequestHeaderLimit.String(), maxRequestHeaderLimitKB)) + } else { + httpIR.Headers.MaxRequestHeadersKB = ptr.To(uint32(kb)) + } + } + } + if headerSettings.EarlyRequestHeaders != nil { headersToAdd, headersToRemove, removeOnMatch, err := translateHeaderModifier(headerSettings.EarlyRequestHeaders, "EarlyRequestHeaders") if err != nil { diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit-with-error.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit-with-error.in.yaml new file mode 100644 index 0000000000..b60c4a74ec --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit-with-error.in.yaml @@ -0,0 +1,29 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + generation: 10 + spec: + headers: + maxRequestHeaderLimit: "512" + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit-with-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit-with-error.out.yaml new file mode 100644 index 0000000000..c2df66e38b --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit-with-error.out.yaml @@ -0,0 +1,142 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + generation: 10 + name: target-gateway-1 + namespace: envoy-gateway + spec: + headers: + maxRequestHeaderLimit: "512" + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: 'Headers: MaxRequestHeaderLimit value 512 must be at least 1Ki.' + observedGeneration: 10 + reason: Invalid + status: "False" + type: Accepted + - lastTransitionTime: null + message: spec.targetRef is deprecated, use spec.targetRefs instead + observedGeneration: 10 + reason: DeprecatedField + status: "True" + type: Warning + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + headers: + withUnderscoresAction: RejectRequest + hostnames: + - '*' + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit.in.yaml new file mode 100644 index 0000000000..05134ef8ce --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit.in.yaml @@ -0,0 +1,29 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + generation: 10 + spec: + headers: + maxRequestHeaderLimit: 96Ki + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit.out.yaml new file mode 100644 index 0000000000..ded993ac32 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-max-request-header-limit.out.yaml @@ -0,0 +1,143 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + generation: 10 + name: target-gateway-1 + namespace: envoy-gateway + spec: + headers: + maxRequestHeaderLimit: 96Ki + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + observedGeneration: 10 + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: spec.targetRef is deprecated, use spec.targetRefs instead + observedGeneration: 10 + reason: DeprecatedField + status: "True" + type: Warning + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + headers: + maxRequestHeadersKB: 96 + withUnderscoresAction: RejectRequest + hostnames: + - '*' + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/ir/xds.go b/internal/ir/xds.go index a1cf02a509..7a94f45960 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -951,6 +951,10 @@ type HeaderSettings struct { // LateRemoveResponseHeadersOnMatch defines header name matchers that would remove headers after envoy response processing. LateRemoveResponseHeadersOnMatch []*StringMatch `json:"lateRemoveResponseHeadersOnMatch,omitempty" yaml:"lateRemoveResponseHeadersOnMatch,omitempty"` + + // MaxRequestHeadersKB defines the maximum request headers size in KiB allowed for incoming connections. + // Maps to the Envoy `max_request_headers_kb` HTTP connection manager setting. + MaxRequestHeadersKB *uint32 `json:"maxRequestHeadersKB,omitempty" yaml:"maxRequestHeadersKB,omitempty"` } // ClientTimeout sets the timeout configuration for downstream connections diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 252d73c925..ae7b305c58 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -2822,6 +2822,11 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { } } } + if in.MaxRequestHeadersKB != nil { + in, out := &in.MaxRequestHeadersKB, &out.MaxRequestHeadersKB + *out = new(uint32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index be3e2eb136..48c038a976 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -406,6 +406,11 @@ func (t *Translator) addHCMToXDSListener( mgr.StripTrailingHostDot = irListener.Host.StripTrailingHostDot } + // Set the maximum request headers size if configured. + if h := irListener.Headers; h != nil && h.MaxRequestHeadersKB != nil { + mgr.MaxRequestHeadersKb = wrapperspb.UInt32(*h.MaxRequestHeadersKB) + } + // Set the :scheme header to match the upstream transport protocol (http/https) if configured. // This ensures the correct scheme is sent to backends using TLS when enabled. if irListener.MatchBackendScheme { diff --git a/internal/xds/translator/testdata/in/xds-ir/max-request-headers-kb.yaml b/internal/xds/translator/testdata/in/xds-ir/max-request-headers-kb.yaml new file mode 100644 index 0000000000..4043ce9b6d --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/max-request-headers-kb.yaml @@ -0,0 +1,18 @@ +http: + - name: "first-listener" + address: "::" + port: 8081 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 8081 + name: "first-route-dest/backend/0" + headers: + maxRequestHeadersKB: 96 diff --git a/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.clusters.yaml new file mode 100644 index 0000000000..886a7d9f6c --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.clusters.yaml @@ -0,0 +1,23 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + ignoreHealthOnHostRemoval: true + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: first-route-dest + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.endpoints.yaml new file mode 100644 index 0000000000..79a5266441 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 8081 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.listeners.yaml new file mode 100644 index 0000000000..96486484ae --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.listeners.yaml @@ -0,0 +1,34 @@ +- address: + socketAddress: + address: '::' + portValue: 8081 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + maxRequestHeadersKb: 96 + normalizePath: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-8081 + useRemoteAddress: true + name: first-listener + maxConnectionsToAcceptPerSocketEvent: 1 + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.routes.yaml new file mode 100644 index 0000000000..0b5b4bee7b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/max-request-headers-kb.routes.yaml @@ -0,0 +1,14 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/release-notes/current/new_features/5368-max-request-header-limit-clienttrafficpolicy.md b/release-notes/current/new_features/5368-max-request-header-limit-clienttrafficpolicy.md new file mode 100644 index 0000000000..2a96e95523 --- /dev/null +++ b/release-notes/current/new_features/5368-max-request-header-limit-clienttrafficpolicy.md @@ -0,0 +1 @@ +Added a `maxRequestHeaderLimit` field under `ClientTrafficPolicy`'s `headers` to configure the maximum request header size (Envoy's `max_request_headers_kb`) without an EnvoyPatchPolicy. The value is a Quantity rounded up to the nearest KiB, must be at least 1Ki, and cannot exceed 8192Ki. diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 12e60a35cc..4217fbaba3 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -3421,6 +3421,7 @@ _Appears in:_ | `earlyRequestHeaders` | _[HTTPHeaderFilter](#httpheaderfilter)_ | false | | EarlyRequestHeaders defines settings for early request header modification, before envoy performs
routing, tracing and built-in header manipulation. | | `lateResponseHeaders` | _[HTTPHeaderFilter](#httpheaderfilter)_ | false | | LateResponseHeaders defines settings for global response header modification. | | `host` | _[HostSettings](#hostsettings)_ | false | | Host enables managing how the Host/Authority header set by clients can be normalized. | +| `maxRequestHeaderLimit` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#quantity-resource-api)_ | false | | MaxRequestHeaderLimit provides configuration for the maximum size of the
request headers allowed for incoming connections, mapping to the Envoy
`max_request_headers_kb` HTTP connection manager setting. Requests whose
headers exceed this limit receive a 431 (Request Header Fields Too Large)
response. The value is rounded up to the nearest KiB, must be at least 1Ki,
and cannot exceed 8192Ki (the maximum Envoy supports).
For example, 60Ki, 96Ki, 128Ki etc.
Note that when the suffix is not provided, the value is interpreted as bytes.
Default: 60Ki bytes. | #### HealthCheck