envoyproxy / envoyproxy/gateway

Client certificate SDS secret not delivered for ext service clusters (EnvoyExtensionPolicy ext_proc / ext_authz), breaking backend mTLS

Open
#9,726 2 comments 0 reactions 1 assignee Claimed by @whlsm View on GitHub
kind/bug stale
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.