Skip to content
Apache Kafka kf security 4 min read

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.

PillarQuestion it answersMechanisms
EncryptionCan someone on the wire read or tamper with my data?TLS (SSL)
AuthenticationWho is connecting?mTLS, SASL/PLAIN, SASL/SCRAM, GSSAPI (Kerberos), OAUTHBEARER
AuthorizationWhat 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:

MechanismCredentialTypical use
PLAINUsername + passwordSimple setups; only safe over TLS
SCRAM-SHA-256 / SCRAM-SHA-512Salted hashed passwordRecommended password-based auth
GSSAPIKerberos ticketEnterprises with existing Kerberos/AD
OAUTHBEAREROAuth 2.0 / OIDC tokenCloud-native, short-lived tokens

SASL/PLAIN sends the password in clear text inside the SASL handshake. Never use SASL_PLAINTEXT with PLAIN outside 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 protocolEncrypted?Authenticated?
PLAINTEXTNoNo
SSLYesmTLS (optional)
SASL_PLAINTEXTNoSASL
SASL_SSLYesSASL (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 a PLAINTEXT listener bound to an external interface — scan your listeners and 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_SSL with SCRAM-SHA-512 or mTLS; reserve PLAINTEXT for 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=false so 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).
Last updated June 1, 2026
Was this helpful?