Опирается на правила: R-KFK-SEC-1R-KFK-SEC-3 и R-KFK-SEC-X1R-KFK-SEC-X2 из Kafka Style Guide → раздел 9. Security.

Важно знать

  • TLS обязателен в проде (security.protocol: SSL). SASL/PLAIN over plaintext — запрещено.
  • ACLs per-сервис — каждый service-account имеет ACL только на свои топики.
  • PII — отдельные restricted topics с узким ACL, либо «слабая ссылка»: в широком топике customerId, PII подгружается через customer-service.
  • PLAINTEXT — только локальная разработка.
  • Один service-account на кластер — компрометация одного сервиса даёт доступ ко всем topics.

Kafka — это общий бус между сервисами. Без security broker становится open relay: любой компонент видит все сообщения, любой может публиковать в любой topic, PII разлетается по подписчикам. UCP формулирует три слоя защиты: транспортный (TLS), авторизационный (ACLs), data-classification (PII в restricted topics).

TLS обязателен

R-KFK-SEC-1: cross-network — только зашифрованно.

spring:
  kafka:
    bootstrap-servers: ${KAFKA_BROKERS}
    properties:
      security.protocol: SSL
      ssl.truststore.location: ${KAFKA_TRUSTSTORE_PATH}
      ssl.truststore.password: ${KAFKA_TRUSTSTORE_PASSWORD}
      ssl.keystore.location: ${KAFKA_KEYSTORE_PATH}
      ssl.keystore.password: ${KAFKA_KEYSTORE_PASSWORD}
      ssl.endpoint.identification.algorithm: https

security.protocol: SSL — все сообщения зашифрованы TLS 1.2+.

ssl.endpoint.identification.algorithm: https — клиент проверяет, что hostname в Kafka-broker-сертификате совпадает с подключаемым адресом. Без этого — MITM возможен.

mTLS (mutual TLS) — broker верифицирует клиента через client-сертификат. Это даёт автоматическую identity-привязку для ACLs (см. ниже).

Альтернатива — SASL/SCRAM-SHA-512 over TLS (SASL_SSL), если client-сертификаты тяжело раздавать. SASL/PLAIN over TLS — допустимо для test, не для prod (password в plain после TLS-decrypt).

Никогда PLAINTEXT в проде

# КАТАСТРОФА
security.protocol: PLAINTEXT

В сетевом capture все сообщения, headers, токены, payload — в открытом виде. Insider attack возможен на любом hop в сети.

Только локальная разработка (docker-compose с одним broker, своя сеть).

ACLs per-сервис

R-KFK-SEC-2: каждый сервис имеет identity и ACL.

service-account: order-service
  ACL:
    READ:   payment.events, inventory.events
    WRITE:  order-service.order.created, order-service.order.confirmed, order-service.order.cancelled

service-account: billing-service
  ACL:
    READ:   order-service.order.confirmed
    WRITE:  billing-service.invoice.created

order-service не может писать в payment.events (это публикует payment-service). billing-service не может писать в order.confirmed (это публикует order-service).

Идентификация client → service-account идёт через mTLS-сертификат (CN=order-service-prod в client cert) или SASL-username.

ACLs управляются через kafka-acls.sh:

kafka-acls.sh --bootstrap-server kafka:9092 \
  --add --allow-principal User:order-service-prod \
  --operation Read \
  --topic payment.events

В реальной инфре ACLs описываются в IaC (Terraform, Pulumi), не руками. Проектирование — DevOps/SRE, использование — application через clientId в KafkaSettings.

PII в restricted topics

R-KFK-SEC-3: два паттерна.

Паттерн 1: отдельный restricted topic

customer-service публикует:
  - customer.events                 ← широкий, без PII (customerId only)
  - customer.events.full            ← restricted, с PII

ACL для customer.events.full:
  READ: notification-service, customer-support-service

Большинство подписчиков читают customer.events (Id-only). Только сервисы, которым реально нужен email/phone, имеют ACL на customer.events.full.

Паттерн 2: «слабая ссылка»

order-service публикует:
  - order.confirmed { orderId, customerId, totalAmount }

notification-service:
  - получает event
  - GET /customers/{customerId}/email (HTTP к customer-service)
  - sendEmail(email, ...)

PII никогда не появляется в Kafka. Каждый раз когда notification нужен email — отдельный API-вызов с audit log.

Цена — больше HTTP-нагрузки на customer-service. Преимущество — нет PII в Kafka backup, в DLQ, в logs.

Для большинства случаев слабая ссылка предпочтительнее: проще, меньше уязвимостей.

Что запрещено

PLAINTEXT в проде

R-KFK-SEC-X1: см. секцию выше. Только локальная разработка.

Один service-account на весь кластер

R-KFK-SEC-X2: классическая ошибка.

service-account: app
  ACL:
    READ:   *
    WRITE:  *

Все сервисы (order-service, payment-service, billing-service, …) используют один и тот же kafka-username: app. ACLs не реализованы — broker даёт всем доступ ко всему.

Что ломается:

  • Blast radius — компрометация одного сервиса (XSS, RCE, leaked credentials) даёт attacker'у доступ ко всем топикам.
  • Audit — невозможно понять, какой сервис опубликовал spurious event («кто-то от имени app»).
  • Mistakes — bug в order-service может писать в payment.events, downstream payment-side consumer обрабатывает «лишнее» событие.

Per-сервис identity + ACLs — must для production.

Что запрещено — таблица

АнтипаттернПравилоЧто взамен
PLAINTEXT в продеR-KFK-SEC-X1TLS / SASL_SSL
Один service-account на кластерR-KFK-SEC-X2per-сервис identity + ACLs
PII в широковещательных topicsR-KFK-SEC-3restricted topic или слабая ссылка
ssl.endpoint.identification.algorithm: пустойR-KFK-SEC-1https для MITM защиты
SASL/PLAIN over PLAINTEXTR-KFK-SEC-1минимум SASL_SSL
Credentials в application.ymlR-KFK-SEC-2env / Vault
ACLs только на read, не на writeR-KFK-SEC-2both, и --operation Create для topic creation

Куда дальше

  • Kafka → раздел 9. Security — нормативные формулировки.
  • Event design — PII не в payload broadcast топиков.
  • Configuration — credentials через env.
  • Auth → AUTH-16 — PII в логах + Kafka общая политика.
  • Security style guide — общие принципы.
  • Distributed → idempotency — ACLs не заменяют idempotency.