Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
kafka-keycloak-oauth — Apache Kafka 4.1.0 (KRaft) com autenticação Keycloak OAuth2 usando Strimzi - contorna a restrição da allowlist de URLs do CVE-2025-27817 | Kitploit
Ferramentas/GitHubGitHub/oriolrius/kafka-keycloak-oauth
Segurança de Infraestrutura em NuvemAnálise de VulnerabilidadesAuditoria de ConfiguraçãoDevSecOpsAutenticaçãoAprendizado e Educação
GitHuboriolrius/kafka-keycloak-oauth

kafka-keycloak-oauth

Apache Kafka 4.1.0 (KRaft) com autenticação Keycloak OAuth2 usando Strimzi - contorna a restrição da allowlist de URLs do CVE-2025-27817

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Ver Repositório
53há 10 mesesAinda não revisado
Compartilhar

Apache Kafka 4.1.0 com Autenticação OAuth2 via Keycloak

Apache Kafka 4.1.0 pronto para produção (modo KRaft) com autenticação OAuth2/OIDC via Keycloak 26.1.1 usando a imagem Kafka do Strimzi.

Por que Este Projeto vs kafka-oauth-keycloak-tls-demo

Esta é uma evolução do POC anterior com melhorias significativas:

  • Strimzi OAuth 0.17.0 (vs 1.0.0) - versão estável de produção incluída na imagem Strimzi Kafka 0.48.0
  • Sem necessidade de build Docker personalizado - usa a imagem oficial Strimzi com OAuth pré-instalado, eliminando a complexidade do Dockerfile
  • Consciência do CVE-2025-27817 - documenta a restrição da lista de permissões de URL e por que o Strimzi OAuth a contorna
  • Arquitetura simplificada - modo KRaft combinado único (broker+controller), não arquitetura dividida
  • Foco no cliente librdkafka - testado com confluent-kafka-python (funciona sem problemas de lista de permissões de URL), não clientes Java nativos
  • Documentação técnica abrangente - checklist de produção, solução de problemas, ajuste de desempenho, detalhes de mapeamento de principal
  • Gerenciamento de certificados mais limpo - certificados de exemplo incluídos para testes imediatos
  • Configuração automatizada do Keycloak - criação de realm/client/mapper via script com configuração de audiência
  • Suíte de testes Python funcional - valida a entrega de mensagens OAuth de ponta a ponta
  • Tratamento explícito da URL do emissor - documenta a dualidade de URL interna vs externa para endpoint de token vs validação de emissor
  • Arquitetura

    • Distribuição Kafka: Imagem Strimzi Kafka 0.48.0 (inclui Apache Kafka 4.1.0 + Strimzi OAuth 0.17.0 pré-empacotado)
    • Versão Kafka: Apache Kafka 4.1.0 (KRaft combinado broker+controller)
    • Biblioteca OAuth: Strimzi Kafka OAuth 0.17.0 (incluída na imagem, contorna a restrição de lista de permissões de URL do CVE-2025-27817)
    • Provedor OAuth: Keycloak 26.1.1
    • Segurança: SASL_SSL (OAuth) para clientes externos, PLAINTEXT para inter-broker, SSL com CA autoassinada

    Contexto do CVE-2025-27817

    O Apache Kafka 4.0.0+ introduziu uma lista de permissões de URL (org.apache.kafka.sasl.oauthbearer.allowed.urls) como propriedade de sistema JVM para corrigir a vulnerabilidade de SSRF/leitura arbitrária de arquivos. Isso quebra o uso padrão de OAuth em clientes Apache Kafka nativos.

    Solução: A biblioteca Strimzi Kafka OAuth não implementa essa restrição, permitindo a funcionalidade OAuth com Kafka 4.1.0.

    Pré-requisitos

    • Docker Compose
    • Python 3.x com uv (para testes)
    • OpenSSL (para geração de certificados)

    Início Rápido

    root@kitploit:~
    # Gerar certificados SSL
    cd kafka-security
    ./generate-certs.sh
    cd ..
    
    # Iniciar serviços
    docker compose up -d
    
    # Verificar Keycloak
    curl http://localhost:8080/health/ready
    
    # Configurar realm e clientes do Keycloak
    ./scripts/setup-keycloak.sh
    
    # Testar produtor OAuth
    source ~/.venv/bin/activate
    uv pip install confluent-kafka
    python tests/quick_test.py
    

    Topologia de Rede

    root@kitploit:~
    keycloak:8080 (HTTP) ←→ kafka-broker:9093 (SASL_SSL/OAuth)
                          ↔ kafka-broker:19092 (PLAINTEXT/inter-broker)
                          ↔ kafka-broker:29093 (PLAINTEXT/controller KRaft)
    

    Configuração SSL

    Estrutura da CA

    • CA Raiz: kafka-security/ca-cert + ca-key
    • Keystore do Broker: kafka-security/broker/kafka.server.keystore.jks (contém certificado do servidor + chave privada)
    • Truststore do Broker: kafka-security/broker/kafka.server.truststore.jks (contém certificado da CA)
    • Senha: changeit (todos os keystores/truststores)

    Detalhes do Certificado

    root@kitploit:~
    # Certificado do broker
    CN=kafka-broker
    SAN=DNS:kafka-broker,DNS:localhost,IP:127.0.0.1
    
    # Validade: 3650 dias
    # Algoritmo de chave: RSA 2048 bits
    # Algoritmo de assinatura: SHA256withRSA
    

    Configuração OAuth do Keycloak

    Realm: kafka-realm

    Clientes

    kafka-broker (confidencial)

    • Client ID: kafka-broker
    • Client Secret: Gerado automaticamente por setup-keycloak.sh
    • Finalidade: Autenticação OAuth inter-broker
    • Mappers:
      • Mapper de audiência: adiciona kafka-broker à claim aud do JWT
      • Mapper de nome de usuário: inclui preferred_username no token

    kafka-producer (confidencial)

    • Client ID: kafka-producer
    • Client Secret: Gerado automaticamente
    • Finalidade: Clientes produtores externos
    • Grant: client_credentials
    • Mappers: Mesmos do kafka-broker

    kafka-consumer (confidencial)

    • Client ID: kafka-consumer
    • Client Secret: Gerado automaticamente
    • Finalidade: Clientes consumidores externos
    • Grant: client_credentials
    • Mappers: Mesmos do kafka-broker

    Endpoint de Token

    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
    

    Estrutura do Token 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"
    }
    

    Configuração do Kafka

    Modo KRaft (kraft-config.properties)

    root@kitploit:~
    # Identidade do nó
    node.id=1
    process.roles=broker,controller
    controller.quorum.voters=1@kafka-broker:29093
    
    # Listeners
    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
    
    # Mecanismo SASL
    sasl.enabled.mechanisms=OAUTHBEARER
    
    # Handlers Strimzi OAuth (por listener para 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
    
    # Configuração OAuth via 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";
    

    Principais Parâmetros Strimzi OAuth

    • oauth.client.id: Identificador do cliente para aquisição de token
    • oauth.client.secret: Segredo do cliente para aquisição de token
    • oauth.token.endpoint.uri: Endpoint de token do Keycloak (o broker usa o hostname interno keycloak:8080)
    • oauth.valid.issuer.uri: Emissor JWT esperado (deve corresponder à claim iss do token, usa localhost:8080 externo)
    • oauth.jwks.endpoint.uri: Endpoint JWKS para validação de assinatura JWT
    • oauth.username.claim: Claim JWT para extração do principal

    Autorização

    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
    

    Nota: Atualmente permissivo para testes. Produção deve usar ACLs.

    Configuração do Cliente

    Produtor 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()
    

    Consumidor 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())
    

    Por que o librdkafka Funciona

    O confluent-kafka-python usa o librdkafka (biblioteca C) que implementa OAuth via sasl.oauthbearer.method=oidc. Essa implementação não verifica a propriedade de sistema org.apache.kafka.sasl.oauthbearer.allowed.urls que bloqueia clientes Apache Kafka Java nativos.

    Solução de Problemas

    Verificar Token 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 esperadas:

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

    Verificar Logs OAuth do Broker

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

    Esperado:

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

    Verificar Listeners do Broker

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

    Esperado:

    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)
    

    Verificar Metadados KRaft

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

    Esperado:

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

    Problemas Comuns

    Problema: {"status":"invalid_token"}

    • Causa: Falha na validação da assinatura JWT
    • Correção: Verifique se oauth.jwks.endpoint.uri está acessível a partir do contêiner do broker
    • Verificação: docker exec kafka-broker curl http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/certs

    Problema: Token audience mismatch

    • Causa: A claim aud do JWT não contém kafka-broker
    • Correção: Execute ./scripts/setup-keycloak.sh para adicionar o mapper de audiência
    • Verificação: Decodifique o token e verifique se a claim aud inclui kafka-broker

    Problema: Token issuer mismatch

    • Causa: O iss do JWT não corresponde a oauth.valid.issuer.uri
    • Correção: Garanta que oauth.valid.issuer.uri=http://localhost:8080/realms/kafka-realm (hostname externo)
    • Nota: O broker usa http://keycloak:8080 para o endpoint de token, mas valida contra o emissor http://localhost:8080

    Problema: Clientes Kafka Java nativos falham com erro de lista de permissões de URL

    • Causa: Correção do CVE-2025-27817 no Apache Kafka 4.1.0
    • Correção: Use clientes baseados em librdkafka (confluent-kafka-python) ou Strimzi OAuth no lado do broker (já configurado)

    Ajuste de Desempenho

    Renovação de Token

    Tokens JWT do Keycloak têm expiração de 5 minutos. O Strimzi OAuth lida automaticamente com a renovação:

    • oauth.refresh.token: Não usado (grant client_credentials)
    • Token em cache e renovado 30s antes da expiração

    Cache JWKS

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

    Configurações de Conexão

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

    Checklist de Produção

    • Substituir certificados autoassinados por certificados assinados por CA
    • Atualizar ssl.endpoint.identification.algorithm=https (remover none)
    • Configurar ACLs adequadas (remover allow.everyone.if.no.acl.found=true)
    • Configurar ACLs:
      root@kitploit:~
      kafka-acls --bootstrap-server localhost:9093 \
        --command-config admin.properties \
        --add --allow-principal User:kafka-producer \
        --operation Write --topic '*'
      
    • Rotacionar segredos dos clientes do Keycloak
    • Habilitar HTTPS no Keycloak
    • Atualizar oauth.token.endpoint.uri e oauth.jwks.endpoint.uri para URLs HTTPS
    • Configurar monitoramento do Kafka (JMX, Prometheus)
    • Configurar agregação de logs para trilha de auditoria OAuth
    • Testar cenários de failover
    • Documentar procedimentos de rotação de segredos
    • Habilitar federação de usuários do Keycloak (LDAP/AD) se necessário

    Estrutura de Diretórios

    root@kitploit:~
    .
    ├── docker-compose.yml              # Orquestração
    ├── .env                            # Segredos (gitignored)
    ├── kafka-config/
    │   ├── kraft-config.properties     # Configuração do broker Kafka
    │   ├── producer.properties         # Config OAuth do produtor (para ferramentas CLI)
    │   └── consumer.properties         # Config OAuth do consumidor (para ferramentas CLI)
    ├── kafka-security/
    │   ├── generate-certs.sh           # Gerador de certificados SSL
    │   ├── ca-cert                     # Certificado da CA raiz
    │   ├── ca-key                      # Chave privada da CA raiz
    │   └── broker/
    │       ├── kafka.server.keystore.jks
    │       └── kafka.server.truststore.jks
    ├── scripts/
    │   └── setup-keycloak.sh           # Configuração de realm/client do Keycloak
    └── tests/
        └── quick_test.py               # Teste de validação OAuth
    
    

    Notas Técnicas

    Por que a Imagem Strimzi Kafka em Vez da Imagem Oficial Apache Kafka

    A imagem Strimzi Kafka (quay.io/strimzi/kafka:0.48.0-kafka-4.1.0) é usada em vez da imagem oficial Apache Kafka porque:

    1. Suporte OAuth Incluído: Inclui a biblioteca Strimzi OAuth 0.17.0 pré-instalada (classes: io.strimzi.kafka.oauth.*)
    2. Contorno do CVE-2025-27817: A biblioteca Strimzi OAuth não implementa a restrição de lista de permissões de URL que quebra o OAuth nativo do Kafka
    3. Pronto para Produção: Testado em ambientes Kubernetes via Strimzi Operator
    4. Imagem Única: Sem necessidade de baixar e montar manualmente arquivos JAR OAuth

    Detalhamento da imagem:

    • Strimzi Kafka 0.48.0 = Versão/release da imagem Docker
    • Apache Kafka 4.1.0 = Versão do broker Kafka incluída
    • Strimzi OAuth 0.17.0 = Versão da biblioteca OAuth incluída

    Dualidade da URL do Emissor

    A configuração do broker tem duas URLs:

    • oauth.token.endpoint.uri=http://keycloak:8080/... (rede Docker interna)
    • oauth.valid.issuer.uri=http://localhost:8080/... (externa, corresponde à claim iss do JWT)

    Isso ocorre porque:

    • O broker busca tokens usando o nome DNS interno
    • O Keycloak emite tokens com URL de emissor externa (configurada nas configurações do realm)
    • A validação JWT exige correspondência exata do emissor

    Mapeamento de Principal

    O broker extrai o principal da claim preferred_username do JWT:

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

    As ACLs referenciam esse principal para autorização.

    Compatibilidade de Versões

    ComponenteVersãoNotas
    Apache Kafka4.1.0Modo KRaft (sem ZooKeeper)
    Imagem Strimzi Kafka0.48.0Imagem Docker: quay.io/strimzi/kafka:0.48.0-kafka-4.1.0
    Biblioteca Strimzi OAuth0.17.0Pré-incluída na imagem Strimzi Kafka 0.48.0
    Keycloak26.1.1Última LTS
    librdkafka2.12.0+Suporte OAuth OIDC
    confluent-kafka-python2.12.0+Corresponde à versão do librdkafka

    Referências

    • Strimzi Kafka OAuth
    • Segurança Apache Kafka
    • Keycloak OIDC
    • CVE-2025-27817
    • Modo KRaft
    Baixar ferramenta