I think I've found the way to connect SolrCloud to an external ZooKeeper
ensemble via SSL.

By default, Solr does not use SSL to connect to ZooKeeper. So if the
ZooKeeper configuration requires SSL for client connections, Solr will
complain like this when it tries to connect to ZooKeeper:

--8<---------------cut here---------------start------------->8---
WARN  - 2022-03-25 12:34:43.681; org.apache.zookeeper.ClientCnxn; Session 0x0 
for sever localhost/127.0.0.1:2182, Closing socket connection. Attempting 
reconnect except it is a SessionExpiredException. => EndOfStreamException: 
Unable to read additional data from server sessionid 0x0, likely server has 
closed socket
        at 
org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:77)
org.apache.zookeeper.ClientCnxn$EndOfStreamException: Unable to read additional 
data from server sessionid 0x0, likely server has closed socket
        at 
org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:77) 
~[zookeeper-3.6.2.jar:3.6.2]
        at 
org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:350)
 ~[zookeeper-3.6.2.jar:3.6.2]
        at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1275) 
~[zookeeper-3.6.2.jar:3.6.2]
--8<---------------cut here---------------end--------------->8---

On the ZooKeeper side, the corresponding log entry is something like
this:

--8<---------------cut here---------------start------------->8---
2022-03-25 12:34:43,652 [myid:1] - ERROR 
[nioEventLoopGroup-4-2:NettyServerCnxnFactory$CertificateVerifier@448] - 
Unsuccessful handshake with session 0x0
2022-03-25 12:34:43,682 [myid:1] - WARN  
[nioEventLoopGroup-4-2:NettyServerCnxnFactory$CnxnChannelHandler@284] - 
Exception caught
io.netty.handler.codec.DecoderException: 
io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 
0000002d000000000000000000000000000075300000000000000000000000100000000000000000000000000000000000
        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: io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 
0000002d000000000000000000000000000075300000000000000000000000100000000000000000000000000000000000
        at 
io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1232)
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1300)
        at 
io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
        at 
io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
        ... 17 more
--8<---------------cut here---------------end--------------->8---

This error message indicates that ZooKeeper was expecting an SSL
connection, but the client (i.e. Solr) was connecting without SSL.

The solution is to add the appropriate ZooKeeper Java properties. Notice
that these are exactly the same properties needed by standalone
ZooKeeper's 'zkServer.sh' and 'zkCli.sh' to connect to ZooKeeper via
SSL [1] [2]. Add the following to bin/solr.in.sh:

--8<---------------cut here---------------start------------->8---
SOLR_OPTS="$SOLR_OPTS
    -Dzookeeper.client.secure=true
    -Dzookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocketNetty
    -Dzookeeper.ssl.keyStore.location=/path/to/zk-keystore.jks
    -Dzookeeper.ssl.keyStore.password=thepassword
    -Dzookeeper.ssl.trustStore.location=/path/to/zk-truststore.jks
    -Dzookeeper.ssl.trustStore.password=thepassword"
--8<---------------cut here---------------end--------------->8---


  [1]: https://stackoverflow.com/questions/43930797/configuring-ssl-in-zookeeper
  [2]: 
https://cwiki.apache.org/confluence/display/zookeeper/zookeeper+ssl+user+guide
    (Note that this ^ webpage says, "There is currently no support for
    SSL for the communication between ZooKeeper servers". That statement
    is no longer correct. "Quorum TLS" is available from ZooKeeper 3.5.5
    onwards).

Reply via email to