Skip to content

feat(server): add optional mTLS client-certificate authentication #3930

Description

@sansmoraxz

Description

Add optional mutual TLS authentication for client-facing Iggy transports.

Iggy supports TLS for TCP, HTTP, WebSocket, and QUIC, but its server TLS configurations do not request or validate client certificates. TLS currently encrypts the connection and authenticates the server only.

This prevents operators from:

  • Restricting connections to clients holding certificates from a trusted CA.
  • Authenticating users or services through X.509 certificates.
  • Using certificate identities for service-to-service access.
  • Resolving certificate identities through an external authentication and authorization provider ( feat(server): Generic external auth callout #3929 ).

Affected area / component

Wire protocol / API

Proposed solution

When certificates are optional and a client does not present one, the connection should remain unauthenticated and use the existing login mechanism.

Certificate verification

When enabled, the listener should:

  • Request a client certificate during the TLS handshake.
  • Validate its chain against the configured client CA trust store.
  • Validate certificate validity and client-authentication key usage.
  • Verify possession of the corresponding private key through the TLS handshake.
  • Reject invalid, expired, or untrusted certificates.
  • Expose only verified certificate information to the authentication layer.

Certificate fields supplied through untrusted application headers must not be accepted as certificate identity.

Local identity mapping

In iggy_user mode, Iggy should extract identity from a configurable certificate field:

[tcp.tls.client_auth.identity]
source = "san_uri"

Potential identity sources include:

  • URI SAN.
  • DNS SAN.
  • Subject distinguished name.
  • SHA-256 certificate fingerprint.

Example mapping:

[[tcp.tls.client_auth.identities]]
value = "spiffe://example.org/services/analytics-ingestor"
user_id = 12

The flow would be:

TLS handshake

  1. verify client certificate
  2. extract certificate identity
  3. map identity to an existing non-root Iggy user
  4. establish an authenticated session
  5. enforce the user’s existing permissions

Unknown identities must fail.

For external identity mapping, the listener should:

  1. verify client certificate
  2. extract verified certificate information
  3. call the external authentication provider once
  4. receive an Iggy user or session-scoped permissions
  5. establish an authenticated session
  6. enforce permissions locally

The callout must fail closed on:

  • Explicit denial.
  • Timeout or provider unavailability.
  • Invalid or malformed response.
  • Missing authorization context.
  • Expired authorization decision.

Alternatives considered

  • mTLS at a reverse proxy: Does not provide native support across all Iggy transports.
  • Certificate fingerprint allowlist/mapping: Complicates certificate rotation.

Contribution

  • I'm willing to submit a pull request to implement this feature

Good first issue

  • I think this could be a good first issue for a new contributor

Metadata

Metadata

Assignees

Labels

apiAPI interface related changes

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions