apache / apache/iggy

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

Open
#3,930 0 comments 0 reactions 1 assignee Claimed by @sansmoraxz View on GitHub
api
Dominant language
Rust
Stars
4.9k
Forks
432
Avg merge
2d 10h
Merged PRs (30d)
173

Description

### 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 (#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:

```toml
[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:

```toml
[[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

- [x] 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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.