Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/oriolrius/kafka-keycloak-oauth
Sicurezza dell'Infrastruttura CloudAnalisi delle VulnerabilitàAudit di ConfigurazioneDevSecOpsAutenticazioneApprendimento e Formazione
GitHuboriolrius/kafka-keycloak-oauth

kafka-keycloak-oauth

Apache Kafka 4.1.0 (KRaft) con autenticazione Keycloak OAuth2 tramite Strimzi - bypassa la restrizione dell'allowlist URL CVE-2025-27817

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Vedi Repository
5310 mesi faNon ancora revisionato
Condividi

Apache Kafka 4.1.0 con autenticazione OAuth2 Keycloak

Apache Kafka 4.1.0 pronto per la produzione (modalità KRaft) con autenticazione OAuth2/OIDC Keycloak 26.1.1 utilizzando l'immagine Kafka Strimzi.

Perché questo progetto vs kafka-oauth-keycloak-tls-demo

Questa è un'evoluzione del POC precedente con miglioramenti significativi:

  • Strimzi OAuth 0.17.0 (vs 1.0.0) - versione di produzione stabile inclusa nell'immagine Strimzi Kafka 0.48.0
  • Nessuna build Docker personalizzata richiesta - utilizza l'immagine Strimzi ufficiale con OAuth preinstallato, elimina la complessità del Dockerfile
  • Consapevolezza CVE-2025-27817 - documenta la restrizione della allowlist URL e perché Strimzi OAuth la bypassa
  • Architettura semplificata - modalità combinata KRaft singola (broker+controller), non architettura divisa
  • Focus sul client librdkafka - testato con confluent-kafka-python (funziona senza problemi di allowlist URL), non client Java nativi
  • Documentazione tecnica completa - checklist di produzione, risoluzione dei problemi, ottimizzazione delle prestazioni, dettagli sul mapping dei principal
  • Gestione certificati più pulita - certificati di esempio inclusi per test immediati
  • Setup Keycloak automatizzato - creazione scriptata di realm/client/mapper con configurazione audience
  • Suite di test Python funzionante - valida la consegna dei messaggi OAuth end-to-end
  • Gestione esplicita dell'URL issuer - documenta la dualità URL interno vs esterno per token endpoint vs validazione issuer
  • Architettura

    • Distribuzione Kafka: immagine Strimzi Kafka 0.48.0 (include Apache Kafka 4.1.0 + Strimzi OAuth 0.17.0 preinstallato)
    • Versione Kafka: Apache Kafka 4.1.0 (KRaft combinato broker+controller)
    • Libreria OAuth: Strimzi Kafka OAuth 0.17.0 (inclusa nell'immagine, bypassa la restrizione allowlist URL CVE-2025-27817)
    • Provider OAuth: Keycloak 26.1.1
    • Sicurezza: SASL_SSL (OAuth) per client esterni, PLAINTEXT per inter-broker, SSL con CA autofirmata

    Contesto CVE-2025-27817

    Apache Kafka 4.0.0+ ha introdotto la allowlist URL (org.apache.kafka.sasl.oauthbearer.allowed.urls) come proprietà di sistema JVM per correggere la vulnerabilità SSRF/lettura file arbitraria. Questo interrompe l'uso OAuth standard nei client Apache Kafka nativi.

    Soluzione: la libreria Strimzi Kafka OAuth non implementa questa restrizione, abilitando la funzionalità OAuth con Kafka 4.1.0.

    Prerequisiti

    • Docker Compose
    • Python 3.x con uv (per i test)
    • OpenSSL (per la generazione dei certificati)

    Avvio Rapido

    root@kitploit:~
    # Genera i certificati SSL
    cd kafka-security
    ./generate-certs.sh
    cd ..
    
    # Avvia i servizi
    docker compose up -d
    
    # Verifica Keycloak
    curl http://localhost:8080/health/ready
    
    # Configura realm e client Keycloak
    ./scripts/setup-keycloak.sh
    
    # Test del producer OAuth
    source ~/.venv/bin/activate
    uv pip install confluent-kafka
    python tests/quick_test.py
    

    Topologia di Rete

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

    Configurazione SSL

    Struttura CA

    • CA radice: kafka-security/ca-cert + ca-key
    • Keystore broker: kafka-security/broker/kafka.server.keystore.jks (contiene certificato server + chiave privata)
    • Truststore broker: kafka-security/broker/kafka.server.truststore.jks (contiene certificato CA)
    • Password: changeit (tutti i keystore/truststore)

    Dettagli Certificato

    root@kitploit:~
    # Certificato broker
    CN=kafka-broker
    SAN=DNS:kafka-broker,DNS:localhost,IP:127.0.0.1
    
    # Validità: 3650 giorni
    # Algoritmo chiave: RSA 2048-bit
    # Algoritmo firma: SHA256withRSA
    

    Configurazione OAuth Keycloak

    Realm: kafka-realm

    Client

    kafka-broker (confidenziale)

    • Client ID: kafka-broker
    • Client Secret: generato automaticamente da setup-keycloak.sh
    • Scopo: autenticazione OAuth inter-broker
    • Mapper:
      • Mapper audience: aggiunge kafka-broker al claim JWT aud
      • Mapper username: include preferred_username nel token

    kafka-producer (confidenziale)

    • Client ID: kafka-producer
    • Client Secret: generato automaticamente
    • Scopo: client producer esterni
    • Grant: client_credentials
    • Mapper: come kafka-broker

    kafka-consumer (confidenziale)

    • Client ID: kafka-consumer
    • Client Secret: generato automaticamente
    • Scopo: client consumer esterni
    • Grant: client_credentials
    • Mapper: come kafka-broker

    Token Endpoint

    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
    

    Struttura 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"
    }
    

    Configurazione Kafka

    Modalità KRaft (kraft-config.properties)

    root@kitploit:~
    # Identità nodo
    node.id=1
    process.roles=broker,controller
    controller.quorum.voters=1@kafka-broker:29093
    
    # Listener
    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
    
    # Meccanismo SASL
    sasl.enabled.mechanisms=OAUTHBEARER
    
    # Handler Strimzi OAuth (per listener per 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
    
    # Configurazione OAuth tramite 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";
    

    Parametri Chiave Strimzi OAuth

    • oauth.client.id: identificatore client per l'acquisizione del token
    • oauth.client.secret: secret client per l'acquisizione del token
    • oauth.token.endpoint.uri: token endpoint Keycloak (il broker usa il nome host interno keycloak:8080)
    • oauth.valid.issuer.uri: issuer JWT atteso (deve corrispondere al claim iss del token, usa localhost:8080 esterno)
    • oauth.jwks.endpoint.uri: endpoint JWKS per la validazione della firma JWT
    • oauth.username.claim: claim JWT per l'estrazione del principal

    Autorizzazione

    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: attualmente permissivo per i test. La produzione dovrebbe usare ACL.

    Configurazione Client

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

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

    Perché librdkafka Funziona

    confluent-kafka-python usa librdkafka (libreria C) che implementa OAuth tramite sasl.oauthbearer.method=oidc. Questa implementazione non controlla la proprietà di sistema org.apache.kafka.sasl.oauthbearer.allowed.urls che blocca i client Apache Kafka Java nativi.

    Risoluzione dei Problemi

    Verifica 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 .
    

    Claim attesi:

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

    Controlla i Log OAuth del Broker

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

    Atteso:

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

    Verifica i Listener del Broker

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

    Atteso:

    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)
    

    Controlla i Metadati KRaft

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

    Atteso:

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

    Problemi Comuni

    Problema: {"status":"invalid_token"}

    • Causa: errore di validazione della firma JWT
    • Soluzione: verifica che oauth.jwks.endpoint.uri sia raggiungibile dal container del broker
    • Controllo: docker exec kafka-broker curl http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/certs

    Problema: Token audience mismatch

    • Causa: il claim aud del JWT non contiene kafka-broker
    • Soluzione: esegui ./scripts/setup-keycloak.sh per aggiungere il mapper audience
    • Verifica: decodifica il token e controlla che il claim aud includa kafka-broker

    Problema: Token issuer mismatch

    • Causa: il claim iss del JWT non corrisponde a oauth.valid.issuer.uri
    • Soluzione: assicurati che oauth.valid.issuer.uri=http://localhost:8080/realms/kafka-realm (nome host esterno)
    • Nota: il broker usa http://keycloak:8080 per il token endpoint ma valida contro l'issuer http://localhost:8080

    Problema: i client Kafka Java nativi falliscono con errore allowlist URL

    • Causa: correzione CVE-2025-27817 in Apache Kafka 4.1.0
    • Soluzione: usa client basati su librdkafka (confluent-kafka-python) o Strimzi OAuth lato broker (già configurato)

    Ottimizzazione delle Prestazioni

    Aggiornamento Token

    I token JWT di Keycloak hanno scadenza di 5 minuti. Strimzi OAuth gestisce automaticamente l'aggiornamento:

    • oauth.refresh.token: non utilizzato (grant client_credentials)
    • Token memorizzato nella cache e aggiornato 30 secondi prima della scadenza

    Caching JWKS

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

    Impostazioni Connessione

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

    Checklist di Produzione

    • Sostituisci i certificati autofirmati con certificati firmati da CA
    • Aggiorna ssl.endpoint.identification.algorithm=https (rimuovi none)
    • Configura ACL appropriate (rimuovi allow.everyone.if.no.acl.found=true)
    • Configura le ACL:
      root@kitploit:~
      kafka-acls --bootstrap-server localhost:9093 \
        --command-config admin.properties \
        --add --allow-principal User:kafka-producer \
        --operation Write --topic '*'
      
    • Ruota i secret dei client Keycloak
    • Abilita HTTPS su Keycloak
    • Aggiorna oauth.token.endpoint.uri e oauth.jwks.endpoint.uri a URL HTTPS
    • Configura il monitoraggio Kafka (JMX, Prometheus)
    • Configura l'aggregazione dei log per l'audit trail OAuth
    • Testa gli scenari di failover
    • Documenta le procedure di rotazione dei secret
    • Abilita la federazione utenti Keycloak (LDAP/AD) se necessario

    Struttura delle Directory

    root@kitploit:~
    .
    ├── docker-compose.yml              # Orchestrazione
    ├── .env                            # Secret (gitignored)
    ├── kafka-config/
    │   ├── kraft-config.properties     # Configurazione broker Kafka
    │   ├── producer.properties         # Config OAuth producer (per strumenti CLI)
    │   └── consumer.properties         # Config OAuth consumer (per strumenti CLI)
    ├── kafka-security/
    │   ├── generate-certs.sh           # Generatore certificati SSL
    │   ├── ca-cert                     # Certificato CA radice
    │   ├── ca-key                      # Chiave privata CA radice
    │   └── broker/
    │       ├── kafka.server.keystore.jks
    │       └── kafka.server.truststore.jks
    ├── scripts/
    │   └── setup-keycloak.sh           # Setup realm/client Keycloak
    └── tests/
        └── quick_test.py               # Test di validazione OAuth
    
    

    Note Tecniche

    Perché l'Immagine Strimzi Kafka Invece dell'Immagine Ufficiale Apache Kafka

    L'immagine Strimzi Kafka (quay.io/strimzi/kafka:0.48.0-kafka-4.1.0) viene utilizzata invece dell'immagine ufficiale Apache Kafka perché:

    1. Supporto OAuth integrato: include la libreria Strimzi OAuth 0.17.0 preinstallata (classi: io.strimzi.kafka.oauth.*)
    2. Bypass CVE-2025-27817: la libreria Strimzi OAuth non implementa la restrizione allowlist URL che interrompe l'OAuth Kafka nativo
    3. Pronto per la produzione: testato in ambienti Kubernetes tramite Strimzi Operator
    4. Immagine singola: nessuna necessità di scaricare e montare manualmente i file JAR OAuth

    Dettaglio immagine:

    • Strimzi Kafka 0.48.0 = versione/release dell'immagine Docker
    • Apache Kafka 4.1.0 = versione broker Kafka inclusa
    • Strimzi OAuth 0.17.0 = versione libreria OAuth inclusa

    Dualità URL Issuer

    La configurazione del broker ha due URL:

    • oauth.token.endpoint.uri=http://keycloak:8080/... (rete Docker interna)
    • oauth.valid.issuer.uri=http://localhost:8080/... (esterno, corrisponde al claim iss del JWT)

    Questo perché:

    • Il broker recupera i token usando il nome DNS interno
    • Keycloak emette token con URL issuer esterno (configurato nelle impostazioni del realm)
    • La validazione JWT richiede corrispondenza esatta dell'issuer

    Mapping Principal

    Il broker estrae il principal dal claim preferred_username del JWT:

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

    Le ACL fanno riferimento a questo principal per l'autorizzazione.

    Compatibilità Versioni

    ComponenteVersioneNote
    Apache Kafka4.1.0Modalità KRaft (senza ZooKeeper)
    Immagine Strimzi Kafka0.48.0Immagine Docker: quay.io/strimzi/kafka:0.48.0-kafka-4.1.0
    Libreria Strimzi OAuth0.17.0Preinstallata nell'immagine Strimzi Kafka 0.48.0
    Keycloak26.1.1Ultima LTS
    librdkafka2.12.0+Supporto OAuth OIDC
    confluent-kafka-python2.12.0+Corrisponde alla versione librdkafka

    Riferimenti

    • Strimzi Kafka OAuth
    • Apache Kafka Security
    • Keycloak OIDC
    • CVE-2025-27817
    • Modalità KRaft
    Scarica lo strumento