TLS and mTLS
Secure the Kafka connector with TLS — the 9093 encrypted listener, server certificates, and mutual TLS where the certificate common name is the principal.
The Kafka connector opens two listeners: 9092 (plaintext) and 9093 (TLS). This guide covers
the TLS listener — server-authentication TLS, mutual TLS, and how the client certificate's
common name becomes the authenticated principal when SASL isn't used.
Port stays required, even if you only want TLS. A TLS-only configuration — TlsPort set,
Port left empty — is rejected: the TLS accept path isn't wired independently of the
plaintext one yet, so Port must stay set (and differ from TlsPort). Restrict access to the
plaintext listener at your network layer (firewall rules, a ClusterIP-only Service) instead of
by unsetting Port.
The 9093 TLS listener
The TLS listener has no certificate configuration of its own — it reuses the server's global
Security block (Cert/Key/Ca), the same block every other TCP connector (gRPC, REST,
STOMP, AMQP, RabbitMQ) shares. There is no Connectors.Kafka.Tls*Cert field to set.
| Setting | Env var | Default | Notes |
|---|---|---|---|
| Plaintext port | CONNECTORS_KAFKA_PORT | 9092 | Must stay set — see the callout above. |
| TLS port | CONNECTORS_KAFKA_TLS_PORT | 9093 | Set to "" (empty) to disable the TLS listener; otherwise must be 1–65535. |
| Server cert | SECURITY_CERT_DATA / SECURITY_CERT_FILENAME | "" | Required for TLS and mTLS. |
| Server key | SECURITY_KEY_DATA / SECURITY_KEY_FILENAME | "" | Required for TLS and mTLS. |
| Client CA | SECURITY_CA_DATA / SECURITY_CA_FILENAME | "" | Presence promotes the mode to mTLS — see below. |
The mode is auto-derived, not a flag: Cert + Key alone is server-authentication TLS;
adding Ca promotes it to mTLS. See
Security → TLS / mTLS for the full field
reference and Docker/Helm examples.
If you expose 9093 externally, the certificate must cover AdvertisedHost. The connector
serves one certificate with no per-SNI selection — a certificate whose SAN covers only the
in-cluster Service DNS fails TLS hostname verification for an external client connecting
through the advertised address.
Server-authentication TLS
With Cert + Key set (no Ca), the server presents its certificate and the minimum
negotiated protocol is TLS 1.2; no client certificate is requested. The client authenticates
separately — with SASL/PLAIN, SCRAM, or OAUTHBEARER over the now-encrypted channel — see
Authentication.
kcat -b localhost:9093 -L \
-X security.protocol=SSL \
-X ssl.ca.location=/path/to/ca.pemimport (
"crypto/tls"
"crypto/x509"
"os"
"github.com/twmb/franz-go/pkg/kgo"
)
caPEM, _ := os.ReadFile("/path/to/ca.pem")
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caPEM)
cl, err := kgo.NewClient(
kgo.SeedBrokers("localhost:9093"),
kgo.DialTLSConfig(&tls.Config{RootCAs: pool}),
)security.protocol=SSL
ssl.truststore.location=/path/to/truststore.jks
ssl.truststore.password=changeitMutual TLS — certificate identity
Adding Ca to the Security block promotes the listener to mTLS: the server now requires
and verifies a client certificate (RequireAndVerifyClientCert) using that CA pool, on every
connection to 9093. A client that fails the chain check never completes the handshake.
When the connection carries no SASL layer, the connector reads the verified certificate's
leaf Subject.CommonName as the authenticated principal — the same identity the Casbin ACL
then authorizes against (see Authentication). An
empty CN, or a certificate whose chain didn't verify, never becomes a principal.
kcat -b localhost:9093 -L \
-X security.protocol=SSL \
-X ssl.ca.location=/path/to/ca.pem \
-X ssl.key.location=/path/to/client.key \
-X ssl.certificate.location=/path/to/client.crtclientCert, _ := tls.LoadX509KeyPair("/path/to/client.crt", "/path/to/client.key")
cl, err := kgo.NewClient(
kgo.SeedBrokers("localhost:9093"),
kgo.DialTLSConfig(&tls.Config{
RootCAs: pool, // the CA that signed the SERVER certificate
Certificates: []tls.Certificate{clientCert},
}),
)security.protocol=SSL
ssl.truststore.location=/path/to/truststore.jks
ssl.truststore.password=changeit
ssl.keystore.location=/path/to/client-keystore.jks
ssl.keystore.password=changeit
ssl.key.password=changeitmTLS and SASL don't stack. Only one identity source wins per connection: the certificate CN
is used only when SASL isn't required. If the listener also has Credentials configured,
the SASL identity takes precedence and the CN is never consulted — see
Authentication.
Related
Authentication
Authenticate Kafka clients to KubeMQ — SASL/PLAIN and SCRAM, OAUTHBEARER/OIDC federated tokens, mTLS client certificates, and the ACL model that authorizes each request.
Configuration
How the Kafka connector is enabled, ported, and secured — the opt-in CONNECTORS_KAFKA_ENABLE flag and the 9092/9093 listeners.
Kafka settings reference
The full field-by-field Connectors.Kafka settings, including the Port/TlsPort pairing rule.
Was this page helpful?
Authentication
Authenticate Kafka clients to KubeMQ — SASL/PLAIN and SCRAM, OAUTHBEARER/OIDC federated tokens, mTLS client certificates, and the ACL authorization model.
Migrate from Kafka
Assess fit with kmq assess kafka, then move topics and consumer-group offsets to KubeMQ with the kmq migrate tool.