This is an automated email from the ASF dual-hosted git repository. eolivelli pushed a commit to branch branch-3.6 in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/branch-3.6 by this push: new c5f55eb ZOOKEEPER-3689: zkCli/ZooKeeperMain relies on system properties for TLS config c5f55eb is described below commit c5f55eb39249f853398adf87a1860ee1025e99c9 Author: Sankalp <san...@amazon.com> AuthorDate: Thu Mar 26 22:19:08 2020 +0100 ZOOKEEPER-3689: zkCli/ZooKeeperMain relies on system properties for TLS config The current zkCli uses system properties to set confidential information like keystore location, password etc. This is not secure as these properties need to be passed on the command line as "-D" arguments. Currently, there is no way to create a ZookeeperAdmin does not have a constructor which takes both canBeReadOnly and ZKClientConfig as parameters. I am introducing a new constructor in ZookeeperAdmin which takes an additional ZKClientConfig parameter. This ZKClientConfig is created by an optional command line argument ``client-configuration``. If no argument is passed, a ZookeeperAdmin object with null client config is created, just like before. Author: Sankalp <san...@amazon.com> Reviewers: Enrico Olivelli <eolive...@apache.org>, Norbert Kalmar <nkal...@apache.org>, Justin Ling Mao <maoling199210...@sina.com> Closes #1285 from sankalpbhatia/ZOOKEEPER-3689 (cherry picked from commit b4a3238d1d0cebe1c97ed23427bbcc69c8477c8a) Signed-off-by: Enrico Olivelli <eolivelli@localhost.localdomain> --- .../src/main/resources/markdown/zookeeperCLI.md | 2 + .../java/org/apache/zookeeper/ZooKeeperMain.java | 19 ++++++++- .../org/apache/zookeeper/admin/ZooKeeperAdmin.java | 48 ++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md b/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md index 637e6b4..c9ebd2b 100644 --- a/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md +++ b/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md @@ -24,6 +24,8 @@ Enter into the ZooKeeper-cli bin/zkCli.sh # connect to the remote host with timeout:3s bin/zkCli.sh -timeout 3000 -server remoteIP:2181 +# connect with a custom client configuration properties file +bin/zkCli.sh -client-configuration /path/to/client.properties ``` ## help Showing helps about ZooKeeper commands diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java index 8d8a419..243aca3 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java @@ -65,6 +65,7 @@ import org.apache.zookeeper.cli.SyncCommand; import org.apache.zookeeper.cli.VersionCommand; import org.apache.zookeeper.client.ZKClientConfig; import org.apache.zookeeper.server.ExitCode; +import org.apache.zookeeper.server.quorum.QuorumPeerConfig; import org.apache.zookeeper.util.ServiceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -130,7 +131,7 @@ public class ZooKeeperMain { } static void usage() { - System.err.println("ZooKeeper -server host:port cmd args"); + System.err.println("ZooKeeper -server host:port -client-configuration properties-file cmd args"); List<String> cmdList = new ArrayList<String>(commandMap.keySet()); Collections.sort(cmdList); for (String cmd : cmdList) { @@ -205,6 +206,8 @@ public class ZooKeeperMain { options.put("timeout", it.next()); } else if (opt.equals("-r")) { options.put("readonly", "true"); + } else if (opt.equals("-client-configuration")) { + options.put("client-configuration", it.next()); } } catch (NoSuchElementException e) { System.err.println("Error: no argument found for option " + opt); @@ -286,7 +289,19 @@ public class ZooKeeperMain { System.setProperty(ZKClientConfig.SECURE_CLIENT, "true"); System.out.println("Secure connection is enabled"); } - zk = new ZooKeeperAdmin(host, Integer.parseInt(cl.getOption("timeout")), new MyWatcher(), readOnly); + + ZKClientConfig clientConfig = null; + + if (cl.getOption("client-configuration") != null) { + try { + clientConfig = new ZKClientConfig(cl.getOption("client-configuration")); + } catch (QuorumPeerConfig.ConfigException e) { + e.printStackTrace(); + ServiceUtils.requestSystemExit(ExitCode.INVALID_INVOCATION.getValue()); + } + } + + zk = new ZooKeeperAdmin(host, Integer.parseInt(cl.getOption("timeout")), new MyWatcher(), readOnly, clientConfig); } public static void main(String[] args) throws IOException, InterruptedException { diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/admin/ZooKeeperAdmin.java b/zookeeper-server/src/main/java/org/apache/zookeeper/admin/ZooKeeperAdmin.java index 05c9928..8240526 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/admin/ZooKeeperAdmin.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/admin/ZooKeeperAdmin.java @@ -150,6 +150,54 @@ public class ZooKeeperAdmin extends ZooKeeper { * connects to one in read-only mode, i.e. read requests are * allowed while write requests are not. It continues seeking for * majority in the background. + * @param conf + * passing this conf object gives each client the flexibility of + * configuring properties differently compared to other instances + * + * @throws IOException + * in cases of network failure + * @throws IllegalArgumentException + * if an invalid chroot path is specified + * + * @see ZooKeeper#ZooKeeper(String, int, Watcher, boolean, ZKClientConfig) + * + * @since 3.6.1 + */ + public ZooKeeperAdmin( + String connectString, + int sessionTimeout, + Watcher watcher, + boolean canBeReadOnly, + ZKClientConfig conf) throws IOException { + super(connectString, sessionTimeout, watcher, canBeReadOnly, conf); + } + + /** + * Create a ZooKeeperAdmin object which is used to perform dynamic reconfiguration + * operations. + * + * @param connectString + * comma separated host:port pairs, each corresponding to a zk + * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If + * the optional chroot suffix is used the example would look + * like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" + * where the client would be rooted at "/app/a" and all paths + * would be relative to this root - ie getting/setting/etc... + * "/foo/bar" would result in operations being run on + * "/app/a/foo/bar" (from the server perspective). + * @param sessionTimeout + * session timeout in milliseconds + * @param watcher + * a watcher object which will be notified of state changes, may + * also be notified for node events + * @param canBeReadOnly + * whether the created client is allowed to go to + * read-only mode in case of partitioning. Read-only mode + * basically means that if the client can't find any majority + * servers but there's partitioned server it could reach, it + * connects to one in read-only mode, i.e. read requests are + * allowed while write requests are not. It continues seeking for + * majority in the background. * * @throws IOException * in cases of network failure