Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ bin/zkCli.sh -waitforconnection -timeout 3000 -server remoteIP:2181
# connect with a custom client configuration properties file
bin/zkCli.sh -client-configuration /path/to/client.properties
```

When connecting to a TLS-only server, provide a client configuration file with
the SSL settings. The `zookeeper.ssl.*` keys are preferred; `ssl.*` keys from a
server `zoo.cfg` are also accepted.

```bash
# client.properties (TLS example)
zookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocketNetty
zookeeper.client.secure=true
zookeeper.ssl.trustStore.location=/path/to/client-truststore.jks
zookeeper.ssl.trustStore.password=changeit
zookeeper.ssl.keyStore.location=/path/to/client-keystore.jks
zookeeper.ssl.keyStore.password=changeit
```

## help
Showing helps about ZooKeeper commands

Expand Down Expand Up @@ -570,4 +585,4 @@ Gives all authentication information added into the current session.
[zkshell: 3] whoami
Auth scheme: User
ip: 127.0.0.1
digest: user1
digest: user1
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.File;
import java.nio.file.Path;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.zookeeper.common.ClientX509Util;
import org.apache.zookeeper.common.ConfigException;
import org.apache.zookeeper.common.ZKConfig;

Expand Down Expand Up @@ -59,6 +60,7 @@ public class ZKClientConfig extends ZKConfig {
* Feature is disabled by default.
*/
public static final long ZOOKEEPER_REQUEST_TIMEOUT_DEFAULT = 0;
private static final String ZOOKEEPER_PREFIX = "zookeeper.";
public static final String ZK_SASL_CLIENT_ALLOW_REVERSE_DNS = "zookeeper.sasl.client.allowReverseDnsLookup";
public static final boolean ZK_SASL_CLIENT_ALLOW_REVERSE_DNS_DEFAULT = false;
/**
Expand Down Expand Up @@ -107,6 +109,12 @@ public ZKClientConfig(Path configPath) throws ConfigException {
super(configPath);
}

@Override
public void addConfiguration(Path configPath) throws ConfigException {
super.addConfiguration(configPath);
applyServerSslConfiguration();
}

/**
* Initialize all the ZooKeeper client properties which are configurable as
* java system property
Expand Down Expand Up @@ -139,6 +147,43 @@ protected void handleBackwardCompatibility() {
setProperty(DNS_SRV_REFRESH_INTERVAL_SECONDS, System.getProperty(DNS_SRV_REFRESH_INTERVAL_SECONDS));
}

private void applyServerSslConfiguration() {
try (ClientX509Util clientX509Util = new ClientX509Util()) {
copyServerSslProperty(clientX509Util.getSslProtocolProperty());
copyServerSslProperty(clientX509Util.getSslEnabledProtocolsProperty());
copyServerSslProperty(clientX509Util.getSslCipherSuitesProperty());
copyServerSslProperty(clientX509Util.getSslKeystoreLocationProperty());
copyServerSslProperty(clientX509Util.getSslKeystorePasswdProperty());
copyServerSslProperty(clientX509Util.getSslKeystorePasswdPathProperty());
copyServerSslProperty(clientX509Util.getSslKeystoreTypeProperty());
copyServerSslProperty(clientX509Util.getSslTruststoreLocationProperty());
copyServerSslProperty(clientX509Util.getSslTruststorePasswdProperty());
copyServerSslProperty(clientX509Util.getSslTruststorePasswdPathProperty());
copyServerSslProperty(clientX509Util.getSslTruststoreTypeProperty());
copyServerSslProperty(clientX509Util.getSslContextSupplierClassProperty());
copyServerSslProperty(clientX509Util.getSslHostnameVerificationEnabledProperty());
copyServerSslProperty(clientX509Util.getSslCrlEnabledProperty());
copyServerSslProperty(clientX509Util.getSslOcspEnabledProperty());
copyServerSslProperty(clientX509Util.getSslClientAuthProperty());
copyServerSslProperty(clientX509Util.getSslHandshakeDetectionTimeoutMillisProperty());
copyServerSslProperty(clientX509Util.getSslAuthProviderProperty());
}
}

private void copyServerSslProperty(String clientProperty) {
if (clientProperty == null || getProperty(clientProperty) != null) {
return;
}
if (!clientProperty.startsWith(ZOOKEEPER_PREFIX)) {
return;
}
String serverProperty = clientProperty.substring(ZOOKEEPER_PREFIX.length());
String serverValue = getProperty(serverProperty);
if (serverValue != null) {
setProperty(clientProperty, serverValue);
}
}

/**
* Returns true if the SASL client is enabled. By default, the client is
* enabled but can be disabled by setting the system property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.zookeeper.common.ClientX509Util;
import org.apache.zookeeper.common.ConfigException;
import org.apache.zookeeper.common.ZKConfig;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -125,6 +126,34 @@ public void testReadConfigurationFile(@TempDir File testDataDir) throws IOExcept
assertEquals(conf.getProperty("dummyProperty"), "dummyValue");
}

@Test
@Timeout(value = 10)
public void testServerSslPropertyFallback(@TempDir File testDataDir) throws IOException, ConfigException {
File file = File.createTempFile("clientConfigSsl", ".conf", testDataDir);
Properties clientConfProp = new Properties();
clientConfProp.setProperty("ssl.trustStore.location", "/tmp/server-truststore.jks");
clientConfProp.setProperty("ssl.trustStore.password", "server-pass");
clientConfProp.setProperty("ssl.keyStore.location", "/tmp/server-keystore.jks");
clientConfProp.setProperty("ssl.keyStore.password", "server-pass");
clientConfProp.setProperty("zookeeper.ssl.trustStore.location", "/tmp/client-truststore.jks");
OutputStream io = new FileOutputStream(file);
try {
clientConfProp.store(io, "Client Configurations");
} finally {
io.close();
}

ZKClientConfig conf = new ZKClientConfig();
conf.addConfiguration(Paths.get(file.getAbsolutePath()));

try (ClientX509Util clientX509Util = new ClientX509Util()) {
assertEquals("/tmp/client-truststore.jks", conf.getProperty(clientX509Util.getSslTruststoreLocationProperty()));
assertEquals("server-pass", conf.getProperty(clientX509Util.getSslTruststorePasswdProperty()));
assertEquals("/tmp/server-keystore.jks", conf.getProperty(clientX509Util.getSslKeystoreLocationProperty()));
assertEquals("server-pass", conf.getProperty(clientX509Util.getSslKeystorePasswdProperty()));
}
}

@Test
@Timeout(value = 10)
public void testSetConfiguration() {
Expand Down