Security — Kafka
This document covers authentication and authorization for the Kafka cluster (brokers) and Kafka UI.
For plain/TLS listeners, see Kafka Configuration.
Security model
Kafka UI authentication and Kafka broker authentication are separate concerns:
- a human user authenticates to Kafka UI via
kafka-ui.applicationConfig.auth(for exampleLOGIN_FORMorLDAP); - the Kafka UI backend connects to Kafka using the technical principal configured in
kafka-ui.connection.authentication; - Kafka brokers evaluate ACLs for the Kafka principal used by the application, not for the human user who logged into the UI.
Example:
- LDAP user
frylogs into Kafka UI; - Kafka UI connects to Kafka as
kafka-ui; - topic creation, message reading, and administrative actions are evaluated by Kafka as principal
kafka-ui.
This means that Kafka audit and authorization decisions are based on the Kafka user configured for the UI (kafka-ui), not on the LDAP username that logged in.
Broker authentication (SCRAM-SHA-512)
Security disabled (default)
By default, authentication and authorization are disabled:
security:
enabled: false
authentication:
enabled: false
authorization:
enabled: false
The plain and TLS listeners operate without authentication. Suitable only for controlled internal environments.
Enabling SCRAM-SHA-512 and simple ACLs
To enable SCRAM-SHA-512 authentication with simple ACLs:
security:
enabled: true
listener: plain
authentication:
enabled: true
type: scram-sha-512
authorization:
enabled: true
type: simple
superUsers:
- platform-admin
With security.enabled: true, Strimzi creates declarative KafkaUser resources and applies ACLs according to security.users.
Producer user (example)
security:
users:
- name: producer-app
acls:
- resource:
type: topic
name: orders.events
patternType: literal
operations:
- Write
- Create
- Describe
- resource:
type: cluster
operations:
- IdempotentWrite
Consumer user (example)
security:
users:
- name: consumer-app
acls:
- resource:
type: topic
name: orders.events
patternType: literal
operations:
- Read
- Describe
- resource:
type: group
name: orders-consumer
patternType: literal
operations:
- Read
Superuser (example)
security:
authorization:
superUsers:
- admin-user
users:
- name: admin-user
The admin-user entry is rendered as a KafkaUser; superuser access is granted by security.authorization.superUsers. Superusers do not need ACLs.
Strimzi generates a Secret with credentials for each KafkaUser:
kubectl -n <NAMESPACE> get kafkauser producer-app -o yaml
kubectl -n <NAMESPACE> get secret producer-app -o jsonpath='{.data.password}' | base64 -d
Typical SCRAM client properties:
bootstrap.servers=tdp-kafka-kafka-bootstrap:9092
security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="producer-app" password="<PASSWORD>";
Kafka UI — web authentication
Kafka UI supports two web authentication modes:
| Mode | Description |
|---|---|
LOGIN_FORM | Username and password defined in kafka-ui.applicationConfig |
LDAP | Authentication delegated to a corporate LDAP/AD server |
LOGIN_FORM (default)
kafka-ui:
applicationConfig:
auth:
type: LOGIN_FORM
spring:
security:
user:
name: admin
password: <PASSWORD>
LDAP (optional)
The chart offers two ways to provide the Kafka UI LDAP bind password. In both, web authentication is delegated to the LDAP server — the difference is how the bind password reaches the pod.
Option 1 — inline password in values (not recommended)
This option stores the bind password in plain text in the values file. Use it only in isolated tests — never in reachable environments or in values files committed to Git.
kafka-ui:
applicationConfig:
auth:
type: LDAP
spring:
ldap:
urls: ldap://<LDAP_HOST>:389
base: "<LDAP_USER_BASE_DN>"
admin-user: "<LDAP_BIND_DN>"
admin-password: "<LDAP_BIND_PASSWORD>"
management:
health:
ldap:
enabled: true
Option 2 — password via Secret (recommended)
The LDAP bind password should not be stored in plain text in the values file. Create a Secret and inject it via kafka-ui.envs.secretMappings. Kafka UI is a Spring Boot application — the environment variable SPRING_LDAP_ADMIN_PASSWORD overrides the spring.ldap.admin-password property at runtime.
Create the Secret before installing the chart:
kubectl create secret generic kafka-ui-ldap-secret \
--from-literal=admin-password=<LDAP_BIND_PASSWORD> \
-n <NAMESPACE>
kafka-ui:
enabled: true
yamlApplicationConfig: null
yamlApplicationConfigConfigMap:
name: tdp-kafka-ui-config
keyName: config.yml
applicationConfig:
auth:
type: LDAP
spring:
ldap:
urls: ldap://<LDAP_HOST>:389
base: "<LDAP_USER_BASE_DN>"
admin-user: "<LDAP_BIND_DN>"
management:
health:
ldap:
enabled: true
envs:
secretMappings:
SPRING_LDAP_ADMIN_PASSWORD:
name: kafka-ui-ldap-secret
keyName: admin-password
| Field | Description | Example |
|---|---|---|
urls | LDAP server address | ldap://ldap.empresa.com.br:389 |
base | User search base DN | dc=empresa,dc=com,dc=br |
admin-user | Bind user DN | cn=kafkaui,dc=empresa,dc=com,dc=br |
admin-password | Bind password — injected via envs.secretMappings (Secret kafka-ui-ldap-secret), never inline in the values file | — |
management.health.ldap.enabled | Enables the Kafka UI LDAP health check | true |
For LDAPS (TLS), replace ldap:// with ldaps:// and use port 636.
For a deployment with a secured broker (security.enabled: true), combine this UI authentication block with the Kafka UI — connection to the broker section block (below) in the same values file.
Kafka UI — broker connection
When security.enabled=true, create a KafkaUser corresponding to the UI's technical principal.
Strimzi generates a Secret with the same name as the user by default.
When security.enabled=true, the chart automatically injects security.protocol, sasl.mechanism, and sasl.jaas.config into the Kafka UI broker connection (kafka-ui.connection). These properties do not need to be set manually.
security:
enabled: true
authentication:
enabled: true
authorization:
enabled: true
kafka-ui:
connection:
clusterName: TDP
bootstrapServers: tdp-kafka-kafka-bootstrap:9092
authentication:
username: kafka-ui
existingSecret:
name: kafka-ui
passwordKey: password
Verify the generated Secret:
kubectl -n <NAMESPACE> get kafkauser kafka-ui -o yaml
kubectl -n <NAMESPACE> get secret kafka-ui -o yaml
If kafka-ui is promoted to superUser, all administrative access via the UI will run with full broker privileges.
Restrict Kafka UI access to a small set of trusted users in this scenario.
Typical SCRAM client properties for consumers:
bootstrap.servers=tdp-kafka-kafka-bootstrap:9092
group.id=orders-consumer
security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="consumer-app" password="<PASSWORD>";
Kafka UI RBAC
The kafka-ui.rbac block injects the rbac section into the Kafbat UI config.yml, allowing UI action restrictions per LDAP user — without granting administrative access to every authenticated user.
Recommended model:
- only a small set of trusted LDAP users should have full UI permissions;
- all other Kafka UI users should receive read-only permissions;
- if
kafka-uiis configured as a KafkasuperUser, UI RBAC should always be enabled.
kafka-ui:
rbac:
enabled: true
roles:
- name: admins
clusters:
- TDP
subjects:
- provider: ldap
type: user
value: fry
permissions:
- resource: topic
value: ".*"
actions: all
- name: readonly
clusters:
- TDP
subjects:
- provider: ldap
type: user
value: leela
permissions:
- resource: topic
value: ".*"
actions:
- view
- messages_read
With this model, fry uses the full UI and leela can only view topics and read messages — but Kafka still sees both operations as principal kafka-ui.
External producers and consumers
External applications must authenticate directly to Kafka with their own identities, without reusing the kafka-ui technical principal.
Recommendations:
- create one
KafkaUserper application or security boundary; - grant only the necessary ACLs;
- let Strimzi generate and manage credentials whenever possible;
- distribute the generated Secret securely to the application runtime.
The examples below assume the client can reach the selected Kafka listener. This chart exposes internal listeners by default — access from outside the cluster requires additional listener exposure, not covered by these examples.
TLS authentication (client)
For client TLS authentication, define the user with authentication.type: tls and connect via the TLS listener:
security:
listener: tls
users:
- name: consumer-tls
authentication:
type: tls
acls:
- resource:
type: topic
name: orders.events
patternType: literal
operations:
- Read
- Describe
- resource:
type: group
name: orders-consumer
patternType: literal
operations:
- Read
The generated Secret contains ca.crt, user.crt, user.key, user.p12, and user.password.
Typical TLS client properties using PEM files:
bootstrap.servers=tdp-kafka-kafka-bootstrap:9093
security.protocol=SSL
ssl.truststore.type=PEM
ssl.keystore.type=PEM
ssl.truststore.certificates=/etc/kafka-user/ca.crt
ssl.keystore.certificate.chain=/etc/kafka-user/user.crt
ssl.keystore.key=/etc/kafka-user/user.key
ACL guidance for producers and consumers
Use one Kafka principal per application or workload type. Avoid sharing a broad principal across multiple systems.
| Type | Typical ACLs |
|---|---|
| Producer | Write, Create, Describe on topic(s); IdempotentWrite on cluster for idempotent production |
| Consumer | Read, Describe on topics; Read on the consumer group |
| Admin / maintenance tool | Separate identity; do not reuse producer or consumer credentials |
| Superuser | Only when strictly required; avoid All unless necessary |
Do not version SCRAM passwords in public values.yaml files. Prefer createSecret: false with external Secrets in production.
Recommendations
| Aspect | Recommendation |
|---|---|
| Development environment | LOGIN_FORM with strong password, access via port-forward |
| Shared environment / production | LDAP with LDAPS (port 636) |
| Production broker | security.enabled: true with SCRAM-SHA-512 and minimal ACLs |
| Credentials | Never version passwords in public values.yaml |
| UI exposure | Prefer Ingress with TLS or controlled port-forward |
Troubleshooting
| Problem | Probable cause | Solution |
|---|---|---|
| Invalid credentials in the UI (LOGIN_FORM) | Incorrect password or typo in name/password | Check kafka-ui.applicationConfig.spring.security.user |
| LDAP login fails with "invalid credentials" | Incorrect bind DN or password | Test bind with external ldapsearch |
| LDAP login fails with "connection refused" | LDAP host/port inaccessible from the pod | Check network connectivity |
| Kafka UI cannot connect to the broker | Incorrect Secret or bootstrap servers | Check kafka-ui.connection and the KafkaUser Secret |
| Startup failure due to RBAC | RBAC resources or actions incompatible with the UI version | Check kafka-ui.rbac.roles and pod logs |
Changes to applicationConfig do not reflect | Pod not restarted after update | kubectl -n <NAMESPACE> rollout restart deployment <RELEASE_NAME>-kafka-ui |