Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
kafka-keycloak-oauth — Apache Kafka 4.1.0 (KRaft) с аутентификацией Keycloak OAuth2 с использованием Strimzi — обход ограничения списка разрешённых URL-адресов CVE-2025-27817 | Kitploit
Инструменты/GitHubGitHub/oriolrius/kafka-keycloak-oauth
Безопасность облачной инфраструктурыАнализ уязвимостейАудит конфигурацииDevSecOpsАутентификацияОбучение и Образование
GitHuboriolrius/kafka-keycloak-oauth

kafka-keycloak-oauth

Apache Kafka 4.1.0 (KRaft) с аутентификацией Keycloak OAuth2 с использованием Strimzi — обход ограничения списка разрешённых URL-адресов CVE-2025-27817

Популярное

Смотреть все →

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

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Репозиторий
5310 месяцев назадЕщё не проверено
Поделиться

Apache Kafka 4.1.0 с аутентификацией Keycloak OAuth2

Production-ready Apache Kafka 4.1.0 (режим KRaft) с аутентификацией Keycloak 26.1.1 OAuth2/OIDC с использованием образа Strimzi Kafka.

Почему этот проект вместо kafka-oauth-keycloak-tls-demo

Это эволюция предыдущего POC со значительными улучшениями:

  • Strimzi OAuth 0.17.0 (вместо 1.0.0) — стабильная production-версия, встроенная в образ Strimzi Kafka 0.48.0
  • Не требуется пользовательская сборка Docker — используется официальный образ Strimzi с предустановленным OAuth, что устраняет сложность Dockerfile
  • Осведомлённость о CVE-2025-27817 — документировано ограничение списка разрешённых URL и причина, по которой Strimzi OAuth обходит его
  • Упрощённая архитектура — единый комбинированный режим KRaft (брокер+контроллер), а не разделённая архитектура
  • Фокус на клиенте librdkafka — протестировано с confluent-kafka-python (работает без проблем со списком разрешённых URL), а не с нативными Java-клиентами
  • Комплексная техническая документация — производственный чек-лист, устранение неполадок, настройка производительности, детали маппинга principal
  • Более чистое управление сертификатами — включены примеры сертификатов для немедленного тестирования
  • Автоматизированная настройка Keycloak — скриптовое создание realm/клиента/маппера с настройкой аудитории
  • Работающий набор тестов Python — проверяет сквозную доставку сообщений через OAuth
  • Явная обработка URL эмитента — документирована двойственность внутреннего и внешнего URL для токен-эндпоинта и проверки эмитента
  • Архитектура

    • Дистрибутив Kafka: образ Strimzi Kafka 0.48.0 (включает Apache Kafka 4.1.0 + предустановленный Strimzi OAuth 0.17.0)
    • Версия Kafka: Apache Kafka 4.1.0 (KRaft, комбинированный брокер+контроллер)
    • Библиотека OAuth: Strimzi Kafka OAuth 0.17.0 (встроена в образ, обходит ограничение списка разрешённых URL CVE-2025-27817)
    • Провайдер OAuth: Keycloak 26.1.1
    • Безопасность: SASL_SSL (OAuth) для внешних клиентов, PLAINTEXT для межброкерного взаимодействия, SSL с самоподписанным CA

    Контекст CVE-2025-27817

    Apache Kafka 4.0.0+ ввёл список разрешённых URL (org.apache.kafka.sasl.oauthbearer.allowed.urls) как системное свойство JVM для устранения уязвимости SSRF/произвольного чтения файлов. Это нарушает стандартное использование OAuth в нативных клиентах Apache Kafka.

    Решение: библиотека Strimzi Kafka OAuth не реализует это ограничение, что обеспечивает функциональность OAuth с Kafka 4.1.0.

    Предварительные требования

    • Docker Compose
    • Python 3.x с uv (для тестирования)
    • OpenSSL (для генерации сертификатов)

    Быстрый старт

    root@kitploit:~
    # Генерация SSL-сертификатов
    cd kafka-security
    ./generate-certs.sh
    cd ..
    
    # Запуск сервисов
    docker compose up -d
    
    # Проверка Keycloak
    curl http://localhost:8080/health/ready
    
    # Настройка realm и клиентов Keycloak
    ./scripts/setup-keycloak.sh
    
    # Тест OAuth-продюсера
    source ~/.venv/bin/activate
    uv pip install confluent-kafka
    python tests/quick_test.py
    

    Сетевая топология

    root@kitploit:~
    keycloak:8080 (HTTP) ←→ kafka-broker:9093 (SASL_SSL/OAuth)
                          ↔ kafka-broker:19092 (PLAINTEXT/межброкерный)
                          ↔ kafka-broker:29093 (PLAINTEXT/контроллер KRaft)
    

    Конфигурация SSL

    Структура CA

    • Корневой CA: kafka-security/ca-cert + ca-key
    • Хранилище ключей брокера: kafka-security/broker/kafka.server.keystore.jks (содержит сертификат сервера + закрытый ключ)
    • Хранилище доверия брокера: kafka-security/broker/kafka.server.truststore.jks (содержит сертификат CA)
    • Пароль: changeit (все хранилища ключей/доверия)

    Детали сертификата

    root@kitploit:~
    # Сертификат брокера
    CN=kafka-broker
    SAN=DNS:kafka-broker,DNS:localhost,IP:127.0.0.1
    
    # Срок действия: 3650 дней
    # Алгоритм ключа: RSA 2048 бит
    # Алгоритм подписи: SHA256withRSA
    

    Конфигурация OAuth Keycloak

    Realm: kafka-realm

    Клиенты

    kafka-broker (конфиденциальный)

    • Client ID: kafka-broker
    • Client Secret: автоматически генерируется setup-keycloak.sh
    • Назначение: межброкерная OAuth-аутентификация
    • Мапперы:
      • Маппер аудитории: добавляет kafka-broker в claim aud JWT
      • Маппер имени пользователя: включает preferred_username в токен

    kafka-producer (конфиденциальный)

    • Client ID: kafka-producer
    • Client Secret: автоматически генерируется
    • Назначение: внешние клиенты-продюсеры
    • Grant: client_credentials
    • Мапперы: те же, что у kafka-broker

    kafka-consumer (конфиденциальный)

    • Client ID: kafka-consumer
    • Client Secret: автоматически генерируется
    • Назначение: внешние клиенты-потребители
    • Grant: client_credentials
    • Мапперы: те же, что у kafka-broker

    Токен-эндпоинт

    root@kitploit:~
    POST http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=client_credentials
    &client_id=kafka-producer
    &client_secret=<secret>
    &scope=profile email
    

    Структура JWT-токена

    root@kitploit:~
    {
      "aud": ["kafka-broker", "account"],
      "iss": "http://localhost:8080/realms/kafka-realm",
      "azp": "kafka-producer",
      "preferred_username": "service-account-kafka-producer",
      "scope": "profile email"
    }
    

    Конфигурация Kafka

    Режим KRaft (kraft-config.properties)

    root@kitploit:~
    # Идентификатор узла
    node.id=1
    process.roles=broker,controller
    controller.quorum.voters=1@kafka-broker:29093
    
    # Слушатели
    listeners=SASL_SSL://0.0.0.0:9093,PLAINTEXT://0.0.0.0:19092,CONTROLLER://0.0.0.0:29093
    advertised.listeners=SASL_SSL://localhost:9093,PLAINTEXT://kafka-broker:19092
    listener.security.protocol.map=SASL_SSL:SASL_SSL,PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
    inter.broker.listener.name=PLAINTEXT
    controller.listener.names=CONTROLLER
    
    # Механизм SASL
    sasl.enabled.mechanisms=OAUTHBEARER
    
    # Обработчики Strimzi OAuth (для каждого слушателя SASL_SSL)
    listener.name.sasl_ssl.oauthbearer.sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
    listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler
    
    # Конфигурация OAuth через JAAS
    listener.name.sasl_ssl.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      oauth.client.id="kafka-broker" \
      oauth.client.secret="<secret>" \
      oauth.token.endpoint.uri="http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/token" \
      oauth.valid.issuer.uri="http://localhost:8080/realms/kafka-realm" \
      oauth.jwks.endpoint.uri="http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/certs" \
      oauth.username.claim="preferred_username";
    

    Ключевые параметры Strimzi OAuth

    • oauth.client.id: идентификатор клиента для получения токена
    • oauth.client.secret: секрет клиента для получения токена
    • oauth.token.endpoint.uri: токен-эндпоинт Keycloak (брокер использует внутреннее имя хоста keycloak:8080)
    • oauth.valid.issuer.uri: ожидаемый эмитент JWT (должен совпадать с claim iss токена, используется внешний localhost:8080)
    • oauth.jwks.endpoint.uri: эндпоинт JWKS для проверки подписи JWT
    • oauth.username.claim: claim JWT для извлечения principal

    Авторизация

    root@kitploit:~
    authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
    super.users=User:kafka-broker;User:ANONYMOUS
    allow.everyone.if.no.acl.found=true
    

    Примечание: в настоящее время разрешающая конфигурация для тестирования. В production следует использовать ACL.

    Конфигурация клиента

    Python-продюсер (confluent-kafka)

    root@kitploit:~
    from confluent_kafka import Producer
    
    conf = {
        'bootstrap.servers': 'localhost:9093',
        'security.protocol': 'SASL_SSL',
        'sasl.mechanisms': 'OAUTHBEARER',
        'sasl.oauthbearer.method': 'oidc',
        'sasl.oauthbearer.client.id': 'kafka-producer',
        'sasl.oauthbearer.client.secret': '<secret>',
        'sasl.oauthbearer.token.endpoint.url': 'http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token',
        'ssl.ca.location': 'kafka-security/ca-cert',
        'ssl.endpoint.identification.algorithm': 'none',
    }
    
    producer = Producer(conf)
    producer.produce('topic', b'message')
    producer.flush()
    

    Python-потребитель (confluent-kafka)

    root@kitploit:~
    from confluent_kafka import Consumer
    
    conf = {
        'bootstrap.servers': 'localhost:9093',
        'group.id': 'test-group',
        'security.protocol': 'SASL_SSL',
        'sasl.mechanisms': 'OAUTHBEARER',
        'sasl.oauthbearer.method': 'oidc',
        'sasl.oauthbearer.client.id': 'kafka-consumer',
        'sasl.oauthbearer.client.secret': '<secret>',
        'sasl.oauthbearer.token.endpoint.url': 'http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token',
        'ssl.ca.location': 'kafka-security/ca-cert',
        'ssl.endpoint.identification.algorithm': 'none',
        'auto.offset.reset': 'earliest',
    }
    
    consumer = Consumer(conf)
    consumer.subscribe(['topic'])
    while True:
        msg = consumer.poll(1.0)
        if msg: print(msg.value())
    

    Почему librdkafka работает

    confluent-kafka-python использует librdkafka (библиотека на C), которая реализует OAuth через sasl.oauthbearer.method=oidc. Эта реализация не проверяет системное свойство org.apache.kafka.sasl.oauthbearer.allowed.urls, которое блокирует нативные Java-клиенты Apache Kafka.

    Устранение неполадок

    Проверка OAuth-токена

    root@kitploit:~
    TOKEN=$(curl -s -X POST http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token \
      -d "grant_type=client_credentials" \
      -d "client_id=kafka-producer" \
      -d "client_secret=<secret>" | jq -r .access_token)
    
    echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | jq .
    

    Ожидаемые claims:

    root@kitploit:~
    {
      "aud": ["kafka-broker", "account"],
      "iss": "http://localhost:8080/realms/kafka-realm",
      "azp": "kafka-producer",
      "preferred_username": "service-account-kafka-producer"
    }
    

    Проверка журналов OAuth брокера

    root@kitploit:~
    docker logs kafka-broker 2>&1 | grep -E "Strimzi|JWTSignatureValidator|OAUTHBEARER"
    

    Ожидаемый результат:

    root@kitploit:~
    [io.strimzi.kafka.oauth.validator.JWTSignatureValidator] JWKS keys change detected
    

    Проверка слушателей брокера

    root@kitploit:~
    docker exec kafka-broker netstat -tlnp | grep java
    

    Ожидаемый результат:

    root@kitploit:~
    tcp6  0.0.0.0:9093   LISTEN  (SASL_SSL)
    tcp6  0.0.0.0:19092  LISTEN  (PLAINTEXT)
    tcp6  0.0.0.0:29093  LISTEN  (CONTROLLER)
    

    Проверка метаданных KRaft

    root@kitploit:~
    docker exec kafka-broker cat /var/lib/kafka/data/meta.properties
    

    Ожидаемый результат:

    root@kitploit:~
    version=1
    cluster.id=kafka-cluster-01
    node.id=1
    

    Частые проблемы

    Проблема: {"status":"invalid_token"}

    • Причина: сбой проверки подписи JWT
    • Решение: убедитесь, что oauth.jwks.endpoint.uri доступен из контейнера брокера
    • Проверка: docker exec kafka-broker curl http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/certs

    Проблема: Token audience mismatch

    • Причина: claim aud JWT не содержит kafka-broker
    • Решение: запустите ./scripts/setup-keycloak.sh для добавления маппера аудитории
    • Проверка: декодируйте токен и убедитесь, что claim aud включает kafka-broker

    Проблема: Token issuer mismatch

    • Причина: iss JWT не совпадает с oauth.valid.issuer.uri
    • Решение: убедитесь, что oauth.valid.issuer.uri=http://localhost:8080/realms/kafka-realm (внешнее имя хоста)
    • Примечание: брокер использует http://keycloak:8080 для токен-эндпоинта, но проверяет эмитент http://localhost:8080

    Проблема: нативные Java-клиенты Kafka завершаются с ошибкой списка разрешённых URL

    • Причина: исправление CVE-2025-27817 в Apache Kafka 4.1.0
    • Решение: используйте клиенты на основе librdkafka (confluent-kafka-python) или Strimzi OAuth на стороне брокера (уже настроено)

    Настройка производительности

    Обновление токена

    JWT-токены от Keycloak имеют срок действия 5 минут. Strimzi OAuth автоматически обрабатывает обновление:

    • oauth.refresh.token: не используется (grant client_credentials)
    • Токен кэшируется и обновляется за 30 секунд до истечения срока действия

    Кэширование JWKS

    root@kitploit:~
    sasl.oauthbearer.jwks.endpoint.refresh.ms=3600000  # 1 час
    sasl.oauthbearer.jwks.endpoint.retry.backoff.ms=100
    sasl.oauthbearer.jwks.endpoint.retry.backoff.max.ms=10000
    

    Настройки подключения

    root@kitploit:~
    connections.max.idle.ms=600000
    connection.failed.authentication.delay.ms=1000
    

    Производственный чек-лист

    • Замените самоподписанные сертификаты на сертификаты, подписанные CA
    • Обновите ssl.endpoint.identification.algorithm=https (удалите none)
    • Настройте правильные ACL (удалите allow.everyone.if.no.acl.found=true)
    • Настройте ACL:
      root@kitploit:~
      kafka-acls --bootstrap-server localhost:9093 \
        --command-config admin.properties \
        --add --allow-principal User:kafka-producer \
        --operation Write --topic '*'
      
    • Ротируйте секреты клиентов Keycloak
    • Включите HTTPS для Keycloak
    • Обновите oauth.token.endpoint.uri и oauth.jwks.endpoint.uri на HTTPS-URL
    • Настройте мониторинг Kafka (JMX, Prometheus)
    • Настройте агрегацию журналов для аудиторского следа OAuth
    • Протестируйте сценарии отказоустойчивости
    • Документируйте процедуры ротации секретов
    • Включите федерацию пользователей Keycloak (LDAP/AD) при необходимости

    Структура каталога

    root@kitploit:~
    .
    ├── docker-compose.yml              # Оркестрация
    ├── .env                            # Секреты (в gitignore)
    ├── kafka-config/
    │   ├── kraft-config.properties     # Конфигурация брокера Kafka
    │   ├── producer.properties         # Конфигурация OAuth продюсера (для CLI-инструментов)
    │   └── consumer.properties         # Конфигурация OAuth потребителя (для CLI-инструментов)
    ├── kafka-security/
    │   ├── generate-certs.sh           # Генератор SSL-сертификатов
    │   ├── ca-cert                     # Сертификат корневого CA
    │   ├── ca-key                      # Закрытый ключ корневого CA
    │   └── broker/
    │       ├── kafka.server.keystore.jks
    │       └── kafka.server.truststore.jks
    ├── scripts/
    │   └── setup-keycloak.sh           # Настройка realm/клиентов Keycloak
    └── tests/
        └── quick_test.py               # Тест проверки OAuth
    
    

    Технические примечания

    Почему образ Strimzi Kafka вместо официального образа Apache Kafka

    Образ Strimzi Kafka (quay.io/strimzi/kafka:0.48.0-kafka-4.1.0) используется вместо официального образа Apache Kafka, потому что:

    1. Встроенная поддержка OAuth: включает предустановленную библиотеку Strimzi OAuth 0.17.0 (классы: io.strimzi.kafka.oauth.*)
    2. Обход CVE-2025-27817: библиотека Strimzi OAuth не реализует ограничение списка разрешённых URL, которое нарушает нативный OAuth Kafka
    3. Готовность к production: проверено в средах Kubernetes через оператор Strimzi
    4. Единый образ: нет необходимости вручную загружать и монтировать JAR-файлы OAuth

    Разбивка образа:

    • Strimzi Kafka 0.48.0 = версия/релиз Docker-образа
    • Apache Kafka 4.1.0 = версия брокера Kafka, встроенная внутри
    • Strimzi OAuth 0.17.0 = версия библиотеки OAuth, встроенная внутри

    Двойственность URL эмитента

    Конфигурация брокера содержит два URL:

    • oauth.token.endpoint.uri=http://keycloak:8080/... (внутренняя сеть Docker)
    • oauth.valid.issuer.uri=http://localhost:8080/... (внешний, совпадает с claim iss JWT)

    Это связано с тем, что:

    • Брокер получает токены, используя внутреннее DNS-имя
    • Keycloak выдаёт токены с внешним URL эмитента (настраивается в параметрах realm)
    • Проверка JWT требует точного совпадения эмитента

    Маппинг principal

    Брокер извлекает principal из claim preferred_username JWT:

    root@kitploit:~
    service-account-kafka-producer → User:service-account-kafka-producer
    

    ACL ссылаются на этот principal для авторизации.

    Совместимость версий

    КомпонентВерсияПримечания
    Apache Kafka4.1.0Режим KRaft (без ZooKeeper)
    Образ Strimzi Kafka0.48.0Docker-образ: quay.io/strimzi/kafka:0.48.0-kafka-4.1.0
    Библиотека Strimzi OAuth0.17.0Предустановлена в образе Strimzi Kafka 0.48.0
    Keycloak26.1.1Последняя LTS
    librdkafka2.12.0+Поддержка OAuth OIDC
    confluent-kafka-python2.12.0+Соответствует версии librdkafka

    Ссылки

    • Strimzi Kafka OAuth
    • Безопасность Apache Kafka
    • Keycloak OIDC
    • CVE-2025-27817
    • Режим KRaft
    Скачать инструмент