diff --git a/api/v1alpha1/authorization_types.go b/api/v1alpha1/authorization_types.go index 41b1c3890d9..0ba7cf9c8fe 100644 --- a/api/v1alpha1/authorization_types.go +++ b/api/v1alpha1/authorization_types.go @@ -82,7 +82,7 @@ type Principal struct { // // The client IP is inferred from the X-Forwarded-For header, a custom header, // or the proxy protocol. - // You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in + // You can use the `ClientIPDetection` or the `ProxyProtocol` field in // the `ClientTrafficPolicy` to configure how the client IP is detected. // // +optional diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 799386f4188..649b4b635f2 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -56,8 +56,17 @@ type ClientTrafficPolicySpec struct { // Note Proxy Protocol must be present when this field is set, else the connection // is closed. // + // Deprecated: Use ProxyProtocol instead. + // // +optional EnableProxyProtocol *bool `json:"enableProxyProtocol,omitempty"` + // ProxyProtocol configures the Proxy Protocol settings. When configured, + // the Proxy Protocol header will be interpreted and the Client Address + // will be added into the X-Forwarded-For header. + // If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. + // + // +optional + ProxyProtocol *ProxyProtocolSettings `json:"proxyProtocol,omitempty"` // ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. // // +optional @@ -344,6 +353,25 @@ type HealthCheckSettings struct { Path string `json:"path"` } +// ProxyProtocolSettings configures the Proxy Protocol settings. When configured, +// the Proxy Protocol header will be interpreted and the Client Address +// will be added into the X-Forwarded-For header. +// If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. +// +// +kubebuilder:validation:MinProperties=0 +type ProxyProtocolSettings struct { + // Optional allows requests without a Proxy Protocol header to be proxied. + // If set to true, the listener will accept requests without a Proxy Protocol header. + // If set to false, the listener will reject requests without a Proxy Protocol header. + // If not set, the default behavior is to reject requests without a Proxy Protocol header. + // Warning: Optional breaks conformance with the specification. Only enable if ALL traffic to the listener comes from a trusted source. + // For more information on security implications, see haproxy.org/download/2.1/doc/proxy-protocol.txt + // + // + // +optional + Optional *bool `json:"optional,omitempty"` +} + //+kubebuilder:object:root=true // ClientTrafficPolicyList contains a list of ClientTrafficPolicy resources. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index e4aff858b2d..a6112dddd52 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1090,6 +1090,11 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(bool) **out = **in } + if in.ProxyProtocol != nil { + in, out := &in.ProxyProtocol, &out.ProxyProtocol + *out = new(ProxyProtocolSettings) + (*in).DeepCopyInto(*out) + } if in.ClientIPDetection != nil { in, out := &in.ClientIPDetection, &out.ClientIPDetection *out = new(ClientIPDetectionSettings) @@ -5440,6 +5445,26 @@ func (in *ProxyProtocol) DeepCopy() *ProxyProtocol { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyProtocolSettings) DeepCopyInto(out *ProxyProtocolSettings) { + *out = *in + if in.Optional != nil { + in, out := &in.Optional, &out.Optional + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyProtocolSettings. +func (in *ProxyProtocolSettings) DeepCopy() *ProxyProtocolSettings { + if in == nil { + return nil + } + out := new(ProxyProtocolSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyTelemetry) DeepCopyInto(out *ProxyTelemetry) { *out = *in 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 0f1078b7af1..311faf9cef9 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 @@ -182,6 +182,8 @@ spec: Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. + + Deprecated: Use ProxyProtocol instead. type: boolean headers: description: HeaderSettings provides configuration for header management. @@ -514,6 +516,24 @@ spec: - UnescapeAndRedirect type: string type: object + proxyProtocol: + description: |- + ProxyProtocol configures the Proxy Protocol settings. When configured, + the Proxy Protocol header will be interpreted and the Client Address + will be added into the X-Forwarded-For header. + If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. + minProperties: 0 + properties: + optional: + description: |- + Optional allows requests without a Proxy Protocol header to be proxied. + If set to true, the listener will accept requests without a Proxy Protocol header. + If set to false, the listener will reject requests without a Proxy Protocol header. + If not set, the default behavior is to reject requests without a Proxy Protocol header. + Warning: Optional breaks conformance with the specification. Only enable if ALL traffic to the listener comes from a trusted source. + For more information on security implications, see haproxy.org/download/2.1/doc/proxy-protocol.txt + type: boolean + type: object targetRef: description: |- TargetRef is the name of the resource this policy is being attached to. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index fb947fca1ae..77fee40bf84 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -253,7 +253,7 @@ spec: The client IP is inferred from the X-Forwarded-For header, a custom header, or the proxy protocol. - You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in + You can use the `ClientIPDetection` or the `ProxyProtocol` field in the `ClientTrafficPolicy` to configure how the client IP is detected. items: description: |- 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 bf1c7e98a1c..85e91f58825 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -181,6 +181,8 @@ spec: Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. + + Deprecated: Use ProxyProtocol instead. type: boolean headers: description: HeaderSettings provides configuration for header management. @@ -513,6 +515,24 @@ spec: - UnescapeAndRedirect type: string type: object + proxyProtocol: + description: |- + ProxyProtocol configures the Proxy Protocol settings. When configured, + the Proxy Protocol header will be interpreted and the Client Address + will be added into the X-Forwarded-For header. + If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. + minProperties: 0 + properties: + optional: + description: |- + Optional allows requests without a Proxy Protocol header to be proxied. + If set to true, the listener will accept requests without a Proxy Protocol header. + If set to false, the listener will reject requests without a Proxy Protocol header. + If not set, the default behavior is to reject requests without a Proxy Protocol header. + Warning: Optional breaks conformance with the specification. Only enable if ALL traffic to the listener comes from a trusted source. + For more information on security implications, see haproxy.org/download/2.1/doc/proxy-protocol.txt + type: boolean + type: object targetRef: description: |- TargetRef is the name of the resource this policy is being attached to. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index f1a4bf57abc..04f43549c7c 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -252,7 +252,7 @@ spec: The client IP is inferred from the X-Forwarded-For header, a custom header, or the proxy protocol. - You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in + You can use the `ClientIPDetection` or the `ProxyProtocol` field in the `ClientTrafficPolicy` to configure how the client IP is detected. items: description: |- diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index a24c34d6a28..e634dab4fca 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -392,12 +392,12 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie // HTTP and TCP listeners can both be configured by common fields below. var ( - keepalive *ir.TCPKeepalive - connection *ir.ClientConnection - tlsConfig *ir.TLSConfig - enableProxyProtocol bool - timeout *ir.ClientTimeout - err, errs error + keepalive *ir.TCPKeepalive + connection *ir.ClientConnection + tlsConfig *ir.TLSConfig + proxyProtocol *ir.ProxyProtocolSettings + timeout *ir.ClientTimeout + err, errs error ) // Build common IR shared by HTTP and TCP listeners, return early if some field is invalid. @@ -416,7 +416,18 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie } // Translate Proxy Protocol - enableProxyProtocol = ptr.Deref(policy.Spec.EnableProxyProtocol, false) + if policy.Spec.ProxyProtocol != nil { + // ProxyProtocol field takes precedence when configured + // Even if it's an empty object {}, we should enable proxy protocol with default settings + proxyProtocol = &ir.ProxyProtocolSettings{ + Optional: ptr.Deref(policy.Spec.ProxyProtocol.Optional, false), + } + } else if ptr.Deref(policy.Spec.EnableProxyProtocol, false) { + // Fallback to legacy EnableProxyProtocol field + proxyProtocol = &ir.ProxyProtocolSettings{ + Optional: false, // Default behavior for legacy field + } + } // Translate Client Timeout Settings timeout, err = buildClientTimeout(policy.Spec.Timeout) @@ -492,7 +503,7 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie httpIR.TCPKeepalive = keepalive httpIR.Connection = connection - httpIR.EnableProxyProtocol = enableProxyProtocol + httpIR.ProxyProtocol = proxyProtocol httpIR.Timeout = timeout httpIR.TLS = tlsConfig } @@ -515,7 +526,7 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie tcpIR.TCPKeepalive = keepalive tcpIR.Connection = connection - tcpIR.EnableProxyProtocol = enableProxyProtocol + tcpIR.ProxyProtocol = proxyProtocol tcpIR.TLS = tlsConfig tcpIR.Timeout = timeout } diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.in.yaml index f3ef317dba0..86a3967de0a 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.in.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.in.yaml @@ -14,7 +14,6 @@ clientTrafficPolicies: connectionLimit: value: 3 closeDelay: 10s - enableProxyProtocol: true timeout: tcp: idleTimeout: 1200s @@ -31,6 +30,8 @@ clientTrafficPolicies: signatureAlgorithms: - sig1 - sig2 + proxyProtocol: + optional: false targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml index 4345a308792..61ae1b4c78d 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml @@ -11,7 +11,8 @@ clientTrafficPolicies: connectionLimit: closeDelay: 10s value: 3 - enableProxyProtocol: true + proxyProtocol: + optional: false targetRef: group: gateway.networking.k8s.io kind: Gateway @@ -199,9 +200,9 @@ xdsIR: limit: closeDelay: 10s value: 3 - enableProxyProtocol: true name: envoy-gateway/gateway-1/tls-1 port: 10443 + proxyProtocol: {} routes: - destination: metadata: @@ -270,9 +271,9 @@ xdsIR: limit: closeDelay: 10s value: 3 - enableProxyProtocol: true name: envoy-gateway/gateway-1/tcp-1 port: 8080 + proxyProtocol: {} routes: - destination: metadata: diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.in.yaml new file mode 100644 index 00000000000..9e161c0d892 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.in.yaml @@ -0,0 +1,97 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-precedence-test + spec: + # Legacy API - should be overridden by new API + enableProxyProtocol: false + # New API - should take precedence + proxyProtocol: + optional: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-precedence-test +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-legacy-only + spec: + # Legacy API only - should work as before + enableProxyProtocol: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-legacy-only +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-new-api-only + spec: + # New API only - no legacy field + proxyProtocol: + optional: false + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-new-api-only +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-precedence-test + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-legacy-only + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: tcp-1 + protocol: TCP + port: 9090 + allowedRoutes: + namespaces: + from: Same +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-new-api-only + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same +tcpRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: TCPRoute + metadata: + namespace: envoy-gateway + name: tcproute-1 + spec: + parentRefs: + - name: gateway-legacy-only + rules: + - backendRefs: + - name: tcp-backend + port: 3000 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml new file mode 100644 index 00000000000..71badcafb0e --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml @@ -0,0 +1,363 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-precedence-test + namespace: envoy-gateway + spec: + enableProxyProtocol: false + proxyProtocol: + optional: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-precedence-test + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-precedence-test + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-legacy-only + namespace: envoy-gateway + spec: + enableProxyProtocol: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-legacy-only + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-legacy-only + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-new-api-only + namespace: envoy-gateway + spec: + proxyProtocol: + optional: false + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-new-api-only + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-new-api-only + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-precedence-test + 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 +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-legacy-only + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: tcp-1 + port: 9090 + protocol: TCP + status: + listeners: + - attachedRoutes: 1 + 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: tcp-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: TCPRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-new-api-only + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + 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-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-legacy-only: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-legacy-only/tcp-1 + ports: + - containerPort: 9090 + name: tcp-9090 + protocol: TCP + servicePort: 9090 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-legacy-only + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-legacy-only + namespace: envoy-gateway-system + envoy-gateway/gateway-new-api-only: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-new-api-only/http-2 + ports: + - containerPort: 8080 + name: http-8080 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-new-api-only + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-new-api-only + namespace: envoy-gateway-system + envoy-gateway/gateway-precedence-test: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-precedence-test/http-1 + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-precedence-test + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-precedence-test + namespace: envoy-gateway-system +tcpRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: TCPRoute + metadata: + creationTimestamp: null + name: tcproute-1 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-legacy-only + rules: + - backendRefs: + - name: tcp-backend + port: 3000 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: service envoy-gateway/tcp-backend not found + reason: BackendNotFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-legacy-only +xdsIR: + envoy-gateway/gateway-legacy-only: + accessLog: + json: + - path: /dev/stdout + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 + tcp: + - address: 0.0.0.0 + name: envoy-gateway/gateway-legacy-only/tcp-1 + port: 9090 + proxyProtocol: {} + routes: + - destination: + metadata: + kind: TCPRoute + name: tcproute-1 + namespace: envoy-gateway + name: tcproute/envoy-gateway/tcproute-1/rule/-1 + name: tcproute/envoy-gateway/tcproute-1 + envoy-gateway/gateway-new-api-only: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-new-api-only + namespace: envoy-gateway + sectionName: http-2 + name: envoy-gateway/gateway-new-api-only/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 + proxyProtocol: {} + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 + envoy-gateway/gateway-precedence-test: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-precedence-test + namespace: envoy-gateway + sectionName: http-1 + name: envoy-gateway/gateway-precedence-test/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + proxyProtocol: + optional: true + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.in.yaml index 60ac2d95a7a..e5c9a899bdb 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.in.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.in.yaml @@ -5,7 +5,8 @@ clientTrafficPolicies: namespace: envoy-gateway name: target-gateway-1-section-http-1 spec: - enableProxyProtocol: true + proxyProtocol: + optional: true targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.out.yaml index 5a33f4837ea..54b6f9f0188 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol.out.yaml @@ -6,7 +6,8 @@ clientTrafficPolicies: name: target-gateway-1-section-http-1 namespace: envoy-gateway spec: - enableProxyProtocol: true + proxyProtocol: + optional: true targetRef: group: gateway.networking.k8s.io kind: Gateway @@ -131,7 +132,6 @@ xdsIR: - path: /dev/stdout http: - address: 0.0.0.0 - enableProxyProtocol: true hostnames: - '*' isHTTP2: false @@ -145,6 +145,8 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 + proxyProtocol: + optional: true - address: 0.0.0.0 hostnames: - '*' diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 695fa6a9d9c..1e0ba51dea4 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -309,8 +309,8 @@ type HTTPListener struct { TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty" yaml:"tcpKeepalive,omitempty"` // Headers configures special header management for the listener Headers *HeaderSettings `json:"headers,omitempty" yaml:"headers,omitempty"` - // EnableProxyProtocol enables the listener to interpret proxy protocol header - EnableProxyProtocol bool `json:"enableProxyProtocol,omitempty" yaml:"enableProxyProtocol,omitempty"` + // ProxyProtocol provides proxy protocol configuration. + ProxyProtocol *ProxyProtocolSettings `json:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty"` // ClientIPDetection controls how the original client IP address is determined for requests. ClientIPDetection *ClientIPDetectionSettings `json:"clientIPDetection,omitempty" yaml:"clientIPDetection,omitempty"` // Path contains settings for path URI manipulations @@ -515,6 +515,16 @@ type PathSettings struct { EscapedSlashesAction PathEscapedSlashAction `json:"escapedSlashesAction" yaml:"escapedSlashesAction"` } +// ProxyProtocolSettings holds configuration for proxy protocol +// +k8s:deepcopy-gen=true +type ProxyProtocolSettings struct { + // Optional allows requests without a Proxy Protocol header to be proxied. + // If set to true, the listener will accept requests without a Proxy Protocol header. + // If set to false, the listener will reject requests without a Proxy Protocol header. + // If not set, the default behavior is to reject requests without a Proxy Protocol header. + Optional bool `json:"optional,omitempty" yaml:"optional,omitempty"` +} + type WithUnderscoresAction egv1a1.WithUnderscoresAction const ( @@ -1153,7 +1163,7 @@ type OIDC struct { // may not be able to handle OIDC redirects and wish to directly supply a token instead. PassThroughAuthHeader bool `json:"passThroughAuthHeader,omitempty"` - // Any request that matches any of the provided matchers won’t be redirected to OAuth server when tokens are not valid. + // Any request that matches any of the provided matchers won't be redirected to OAuth server when tokens are not valid. // Automatic access token refresh will be performed for these requests, if enabled. // This behavior can be useful for AJAX requests. DenyRedirect *egv1a1.OIDCDenyRedirect `json:"denyRedirect,omitempty"` @@ -1986,8 +1996,8 @@ type TCPListener struct { TLS *TLSConfig `json:"tls,omitempty" yaml:"tls,omitempty"` // TCPKeepalive configuration for the listener TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty" yaml:"tcpKeepalive,omitempty"` - // EnableProxyProtocol enables the listener to interpret proxy protocol header - EnableProxyProtocol bool `json:"enableProxyProtocol,omitempty" yaml:"enableProxyProtocol,omitempty"` + // ProxyProtocol provides proxy protocol configuration. + ProxyProtocol *ProxyProtocolSettings `json:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty"` // ClientTimeout sets the timeout configuration for downstream connections. Timeout *ClientTimeout `json:"timeout,omitempty" yaml:"clientTimeout,omitempty"` // Connection settings for clients diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index c45b5b868ba..e1d2c936c5f 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -1610,6 +1610,11 @@ func (in *HTTPListener) DeepCopyInto(out *HTTPListener) { *out = new(HeaderSettings) (*in).DeepCopyInto(*out) } + if in.ProxyProtocol != nil { + in, out := &in.ProxyProtocol, &out.ProxyProtocol + *out = new(ProxyProtocolSettings) + **out = **in + } if in.ClientIPDetection != nil { in, out := &in.ClientIPDetection, &out.ClientIPDetection *out = new(ClientIPDetectionSettings) @@ -2769,6 +2774,21 @@ func (in *ProxyProtocol) DeepCopy() *ProxyProtocol { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyProtocolSettings) DeepCopyInto(out *ProxyProtocolSettings) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyProtocolSettings. +func (in *ProxyProtocolSettings) DeepCopy() *ProxyProtocolSettings { + if in == nil { + return nil + } + out := new(ProxyProtocolSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Random) DeepCopyInto(out *Random) { *out = *in @@ -3467,6 +3487,11 @@ func (in *TCPListener) DeepCopyInto(out *TCPListener) { *out = new(TCPKeepalive) (*in).DeepCopyInto(*out) } + if in.ProxyProtocol != nil { + in, out := &in.ProxyProtocol, &out.ProxyProtocol + *out = new(ProxyProtocolSettings) + **out = **in + } if in.Timeout != nil { in, out := &in.Timeout, &out.Timeout *out = new(ClientTimeout) diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index b896f31990d..9963d5cf0f1 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -389,7 +389,7 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis } // Add the proxy protocol filter if needed - patchProxyProtocolFilter(xdsListener, irListener.EnableProxyProtocol) + patchProxyProtocolFilter(xdsListener, irListener.ProxyProtocol) if irListener.IsHTTP2 { mgr.HttpFilters = append(mgr.HttpFilters, xdsfilters.GRPCWeb) diff --git a/internal/xds/translator/proxy_protocol.go b/internal/xds/translator/proxy_protocol.go index c48fa5e2f8c..453cb0ed29e 100644 --- a/internal/xds/translator/proxy_protocol.go +++ b/internal/xds/translator/proxy_protocol.go @@ -10,13 +10,15 @@ import ( proxyprotocolv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" "google.golang.org/protobuf/types/known/anypb" + + "github.com/envoyproxy/gateway/internal/ir" ) // patchProxyProtocolFilter builds and appends the Proxy Protocol Filter to the // HTTP Listener's Listener Filters if applicable. -func patchProxyProtocolFilter(xdsListener *listenerv3.Listener, enableProxyProtocol bool) { - // Return early if unset - if xdsListener == nil || !enableProxyProtocol { +func patchProxyProtocolFilter(xdsListener *listenerv3.Listener, proxyProtocolSettings *ir.ProxyProtocolSettings) { + // Early return if listener is nil + if xdsListener == nil { return } @@ -27,18 +29,27 @@ func patchProxyProtocolFilter(xdsListener *listenerv3.Listener, enableProxyProto } } - proxyProtocolFilter := buildProxyProtocolFilter() + // Early return if proxy protocol is not enabled + if proxyProtocolSettings == nil { + return + } - if proxyProtocolFilter != nil { - // Add the Proxy Protocol filter as first to listeners. - xdsListener.ListenerFilters = append([]*listenerv3.ListenerFilter{proxyProtocolFilter}, xdsListener.ListenerFilters...) + // Build and patch the Proxy Protocol Filter. + filter := buildProxyProtocolFilter(proxyProtocolSettings) + if filter != nil { + xdsListener.ListenerFilters = append(xdsListener.ListenerFilters, filter) } } -// buildProxypProtocolFilter returns a Proxy Protocol listener filter from the provided IR listener. -func buildProxyProtocolFilter() *listenerv3.ListenerFilter { +// buildProxyProtocolFilter returns a Proxy Protocol listener filter from the provided IR listener. +func buildProxyProtocolFilter(proxyProtocolSettings *ir.ProxyProtocolSettings) *listenerv3.ListenerFilter { pp := &proxyprotocolv3.ProxyProtocol{} + // Configure allow_requests_without_proxy_protocol if ProxyProtocolSettings are provided + if proxyProtocolSettings.Optional { + pp.AllowRequestsWithoutProxyProtocol = proxyProtocolSettings.Optional + } + ppAny, err := anypb.New(pp) if err != nil { return nil diff --git a/internal/xds/translator/proxy_protocol_test.go b/internal/xds/translator/proxy_protocol_test.go index b86c2d765e7..d3b6f9bdf96 100644 --- a/internal/xds/translator/proxy_protocol_test.go +++ b/internal/xds/translator/proxy_protocol_test.go @@ -9,46 +9,57 @@ import ( "testing" listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" - "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + + "github.com/envoyproxy/gateway/internal/ir" ) func TestPatchProxyProtocolFilter(t *testing.T) { type testCase struct { - name string - listener *listenerv3.Listener + name string + listener *listenerv3.Listener + proxyProtocolSettings *ir.ProxyProtocolSettings + expectedFilterName string + expectedFilterCount int } - enableProxyProtocol := true - testCases := []testCase{ { - name: "listener with proxy proto available already", - listener: &listenerv3.Listener{ - ListenerFilters: []*listenerv3.ListenerFilter{ - { - Name: wellknown.ProxyProtocol, - }, - }, + name: "proxyProtocolSettings=nil (disabled)", + listener: &listenerv3.Listener{}, + proxyProtocolSettings: nil, + expectedFilterName: "", + expectedFilterCount: 0, + }, + { + name: "proxyProtocolSettings configured with Optional=false", + listener: &listenerv3.Listener{}, + proxyProtocolSettings: &ir.ProxyProtocolSettings{ + Optional: false, }, + expectedFilterName: "envoy.filters.listener.proxy_protocol", + expectedFilterCount: 1, }, { - name: "listener with tls, append proxy proto", - listener: &listenerv3.Listener{ - ListenerFilters: []*listenerv3.ListenerFilter{ - { - Name: wellknown.TLSInspector, - }, - }, + name: "proxyProtocolSettings configured with Optional=true", + listener: &listenerv3.Listener{}, + proxyProtocolSettings: &ir.ProxyProtocolSettings{ + Optional: true, }, + expectedFilterName: "envoy.filters.listener.proxy_protocol", + expectedFilterCount: 1, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - patchProxyProtocolFilter(tc.listener, enableProxyProtocol) - // proxy proto filter should be added always as first - require.Equal(t, wellknown.ProxyProtocol, tc.listener.ListenerFilters[0].Name) + patchProxyProtocolFilter(tc.listener, tc.proxyProtocolSettings) + + assert.Len(t, tc.listener.ListenerFilters, tc.expectedFilterCount) + + if tc.expectedFilterCount > 0 { + assert.Equal(t, tc.expectedFilterName, tc.listener.ListenerFilters[0].Name) + } }) } } diff --git a/internal/xds/translator/testdata/in/xds-ir/listener-proxy-protocol.yaml b/internal/xds/translator/testdata/in/xds-ir/listener-proxy-protocol.yaml index 41bbd6eadf9..5818d84995a 100644 --- a/internal/xds/translator/testdata/in/xds-ir/listener-proxy-protocol.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/listener-proxy-protocol.yaml @@ -20,7 +20,8 @@ http: - name: secret-2 certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] privateKey: [107, 101, 121, 45, 100, 97, 116, 97] - enableProxyProtocol: true + proxyProtocol: + optional: false routes: - name: "first-route" hostname: "*" @@ -35,7 +36,8 @@ tcp: - name: "second-listener" address: "::" port: 10081 - enableProxyProtocol: true + proxyProtocol: + optional: false routes: - name: "tcp-route-dest" destination: diff --git a/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml b/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml index cc24bfbdf00..48b7ae0e816 100644 --- a/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml @@ -5,7 +5,8 @@ tcp: limit: closeDelay: 10s value: 3 - enableProxyProtocol: true + proxyProtocol: + optional: false name: envoy-gateway/gateway-1/tls-1 port: 10443 tcpKeepalive: diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 0b3dbe724ea..12b9dc05b16 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -705,10 +705,10 @@ func (t *Translator) processTCPListenerXdsTranslation( // Add the proxy protocol filter if needed // TODO: should make sure all listeners that will be translated into same xDS listener have - // same EnableProxyProtocol value, otherwise listeners with EnableProxyProtocol=false will - // never accept connection, because listeners with EnableProxyProtocol=true has configured + // same proxy protocol configuration, otherwise listeners with proxy protocol disabled will + // never accept connection, because listeners with proxy protocol enabled have configured // proxy protocol listener filter for xDS listener, all connection must have ProxyProtocol header. - patchProxyProtocolFilter(xdsListener, tcpListener.EnableProxyProtocol) + patchProxyProtocolFilter(xdsListener, tcpListener.ProxyProtocol) for _, route := range tcpListener.Routes { if err := processXdsCluster(tCtx, diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index b5ad578b929..01a0d71507b 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -769,7 +769,8 @@ _Appears in:_ | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | | TargetRefs are the names of the Gateway resources this policy
is being attached to. | | `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | | TargetSelectors allow targeting resources for this policy based on labels | | `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ | false | | TcpKeepalive settings associated with the downstream client connection.
If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives.
Disabled by default. | -| `enableProxyProtocol` | _boolean_ | false | | EnableProxyProtocol interprets the ProxyProtocol header and adds the
Client Address into the X-Forwarded-For header.
Note Proxy Protocol must be present when this field is set, else the connection
is closed. | +| `enableProxyProtocol` | _boolean_ | false | | EnableProxyProtocol interprets the ProxyProtocol header and adds the
Client Address into the X-Forwarded-For header.
Note Proxy Protocol must be present when this field is set, else the connection
is closed.
Deprecated: Use ProxyProtocol instead. | +| `proxyProtocol` | _[ProxyProtocolSettings](#proxyprotocolsettings)_ | false | | ProxyProtocol configures the Proxy Protocol settings. When configured,
the Proxy Protocol header will be interpreted and the Client Address
will be added into the X-Forwarded-For header.
If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. | | `clientIPDetection` | _[ClientIPDetectionSettings](#clientipdetectionsettings)_ | false | | ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. | | `tls` | _[ClientTLSSettings](#clienttlssettings)_ | false | | TLS settings configure TLS termination settings with the downstream client. | | `path` | _[PathSettings](#pathsettings)_ | false | | Path enables managing how the incoming path set by clients can be normalized. | @@ -3562,7 +3563,7 @@ _Appears in:_ | Field | Type | Required | Default | Description | | --- | --- | --- | --- | --- | -| `clientCIDRs` | _[CIDR](#cidr) array_ | false | | ClientCIDRs are the IP CIDR ranges of the client.
Valid examples are "192.168.1.0/24" or "2001:db8::/64"
If multiple CIDR ranges are specified, one of the CIDR ranges must match
the client IP for the rule to match.
The client IP is inferred from the X-Forwarded-For header, a custom header,
or the proxy protocol.
You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in
the `ClientTrafficPolicy` to configure how the client IP is detected. | +| `clientCIDRs` | _[CIDR](#cidr) array_ | false | | ClientCIDRs are the IP CIDR ranges of the client.
Valid examples are "192.168.1.0/24" or "2001:db8::/64"
If multiple CIDR ranges are specified, one of the CIDR ranges must match
the client IP for the rule to match.
The client IP is inferred from the X-Forwarded-For header, a custom header,
or the proxy protocol.
You can use the `ClientIPDetection` or the `ProxyProtocol` field in
the `ClientTrafficPolicy` to configure how the client IP is detected. | | `jwt` | _[JWTPrincipal](#jwtprincipal)_ | false | | JWT authorize the request based on the JWT claims and scopes.
Note: in order to use JWT claims for authorization, you must configure the
JWT authentication in the same `SecurityPolicy`. | | `headers` | _[AuthorizationHeaderMatch](#authorizationheadermatch) array_ | false | | Headers authorize the request based on user identity extracted from custom headers.
If multiple headers are specified, all headers must match for the rule to match. | @@ -3864,6 +3865,23 @@ _Appears in:_ | `version` | _[ProxyProtocolVersion](#proxyprotocolversion)_ | true | | Version of ProxyProtol
Valid ProxyProtocolVersion values are
"V1"
"V2" | +#### ProxyProtocolSettings + + + +ProxyProtocolSettings configures the Proxy Protocol settings. When configured, +the Proxy Protocol header will be interpreted and the Client Address +will be added into the X-Forwarded-For header. +If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Default | Description | +| --- | --- | --- | --- | --- | +| `optional` | _boolean_ | false | | Optional allows requests without a Proxy Protocol header to be proxied.
If set to true, the listener will accept requests without a Proxy Protocol header.
If set to false, the listener will reject requests without a Proxy Protocol header.
If not set, the default behavior is to reject requests without a Proxy Protocol header.
Warning: Optional breaks conformance with the specification. Only enable if ALL traffic to the listener comes from a trusted source.
For more information on security implications, see haproxy.org/download/2.1/doc/proxy-protocol.txt | + + #### ProxyProtocolVersion _Underlying type:_ _string_ diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index c16d276ed17..a5ec8102e0b 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -20154,6 +20154,8 @@ spec: Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. + + Deprecated: Use ProxyProtocol instead. type: boolean headers: description: HeaderSettings provides configuration for header management. @@ -20486,6 +20488,24 @@ spec: - UnescapeAndRedirect type: string type: object + proxyProtocol: + description: |- + ProxyProtocol configures the Proxy Protocol settings. When configured, + the Proxy Protocol header will be interpreted and the Client Address + will be added into the X-Forwarded-For header. + If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. + minProperties: 0 + properties: + optional: + description: |- + Optional allows requests without a Proxy Protocol header to be proxied. + If set to true, the listener will accept requests without a Proxy Protocol header. + If set to false, the listener will reject requests without a Proxy Protocol header. + If not set, the default behavior is to reject requests without a Proxy Protocol header. + Warning: Optional breaks conformance with the specification. Only enable if ALL traffic to the listener comes from a trusted source. + For more information on security implications, see haproxy.org/download/2.1/doc/proxy-protocol.txt + type: boolean + type: object targetRef: description: |- TargetRef is the name of the resource this policy is being attached to. @@ -39420,7 +39440,7 @@ spec: The client IP is inferred from the X-Forwarded-For header, a custom header, or the proxy protocol. - You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in + You can use the `ClientIPDetection` or the `ProxyProtocol` field in the `ClientTrafficPolicy` to configure how the client IP is detected. items: description: |- diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index fce013c4ed4..1e245f785fd 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -2842,6 +2842,8 @@ spec: Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. + + Deprecated: Use ProxyProtocol instead. type: boolean headers: description: HeaderSettings provides configuration for header management. @@ -3174,6 +3176,24 @@ spec: - UnescapeAndRedirect type: string type: object + proxyProtocol: + description: |- + ProxyProtocol configures the Proxy Protocol settings. When configured, + the Proxy Protocol header will be interpreted and the Client Address + will be added into the X-Forwarded-For header. + If both EnableProxyProtocol and ProxyProtocol are set, ProxyProtocol takes precedence. + minProperties: 0 + properties: + optional: + description: |- + Optional allows requests without a Proxy Protocol header to be proxied. + If set to true, the listener will accept requests without a Proxy Protocol header. + If set to false, the listener will reject requests without a Proxy Protocol header. + If not set, the default behavior is to reject requests without a Proxy Protocol header. + Warning: Optional breaks conformance with the specification. Only enable if ALL traffic to the listener comes from a trusted source. + For more information on security implications, see haproxy.org/download/2.1/doc/proxy-protocol.txt + type: boolean + type: object targetRef: description: |- TargetRef is the name of the resource this policy is being attached to. @@ -22108,7 +22128,7 @@ spec: The client IP is inferred from the X-Forwarded-For header, a custom header, or the proxy protocol. - You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in + You can use the `ClientIPDetection` or the `ProxyProtocol` field in the `ClientTrafficPolicy` to configure how the client IP is detected. items: description: |-