Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions api/v1alpha1/clienttrafficpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions internal/gatewayapi/clienttrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Loading