Hi, May I ask for some help about setting up SSL for Zookeeper, please?
My goal is just to add SSL for my zookeeper server then just test it using openssl s_client. So far I got this from the logs (WARN) "Empty server certificate chain". So here's what I've done so far. #1 Install Kafka and Zookeeper in my Ubuntu machine (using multipass). I downloaded the latest version here <https://www.apache.org/dyn/closer.cgi?path=/kafka/2.8.0/kafka_2.12-2.8.0.tgz> #2 I was able to connect Kafka to Zookeeper just fine. Zookeeper: kafka@zoo:/etc/kafka$ bin/zookeeper-server-start.sh config/zookeeper.properties [image: image.png] #3 Test the SSL connection without setting up the zookeeper.properties and .jks files kafka@zoo:/etc/kafka$ openssl s_client -showcerts -connect localhost:2181 CONNECTED(00000003) write:errno=0 --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 0 bytes and written 283 bytes Verification: OK --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok) --- #4 Setup SSL zookeeper.properties and .jks files Below and the commands I've done to generate the and sign the SSL (the .jks files) Example steps to implement CA, truststore and keystore for zookeeper SSL security : 𝟏. 𝐆𝐞𝐧𝐞𝐫𝐚𝐭𝐞 𝐂𝐀 == openssl req -new -x509 -keyout ca-key -out ca-cert -days 3650 𝟐. 𝐂𝐫𝐞𝐚𝐭𝐞 𝐓𝐫𝐮𝐬𝐭𝐬𝐭𝐨𝐫𝐞 == keytool -keystore kafka.zookeeper.truststore.jks -alias ca-cert -import -file ca-cert 𝟑. 𝐂𝐫𝐞𝐚𝐭𝐞 𝐊𝐞𝐲𝐬𝐭𝐨𝐫𝐞 == keytool -keystore kafka.zookeeper.keystore.jks -alias zookeeper -validity 3650 -genkey -keyalg RSA -ext SAN=dns:localhost 𝟒. 𝐂𝐫𝐞𝐚𝐭𝐞 𝐜𝐞𝐫𝐭𝐢𝐟𝐢𝐜𝐚𝐭𝐞 𝐬𝐢𝐠𝐧𝐢𝐧𝐠 𝐫𝐞𝐪𝐮𝐞𝐬𝐭 (𝐂𝐒𝐑) == keytool -keystore kafka.zookeeper.keystore.jks -alias zookeeper -certreq -file ca-request-zookeeper 𝟓. 𝐒𝐢𝐠𝐧 𝐭𝐡𝐞 𝐂𝐒𝐑 == openssl x509 -req -CA ca-cert -CAkey ca-key -in ca-request-zookeeper -out ca-signed-zookeeper -days 3650 -CAcreateserial 𝟔. 𝐈𝐦𝐩𝐨𝐫𝐭 𝐭𝐡𝐞 𝐂𝐀 𝐢𝐧𝐭𝐨 𝐊𝐞𝐲𝐬𝐭𝐨𝐫𝐞 == keytool -keystore kafka.zookeeper.keystore.jks -alias ca-cert -import -file ca-cert 𝟕. 𝐈𝐦𝐩𝐨𝐫𝐭 𝐭𝐡𝐞 𝐬𝐢𝐠𝐧𝐞𝐝 𝐜𝐞𝐫𝐭𝐢𝐟𝐢𝐜𝐚𝐭𝐞 𝐢𝐧𝐭𝐨 𝐊𝐞𝐲𝐬𝐭𝐨𝐫𝐞 == keytool -keystore kafka.zookeeper.keystore.jks -alias zookeeper -import -file ca-signed-zookeeper See the files are there in /etc/kafka kafka@zoo:/etc/kafka$ ls LICENSE bin ca-cert.srl ca-request-zookeeper config kafka.zookeeper.truststore.jks licenses site-docs NOTICE ca-cert ca-key ca-signed-zookeeper kafka.zookeeper.keystore.jks libs logs I added some lines in zookeeper.properties and here's the content of that file: kafka@zoo:/etc/kafka$ cat config/zookeeper.properties # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # the directory where the snapshot is stored. dataDir=/tmp/zookeeper # the port at which the clients will connect clientPort=2181 secureClientPort=2182 authProvider.x509=org.apache.zookeeper.server.auth.X509AuthenticationProvider serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory ssl.trustStore.location=kafka.zookeeper.truststore.jks ssl.trustStore.password=123456 ssl.keyStore.location=kafka.zookeeper.keystore.jks ssl.keyStore.password=123456 ssl.clientAuth=need # disable the per-ip limit on the number of connections since this is a non-production config maxClientCnxns=0 # Disable the adminserver by default to avoid port conflicts. # Set the port to something non-conflicting if choosing to enable this admin.enableServer=false # admin.serverPort=8080 #5 Test the SSL kafka@zoo:/etc/kafka$ openssl s_client -showcerts -connect localhost:2182 CONNECTED(00000003) Can't use SSL_get_servername depth=1 C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd verify error:num=19:self signed certificate in certificate chain verify return:1 depth=1 C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd verify return:1 depth=0 C = Unknown, ST = Unknown, L = Budapest, O = K Inc., OU = K, CN = John verify return:1 140307772192064:error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate:../ssl/record/rec_layer_s3.c:1543:SSL alert number 42 --- Certificate chain 0 s:C = Unknown, ST = Unknown, L = Budapest, O = K Inc., OU = K, CN = John i:C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd -----BEGIN CERTIFICATE----- MIIDLjCCAhYCFDmPPYOIc+LFjLje1r6oWDALW4w9MA0GCSqGSIb3DQEBCwUAMEQx CzAJBgNVBAYTAkFVMRIwEAYDVQQIDAlNZWxib3VybmUxITAfBgNVBAoMGEludGVy bmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA3MzAwMjQ4MTJaFw0zMTA3MjgwMjQ4 MTJaMGMxEDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xETAPBgNV BAcTCEJ1ZGFwZXN0MQ8wDQYDVQQKEwZLIEluYy4xCjAIBgNVBAsTAUsxDTALBgNV BAMTBEpvaG4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXvPlp6/yp 3S2QQtumEdLFamTRHt6sZVXG1jT4fWMj5gWSaqFKtnjn0At334qycG7IQtY/9Qnf H3OCghpjN3P5h/ImGQKDbL9E4AhE2SI6kz5MRO7HRhpneRloUwuSqWQr0ARVaC12 e6EOGIhZlSMer68A/tOCqYKy95ZOWRugwSeghNyEeV1hi7buew9N1tpVKxa01CoB tFwwiKbcXAhX4Ea0pnOQxDF6QmrMPVzrt03PEkBxpm/t/Hl4fdxt4UuuldNcyiPN wdj/zjwFAqBxI9xMo5zzxh7bxT4uv8Ij701GXZr0jKfsV97KMiIJ5fNMlDf3awUa RfLFVbph4tuPAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFc9IVeyqdIlrEjtT9kc vLrLCXy3mJuxmpxN7SnAOeNGqWkOonjIXmumQUiuBGk++F13a0+yD3JUN5o+zpVE k5ptk2nPsWkrhWaR6t1OG5ucdNHNtNE49tY1eqWBHOulnyVih2D52fXhUHB78Rtc vXbgXHOXDoLznCPe0JcHcuvtruiiKr0KTjABBlVQogxkUDq9ttvXqb1lUtosqPgG aSHOpEE0sRi+YfHQv6ludK982O/bfc8FZu0xJwp9PIMwFkXMoUyp7gxoFQtncTaM E8Mz8OekXT8sBQ5WBoArs9LRbeQfot2uhTA0/FfUK3v7r2twHwfRK9Zl6SiDV5Pk XkA= -----END CERTIFICATE----- 1 s:C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd i:C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd -----BEGIN CERTIFICATE----- MIIDaTCCAlGgAwIBAgIUfsM/BlsOkJyd5IrQBNOFq0lsx08wDQYJKoZIhvcNAQEL BQAwRDELMAkGA1UEBhMCQVUxEjAQBgNVBAgMCU1lbGJvdXJuZTEhMB8GA1UECgwY SW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTIxMDczMDAyNDQ0NloXDTMxMDcy ODAyNDQ0NlowRDELMAkGA1UEBhMCQVUxEjAQBgNVBAgMCU1lbGJvdXJuZTEhMB8G A1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAsaUHS0ZXo4y4vBvPyhnI7MVyXppZmZW4laqniglQLZAZ fJQBApfDH9hQJQTNZQ6bPkukPOFGbJ3+LPBlmdojk6Rio9cV05FqAN2iH6Gbbn9a IPkSyBBbCsn8Y1Mq5scfMzgSAJfW8dw3GixDzf/+I1ZkPRkfk9A1K0tJLxmb4zcR J9LPIA90Qqr807CFgFbasq1d8e8hrKVkmpoC6gZCGxVbACZvvW3RJ9uOicDql99u UbPEGY8JjxN8zgubEkdIEXBFJxeic9HCgkfeydK1YJvVLAnIWAyCva8smoVGShu5 IvdNYFcKcbC+s1i4EdHUDauRJwMhSZ+ZmjZGl/3RpwIDAQABo1MwUTAdBgNVHQ4E FgQUldMJGkGoz78mBgJq9CAow0lTBaQwHwYDVR0jBBgwFoAUldMJGkGoz78mBgJq 9CAow0lTBaQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQn73 Zk+L78Gy9v7/xu2EaJjt+PEb0WhP6cknUs/MEwBJoTH1VYsUK4cqZ7PA5TDbRfM0 UHnmQuS5A9MP3eeqIUllp8YusBl4bYxIkS+5JJwmtLSlcE3JPtBmgSo1c+GKnnCh +9CfGqC7e2YNjwo1wYAgErAKV8RNh49KFn1/oAr8iT18J2pEvnQE5cU+uv7esOy7 DwwVEVOkqVfWAhlI3YcK8Q7cUMJpF0ksFVHJwn05mPI3gmAnK4M6FxtMg6T+IdUE gJp/njW8pf/ZnF9t4Up+qD/IHsLAqv9EHBgDaTJcpTG9mh/s9HeqGaYSv2f5pIxk eJyw+IlbMjZ4kLgoKw== -----END CERTIFICATE----- --- Server certificate subject=C = Unknown, ST = Unknown, L = Budapest, O = K Inc., OU = K, CN = John issuer=C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd --- Acceptable client certificate CA names C = AU, ST = Melbourne, O = Internet Widgits Pty Ltd Client Certificate Types: ECDSA sign, RSA sign, DSA sign Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:DSA+SHA256:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:ECDSA+SHA1:RSA+SHA1:DSA+SHA1 Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:DSA+SHA256:ECDSA+SHA224:RSA+SHA224:DSA+SHA224 Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits --- SSL handshake has read 2231 bytes and written 388 bytes Verification error: self signed certificate in certificate chain --- New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: F9EBF583C0FE33D2AEB8FF1CF81A1B79A577D0FFC8D6B028D4FE5020F5554EE1 Session-ID-ctx: Master-Key: 2A655AEB537244E0129B8967A6942488C999B7A02CCD43E7707D2DD8E0A366CC673D843E945A584A8834988BFD9B8141 PSK identity: None PSK identity hint: None SRP username: None Start Time: 1627615015 Timeout : 7200 (sec) Verify return code: 19 (self signed certificate in certificate chain) Extended master secret: yes --- # 6 Logs from zookeeper: [2021-07-30 11:17:32,076] ERROR Unsuccessful handshake with session 0x0 (org.apache.zookeeper.server.NettyServerCnxnFactory) [2021-07-30 11:17:32,090] WARN Exception caught (org.apache.zookeeper.server.NettyServerCnxnFactory) io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Empty server certificate chain at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:478) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: javax.net.ssl.SSLHandshakeException: Empty server certificate chain at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:292) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:283) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:390) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:375) at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1074) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1061) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1008) at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1565) at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1579) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1463) at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1290) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1337) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ... 17 more Best regards, John Mark Causing