Learning Platform
Глоссарий Troubleshooting
Урок 10.04 · 30 мин
Продвинутый
ACLAuthorizationStandardAuthorizerResource TypesOperationsLITERALPREFIXEDkafka-acls.sh

Авторизация с ACL

Аутентификация отвечает на вопрос “кто вы?”. Авторизация отвечает на вопрос “что вам разрешено?”. В Kafka авторизация реализована через ACL (Access Control Lists) — явные правила, определяющие, какой principal может выполнять какие операции с какими ресурсами.


Authorizer в Kafka 4.0 (KRaft)

В Kafka 4.0 используется StandardAuthorizer — KRaft-нативный authorizer. Его предшественник AclAuthorizer хранил ACL в ZooKeeper и полностью удалён вместе с ZooKeeper.

# ВАЖНО: только StandardAuthorizer в Kafka 4.0
# AclAuthorizer (kafka.security.authorizer.AclAuthorizer) — УДАЛЁН
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer

# Deny by default: если для операции нет ACL — ЗАПРЕТ
allow.everyone.if.no.acl.found=false

# Super users: обходят все ACL-проверки
super.users=User:admin;User:kafka-controller

# Разрешить старт брокера до загрузки всех ACL из metadata log
early.start.listeners=CONTROLLER
WARNING

allow.everyone.if.no.acl.found=true (default в dev-конфигурациях) разрешает ВСЕ операции ВСЕМ пользователям при отсутствии ACL. В production ОБЯЗАТЕЛЬНО false. Одна неправильная настройка = полный доступ ко всем данным.

ACL в Kafka 4.0 хранятся в __cluster_metadata internal topic (KRaft log контроллера). Изменения ACL применяются через kafka-acls.sh и реплицируются на все брокеры через KRaft consensus.


ACL Resource Hierarchy

Kafka ACL: Иерархия ресурсов и разрешений
ClusterРесурс Cluster — верхний уровень. Операции: Create (топики, ACLs), ClusterAction (контроллер), Alter/Describe (конфигурация кластера). ACL на уровне Cluster действуют глобально. super.users обходят все ACL-проверки. authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer (Kafka 4.0, KRaft — НЕ AclAuthorizer).
TopicРесурс Topic — самый частый. Операции: Read (consume), Write (produce), Create, Delete, Describe, DescribeConfigs, AlterConfigs. PatternType: LITERAL (точное имя) или PREFIXED (orders.* — все топики с префиксом 'orders.'). Пример: --allow-principal User:producer --operation Write --topic orders
GroupРесурс Group — consumer groups. Операции: Read (join group, commit offsets), Describe (list members). Каждый consumer group ID требует ACL на Read для участия в группе. PREFIXED ACL: --resource-pattern-type prefixed --group 'myapp.' покрывает все группы myapp.*
TransactionalIdРесурс TransactionalId — для транзакционных продюсеров. Операции: Write (initTransactions), Describe, IdempotentWrite. Каждый transactional.id требует Write ACL. Без этого ACL продюсер с enable.idempotence=true и transactional.id получит AuthorizationException.
DelegationTokenРесурс DelegationToken — для делегированных токенов аутентификации. Операции: Describe (просмотр), Create (создание нового токена). Используется в сценариях, где Kerberos или SCRAM credentials нельзя передать напрямую (например, Kafka Streams задачи в Kubernetes).
TopicТопик — основной ресурс для продюсеров и консьюмеров. Поддерживает наибольшее число операций.
+Read на Topic: потребитель может читать сообщения из топика. Требуется вместе с Read на Group для полноценного consumer group consume.
+Write на Topic: продюсер может публиковать сообщения в топик. Основное разрешение для producer. Отдельно от Create (создание топика).
+Create на Topic: позволяет создавать топик. Обычно назначается администраторам или CI/CD. В большинстве продакшн-систем auto.create.topics.enable=false и создание требует явного ACL.
+Delete на Topic: позволяет удалять топик или его записи (kafka-delete-records.sh). Опасная операция — данные теряются безвозвратно. Назначайте только администраторам.
+Describe на Topic: просмотр метаданных (начальные/конечные смещения, ISR, лидеры). Требуется потребителям для metadata refresh. Без Describe клиент получает TOPIC_AUTHORIZATION_FAILED.
+All на Topic: сокращение для всех операций на топике. Удобно для сервисов-владельцев, но нарушает принцип минимальных привилегий. Используйте только для admin-аккаунтов.
GroupConsumer Group — группа потребителей. Ограниченный набор операций.
+Read на Group: позволяет присоединяться к consumer group, участвовать в ребалансировке, коммитить смещения. БЕЗ Read на Group consumer получит GroupAuthorizationException при попытке JoinGroup.
Write на Group: не применяется. Consumer groups не поддерживают операцию Write.
Create на Group: не применяется. Consumer groups создаются автоматически при первом JoinGroup запросе.
Delete на Group: не применяется через ACL. Удаление группы выполняется через kafka-consumer-groups.sh --delete (требует Cluster-level права).
+Describe на Group: просмотр состояния group (члены, смещения, лаг). Требуется для kafka-consumer-groups.sh --describe и для мониторинга лага.
+All на Group: включает Read + Describe. Для consumer group достаточно и обычно используется в упрощённых ACL конфигурациях.
TransactionalIdTransactionalId — идентификатор транзакционного продюсера.
Read на TransactionalId: не применяется.
+Write на TransactionalId: позволяет инициализировать транзакцию (initTransactions()), отправлять сообщения в рамках транзакции. БЕЗ Write на TransactionalId продюсер получит TransactionalIdAuthorizationException.
Create на TransactionalId: не применяется.
Delete на TransactionalId: не применяется.
+Describe на TransactionalId: просмотр состояния транзакции. Используется для диагностики зависших транзакций.
+All на TransactionalId: Write + Describe. Назначается сервисам с transactional.id.
LITERALordersТочное совпадение имени ресурса. --topic orders — ACL действует только на топик с именем 'orders'. Самый безопасный вариант — минимальные привилегии. По умолчанию, если --resource-pattern-type не указан.
PREFIXEDorders.*Совпадение по префиксу. --resource-pattern-type prefixed --topic 'orders.' — ACL действует на все топики, начинающиеся с 'orders.' (orders.created, orders.updated, orders.deleted). Удобно для сервисов, владеющих namespace. Используйте осторожно: слишком широкий префикс = чрезмерные права.
allow.everyone.if.no.acl.foundfalse (default)Если false (по умолчанию): операция без соответствующего ACL запрещена. Это безопасный режим — deny by default. Если true: операции без ACL разрешены всем. Используется только в dev/test средах. В production ВСЕГДА оставляйте false.

Диаграмма выше показывает иерархию ресурсов и матрицу операций. Каждый ACL определяет: principal (кому), operation (что разрешено), resource type + name (на каком ресурсе), permission type (ALLOW или DENY).


Resource Types: пять типов ресурсов

Topic

Самый частый тип. ACL на топик контролирует produce и consume.

Topic: операции
ReadConsume из топика. Читать сообщения через FetchRequest. ВАЖНО: для consume нужны ОБА — Read на Topic И Read на Group (для commit offsets). Только Read на Topic без Group ACL — consumer не сможет присоединиться к consumer group.
WriteProduce в топик. Отправлять ProduceRequest. Для транзакционного producer дополнительно нужен Write на TransactionalId и IdempotentWrite на Cluster.
CreateАвто-создание топика при первом produce. Если auto.create.topics.enable=true на брокере и producer пишет в несуществующий топик — нужен Create на Cluster или Create на Topic. В production обычно auto.create.topics.enable=false.
DescribeПолучение метаданных топика: количество партиций, replica assignment, leader. Без Describe consumer не может выполнить metadata refresh и не знает, к какому брокеру обращаться. Часто забывают — и получают 'TopicAuthorizationException' при metadata запросе.

Group

Consumer Group ACL контролирует участие в consumer group.

Group: операции
ReadПрисоединиться к consumer group (JoinGroup request), commit offsets (OffsetCommit request), fetch committed offsets (OffsetFetch). Это самый важный ACL для consumer: без Read на Group consumer не может использовать consumer group.
DescribeОписать consumer group: список членов, их partition assignment, committed offsets, group lag. Используется kafka-consumer-groups.sh --describe и AdminClient.describeConsumerGroups(). Нужен для мониторинга и диагностики lag без участия в группе.

Cluster

Cluster-level операции: AdminClient действия и inter-broker.

Cluster: операции
CreateСоздание топиков через AdminClient.createTopics(). Отличается от Topic:Create: здесь это операция на уровне кластера через AdminClient, не авто-создание через produce. В production: только admin service имеет Cluster:Create.
IdempotentWriteВключить idempotent producer (enable.idempotence=true). Idempotent producer получает Producer ID от брокера. Без Cluster:IdempotentWrite idempotent producer получит ClusterAuthorizationException. Требуется для любого producer с enable.idempotence=true или acks=all.
ClusterActionВнутренние broker-to-broker операции: репликация (LeaderAndIsr, StopReplica), controller действия. Эту операцию должны иметь только брокеры (kafka-broker principal). Клиентские приложения никогда не нуждаются в ClusterAction.

TransactionalId

Transactional producer использует transactional.id для гарантии exactly-once. ACL на TransactionalId контролирует, кто может использовать конкретный transactional.id.

Write on TransactionalId: инициализировать транзакцию (initTransactions)
Describe on TransactionalId: описать транзакционное состояние

DelegationToken

Delegation tokens позволяют сервисам делегировать аутентификацию другим компонентам без передачи credentials.


PatternType: LITERAL vs PREFIXED

PatternType определяет, как имя ресурса в ACL сопоставляется с реальными ресурсами.

LITERAL vs PREFIXED Pattern Matching
PatternType определяет область применения ACL
LITERAL (точное совпадение)ACL применяется только к ресурсу с точно таким именем. --topic orders применяется только к топику 'orders'. Топики 'orders-created', 'orders-archive' — НЕ покрываются. Используйте LITERAL когда сервис работает с конкретным топиком.
PREFIXED (по префиксу)ACL применяется ко всем ресурсам, начинающихся с указанного префикса. --topic 'orders.' --resource-pattern-type prefixed применяется к 'orders.created', 'orders.updated', 'orders.archived' и любому другому топику с prefix 'orders.'. Идеально для service namespace ownership.

kafka-acls.sh: команды

Выдать права producer

# Producer: Write + Describe на топик (минимум для produce)
kafka-acls.sh --bootstrap-server localhost:9092 \
  --command-config admin.properties \
  --add \
  --allow-principal User:producer-app \
  --operation Write \
  --operation Describe \
  --topic orders

Выдать права consumer

# Consumer: Read на топик + Read на consumer group
kafka-acls.sh --bootstrap-server localhost:9092 \
  --command-config admin.properties \
  --add \
  --allow-principal User:consumer-app \
  --operation Read \
  --operation Describe \
  --topic orders

kafka-acls.sh --bootstrap-server localhost:9092 \
  --command-config admin.properties \
  --add \
  --allow-principal User:consumer-app \
  --operation Read \
  --group consumer-group-1

Transactional producer (минимальный набор ACL)

# 1. Write + Describe на топик
kafka-acls.sh --add --allow-principal User:txn-producer \
  --operation Write --operation Describe --topic orders

# 2. Write на TransactionalId
kafka-acls.sh --add --allow-principal User:txn-producer \
  --operation Write \
  --transactional-id txn-orders

# 3. Idempotent write на кластере
kafka-acls.sh --add --allow-principal User:txn-producer \
  --operation IdempotentWrite \
  --cluster

# Если consumer group тоже нужна (transactional consumer):
kafka-acls.sh --add --allow-principal User:txn-producer \
  --operation Read --group txn-group

PREFIXED ACL для service namespace

# Payments service: все топики с prefix 'payments.'
kafka-acls.sh --bootstrap-server localhost:9092 \
  --add \
  --allow-principal User:payments-svc \
  --operation Write --operation Read --operation Describe \
  --topic 'payments.' \
  --resource-pattern-type prefixed

# Payments service: все consumer groups с prefix 'payments-'
kafka-acls.sh --bootstrap-server localhost:9092 \
  --add \
  --allow-principal User:payments-svc \
  --operation Read \
  --group 'payments-' \
  --resource-pattern-type prefixed

Просмотр и удаление ACL

# Список всех ACL на топик 'orders'
kafka-acls.sh --bootstrap-server localhost:9092 \
  --command-config admin.properties \
  --list --topic orders

# Список всех ACL в кластере
kafka-acls.sh --bootstrap-server localhost:9092 \
  --command-config admin.properties \
  --list

# Удалить ACL
kafka-acls.sh --bootstrap-server localhost:9092 \
  --remove \
  --allow-principal User:old-producer \
  --operation Write --topic orders

ACL-стратегия для production

Namespace-based подход

Каждый сервис владеет namespace (prefix) для своих ресурсов. Payments service создаёт топики payments.transactions, payments.refunds, payments.events — и получает PREFIXED ACL на payments..

Сервис            Prefix          ACL pattern type
payments-svc    → payments.     → PREFIXED Write на Topic
orders-svc      → orders.       → PREFIXED Write на Topic
notifications   → notify.       → PREFIXED Write на Topic

Преимущества:

  • Один ACL вместо N ACL при добавлении нового топика.
  • Сервис не может случайно записать в чужой namespace.
  • Понятная модель ownership.

Принцип минимальных привилегий

TIP

Начните с deny-by-default (allow.everyone.if.no.acl.found=false) и super.users для admin. Затем добавляйте ACL per-service по мере необходимости. Принцип минимальных привилегий: каждый сервис имеет ровно те права, которые нужны для его работы — не больше.

Отдельные principals для каждого приложения — никогда не делите credentials между сервисами. Если сервис A скомпрометирован — только его credentials отзываются, остальные в безопасности.

Deny ACL для инцидент-реагирования

# Немедленно заблокировать скомпрометированный сервис
kafka-acls.sh --add \
  --deny-principal User:compromised-app \
  --operation All \
  --topic '*' \
  --resource-pattern-type prefixed \
  --group '*' \
  --resource-pattern-type prefixed

DENY ACL имеет приоритет над ALLOW ACL — даже если у principal есть разрешающее правило, DENY перекрывает его.


ACL и SASL principal mapping

Как Kafka формирует principal из SASL аутентификации:

SASL механизмPrincipal форматПример
PLAINUser:<username>User:alice
SCRAMUser:<username>User:producer-app
OAUTHBEARERUser:<claim> (по умолчанию sub)User:kafka-producer-client-id
GSSAPIUser:<kerberos-principal>User:[email protected]
mTLSUser:<CN из сертификата>User:payment-service

Для OAUTHBEARER можно настроить, какой JWT claim использовать как principal:

# Использовать claim 'preferred_username' вместо 'sub'
sasl.oauthbearer.sub.claim.name=preferred_username

Для полной кастомизации — principal.builder.class с реализацией KafkaPrincipalBuilder.


Типичные ошибки с ACL

Consumer не может consume из топика:

  • Забыли Group:Read ACL (consumer не может join/commit в consumer group).
  • Забыли Topic:Describe (metadata refresh failing).

Transactional producer получает ошибку:

  • Забыли Cluster:IdempotentWrite.
  • Забыли TransactionalId:Write.

Service создаёт топики через AdminClient:

  • Нужен Cluster:Create (не Topic:Create).

PREFIXED ACL не работает:

  • Убедитесь, что указали --resource-pattern-type prefixed в kafka-acls.sh.
  • По умолчанию тип LITERAL — при отсутствии флага создаётся LITERAL ACL.

Ключевые выводы

  1. Kafka 4.0 использует StandardAuthorizer — ACL в KRaft metadata log. AclAuthorizer удалён.
  2. allow.everyone.if.no.acl.found=false — обязательно в production. Deny by default.
  3. Consumer minimum: Topic:Read + Topic:Describe + Group:Read. Producer minimum: Topic:Write + Topic:Describe.
  4. Transactional producer дополнительно: TransactionalId:Write + Cluster:IdempotentWrite.
  5. PREFIXED ACL для service namespace ownership — один ACL для всех топиков сервиса.
  6. DENY ACL для инцидент-реагирования: перекрывает ALLOW ACL.
Проверка знанийKnowledge check
Сервис order-processor использует transactional producer (transactional.id=order-txn) для записи в топик orders-enriched и коммита offset-ов consumer group order-processor-group. Какие ACL (минимум) необходимы для этого сервиса?
ОтветAnswer
Минимальный набор ACL для сервиса order-processor: 1. Topic:Write на 'orders-enriched' — produce в топик. 2. Topic:Describe на 'orders-enriched' — metadata refresh. 3. TransactionalId:Write на 'order-txn' — initTransactions для transactional producer. 4. Cluster:IdempotentWrite — для idempotent producer (transactional producer всегда idempotent). 5. Topic:Read на исходный топик (если сервис также читает, например 'orders-raw') + Topic:Describe. 6. Group:Read на 'order-processor-group' — join group + commit offsets. Если топик 'orders-raw' не нужен — минимум: 4 ACL (Topic:Write+Describe на orders-enriched, TransactionalId:Write на order-txn, Cluster:IdempotentWrite, Group:Read на order-processor-group).

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. В Kafka 4.0 KRaft-кластере команда пытается установить authorizer.class.name=kafka.security.authorizer.AclAuthorizer. Что произойдёт при запуске брокера?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6