In KRaft mode the built-in authorizer is org.apache.kafka.metadata.authorizer.StandardAuthorizer, which keeps ACLs in the metadata log beside the topics. With allow.everyone.if.no.acl.found=false (the default), a resource without ACLs is open only to super.users. An ACL lets or forbids a principal an operation (Read, Write, Create, Delete, Alter, Describe and six more) on a resource (a topic, group, the cluster, a transactional ID and others), named literally or by prefix; a matching DENY always wins. BookNest's admin creates two SCRAM users and grants each the least it needs:
k acls --add --allow-principal User:producer --producer \
--topic booknest. --resource-pattern-type prefixed # every booknest.* topic
k acls --add --allow-principal User:analytics --consumer \
--topic booknest.order-events --group booknest-analytics
k acls --add --allow-principal User:booknest-packer --consumer \
--topic booknest.order-events --group booknest-packers # the mutual-TLS client
k acls --list --principal User:analyticsAdding ACLs for resource `ResourcePattern(resourceType=TOPIC, name=booknest., patternType=PREFIXED)`: (principal=User:producer, host=*, operation=DESCRIBE, permissionType=ALLOW) ... Current ACLs for resource `ResourcePattern(resourceType=GROUP, name=booknest-analytics, patternType=LITERAL)`: (principal=User:analytics, host=*, operation=READ, permissionType=ALLOW)
k wraps kafka-<tool>.sh with the admin's client properties. --producer grants Describe, Create and Write; --consumer grants Describe and Read on the topic plus Read on the group, so the group name is part of the permission. Prefixed patterns stay short when topic names follow a convention (Kafka at BookNest); transactional producers (Transactions and Exactly-Once) also need Write and Describe on their transactional.id. Every denial is logged to kafka.authorizer.logger, where an audit trail starts.