Repository: envoyproxy/gateway
Pull request #5372 (2025-02-28 04:49:56)

fix: backendSettings for extAuth
Fixes: https://github.com/envoyproxy/gateway/issues/5371

Release Notes: Yes


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/5372?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 65.09%. Comparing base [(`c4bc5b2`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/c4bc5b2dfc38248f0bb7f52110d6938b274e2739?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`5816f6c`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/5816f6ce15e2f120d184a4dd737354622a360b89?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).
> Report is 1 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #5372      +/-   ##
==========================================
- Coverage   65.10%   65.09%   -0.01%     
==========================================
  Files         213      213              
  Lines       33586    33588       +2     
==========================================
- Hits        21867    21865       -2     
- Misses      10393    10396       +3     
- Partials     1326     1327       +1     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/5372?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).


Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index dbdec72e6..5ca6f5160 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -63,7 +63,7 @@ jobs:
       - name: Login to DockerHub
         uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567  # v3.3.0
         with:
-          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          username: ${{ vars.DOCKERHUB_USERNAME }}
           password: ${{ secrets.DOCKERHUB_PASSWORD }}
       - name: Retag and push existing gateway-dev image
         run: |
diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go
index 79b0e5a54..d230e2a4c 100644
--- a/api/v1alpha1/backendtrafficpolicy_types.go
+++ b/api/v1alpha1/backendtrafficpolicy_types.go
@@ -15,13 +15,13 @@ const (
 	KindBackendTrafficPolicy = "BackendTrafficPolicy"
 )
 
+// BackendTrafficPolicy allows the user to configure the behavior of the connection
+// between the Envoy Proxy listener and the backend service.
+//
 // +kubebuilder:object:root=true
 // +kubebuilder:resource:categories=envoy-gateway,shortName=btp
 // +kubebuilder:subresource:status
 // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
-
-// BackendTrafficPolicy allows the user to configure the behavior of the connection
-// between the Envoy Proxy listener and the backend service.
 type BackendTrafficPolicy struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -33,16 +33,15 @@ type BackendTrafficPolicy struct {
 	Status gwapiv1a2.PolicyStatus `json:"status,omitempty"`
 }
 
-// +kubebuilder:validation:XValidation:rule="(has(self.targetRef) && !has(self.targetRefs)) || (!has(self.targetRef) && has(self.targetRefs)) || (has(self.targetSelectors) && self.targetSelectors.size() > 0) ", message="either targetRef or targetRefs must be used"
+// BackendTrafficPolicySpec defines the desired state of BackendTrafficPolicy.
 //
+// +kubebuilder:validation:XValidation:rule="(has(self.targetRef) && !has(self.targetRefs)) || (!has(self.targetRef) && has(self.targetRefs)) || (has(self.targetSelectors) && self.targetSelectors.size() > 0) ", message="either targetRef or targetRefs must be used"
 // +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? self.targetRef.group == 'gateway.networking.k8s.io' : true ", message="this policy can only have a targetRef.group of gateway.networking.k8s.io"
 // +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? self.targetRef.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', 'TCPRoute', 'TLSRoute'] : true", message="this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute"
 // +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? !has(self.targetRef.sectionName) : true",message="this policy does not yet support the sectionName field"
 // +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.group == 'gateway.networking.k8s.io') : true ", message="this policy can only have a targetRefs[*].group of gateway.networking.k8s.io"
 // +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', 'TCPRoute', 'TLSRoute']) : true ", message="this policy can only have a targetRefs[*].kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute"
 // +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, !has(ref.sectionName)) : true",message="this policy does not yet support the sectionName field"
-//
-// BackendTrafficPolicySpec defines the desired state of BackendTrafficPolicy.
 type BackendTrafficPolicySpec struct {
 	PolicyTargetReferences `json:",inline"`
 	ClusterSettings        `json:",inline"`
@@ -74,11 +73,28 @@ type BackendTrafficPolicySpec struct {
 	//
 	// +optional
 	ResponseOverride []*ResponseOverride `json:"responseOverride,omitempty"`
+	// HTTPUpgrade defines the configuration for HTTP protocol upgrades.
+	// If not specified, the default upgrade configuration(websocket) will be used.
+	//
+	// +optional
+	// +notImplementedHide
+	HTTPUpgrade []*ProtocolUpgradeConfig `json:"httpUpgrade,omitempty"`
 }
 
-// +kubebuilder:object:root=true
+type ProtocolUpgradeConfig struct {
+	// Type is the case-insensitive type of protocol upgrade.
+	// e.g. `websocket`, `CONNECT`, `spdy/3.1` etc.
+	//
+	// +kubebuilder:validation:Required
+	Type string `json:"type"`
+	// Disabled indicates whether the upgrade is disabled.
+	// +optional
+	Disabled *bool `json:"disabled"`
+}
 
 // BackendTrafficPolicyList contains a list of BackendTrafficPolicy resources.
+//
+// +kubebuilder:object:root=true
 type BackendTrafficPolicyList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/api/v1alpha1/basic_auth_types.go b/api/v1alpha1/basic_auth_types.go
index f7bec2837..cc98c1e6f 100644
--- a/api/v1alpha1/basic_auth_types.go
+++ b/api/v1alpha1/basic_auth_types.go
@@ -26,4 +26,13 @@ type BasicAuth struct {
 	//
 	// Note: The secret must be in the same namespace as the SecurityPolicy.
 	Users gwapiv1.SecretObjectReference `json:"users"`
+
+	// This field specifies the header name to forward a successfully authenticated user to
+	// the backend. The header will be added to the request with the username as the value.
+	//
+	// If it is not specified, the username will not be forwarded.
+	//
+	// +optional
+	// +notImplementedHide
+	ForwardUsernameHeader *string `json:"forwardUsernameHeader,omitempty"`
 }
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 5efdb1bde..bbb7c1145 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -626,6 +626,17 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec)
 			}
 		}
 	}
+	if in.HTTPUpgrade != nil {
+		in, out := &in.HTTPUpgrade, &out.HTTPUpgrade
+		*out = make([]*ProtocolUpgradeConfig, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(ProtocolUpgradeConfig)
+				(*in).DeepCopyInto(*out)
+			}
+		}
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec.
@@ -642,6 +653,11 @@ func (in *BackendTrafficPolicySpec) DeepCopy() *BackendTrafficPolicySpec {
 func (in *BasicAuth) DeepCopyInto(out *BasicAuth) {
 	*out = *in
 	in.Users.DeepCopyInto(&out.Users)
+	if in.ForwardUsernameHeader != nil {
+		in, out := &in.ForwardUsernameHeader, &out.ForwardUsernameHeader
+		*out = new(string)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BasicAuth.
@@ -4413,6 +4429,26 @@ func (in *ProcessingModeOptions) DeepCopy() *ProcessingModeOptions {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ProtocolUpgradeConfig) DeepCopyInto(out *ProtocolUpgradeConfig) {
+	*out = *in
+	if in.Disabled != nil {
+		in, out := &in.Disabled, &out.Disabled
+		*out = new(bool)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProtocolUpgradeConfig.
+func (in *ProtocolUpgradeConfig) DeepCopy() *ProtocolUpgradeConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ProtocolUpgradeConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ProxyAccessLog) DeepCopyInto(out *ProxyAccessLog) {
 	*out = *in
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
index c135bead9..3b7415212 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
@@ -532,6 +532,24 @@ spec:
                       Default: TerminateConnection
                     type: string
                 type: object
+              httpUpgrade:
+                description: |-
+                  HTTPUpgrade defines the configuration for HTTP protocol upgrades.
+                  If not specified, the default upgrade configuration(websocket) will be used.
+                items:
+                  properties:
+                    disabled:
+                      description: Disabled indicates whether the upgrade is disabled.
+                      type: boolean
+                    type:
+                      description: |-
+                        Type is the case-insensitive type of protocol upgrade.
+                        e.g. `websocket`, `CONNECT`, `spdy/3.1` etc.
+                      type: string
+                  required:
+                  - type
+                  type: object
+                type: array
               loadBalancer:
                 description: |-
                   LoadBalancer policy to apply when routing traffic from the gateway 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 a48bc49ec..6aa0d9dce 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml
@@ -384,6 +384,13 @@ spec:
                 description: BasicAuth defines the configuration for the HTTP Basic
                   Authentication.
                 properties:
+                  forwardUsernameHeader:
+                    description: |-
+                      This field specifies the header name to forward a successfully authenticated user to
+                      the backend. The header will be added to the request with the username as the value.
+
+                      If it is not specified, the username will not be forwarded.
+                    type: string
                   users:
                     description: |-
                       The Kubernetes secret which contains the username-password pairs in
diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go
index 9d3505318..0bbd78fd7 100644
--- a/internal/gatewayapi/securitypolicy.go
+++ b/internal/gatewayapi/securitypolicy.go
@@ -1152,6 +1152,7 @@ func (t *Translator) buildExtAuth(
 	switch {
 	case http != nil:
 		protocol = ir.HTTP
+		backendSettings = http.BackendSettings
 		switch {
 		case len(http.BackendRefs) > 0:
 			backendRefs = http.BackendCluster.BackendRefs
@@ -1167,6 +1168,7 @@ func (t *Translator) buildExtAuth(
 		}
 	case grpc != nil:
 		protocol = ir.GRPC
+		backendSettings = grpc.BackendSettings
 		switch {
 		case len(grpc.BackendCluster.BackendRefs) > 0:
 			backendRefs = grpc.BackendRefs
diff --git a/release-notes/current.yaml b/release-notes/current.yaml
index 155da1509..913c715c0 100644
--- a/release-notes/current.yaml
+++ b/release-notes/current.yaml
@@ -18,10 +18,10 @@ new features: |
   Added support for HorizontalPodAutoscaler to helm chart
 
 bug fixes: |
-
   Fix traffic splitting when filters are attached to the backendRef.
   Added support for Secret and ConfigMap parsing in Standalone mode.
   Bypass overload manager for stats and ready listeners
+  Fix translating backendSettings for extAuth
 
 # Enhancements that improve performance.
 performance improvements: |


Test patch:
diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml
index f15efe463..497c6ff48 100644
--- a/.github/workflows/build_and_test.yaml
+++ b/.github/workflows/build_and_test.yaml
@@ -213,7 +213,7 @@ jobs:
       if: github.event_name == 'push'
       uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567  # v3.3.0
       with:
-        username: ${{ secrets.DOCKERHUB_USERNAME }}
+        username: ${{ vars.DOCKERHUB_USERNAME }}
         password: ${{ secrets.DOCKERHUB_PASSWORD }}
 
     - name: Setup Multiarch Environment
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml
index 7e067b8ea..7951e9ce2 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-dns-lookup-family.out.yaml
@@ -439,6 +439,10 @@ xdsIR:
                   weight: 1
               path: ""
             name: securitypolicy/envoy-gateway/policy-for-gateway-1
+            traffic:
+              dns:
+                dnsRefreshRate: 30s
+                lookupFamily: IPv4Preferred
         traffic:
           dns:
             dnsRefreshRate: 5s
@@ -480,6 +484,10 @@ xdsIR:
                   weight: 1
               path: ""
             name: securitypolicy/envoy-gateway/policy-for-gateway-1
+            traffic:
+              dns:
+                dnsRefreshRate: 30s
+                lookupFamily: IPv4Preferred
         traffic:
           dns:
             dnsRefreshRate: 5s
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml
index 1c24de65e..93a6223fa 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.in.yaml
@@ -169,3 +169,9 @@ securityPolicies:
           headersToBackend:
             - header1
             - header2
+          backendSettings:
+            circuitBreaker:
+              maxConnections: 30001
+              maxParallelRequests: 1022
+              maxParallelRetries: 1023
+              maxPendingRequests: 1024
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml
index 1b74752bd..5dd39981f 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backendref.out.yaml
@@ -188,6 +188,12 @@ securityPolicies:
         - name: http-backend
           namespace: envoy-gateway
           port: 80
+        backendSettings:
+          circuitBreaker:
+            maxConnections: 30001
+            maxParallelRequests: 1022
+            maxParallelRetries: 1023
+            maxPendingRequests: 1024
         headersToBackend:
         - header1
         - header2
@@ -358,6 +364,12 @@ xdsIR:
               - header2
               path: /auth
             name: securitypolicy/default/policy-for-gateway-1
+            traffic:
+              circuitBreaker:
+                maxConnections: 30001
+                maxParallelRequests: 1022
+                maxParallelRetries: 1023
+                maxPendingRequests: 1024
     readyListener:
       address: 0.0.0.0
       ipFamily: IPv4
diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml
index d532bfd8d..dfda65a47 100644
--- a/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml
@@ -111,6 +111,12 @@ http:
           extAuth:
             name: securitypolicy/default/policy-for-gateway-1
             failOpen: true
+            traffic:
+              circuitBreaker:
+                maxConnections: 30001
+                maxParallelRequests: 1022
+                maxParallelRetries: 1023
+                maxPendingRequests: 1024
             http:
               authority: primary.foo.com
               destination:
diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml
index 3ff821f5e..8c4d92eea 100644
--- a/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml
@@ -84,7 +84,10 @@
           initialStreamWindowSize: 65536
 - circuitBreakers:
     thresholds:
-    - maxRetries: 1024
+    - maxConnections: 30001
+      maxPendingRequests: 1024
+      maxRequests: 1022
+      maxRetries: 1023
   commonLbConfig:
     localityWeightedLbConfig: {}
   connectTimeout: 10s
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 3d309ad68..32c07223e 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -3170,6 +3170,21 @@ _Appears in:_
 | `attributes` | _string array_ |  false  |  | Defines which attributes are sent to the external processor. Envoy Gateway currently<br />supports only the following attribute prefixes: connection, source, destination,<br />request, response, upstream and xds.route.<br />https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes |
 
 
+#### ProtocolUpgradeConfig
+
+
+
+
+
+_Appears in:_
+- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
+
+| Field | Type | Required | Default | Description |
+| ---   | ---  | ---      | ---     | ---         |
+| `type` | _string_ |  true  |  | Type is the case-insensitive type of protocol upgrade.<br />e.g. `websocket`, `CONNECT`, `spdy/3.1` etc. |
+| `disabled` | _boolean_ |  false  |  | Disabled indicates whether the upgrade is disabled. |
+
+
 #### ProviderType
 
 _Underlying type:_ _string_