From 550634227a2d62cd26292235dffda90406c0db85 Mon Sep 17 00:00:00 2001 From: Ardika Bagus Date: Sat, 20 Apr 2024 21:27:37 +0700 Subject: [PATCH] feat: PreserveExternalRequestID on ClientTrafficPolicy Signed-off-by: Ardika Bagus --- api/v1alpha1/clienttrafficpolicy_types.go | 7 +++ api/v1alpha1/zz_generated.deepcopy.go | 5 ++ ...y.envoyproxy.io_clienttrafficpolicies.yaml | 6 ++ internal/gatewayapi/clienttrafficpolicy.go | 5 +- .../clienttrafficpolicy-headers.in.yaml | 1 + .../clienttrafficpolicy-headers.out.yaml | 3 + internal/ir/xds.go | 5 ++ internal/xds/translator/listener.go | 3 +- .../headers-with-preserve-x-request-id.yaml | 32 ++++++++++ ...s-with-preserve-x-request-id.clusters.yaml | 34 ++++++++++ ...-with-preserve-x-request-id.endpoints.yaml | 24 +++++++ ...-with-preserve-x-request-id.listeners.yaml | 63 +++++++++++++++++++ ...ers-with-preserve-x-request-id.routes.yaml | 28 +++++++++ site/content/en/latest/api/extension_types.md | 1 + 14 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 619bbeb50f3..b95292abdd3 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -104,6 +104,13 @@ type HeaderSettings struct { // is encountered. The default action is to reject the request. // +optional WithUnderscoresAction *WithUnderscoresAction `json:"withUnderscoresAction,omitempty"` + + // PreserveExternalRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge + // (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. + // It defaults to false. + // + // +optional + PreserveExternalRequestID *bool `json:"preserveExternalRequestID,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 7dcd9227d55..b97285fbf43 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -2183,6 +2183,11 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = new(WithUnderscoresAction) **out = **in } + if in.PreserveExternalRequestID != nil { + in, out := &in.PreserveExternalRequestID, &out.PreserveExternalRequestID + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 000886cf656..3638a93b36a 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -150,6 +150,12 @@ spec: EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests and responses. type: boolean + preserveExternalRequestID: + description: |- + PreserveExternalRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge + (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. + It defaults to false. + type: boolean withUnderscoresAction: description: |- WithUnderscoresAction configures the action to take when an HTTP header with underscores diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index c8f4ca7ed8f..65730737e07 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -539,8 +539,9 @@ func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, http return } httpIR.Headers = &ir.HeaderSettings{ - EnableEnvoyHeaders: ptr.Deref(headerSettings.EnableEnvoyHeaders, false), - WithUnderscoresAction: ir.WithUnderscoresAction(ptr.Deref(headerSettings.WithUnderscoresAction, egv1a1.WithUnderscoresActionRejectRequest)), + EnableEnvoyHeaders: ptr.Deref(headerSettings.EnableEnvoyHeaders, false), + WithUnderscoresAction: ir.WithUnderscoresAction(ptr.Deref(headerSettings.WithUnderscoresAction, egv1a1.WithUnderscoresActionRejectRequest)), + PreserveExternalRequestID: ptr.Deref(headerSettings.PreserveExternalRequestID, false), } } diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml index 136450f2abd..903261f1d39 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml @@ -8,6 +8,7 @@ clientTrafficPolicies: headers: enableEnvoyHeaders: true withUnderscoresAction: Allow + preserveExternalRequestID: true targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml index 4a71a59d6d0..39fdf87d7a7 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml @@ -8,6 +8,7 @@ clientTrafficPolicies: spec: headers: enableEnvoyHeaders: true + preserveXRequestID: true withUnderscoresAction: Allow targetRef: group: gateway.networking.k8s.io @@ -130,6 +131,7 @@ xdsIR: - address: 0.0.0.0 headers: enableEnvoyHeaders: true + preserveExternalRequestID: true withUnderscoresAction: Allow hostnames: - '*' @@ -142,6 +144,7 @@ xdsIR: - address: 0.0.0.0 headers: enableEnvoyHeaders: true + preserveExternalRequestID: true withUnderscoresAction: Allow hostnames: - '*' diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 7db99e3b6e8..c9742c69a9f 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -406,6 +406,11 @@ type HeaderSettings struct { // is encountered. The default action is to reject the request. // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-enum-config-core-v3-httpprotocoloptions-headerswithunderscoresaction WithUnderscoresAction WithUnderscoresAction `json:"withUnderscoresAction,omitempty" yaml:"withUnderscoresAction,omitempty"` + + // PreserveExternalRequestID configures whether Envoy will keep the x-request-id header if passed for a request that is edge + // (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. + // It defaults to false. + PreserveExternalRequestID bool `json:"preserveExternalRequestID,omitempty" yaml:"preserveExternalRequestID,omitempty"` } // ClientTimeout sets the timeout configuration for downstream connections diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index f909fd3ff8c..a0a7e564754 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -256,7 +256,8 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis CommonHttpProtocolOptions: &corev3.HttpProtocolOptions{ HeadersWithUnderscoresAction: buildHeadersWithUnderscoresAction(irListener.Headers), }, - Tracing: hcmTracing, + Tracing: hcmTracing, + PreserveExternalRequestId: ptr.Deref(irListener.Headers, ir.HeaderSettings{}).PreserveExternalRequestID, } if irListener.Timeout != nil && irListener.Timeout.HTTP != nil { diff --git a/internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml b/internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml new file mode 100644 index 00000000000..a75c7edac30 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml @@ -0,0 +1,32 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 8081 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 8081 + headers: + preserveExternalRequestID: true +- name: "second-listener" + address: "0.0.0.0" + port: 8082 + hostnames: + - "*" + routes: + - name: "second-route" + hostname: "*" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "2.2.2.2" + port: 8082 + diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml new file mode 100755 index 00000000000..d65e267ad7d --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml @@ -0,0 +1,34 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml new file mode 100755 index 00000000000..9ad09dd91b0 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml @@ -0,0 +1,24 @@ +- 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 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 8082 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml new file mode 100644 index 00000000000..64401c87014 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml @@ -0,0 +1,63 @@ +- address: + socketAddress: + address: 0.0.0.0 + 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: {} + 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 + normalizePath: true + preserveExternalRequestId: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: first-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8082 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: {} + 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 + normalizePath: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: second-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml new file mode 100755 index 00000000000..ff93cfff360 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml @@ -0,0 +1,28 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 5756c6df0cc..5e97bb37b84 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1614,6 +1614,7 @@ _Appears in:_ | --- | --- | --- | --- | | `enableEnvoyHeaders` | _boolean_ | false | EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests
and responses. | | `withUnderscoresAction` | _[WithUnderscoresAction](#withunderscoresaction)_ | false | WithUnderscoresAction configures the action to take when an HTTP header with underscores
is encountered. The default action is to reject the request. | +| `preserveExternalRequestID` | _boolean_ | false | PreserveExternalRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge
(Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour.
It defaults to false. | #### HealthCheck