envoyproxy / envoyproxy/gateway
Client certificate SDS secret not delivered for ext service clusters (EnvoyExtensionPolicy ext_proc / ext_authz), breaking backend mTLS
- Dominant language
- Go
- Stars
- 3k
- Forks
- 864
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 148
Description
## Description
When `EnvoyProxy.spec.backendTLS.clientCertificateRef` is configured and an `EnvoyExtensionPolicy` routes to an ext_proc backend that requires mutual TLS (the backend validates client certificates), the generated cluster's `transport_socket_matches` correctly references the client certificate by SDS name (`/`), **but the SDS secret resource itself is never added to the xDS snapshot**. Envoy waits for the SDS resource indefinitely, the TLS context never completes, and every connection to the ext_proc backend fails. With `failOpen: false` this fail-closes the entire route (HTTP 500).
The CA secret (from `BackendTLSPolicy`) *is* delivered, which makes the failure look like a server-side TLS problem while it is actually a missing client-certificate SDS resource.
## Root cause
`processClientCertificates` registers client-certificate SDS resources, but it is only called for route destinations (`internal/xds/translator/translator.go`, HTTP and TCP route paths).
Ext service clusters (ext_proc, ext_authz) are built via `createExtServiceXDSCluster` in `internal/xds/translator/utils.go`, which calls `addXdsCluster`. That path adds the **CA** secret (`buildXdsUpstreamTLSCASecret`) but never the client certificates — `grep processClientCertificates internal/xds/translator/utils.go` returns 0 matches.
Verified on **v1.8.3** and current **main** (the newer `processMergedBackendClusters` path only covers route backends, not ext service clusters).
## Reproduction (v1.8.3, Kubernetes provider)
1. `EnvoyProxy` with `backendTLS.clientCertificateRef` → Secret `ns/client-cert`
2. `BackendTLSPolicy` targeting the ext_proc Service (CA validation, backend presents a server cert)
3. `EnvoyExtensionPolicy` with `extProc.backendRefs` → that Service, `failOpen: false`
4. Send traffic through a route the policy targets.
Observed via the proxy's `config_dump`:
- the ext_proc cluster's `transport_socket_matches` references `ns/client-cert` via SDS
- `dynamic_active_secrets` contains the CA (`/-ca`) but **never** `ns/client-cert`
- `cluster.upstream_cx_connect_fail` increases; requests return 500
## Suggested fix
Mirror the route handling in `createExtServiceXDSCluster`:
```go
if err := addXdsCluster(tCtx, args); err != nil {
return err
}
return processClientCertificates(tCtx, rd.Settings)
```
We are running this one-line patch on top of v1.8.3 and it restores mTLS to ext_proc backends: the client-cert SDS resource is delivered, the handshake completes, and fail-closed behavior only triggers on genuine backend failure.
Happy to send a PR with the fix plus a translator test if that's useful.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.