Skip to content

doc: design for mutual TLS client authentication - #38419

Draft
jubrad wants to merge 1 commit into
MaterializeInc:mainfrom
jubrad:mtls-design-doc
Draft

doc: design for mutual TLS client authentication#38419
jubrad wants to merge 1 commit into
MaterializeInc:mainfrom
jubrad:mtls-design-doc

Conversation

@jubrad

@jubrad jubrad commented Aug 23, 2026

Copy link
Copy Markdown
Member

Design doc only. The prototype is in a follow-up PR, which includes this commit.

The problem

The only way to restrict who may open a connection to an environment today is
a network policy: CIDR blocks matched against the client's IP. That fits poorly
with how customers run. Egress IPs are unstable behind NAT gateways, corporate
VPNs, and cloud NAT pools; an IP is not an identity, so anyone sharing an
allowlisted egress path inherits the admission decision; and an allowlist has no
expiry, rotation, or revocation.

The obstacle specific to us is balancerd. Every cloud connection lands there,
and it terminates TLS and opens a separate pgwire connection to
environmentd. So the client certificate is consumed by a process with no
catalog and no tenant configuration, while the process that has the
configuration never sees the certificate.

The proposal

Proof of possession and trust evaluation are separable. The handshake's
CertificateVerify proves the client holds the leaf's private key, and only
whoever terminated TLS can obtain that proof. Deciding whether the issuer is
acceptable is a pure function of a chain and a set of trust anchors, so it can
happen elsewhere.

balancerd therefore obtains the proof and forwards the chain; environmentd
judges it against anchors from the catalog. balancerd never learns any
tenant's certificate authority and stays stateless. A forwarded chain is
honoured only from a peer that authenticates as a trusted proxy, so an attacker
who can reach environmentd directly cannot forge one.

Configuration is three system parameters, following the OIDC precedent.
Enforcement runs before the authenticator dispatches, so a rejected client is
never offered a password prompt, a SASL challenge, or a token exchange, which is
the property that makes this a real substitute for a network-level gate.

Roadmap

The doc records three phases:

  1. System parameters, environmentd enforces. Untrusted connections reach the
    dataplane and are rejected there.
  2. Edge filtering at balancerd over a cacheable environmentd API, so
    untrusted connections never reach the dataplane. environmentd stays
    authoritative, making the edge a filter whose staleness degrades filtering
    rather than correctness.
  3. CREATE CERTIFICATE AUTHORITY, for FOR ROLES scoping, per-authority
    identity binding, named rotation, and audit.

Alternatives cover the catalog object's full syntax, edge filtering and its two
candidate distribution mechanisms, TLS passthrough, folding certificates into
network policies, and certificate-as-authenticator.

Notes for reviewers

Three things are worth disagreeing with:

  • Starting with system parameters rather than CREATE CERTIFICATE AUTHORITY.
  • Applying one policy to every external surface, which means require costs an
    operator their webhook sources until the surfaces can be separated.
  • Leaving revocation (CRL/OCSP) unaddressed.

Release notes

No user-visible change; documentation only.

Proposes mutual TLS as an admission gate for external SQL connections, as an
alternative to IP-based network policies. Egress IPs are unstable behind NAT
gateways and cloud NAT pools, an IP is not an identity, and an allowlist has no
rotation or revocation story.

The obstacle specific to Materialize is balancerd, which terminates TLS and
opens a separate pgwire connection to environmentd, so the process that sees the
client certificate has no tenant configuration and the process with the
configuration never sees the certificate.

The design separates proof of possession from trust evaluation. The handshake
proves the client holds the leaf's private key and only the terminating proxy
can obtain that proof, but judging the issuer is a pure function of a chain and
a set of trust anchors. balancerd therefore forwards the chain and environmentd
judges it, so balancerd never learns any tenant's certificate authority and
stays stateless. environmentd honours a forwarded chain only from a peer that
authenticates against a configured proxy authority.

Also records a three phase roadmap: system parameters with environmentd
enforcing, then edge filtering at balancerd over a cacheable API, then
CREATE CERTIFICATE AUTHORITY for per-authority scoping. Alternatives cover the
catalog object syntax, edge filtering, TLS passthrough, and folding certificates
into network policies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant