Skip to content

Commit c3bfa24

Browse files
committed
ZOOKEEPER-4990: accept ssl.* in client config
1 parent 5127900 commit c3bfa24

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,21 @@ bin/zkCli.sh -waitforconnection -timeout 3000 -server remoteIP:2181
2929
# connect with a custom client configuration properties file
3030
bin/zkCli.sh -client-configuration /path/to/client.properties
3131
```
32+
33+
When connecting to a TLS-only server, provide a client configuration file with
34+
the SSL settings. The `zookeeper.ssl.*` keys are preferred; `ssl.*` keys from a
35+
server `zoo.cfg` are also accepted.
36+
37+
```bash
38+
# client.properties (TLS example)
39+
zookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocketNetty
40+
zookeeper.client.secure=true
41+
zookeeper.ssl.trustStore.location=/path/to/client-truststore.jks
42+
zookeeper.ssl.trustStore.password=changeit
43+
zookeeper.ssl.keyStore.location=/path/to/client-keystore.jks
44+
zookeeper.ssl.keyStore.password=changeit
45+
```
46+
3247
## help
3348
Showing helps about ZooKeeper commands
3449

@@ -570,4 +585,4 @@ Gives all authentication information added into the current session.
570585
[zkshell: 3] whoami
571586
Auth scheme: User
572587
ip: 127.0.0.1
573-
digest: user1
588+
digest: user1

zookeeper-server/src/main/java/org/apache/zookeeper/client/ZKClientConfig.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.File;
2222
import org.apache.yetus.audience.InterfaceAudience;
2323
import org.apache.zookeeper.ZooKeeper;
24+
import org.apache.zookeeper.common.ClientX509Util;
2425
import org.apache.zookeeper.common.ZKConfig;
2526
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
2627

@@ -64,6 +65,7 @@ public class ZKClientConfig extends ZKConfig {
6465
* Feature is disabled by default.
6566
*/
6667
public static final long ZOOKEEPER_REQUEST_TIMEOUT_DEFAULT = 0;
68+
private static final String ZOOKEEPER_PREFIX = "zookeeper.";
6769

6870
public ZKClientConfig() {
6971
super();
@@ -78,6 +80,12 @@ public ZKClientConfig(String configPath) throws ConfigException {
7880
super(configPath);
7981
}
8082

83+
@Override
84+
public void addConfiguration(File configFile) throws ConfigException {
85+
super.addConfiguration(configFile);
86+
applyServerSslConfiguration();
87+
}
88+
8189
/**
8290
* Initialize all the ZooKeeper client properties which are configurable as
8391
* java system property
@@ -108,6 +116,43 @@ protected void handleBackwardCompatibility() {
108116
setProperty(SECURE_CLIENT, System.getProperty(SECURE_CLIENT));
109117
}
110118

119+
private void applyServerSslConfiguration() {
120+
try (ClientX509Util clientX509Util = new ClientX509Util()) {
121+
copyServerSslProperty(clientX509Util.getSslProtocolProperty());
122+
copyServerSslProperty(clientX509Util.getSslEnabledProtocolsProperty());
123+
copyServerSslProperty(clientX509Util.getSslCipherSuitesProperty());
124+
copyServerSslProperty(clientX509Util.getSslKeystoreLocationProperty());
125+
copyServerSslProperty(clientX509Util.getSslKeystorePasswdProperty());
126+
copyServerSslProperty(clientX509Util.getSslKeystorePasswdPathProperty());
127+
copyServerSslProperty(clientX509Util.getSslKeystoreTypeProperty());
128+
copyServerSslProperty(clientX509Util.getSslTruststoreLocationProperty());
129+
copyServerSslProperty(clientX509Util.getSslTruststorePasswdProperty());
130+
copyServerSslProperty(clientX509Util.getSslTruststorePasswdPathProperty());
131+
copyServerSslProperty(clientX509Util.getSslTruststoreTypeProperty());
132+
copyServerSslProperty(clientX509Util.getSslContextSupplierClassProperty());
133+
copyServerSslProperty(clientX509Util.getSslHostnameVerificationEnabledProperty());
134+
copyServerSslProperty(clientX509Util.getSslCrlEnabledProperty());
135+
copyServerSslProperty(clientX509Util.getSslOcspEnabledProperty());
136+
copyServerSslProperty(clientX509Util.getSslClientAuthProperty());
137+
copyServerSslProperty(clientX509Util.getSslHandshakeDetectionTimeoutMillisProperty());
138+
copyServerSslProperty(clientX509Util.getSslAuthProviderProperty());
139+
}
140+
}
141+
142+
private void copyServerSslProperty(String clientProperty) {
143+
if (clientProperty == null || getProperty(clientProperty) != null) {
144+
return;
145+
}
146+
if (!clientProperty.startsWith(ZOOKEEPER_PREFIX)) {
147+
return;
148+
}
149+
String serverProperty = clientProperty.substring(ZOOKEEPER_PREFIX.length());
150+
String serverValue = getProperty(serverProperty);
151+
if (serverValue != null) {
152+
setProperty(clientProperty, serverValue);
153+
}
154+
}
155+
111156
/**
112157
* Returns true if the SASL client is enabled. By default, the client is
113158
* enabled but can be disabled by setting the system property

zookeeper-server/src/test/java/org/apache/zookeeper/client/ZKClientConfigTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.HashMap;
3737
import java.util.Map;
3838
import java.util.Properties;
39+
import org.apache.zookeeper.common.ClientX509Util;
3940
import org.apache.zookeeper.common.ZKConfig;
4041
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
4142
import org.junit.jupiter.api.BeforeAll;
@@ -138,6 +139,37 @@ public void testReadConfigurationFile() throws IOException, ConfigException {
138139
file.delete();
139140
}
140141

142+
@Test
143+
@Timeout(value = 10)
144+
public void testServerSslPropertyFallback() throws IOException, ConfigException {
145+
File file = File.createTempFile("clientConfigSsl", ".conf", testData);
146+
file.deleteOnExit();
147+
Properties clientConfProp = new Properties();
148+
clientConfProp.setProperty("ssl.trustStore.location", "/tmp/server-truststore.jks");
149+
clientConfProp.setProperty("ssl.trustStore.password", "server-pass");
150+
clientConfProp.setProperty("ssl.keyStore.location", "/tmp/server-keystore.jks");
151+
clientConfProp.setProperty("ssl.keyStore.password", "server-pass");
152+
clientConfProp.setProperty("zookeeper.ssl.trustStore.location", "/tmp/client-truststore.jks");
153+
OutputStream io = new FileOutputStream(file);
154+
try {
155+
clientConfProp.store(io, "Client Configurations");
156+
} finally {
157+
io.close();
158+
}
159+
160+
ZKClientConfig conf = new ZKClientConfig();
161+
conf.addConfiguration(file.getAbsolutePath());
162+
163+
try (ClientX509Util clientX509Util = new ClientX509Util()) {
164+
assertEquals("/tmp/client-truststore.jks", conf.getProperty(clientX509Util.getSslTruststoreLocationProperty()));
165+
assertEquals("server-pass", conf.getProperty(clientX509Util.getSslTruststorePasswdProperty()));
166+
assertEquals("/tmp/server-keystore.jks", conf.getProperty(clientX509Util.getSslKeystoreLocationProperty()));
167+
assertEquals("server-pass", conf.getProperty(clientX509Util.getSslKeystorePasswdProperty()));
168+
}
169+
170+
file.delete();
171+
}
172+
141173
@Test
142174
@Timeout(value = 10)
143175
public void testSetConfiguration() {

0 commit comments

Comments
 (0)