Skip to content

Commit 265fdeb

Browse files
sboulkouralbsga4
andauthored
api: add host normalization to ClientTrafficPolicy (#9115)
* feat(api): add host normalization to ClientTrafficPolicy Add a new `host` section to `ClientTrafficPolicy` to normalize the Host/Authority header on the listener, parallel to the existing `path` section: - `host.stripTrailingHostDot` maps to Envoy `strip_trailing_host_dot`, so requests with `Host: example.com.` match routes for `example.com` (NGINX-parity behavior). Both were previously only achievable via fragile EnvoyPatchPolicy. This change is split out of #8825 per maintainer review, which scoped that PR to `maxRequestHeaderBytes`. Fixes #8832 Co-authored-by: albsga4 <asalvador@newrelic.com> Signed-off-by: Salim Boulkour <salim.boulkour@algolia.com>
1 parent f4acd4f commit 265fdeb

26 files changed

Lines changed: 912 additions & 0 deletions

api/v1alpha1/clienttrafficpolicy_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ type HeaderSettings struct {
183183
//
184184
// +optional
185185
LateResponseHeaders *HTTPHeaderFilter `json:"lateResponseHeaders,omitempty"`
186+
187+
// Host enables managing how the Host/Authority header set by clients can be normalized.
188+
//
189+
// +optional
190+
Host *HostSettings `json:"host,omitempty"`
186191
}
187192

188193
// WithUnderscoresAction configures the action to take when an HTTP header with underscores

api/v1alpha1/hostsettings_types.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright Envoy Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
package v1alpha1
7+
8+
// HostSettings provides settings that manage how the incoming Host/Authority header
9+
// set by clients is normalized.
10+
type HostSettings struct {
11+
// StripTrailingHostDot determines if the trailing dot of the host should be removed
12+
// from the Host/Authority header before any processing of the request.
13+
// This affects the upstream host header as well. Without this option, incoming requests
14+
// with host "example.com." will not match routes with domains set to "example.com".
15+
// When the host includes a port (for example "example.com.:443"), only the trailing dot
16+
// from the host section is stripped, leaving the port as-is ("example.com:443").
17+
// Defaults to false.
18+
//
19+
// +optional
20+
StripTrailingHostDot *bool `json:"stripTrailingHostDot,omitempty"`
21+
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,21 @@ spec:
499499
EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests
500500
and responses.
501501
type: boolean
502+
host:
503+
description: Host enables managing how the Host/Authority header
504+
set by clients can be normalized.
505+
properties:
506+
stripTrailingHostDot:
507+
description: |-
508+
StripTrailingHostDot determines if the trailing dot of the host should be removed
509+
from the Host/Authority header before any processing of the request.
510+
This affects the upstream host header as well. Without this option, incoming requests
511+
with host "example.com." will not match routes with domains set to "example.com".
512+
When the host includes a port (for example "example.com.:443"), only the trailing dot
513+
from the host section is stripped, leaving the port as-is ("example.com:443").
514+
Defaults to false.
515+
type: boolean
516+
type: object
502517
lateResponseHeaders:
503518
description: LateResponseHeaders defines settings for global response
504519
header modification.

charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,21 @@ spec:
498498
EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests
499499
and responses.
500500
type: boolean
501+
host:
502+
description: Host enables managing how the Host/Authority header
503+
set by clients can be normalized.
504+
properties:
505+
stripTrailingHostDot:
506+
description: |-
507+
StripTrailingHostDot determines if the trailing dot of the host should be removed
508+
from the Host/Authority header before any processing of the request.
509+
This affects the upstream host header as well. Without this option, incoming requests
510+
with host "example.com." will not match routes with domains set to "example.com".
511+
When the host includes a port (for example "example.com.:443"), only the trailing dot
512+
from the host section is stripped, leaving the port as-is ("example.com:443").
513+
Defaults to false.
514+
type: boolean
515+
type: object
501516
lateResponseHeaders:
502517
description: LateResponseHeaders defines settings for global response
503518
header modification.

internal/gatewayapi/clienttrafficpolicy.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,12 @@ func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, http
923923
}
924924
}
925925

926+
if headerSettings.Host != nil && headerSettings.Host.StripTrailingHostDot != nil {
927+
httpIR.Host = &ir.HostSettings{
928+
StripTrailingHostDot: *headerSettings.Host.StripTrailingHostDot,
929+
}
930+
}
931+
926932
var errs error
927933

928934
if headerSettings.EarlyRequestHeaders != nil {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
clientTrafficPolicies:
2+
- apiVersion: gateway.envoyproxy.io/v1alpha1
3+
kind: ClientTrafficPolicy
4+
metadata:
5+
namespace: envoy-gateway
6+
name: target-gateway-1
7+
spec:
8+
headers:
9+
host: {}
10+
targetRef:
11+
group: gateway.networking.k8s.io
12+
kind: Gateway
13+
name: gateway-1
14+
gateways:
15+
- apiVersion: gateway.networking.k8s.io/v1
16+
kind: Gateway
17+
metadata:
18+
namespace: envoy-gateway
19+
name: gateway-1
20+
spec:
21+
gatewayClassName: envoy-gateway-class
22+
listeners:
23+
- name: http-1
24+
protocol: HTTP
25+
port: 80
26+
allowedRoutes:
27+
namespaces:
28+
from: Same
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
clientTrafficPolicies:
2+
- apiVersion: gateway.envoyproxy.io/v1alpha1
3+
kind: ClientTrafficPolicy
4+
metadata:
5+
name: target-gateway-1
6+
namespace: envoy-gateway
7+
spec:
8+
headers:
9+
host: {}
10+
targetRef:
11+
group: gateway.networking.k8s.io
12+
kind: Gateway
13+
name: gateway-1
14+
status:
15+
ancestors:
16+
- ancestorRef:
17+
group: gateway.networking.k8s.io
18+
kind: Gateway
19+
name: gateway-1
20+
namespace: envoy-gateway
21+
conditions:
22+
- lastTransitionTime: null
23+
message: Policy has been accepted.
24+
reason: Accepted
25+
status: "True"
26+
type: Accepted
27+
- lastTransitionTime: null
28+
message: spec.targetRef is deprecated, use spec.targetRefs instead
29+
reason: DeprecatedField
30+
status: "True"
31+
type: Warning
32+
controllerName: gateway.envoyproxy.io/gatewayclass-controller
33+
gateways:
34+
- apiVersion: gateway.networking.k8s.io/v1
35+
kind: Gateway
36+
metadata:
37+
name: gateway-1
38+
namespace: envoy-gateway
39+
spec:
40+
gatewayClassName: envoy-gateway-class
41+
listeners:
42+
- allowedRoutes:
43+
namespaces:
44+
from: Same
45+
name: http-1
46+
port: 80
47+
protocol: HTTP
48+
status:
49+
listeners:
50+
- attachedRoutes: 0
51+
conditions:
52+
- lastTransitionTime: null
53+
message: Sending translated listener configuration to the data plane
54+
reason: Programmed
55+
status: "True"
56+
type: Programmed
57+
- lastTransitionTime: null
58+
message: Listener has been successfully translated
59+
reason: Accepted
60+
status: "True"
61+
type: Accepted
62+
- lastTransitionTime: null
63+
message: Listener references have been resolved
64+
reason: ResolvedRefs
65+
status: "True"
66+
type: ResolvedRefs
67+
name: http-1
68+
supportedKinds:
69+
- group: gateway.networking.k8s.io
70+
kind: HTTPRoute
71+
- group: gateway.networking.k8s.io
72+
kind: GRPCRoute
73+
infraIR:
74+
envoy-gateway/gateway-1:
75+
proxy:
76+
listeners:
77+
- name: envoy-gateway/gateway-1/http-1
78+
ports:
79+
- containerPort: 10080
80+
name: http-80
81+
protocol: HTTP
82+
servicePort: 80
83+
metadata:
84+
labels:
85+
gateway.envoyproxy.io/owning-gateway-name: gateway-1
86+
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
87+
ownerReference:
88+
kind: GatewayClass
89+
name: envoy-gateway-class
90+
name: envoy-gateway/gateway-1
91+
namespace: envoy-gateway-system
92+
xdsIR:
93+
envoy-gateway/gateway-1:
94+
accessLog:
95+
json:
96+
- path: /dev/stdout
97+
globalResources:
98+
proxyServiceCluster:
99+
metadata:
100+
kind: Service
101+
name: envoy-envoy-gateway-gateway-1-196ae069
102+
namespace: envoy-gateway-system
103+
sectionName: "8080"
104+
name: envoy-gateway/gateway-1
105+
settings:
106+
- addressType: IP
107+
endpoints:
108+
- host: 7.6.5.4
109+
port: 8080
110+
zone: zone1
111+
metadata:
112+
kind: Service
113+
name: envoy-envoy-gateway-gateway-1-196ae069
114+
namespace: envoy-gateway-system
115+
sectionName: "8080"
116+
name: envoy-gateway/gateway-1
117+
protocol: TCP
118+
http:
119+
- address: 0.0.0.0
120+
externalPort: 80
121+
headers:
122+
withUnderscoresAction: RejectRequest
123+
hostnames:
124+
- '*'
125+
metadata:
126+
kind: Gateway
127+
name: gateway-1
128+
namespace: envoy-gateway
129+
sectionName: http-1
130+
name: envoy-gateway/gateway-1/http-1
131+
path:
132+
escapedSlashesAction: UnescapeAndRedirect
133+
mergeSlashes: true
134+
port: 10080
135+
readyListener:
136+
address: 0.0.0.0
137+
ipFamily: IPv4
138+
path: /ready
139+
port: 19003
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
clientTrafficPolicies:
2+
- apiVersion: gateway.envoyproxy.io/v1alpha1
3+
kind: ClientTrafficPolicy
4+
metadata:
5+
namespace: envoy-gateway
6+
name: target-gateway-1
7+
spec:
8+
headers:
9+
host:
10+
stripTrailingHostDot: true
11+
targetRef:
12+
group: gateway.networking.k8s.io
13+
kind: Gateway
14+
name: gateway-1
15+
gateways:
16+
- apiVersion: gateway.networking.k8s.io/v1
17+
kind: Gateway
18+
metadata:
19+
namespace: envoy-gateway
20+
name: gateway-1
21+
spec:
22+
gatewayClassName: envoy-gateway-class
23+
listeners:
24+
- name: http-1
25+
protocol: HTTP
26+
port: 80
27+
allowedRoutes:
28+
namespaces:
29+
from: Same

0 commit comments

Comments
 (0)