Security Overview
By default a Kafka cluster is wide open: clients connect over plaintext, no credentials are required, and any connected principal can read or write any topic. That is fine on a laptop, but in production an unsecured broker is a data breach waiting to happen. Kafka security is built on three independent but complementary pillars — encryption in transit, authentication, and authorization — and this page maps how they fit together so you know which detail page to reach for next.
The three pillars
Each pillar answers a different question, and you can enable them independently. In practice a hardened cluster uses all three.
| Pillar | Question it answers | Mechanisms |
|---|---|---|
| Encryption | Can someone on the wire read or tamper with my data? | TLS (SSL) |
| Authentication | Who is connecting? | mTLS, SASL/PLAIN, SASL/SCRAM, GSSAPI (Kerberos), OAUTHBEARER |
| Authorization | What is this identity allowed to do? | ACLs (and pluggable authorizers) |
Authentication establishes a principal (an identity such as User:orders-service). Authorization then evaluates ACLs against that principal. Encryption protects the bytes regardless of who is talking. Get them in that order — there is no point authorizing a connection you cannot trust the identity of, and no point trusting an identity sent over plaintext.
Encryption in transit (TLS)
TLS encrypts every connection between clients and brokers, and between brokers themselves (inter-broker traffic and KRaft controller traffic). It guarantees confidentiality and integrity, and — when the client validates the broker certificate — server authenticity. Kafka still calls this “SSL” in its configuration keys for historical reasons, but it negotiates modern TLS. Enabling TLS requires a keystore on each broker and a truststore on each client that trusts the signing CA. See SSL/TLS encryption for keystore generation and the full broker config.
Authentication
Authentication proves the identity of the connecting party. Kafka supports two broad families.
mTLS (mutual TLS) reuses the TLS layer: the client presents its own certificate, and the broker derives the principal from the certificate’s Distinguished Name. No passwords are exchanged, which makes it ideal for service-to-service traffic.
SASL is a pluggable framework offering several mechanisms:
| Mechanism | Credential | Typical use |
|---|---|---|
PLAIN | Username + password | Simple setups; only safe over TLS |
SCRAM-SHA-256 / SCRAM-SHA-512 | Salted hashed password | Recommended password-based auth |
GSSAPI | Kerberos ticket | Enterprises with existing Kerberos/AD |
OAUTHBEARER | OAuth 2.0 / OIDC token | Cloud-native, short-lived tokens |
SASL/PLAIN sends the password in clear text inside the SASL handshake. Never use
SASL_PLAINTEXTwithPLAINoutside a trusted network — always pair it with TLS (SASL_SSL). SCRAM is the safer default because the password never crosses the wire.
A minimal SCRAM client configuration looks like this.
security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
username="orders-service" \
password="${ORDERS_SECRET}";
ssl.truststore.location=/etc/kafka/secrets/truststore.jks
ssl.truststore.password=${TRUSTSTORE_PASSWORD}
The SASL authentication page covers creating SCRAM credentials and configuring each mechanism end to end.
Authorization (ACLs)
Once a principal is established, the broker’s authorizer decides whether each operation is permitted. Kafka ships with StandardAuthorizer (the KRaft-native authorizer that stores ACLs in the metadata log). An ACL binds a principal, an operation (Read, Write, Create, Describe, …), and a resource pattern (a topic, group, cluster, or transactional id).
kafka-acls.sh --bootstrap-server broker:9093 \
--command-config admin.properties \
--add \
--allow-principal User:orders-service \
--operation Write --operation Describe \
--topic orders
Output:
Adding ACLs for resource `ResourcePattern(resourceType=TOPIC, name=orders, patternType=LITERAL)`:
(principal=User:orders-service, host=*, operation=WRITE, permissionType=ALLOW)
(principal=User:orders-service, host=*, operation=DESCRIBE, permissionType=ALLOW)
See authorization with ACLs for the full operation/resource matrix and patterns like prefixed ACLs.
Listeners and security protocols
Security is configured per listener. A broker can expose several listeners on different ports, each combining a transport (plaintext or TLS) with an authentication method (none or SASL). The combination is the security protocol.
| Security protocol | Encrypted? | Authenticated? |
|---|---|---|
PLAINTEXT | No | No |
SSL | Yes | mTLS (optional) |
SASL_PLAINTEXT | No | SASL |
SASL_SSL | Yes | SASL (and/or mTLS) |
A typical hardened broker exposes an internal mTLS listener for inter-broker traffic and an external SASL_SSL listener for applications.
listeners=INTERNAL://:9092,EXTERNAL://:9093
listener.security.protocol.map=INTERNAL:SSL,EXTERNAL:SASL_SSL
inter.broker.listener.name=INTERNAL
sasl.enabled.mechanisms=SCRAM-SHA-512
ssl.client.auth=required
Map listener names to protocols explicitly with
listener.security.protocol.map. A common production mistake is leaving aPLAINTEXTlistener bound to an external interface — scan yourlistenersand firewall rules to confirm no unauthenticated port is reachable.
Best practices
- Enable all three pillars together: TLS for the wire, SASL or mTLS for identity, ACLs for least-privilege access.
- Prefer
SASL_SSLwith SCRAM-SHA-512 or mTLS; reservePLAINTEXTfor local development only. - Use a dedicated principal per application and grant the narrowest ACLs that work, rather than wildcard
User:*grants. - Set
allow.everyone.if.no.acl.found=falseso the authorizer denies by default once enabled. - Keep keystores, truststores, and JAAS secrets out of source control — inject them via environment variables or a secret manager.
- Rotate certificates and SCRAM credentials on a schedule, and audit ACL changes (see audit and compliance).