Commit 9108432
auth: prototype mutual TLS client authentication
Adds mutual TLS as an admission gate for external pgwire connections, enforced
before any credential exchange. Off by default; no behaviour change for
deployments that do not opt in.
Proof of possession and trust evaluation are separated, which is what makes this
work through balancerd. balancerd requests client certificates with a permissive
verify callback, so OpenSSL still validates CertificateVerify (possession is
proven) while the trust decision is deferred to the party that holds the tenant's
anchors. The chain is forwarded to environmentd in a new mz_client_cert startup
parameter as base64 concatenated PEM, leaf first. balancerd never learns any
tenant's certificate authority and stays stateless.
environmentd honours a forwarded chain only from a peer whose own certificate
chains to --tls-proxy-ca, so the balancerd to environmentd leg gains a client
identity (--internal-tls-cert/--internal-tls-key). Without a proxy authority
configured, forwarded certificates are ignored entirely. A client that supplies
mz_client_cert itself is rejected, as with mz_forwarded_for.
Configuration is three system parameters, following the OIDC precedent:
mtls_client_ca (PEM bundle of trust anchors), mtls_mode (disable, allow,
require), and mtls_identity_binding (none, common-name). Anchors and mode are
read from the live ConfigSet rather than via get_system_vars, so the check costs
no coordinator round trip on the connection path.
Two details worth noting. Trust anchors are built with
X509_V_FLAG_PARTIAL_CHAIN, so pinning an intermediate as the sole anchor works
rather than failing with "unable to get local issuer certificate". A leaf with no
Common Name fails a common-name binding outright, because pgwire defaults an
absent user parameter to the empty string and a SPIFFE-shaped certificate would
otherwise satisfy the binding.
Also fixes a pre-existing balancerd bug this work surfaced: the startup parameter
rejection paths called FramedConn::send without flushing, so a client rejected
for supplying mz_connection_uuid or mz_forwarded_for saw a bare connection close
instead of the error.
Adds unit tests for the policy in mz-authenticator, integration tests for the
direct path in src/environmentd/tests/mtls.rs, and tests for the forwarded path
in src/balancerd/tests/server.rs covering anchor rotation, an unauthenticated
proxy being disbelieved, and a forged mz_client_cert being refused.
The HTTP, WebSocket, and webhook paths are in scope for the feature but not yet
wired.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent e12bb7f commit 9108432
24 files changed
Lines changed: 2434 additions & 59 deletions
File tree
- misc/python/materialize
- mzcompose
- parallel_workload
- src
- adapter-types/src
- authenticator
- src
- balancerd
- src
- bin
- tests
- environmentd
- src
- environmentd
- tests
- pgwire-common
- src
- pgwire
- src
- server-core/src
- sqllogictest/src
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
768 | 768 | | |
769 | 769 | | |
770 | 770 | | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
771 | 774 | | |
772 | 775 | | |
773 | 776 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3326 | 3326 | | |
3327 | 3327 | | |
3328 | 3328 | | |
| 3329 | + | |
| 3330 | + | |
| 3331 | + | |
| 3332 | + | |
| 3333 | + | |
3329 | 3334 | | |
3330 | 3335 | | |
3331 | 3336 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
187 | 187 | | |
188 | 188 | | |
189 | 189 | | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
190 | 222 | | |
191 | 223 | | |
192 | 224 | | |
| |||
452 | 484 | | |
453 | 485 | | |
454 | 486 | | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
455 | 490 | | |
456 | 491 | | |
457 | 492 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| 16 | + | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
| 20 | + | |
18 | 21 | | |
19 | 22 | | |
20 | 23 | | |
| |||
0 commit comments