Translating Kafka ACLs
Turn an Apache Kafka ACL set into KubeMQ authorization rules — the resource mapping, the operations that differ, and a worked example.
KubeMQ does not keep a Kafka ACL store. Access for Kafka clients is written as KubeMQ authorization
rules — the same policy every KubeMQ connector uses — and this page is the translation table. The
Kafka ACL admin calls are answered honestly rather than faked: kafka-acls --add (CreateAcls) is
refused with SECURITY_DISABLED and a message naming the policy mechanism, and DescribeAcls
returns an empty list — so a script that provisions ACLs fails loudly instead of appearing to
succeed. Authorization is off by
default; it is enabled and supplied as described in
Security → Authorization.
The rule shape
A policy is a JSON array of rules. For Kafka, every rule sets EventsStore: true — Kafka topics,
consumer groups and transactional ids all live there:
[
{ "EventsStore": true, "ClientID": "orders-service", "Channel": "orders", "Read": false, "Write": true }
]ClientIDis the authenticated principal: the SASL username, the OAUTHBEARER token'ssub, or the client certificate's common name (Authentication).Channelis the bare name of a topic, a consumer group, or a transactional id — there is no resource-type prefix, so a topic and a group with the same name share a rule.- Both are regular expressions matched against the whole value:
ordersmatches onlyorders;orders-.*matches everyorders-topic;.*matches everything, including the*that stands for "the whole cluster" below.
With authorization on, a request with no authenticated principal is refused — there is no anonymous access.
Translation table
| Kafka ACL | KubeMQ rule |
|---|---|
Topic READ | Read on the topic |
Topic WRITE | Write on the topic |
Topic DESCRIBE, DESCRIBE_CONFIGS | Read on the topic |
Topic CREATE, DELETE, ALTER, ALTER_CONFIGS | Write on the topic |
Group READ (consume and commit offsets) | Read and Write on the group — see below |
Group DESCRIBE | Read on the group |
Group DELETE | Write on the group |
TransactionalId WRITE | Write on the transactional id |
Cluster IDEMPOTENT_WRITE | Write on channel * (a rule with Channel: ".*" covers it) |
Cluster DESCRIBE (list groups, describe cluster) | Read on channel * |
Where it differs from Kafka
Two operations need more than their Kafka equivalent:
- Committing a consumer offset needs
Writeon the group. Apache Kafka asks for GroupREAD. A consumer translated with only Read consumes but fails its first commit withGROUP_AUTHORIZATION_FAILED. - A transaction's offset commit needs
Writeon the group (AddOffsetsToTxn,TxnOffsetCommit), where Kafka again asks for Read. Exactly-once pipelines — Kafka Streams withexactly_once_v2, consume-transform-produce — hit this first.
And one needs less spelling out: an idempotent producer — the default since Kafka 3.0 —
initialises with Write on the cluster channel *. Kafka 2.8+ accepts Topic Write in its place;
here, add the cluster rule.
Worked example
A Kafka ACL set for one service that consumes orders, writes orders-enriched transactionally,
and runs as orders-service:
User:orders-service Topic:orders READ
User:orders-service Topic:orders-enriched WRITE
User:orders-service Group:enricher READ
User:orders-service TransactionalId:enricher- WRITE (prefixed)[
{ "EventsStore": true, "ClientID": "orders-service", "Channel": "orders", "Read": true, "Write": false },
{ "EventsStore": true, "ClientID": "orders-service", "Channel": "orders-enriched", "Read": false, "Write": true },
{ "EventsStore": true, "ClientID": "orders-service", "Channel": "enricher", "Read": true, "Write": true },
{ "EventsStore": true, "ClientID": "orders-service", "Channel": "enricher-.*", "Read": false, "Write": true },
{ "EventsStore": true, "ClientID": "orders-service", "Channel": "\\*", "Read": false, "Write": true }
]The group rule carries Write for the offset commits; the last rule is the idempotent-producer
cluster grant, written as \\* so it matches only the cluster channel rather than every name.
A denied request answers with the same codes Kafka uses: TOPIC_AUTHORIZATION_FAILED,
GROUP_AUTHORIZATION_FAILED, TRANSACTIONAL_ID_AUTHORIZATION_FAILED or
CLUSTER_AUTHORIZATION_FAILED. In a request that names several topics, only the denied ones fail.
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.
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.