Kafka mTLS Config Generator
The keytool and
openssl commands for an mTLS client, and the
config. The principal the broker derives is what your ACLs have to match.
mtls-setup.sh
updates as you type Common mistakes
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
Assuming mTLS gives authorisation
The certificate establishes an identity. What that identity may do is ACLs, evaluated separately, and by default an authenticated principal can do nothing.
Instead:Grant ACLs to the principal derived from the certificate.
Ignoring ssl.principal.mapping.rules
Without mapping, the principal is the entire distinguished name including OU and O, so an ACL written for CN=app does not match.
Instead:Set the mapping rules, and check the resulting principal in the broker log.
Forgetting the certificates expire
Client and broker certificates expire on a date nobody diaried, and the failure is a cluster-wide authentication outage.
Instead:Track expiry and automate renewal before it becomes an incident.
With mTLS the certificate is the identity, and that is the difficulty
The handshake succeeding tells you nothing about whether the client is authorised.
The principal is the distinguished name unless you map it
The broker derives a principal from the client certificate's subject, which is the full DN including field order: CN=orders,O=example. Every ACL must match it exactly, so a certificate reissued with the fields in a different order silently loses all its permissions. ssl.principal.mapping.rules shortens it to just the CN, and that rule is the difference between a workable ACL scheme and one that breaks on every renewal.
Import the CA before the signed certificate
keytool cannot build a chain to an issuer it does not already hold, so importing them the other way round fails with a message about a reply not being trusted, which reads as though the certificate itself is bad. The order in the generated commands is deliberate.
The truststore holds the CA, not the broker certificate
Pinning the broker's own leaf certificate works until it is renewed, and then every client fails at once. The CA is the thing with the long life, and it is what lets a broker certificate be replaced without touching a single client.
ssl.client.auth=requested is not authentication
With requested rather than required, the broker accepts a connection that presents no client certificate, and that connection is ANONYMOUS. Any ACL granting ANONYMOUS applies to it, and if allow.everyone.if.no.acl.found is set it has full access. The setting that makes mTLS authentication rather than encryption is on the broker, not the client.
Expiry is a scheduled outage
On the day the client certificate expires, every client using it stops connecting, and the error is a handshake failure naming neither the certificate nor the expiry. Short validity is only safer than long if rotation is automated; otherwise it just makes the outage arrive sooner. The TLS decoder on this site reads a certificate's expiry without sending it anywhere.