-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Using SASL with librdkafka on Windows
For a trivial zookeeper/kafka ensemble/cluster all running on machine: HOST, perform the following steps to enable SASL via SSPI.
For a Unix-based system (Debian/Ubuntu, RedHat, MacOS/OSX) please follow guide Using SASL with librdkafka.
Kerberos keytabs (file-based pre-authenticated keys) are created for each broker in the cluster. The client will use SSPI and does not need keytab files. They keytabs are distributed to the broker nodes.
Decide on the following things:
- REALM - Your Kerberos realm, typically your operational domain in upper case. E.g., YOURDOMAIN.COM.
- HOST - Broker hostname, E.g., broker1. Quantify as necessary. Any casing works.
- HOST_FQDN - The fully qualified name of the HOST. E.g. broker1.yourcompany.com. Any casing works.
- DOMAIN - The Windows domain of the broker HOST. E.g. LONDON. Any casing works.
Create AD user for Zookeeper/Kafka (the format is AD DOMAIN\AD user name):
• DOMAIN\Zookeeper_test (say the password is zk_password)
• DOMAIN\Kafka_test (say the password is kfk_password)
Ask the AD administrator to run:
SETSPN -S zookeeper/HOST@REALM DOMAIN\Zookeeper_test
SETSPN -S zookeeper/HOST_FQDN@REALM DOMAIN\Zookeeper_test
SETSPN -S kafka/HOST@REALM DOMAIN\Kafka_test
SETSPN -S kafka/HOST_FQDN@REALM DOMAIN\Kafka_test
https://technet.microsoft.com/en-us/library/cc753771(v=ws.11).aspx
You will need the respective AD user password from step 1; the SPN from step 2; and a folder for the generated output (you can call this folder C:\keytabs).
We will create keytab data for both the simple and fully qualified DOMAIN name of the HOST.
Note that the ktpass utility might not be available on all versions of Windows:
ktpass -princ zookeeper/HOST@REALM -mapuser DOMAIN\Zookeeper_test -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -pass zk_password -out C:\keytabs\zookeeper.ktab
ktpass -princ zookeeper/HOST_FQDN@REALM -mapuser DOMAIN\Zookeeper_test -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -pass zk_password -in C:\keytabs\zookeeper.ktab -out C:\keytabs\zookeeper.ktab
ktpass -princ kafka/HOST@REALM -mapuser DOMAIN\Kafka_test -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -pass kfk_password -out C:\keytabs\kafka.ktab
ktpass -princ kafka/HOST_FQDN@REALM -mapuser DOMAIN\Kafka_test -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -pass kfk_password -in C:\keytabs\kafka.ktab -out C:\keytabs\kafka.ktab
Once the keytabs are created place them in a similar directory where Zookeeper/Kafka can access them. We will use these local files in the next sections.
Note: Zookeeper authentication is optional and not required for client->Kafka cluster authentication.
1.Add the following entries (at the end of the file) to the zookeeper config file (zoo.cfg):
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000
2.In the same directory where the zoo.cfg file is edit the jaas.conf file so that it has this content:
(Description of values) https://docs.oracle.com/javase/7/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html
Server {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab="true"
principal="zookeeper/HOST_FQDN@REALM"
storeKey="true"
serviceName="zookeeper"
keyTab="C:/keytabs/zookeeper.ktab";
};
3.Edit the zookeeper runner batch file (zkServer.cmd) to have this:
-Djava.security.auth.login.config="%~dp0../conf/jaas.conf"
Note: The %~dp0 (that’s a zero) variable will expand to the drive letter and path of the batch file.
The updated command file should look like this:
call %JAVA% "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -Dsun.security.krb5.debug=true -Djava.security.auth.login.config="%~dp0../conf/jaas.conf" -cp "%CLASSPATH%" %ZOOMAIN% "%ZOOCFG%" %*
Note: the bold entry is optional and only required if you want to see detailed information from the security module.
4.When you run Zookeeper process make sure it runs as DOMAIN\Zookeeper_test.
1.Add the following entries (in the Socket Server Settings) to the kafka server config file (server.properties):
listeners=SASL_PLAINTEXT://HOST_FQDN:9093
security.inter.broker.protocol=SASL_PLAINTEXT
zookeeper.set.acl=true
sasl.mechanism=GSSAPI
2.In the same directory where server.properties file is edit the kafka_server_jaas.conf file so that it has this content:
//For connections to Kafka.
KafkaServer {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab="true"
principal="kafka/HOST_FQDN@REALM"
storeKey="true"
serviceName="kafka"
keyTab="C:/keytabs/kafka.ktab";
};
//For connections to Zookeeper.
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab="true"
principal="kafka/HOST_FQDN@REALM"
serviceName="kafka"
keyTab="C:/keytabs/kafka.ktab";
};
3.Edit the kafka runner batch file (windows\kafka-server-start.bat) to have this:
-Djava.security.auth.login.config="%~dp0../../config/kafka_server_jaas.conf"
The updated command file should look like this:
set KAFKA_LOG4J_OPTS=-Dlog4j.configuration=file:"%~dp0../../config/log4j.properties" -Dkafka.logs.dir="%Dkafka_logs_dir%" -Djava.security.auth.login.config="%~dp0../../config/kafka_server_jaas.conf" -Dsun.security.krb5.debug=true
Note: the bold entry is optional and only required if you want to see detailed information from the security module.
If all works immediately then great, otherwise you need to have a look at the console output with the following modifier in the jaas files (both Zookeeper and Kafka): debug="true"
4.When you run Kafka process make sure it runs as DOMAIN\Kafka_test.
Now you can try out the SASL_WIN32 kafka driver as updated by @zyzil. Please see here. For example:
rdkafka_example.exe -P -t SOME_TOPIC -b HOST_FQDN:9093 -X security.protocol=SASL_PLAINTEXT -X sasl.kerberos.service.name= kafka/HOST_FQDN@REALM -X sasl.kerberos.principal=kafka -d security,protocol,broker
Here is a sample output from a successful demonstration of running the above. Note the bold sections:
LOG-7-BRKMAIN: :0/internal: Enter main broker thread
LOG-7-BROKER: sasl_plaintext://HOST_FQDN:9093/bootstrap: Added new broker with NodeId -1
LOG-7-STATE: :0/internal: Broker changed state INIT -> UP
Created producer rdkafka#producer-10.009000.
LOG-7-BRKMAIN: sasl_plaintext://HOST_FQDN:9093/bootstrap: Enter main broker thread
LOG-7-CONNECT: sasl_plaintext://HOST_FQDN:9093/bootstrap: broker in state INIT connecting
LOG-7-CONNECT: sasl_plaintext://HOST_FQDN:9093/bootstrap: Connecting to ipv4#ip_address:9093 (sasl_plaintext) with socket 380
LOG-7-STATE: sasl_plaintext://HOST_FQDN:9093/bootstrap: Broker changed state INIT -> CONNECT
LOG-7-CONNECT: sasl_plaintext://HOST_FQDN:9093/bootstrap: Connected to ipv4#ip_address:9093
LOG-7-CONNECTED: sasl_plaintext://HOST_FQDN:9093/bootstrap: Connected (#1)
LOG-7-APIVERSION: sasl_plaintext://HOST_FQDN:9093/bootstrap: Using (configuration fallback) 0.9.0 protocol features
LOG-7-FEATURE: sasl_plaintext://HOST_FQDN:9093/bootstrap: Updated enabled protocol features to BrokerBalancedConsumer,ThrottleTime,Sasl,BrokerGroupCoordinator,LZ4
LOG-7-AUTH: sasl_plaintext://HOST_FQDN:9093/bootstrap: Auth in state CONNECT (handshake not supported)
LOG-7-STATE: sasl_plaintext://HOST_FQDN:9093/bootstrap: Broker changed state CONNECT -> AUTH
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Initializing SASL client: service name kafka/HOST_FQDN@REALM, hostname HOST_FQDN, mechanisms GSSAPI
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Acquired Kerberos credentials handle (expiry in 2147483446.-711548929s)
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Send SASL frame to broker (2473 bytes)
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Received SASL frame from broker (103 bytes)
LOG-7-SASLAUTH: sasl_plaintext://HOST_FQDN:9093/bootstrap: Initialized security
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Send SASL frame to broker (0 bytes)
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Received SASL frame from broker (50 bytes)
LOG-7-SASLAUTH: sasl_plaintext://HOST_FQDN:9093/bootstrap: Validated server token
LOG-7-SASLAUTH: sasl_plaintext://HOST_FQDN:9093/bootstrap: **Sending response message for user: WINDOWS_LOGON@REALM**
LOG-7-SASL: sasl_plaintext://HOST_FQDN:9093/bootstrap: Send SASL frame to broker (68 bytes)
LOG-7-SASLAUTH: sasl_plaintext://HOST_FQDN:9093/bootstrap: **Authenticated**
LOG-7-STATE: sasl_plaintext://HOST_FQDN:9093/bootstrap: Broker changed state AUTH -> UP
LOG-7-SEND: sasl_plaintext://HOST_FQDN:9093/bootstrap: Sent MetadataRequest (v0, 37 bytes @ 0, CorrId 1)
LOG-7-RECV: sasl_plaintext://HOST_FQDN:9093/bootstrap: Received MetadataResponse (v0, 60 bytes, CorrId 1, rtt 141.00ms)
LOG-7-UPDATE: sasl_plaintext://HOST_FQDN:9093/bootstrap: NodeId changed from -1 to 1
LOG-7-UPDATE: sasl_plaintext://HOST_FQDN:9093/1: Name changed from sasl_plaintext://HOST_FQDN:9093/bootstrap to sasl_plaintext://HOST_FQDN:9093/1
LOG-7-STATE: sasl_plaintext://HOST_FQDN:9093/1: Broker changed state UP -> UPDATE
LOG-7-SEND: sasl_plaintext://HOST_FQDN:9093/1: Sent MetadataRequest (v0, 37 bytes @ 0, CorrId 2)
LOG-7-STATE: sasl_plaintext://HOST_FQDN:9093/1: Broker changed state UPDATE -> UP
LOG-7-RECV: sasl_plaintext://HOST_FQDN:9093/1: Received MetadataResponse (v0, 60 bytes, CorrId 2, rtt 125.00ms)
LOG-7-SEND: sasl_plaintext://HOST_FQDN:9093/1: Sent MetadataRequest (v0, 37 bytes @ 0, CorrId 3)
LOG-7-RECV: sasl_plaintext://HOST_FQDN:9093/1: Received MetadataResponse (v0, 60 bytes, CorrId 3, rtt 125.00ms)
LOG-7-SEND: sasl_plaintext://HOST_FQDN:9093/1: Sent MetadataRequest (v0, 37 bytes @ 0, CorrId 4)
LOG-7-RECV: sasl_plaintext://HOST_FQDN:9093/1: Received MetadataResponse (v0, 86 bytes, CorrId 4, rtt 125.00ms)
LOG-7-TOPBRK: sasl_plaintext://HOST_FQDN:9093/1: Topic **SOME_TOPIC** [0]: joining broker (rktp 00826C80)
**sending message**
% Produced message (15 bytes)
LOG-7-SEND: sasl_plaintext://HOST_FQDN:9093/1: Sent ProduceRequest (v1, 96 bytes @ 0, CorrId 5)
LOG-7-RECV: sasl_plaintext://HOST_FQDN:9093/1: **Received ProduceResponse** (v1, 38 bytes, CorrId 5, rtt 140.00ms)