Skip to content

Using SASL GSSAPI with librdkafka in a cross‐realm scenario with Windows SSPI and MIT Kerberos

Emanuele Sabellico edited this page Aug 25, 2025 · 11 revisions

In this tutorial we'll see how to set up SASL/GSSAPI in a cross-realm scenario with Windows Active Directory and MIT Kerberos. On Windows librdkafka uses SSPI to automatically authenticate with current user. If cross-realm trust is set up, Windows users can directly authenticate as Kafka principals.

Requirements

Everything will be set up on a Windows Server instance, by using WSL2 for running Apache Kafka 4.0 on Ubuntu.

Configuration

Install Active Directory

  • Go to Server Manager
  • Select "Add roles and Features"
  • Check "Active Directory Domain Services"
  • Install it
  • After installation: "Promote this server to domain controller"
  • Add a new forest with name testwindomain.com (NetBIOS name: TESTWINDOMAIN)
  • Finish the configuration and restart
  • To login now you've to use TESTWINDOMAIN\<admin_user>

Install the required dependencies through WinGet

  • winget.exe install Microsoft.DotNet.SDK.8
  • winget.exe install Git.SDK

Install WSL2 with Ubuntu

  • Enable the WSL feature with this PowerShell command
    • Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux, VirtualMachinePlatform
  • Install the Ubuntu distribution
    • wsl --install Ubuntu
  • Install Linux dependencies
    • apt update && apt install -y krb5* openjdk-21-jdk
  • Get WSL IP address on PS
    • wsl hostname -I
  • Go to Windows DNS Manager and add a new Forward Lookup Zone (Primary) with name testkafkadomain.com
  • Add two hosts: kdc and kafka, both using the WSL IP address.

Configure MIT Kerberos on Linux

  • Edit /etc/krb5.conf
  • Change default realm in /etc/krb5.conf to TESTKAFKADOMAIN.COM
  • Add realm configuration:
TESTKAFKADOMAIN.COM = {
      kdc = kdc.testkafkadomain.com
      admin_server = kdc.testkafkadomain.com
      default_domain = testkafkadomain.com
}
  • Create the Kerberos DB
    • kdb5_util create -s
  • Create an ACL at /etc/krb5kdc/kadm5.acl with contents */[email protected] *
  • Restart the servers:
    • systemctl restart krb5-admin-server
    • systemctl restart krb5-kdc
  • Create the principal for Kafka brokers and add a keytab for it
    • mkdir /etc/security/keytabs
    • kadmin.local addprinc -randkey kafka/kafka.testkafkadomain.com
    • kadmin.local ktadd -k /etc/security/keytabs/kafka.testkafkadomain.com.keytab kafka/kafka.testkafkadomain.com

Install Kafka

  • Download and extract the binaries
    • wget -O kafka_2.13-4.0.0.tgz https://dlcdn.apache.org/kafka/4.0.0/kafka_2.13-4.0.0.tgz && \ tar -xvf kafka_2.13-4.0.0.tgz && cd kafka_2.13-4.0.0
  • Edit config/server.properties
  • Add SASL_PLAINTEXT://kafka.testkafkadomain.com:9094 to advertised.listeners and the corresponding value to listeners.
  • Add these new properties:
sasl.enabled.mechanisms=GSSAPI
sasl.kerberos.service.name=kafka
sasl.kerberos.principal.to.local.rules=RULE:[1:$1@$0](.*)s/(.*)@(.*)/$1_$2/,RULE:[2:$1@$0](.*)s/(.*)@(.*)/$1_$2/
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
super.users=User:kafka_TESTKAFKADOMAIN.COM
  • The rules are respectively for primary@REALM and primary/instance@REALM, they strip the instance if present and replace @ with _ as it's not a valid character for Kafka principals. This allows to keep users coming from separate realm as different Kafka principals. The super user is an example of the result of this transformation.
  • Change log.dirs to <home_directory>/kafka_2.13-4.0.0/log-dirs
  • Change inter.broker.listener.name to SASL_PLAINTEXT
  • Change CONTROLLER security protocol map to SASL_PLAINTEXT in listener.security.protocol.map
  • Set advertised.listeners to PLAINTEXT://localhost:9092,SASL_PLAINTEXT://kafka.testkafkadomain.com:9094,CONTROLLER://kafka.testkafkadomain.com:9093
  • Edit kafka_server_jaas.conf inside kafka_2.13-4.0.0, use this configuration:
KafkaServer {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    keyTab="/etc/security/keytabs/kafka.testkafkadomain.com.keytab"
    principal="kafka/[email protected]";
};
  • Still inside kafka_2.13-4.0.0, create the logs directory
    • mkdir log-dirs
  • Create a cluster ID
    • KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
  • Format the storage with the generated ID
    • bin/kafka-storage.sh format --standalone -t $KAFKA_CLUSTER_ID -c config/server.properties
  • Tell Kafka to use the jaas file
    • export KAFKA_OPTS="-Djava.security.auth.login.config=$PWD/kafka_server_jaas.conf"
  • Finally start Kafka
    • bin/kafka-server-start.sh config/server.properties

Configure Kafka ACLs

  • Create a command.properties file with these contents:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \
   useKeyTab=true \
   storeKey=true \
   keyTab="/etc/security/keytabs/kafka.testkafkadomain.com.keytab" \
   principal="kafka/[email protected]";
  • Allow the Windows producer to produce to Kafka topic test1
bin/kafka-acls.sh --bootstrap-server kafka.testkafkadomain.com:9094 --command-config command.properties --add --allow-principal "User:kafka_producer_TESTWINDOMAIN.COM" --topic test1 --resource-pattern-type LITERAL --operation Write

Establish mutual trust

This is the key part, we must add a shared principal with same password to obtain a cross realm TGT for a Windows realm principal to MIT Kerberos. Replace the example password.

  • On MIT Kerberos add the krbtgt primary from TESTWINDOMAIN.COM realm to TESTKAFKADOMAIN.COM one
  • On Windows add the corresponding trust with same password
    • netdom trust TESTKAFKADOMAIN.COM /Domain:TESTWINDOMAIN.COM /add /realm /passwordt:example
  • On Windows add a kdc for TESTKAFKADOMAIN.COM
    • ksetup /addkdc TESTKAFKADOMAIN.COM kdc.testkafkadomain.com
  • On Windows add the mapping for hostnames like .testkafkadomain.com to the TESTKAFKADOMAIN.COM realm
    • ksetup /addhosttorealmmap .testkafkadomain.com TESTKAFKADOMAIN.COM

Create a Producer on Windows

This is the final part. We now start a .NET producer on Windows using the logged in user and authenticating to Kafka using MIT Kerberos.

  • Create new Active Directory user TESTWINDOWDOMAIN\kafka_producer
    • New-ADUser -Name "kafka_producer" -SamAccountName "kafka_producer" -UserPrincipalName "[email protected]" -AccountPassword (ConvertTo-SecureString "Example@!" -AsPlainText -Force) -Enabled $true
  • Add it to the Administrators group to allow to login locally (only for this example):
    • Add-ADGroupMember -Identity "Administrators" -Members "kafka_producer"
  • Start a new shell with user TESTWINDOMAIN\kafka_producer
    • runas /user:TESTWINDOMAIN\kafka_producer cmd
  • Clone confluent-kafka-dotnet
    • cd %USERPROFILE% && C:\git-sdk-64\cmd\git.exe clone https://github.com/confluentinc/confluent-kafka-dotnet.git
  • Go to the Producer example
    • cd %USERPROFILE%\confluent-kafka-dotnet\examples\Producer
  • Edit Program.cs and change the config to:
    • var config = new ProducerConfig { BootstrapServers = brokerList, SecurityProtocol = SecurityProtocol.SaslPlaintext, SaslMechanism = SaslMechanism.Gssapi };
  • Start the Producer and you can produce some messages
    • dotnet run kafka.testkafkadomain.com:9094 test1
Clone this wiki locally