Skip to content

Implement multi identity caller that looks at the server cert while selecting the client one#613

Merged
sfc-gh-mjankowski merged 2 commits intomainfrom
mjankowski-multi-identity-caller
Mar 19, 2026
Merged

Implement multi identity caller that looks at the server cert while selecting the client one#613
sfc-gh-mjankowski merged 2 commits intomainfrom
mjankowski-multi-identity-caller

Conversation

@sfc-gh-mjankowski
Copy link
Copy Markdown
Collaborator

@sfc-gh-mjankowski sfc-gh-mjankowski commented Mar 16, 2026

The mTLS handshake and where we inject new logic

The diagram below shows the messages exchanged during a standard mTLS
handshake (TLS 1.2 flow shown for clarity; TLS 1.3 reorders some messages
but the certificate selection logic is equivalent). The highlighted step
is where MultiIdentityCredentials injects its identity-selection logic.

  Proxy (client)                                    Target (server)
  ─────────────                                     ───────────────
       │                                                  │
       │─── ClientHello ─────────────────────────────────▶│
       │    (supported ciphers, TLS version, random)      │
       │                                                  │
       │◀── ServerHello ──────────────────────────────────│
       │    (chosen cipher, TLS version, random)          │
       │                                                  │
       │◀── Server Certificate ───────────────────────────│
       │    (server's leaf cert + chain)                   │
       │                                                  │
       │    ┌─────────────────────────────────────────┐   │
       │◀───│ CertificateRequest                      │───│
       │    │  • AcceptableCAs: [CA-Acme, ...]        │   │
       │    │    (DER-encoded subject DNs of CAs the  │   │
       │    │     server trusts for client certs)      │   │
       │    └─────────────────────────────────────────┘   │
       │                                                  │
       │◀── ServerHelloDone ──────────────────────────────│
       │                                                  │
       │    ╔═════════════════════════════════════════╗   │
       │    ║  ** OUR NEW LOGIC RUNS HERE **          ║   │
       │    ║                                         ║   │
       │    ║  GetClientCertificate callback fires:   ║   │
       │    ║                                         ║   │
       │    ║  1. Read AcceptableCAs from the server  ║   │
       │    ║  2. For each identity we hold:          ║   │
       │    ║     - extract leaf cert's Issuer DN     ║   │
       │    ║     - check if it's in AcceptableCAs    ║   │
       │    ║  3. Return the first matching cert      ║   │
       │    ║     (or fall back to identity[0])       ║   │
       │    ╚═════════════════════════════════════════╝   │
       │                                                  │
       │─── Client Certificate ──────────────────────────▶│
       │    (the cert selected by our logic above)        │
       │                                                  │
       │─── ClientKeyExchange ───────────────────────────▶│
       │    (premaster secret encrypted with server key)  │
       │                                                  │
       │─── CertificateVerify ───────────────────────────▶│
       │    (signature proving we own the private key     │
       │     of the cert we just sent)                    │
       │                                                  │
       │─── [ChangeCipherSpec] ──────────────────────────▶│
       │─── Finished ────────────────────────────────────▶│
       │                                                  │
       │◀── [ChangeCipherSpec] ───────────────────────────│
       │◀── Finished ─────────────────────────────────────│
       │                                                  │
       │    ══════ Encrypted channel established ══════   │
       │                                                  │

In standard (single-identity) mTLS the client always sends the same
certificate regardless of what the server asks for. With
MultiIdentityCredentials, the GetClientCertificate callback inspects
the server's CertificateRequest and dynamically picks the right identity.

Proxy server wiring

The proxy server's credential extraction was refactored to support two paths:

  • Single identity (zero or one clientCredSources): preserves the existing WrappedTransportCredentials behavior with its own refresh/metrics/logging.
  • Multiple identities (two or more clientCredSources): loads each source as a ClientIdentity and creates a MultiIdentityCredentials.

The server-side (incoming) credentials are unchanged and still use the single credSource.

@sfc-gh-mjankowski sfc-gh-mjankowski force-pushed the mjankowski-multi-identity-caller branch 8 times, most recently from d3a16e3 to af35f4b Compare March 17, 2026 13:22
@sfc-gh-mjankowski sfc-gh-mjankowski changed the title [WIP] Implement multi identity caller that looks at the server cert while s… [WIP] Implement multi identity caller that looks at the server cert while selecting the client one Mar 17, 2026
@sfc-gh-mjankowski sfc-gh-mjankowski marked this pull request as ready for review March 17, 2026 15:25
@sfc-gh-mjankowski sfc-gh-mjankowski changed the title [WIP] Implement multi identity caller that looks at the server cert while selecting the client one Implement multi identity caller that looks at the server cert while selecting the client one Mar 17, 2026
@sfc-gh-mjankowski sfc-gh-mjankowski force-pushed the mjankowski-multi-identity-caller branch 9 times, most recently from 8a3e2cb to 4872714 Compare March 18, 2026 15:15
Comment thread auth/mtls/client.go Outdated
Comment thread cmd/proxy-server/server/server.go Outdated
Comment thread cmd/proxy-server/server/server.go
Comment thread auth/mtls/client_multi_credentials.go Outdated
Comment thread auth/mtls/client_multi_credentials.go Outdated
Comment thread auth/mtls/client_multi_credentials.go Outdated
Comment thread auth/mtls/client_multi_credentials.go
@sfc-gh-mjankowski sfc-gh-mjankowski force-pushed the mjankowski-multi-identity-caller branch from 4872714 to a52c491 Compare March 19, 2026 08:47
Comment thread auth/mtls/client_multi_credentials.go Outdated
Comment thread auth/mtls/client.go Outdated
Comment thread auth/mtls/client.go Outdated
Comment thread auth/mtls/client_multi_credentials.go Outdated
@sfc-gh-mjankowski sfc-gh-mjankowski force-pushed the mjankowski-multi-identity-caller branch 2 times, most recently from aeeb35c to 57a8bdb Compare March 19, 2026 10:02
Comment thread auth/mtls/client_multi_credentials_test.go
@sfc-gh-mjankowski sfc-gh-mjankowski force-pushed the mjankowski-multi-identity-caller branch from 57a8bdb to aed72f8 Compare March 19, 2026 11:44
Copy link
Copy Markdown
Collaborator

@sfc-gh-ssapkowski sfc-gh-ssapkowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@sfc-gh-mjankowski sfc-gh-mjankowski merged commit 29f309a into main Mar 19, 2026
6 checks passed
@sfc-gh-mjankowski sfc-gh-mjankowski deleted the mjankowski-multi-identity-caller branch March 19, 2026 13:28
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.

3 participants