From b4b1b2a02020217a3d1cc63ea79992953fa22e4e Mon Sep 17 00:00:00 2001 From: varaga <31006611+varaga@users.noreply.github.com> Date: Fri, 15 Jun 2018 22:02:01 +0100 Subject: [PATCH] Provisioning support for ZooKeeper Authorization (#5701) Review comments implemented --- docs/content/configuration/index.md | 3 ++ .../java/io/druid/curator/CuratorConfig.java | 30 ++++++++++++- .../java/io/druid/curator/CuratorModule.java | 45 ++++++++++++------- .../io/druid/curator/CuratorConfigTest.java | 9 +++- 4 files changed, 68 insertions(+), 19 deletions(-) diff --git a/docs/content/configuration/index.md b/docs/content/configuration/index.md index cb1d112a76f..fedb31939cc 100644 --- a/docs/content/configuration/index.md +++ b/docs/content/configuration/index.md @@ -42,6 +42,9 @@ We recommend just setting the base ZK path and the ZK service host, but all ZK p |--------|-----------|-------| |`druid.zk.paths.base`|Base Zookeeper path.|`/druid`| |`druid.zk.service.host`|The ZooKeeper hosts to connect to. This is a REQUIRED property and therefore a host address must be supplied.|none| +|`druid.zk.service.user`|The username to authenticate with ZooKeeper. This is an optional property.|none| +|`druid.zk.service.pwd`|The [Password Provider](../operations/password-provider.html) or the string password to authenticate with ZooKeeper. This is an optional property.|none| +|`druid.zk.service.authScheme`|digest is the only authentication scheme supported. |digest| #### Zookeeper Behavior diff --git a/server/src/main/java/io/druid/curator/CuratorConfig.java b/server/src/main/java/io/druid/curator/CuratorConfig.java index 7ef233eabbf..152bf24b917 100644 --- a/server/src/main/java/io/druid/curator/CuratorConfig.java +++ b/server/src/main/java/io/druid/curator/CuratorConfig.java @@ -19,10 +19,13 @@ package io.druid.curator; +import javax.validation.constraints.Min; + import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Preconditions; -import javax.validation.constraints.Min; +import io.druid.metadata.DefaultPasswordProvider; +import io.druid.metadata.PasswordProvider; /** */ @@ -41,6 +44,15 @@ public class CuratorConfig @JsonProperty("acl") private boolean enableAcl = false; + @JsonProperty("user") + private String zkUser; + + @JsonProperty("pwd") + private PasswordProvider zkPwd = new DefaultPasswordProvider(""); + + @JsonProperty("authScheme") + private String authScheme = "digest"; + public String getZkHosts() { return zkHosts; @@ -82,4 +94,20 @@ public class CuratorConfig Preconditions.checkNotNull(enableAcl, "enableAcl"); this.enableAcl = enableAcl; } + + public String getZkUser() + { + return zkUser; + } + + public String getZkPwd() + { + return zkPwd.getPassword(); + } + + public String getAuthScheme() + { + return authScheme; + } + } diff --git a/server/src/main/java/io/druid/curator/CuratorModule.java b/server/src/main/java/io/druid/curator/CuratorModule.java index 2333720f40b..30aabc1ada0 100644 --- a/server/src/main/java/io/druid/curator/CuratorModule.java +++ b/server/src/main/java/io/druid/curator/CuratorModule.java @@ -19,13 +19,9 @@ package io.druid.curator; -import com.google.inject.Binder; -import com.google.inject.Module; -import com.google.inject.Provides; -import io.druid.guice.JsonConfigProvider; -import io.druid.guice.LazySingleton; -import io.druid.java.util.common.lifecycle.Lifecycle; -import io.druid.java.util.common.logger.Logger; +import java.nio.charset.StandardCharsets; +import java.util.List; + import org.apache.curator.ensemble.EnsembleProvider; import org.apache.curator.ensemble.exhibitor.DefaultExhibitorRestClient; import org.apache.curator.ensemble.exhibitor.ExhibitorEnsembleProvider; @@ -33,13 +29,23 @@ import org.apache.curator.ensemble.exhibitor.Exhibitors; import org.apache.curator.ensemble.fixed.FixedEnsembleProvider; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.CuratorFrameworkFactory.Builder; import org.apache.curator.framework.api.ACLProvider; import org.apache.curator.framework.imps.DefaultACLProvider; import org.apache.curator.retry.BoundedExponentialBackoffRetry; +import org.apache.curator.shaded.com.google.common.base.Strings; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.data.ACL; -import java.util.List; +import com.google.inject.Binder; +import com.google.inject.Module; +import com.google.inject.Provides; + +import io.druid.guice.JsonConfigProvider; +import io.druid.guice.LazySingleton; +import io.druid.java.util.common.StringUtils; +import io.druid.java.util.common.lifecycle.Lifecycle; +import io.druid.java.util.common.logger.Logger; /** */ @@ -70,15 +76,20 @@ public class CuratorModule implements Module CuratorConfig config, EnsembleProvider ensembleProvider, Lifecycle lifecycle ) { - final CuratorFramework framework = - CuratorFrameworkFactory.builder() - .ensembleProvider(ensembleProvider) - .sessionTimeoutMs(config.getZkSessionTimeoutMs()) - .retryPolicy(new BoundedExponentialBackoffRetry( - BASE_SLEEP_TIME_MS, MAX_SLEEP_TIME_MS, MAX_RETRIES)) - .compressionProvider(new PotentiallyGzippedCompressionProvider(config.getEnableCompression())) - .aclProvider(config.getEnableAcl() ? new SecuredACLProvider() : new DefaultACLProvider()) - .build(); + final Builder builder = CuratorFrameworkFactory.builder(); + if (!Strings.isNullOrEmpty(config.getZkUser()) && !Strings.isNullOrEmpty(config.getZkPwd())) { + builder.authorization( + config.getAuthScheme(), + StringUtils.format("%s:%s", config.getZkUser(), config.getZkPwd()).getBytes(StandardCharsets.UTF_8) + ); + } + final CuratorFramework framework = builder + .ensembleProvider(ensembleProvider) + .sessionTimeoutMs(config.getZkSessionTimeoutMs()) + .retryPolicy(new BoundedExponentialBackoffRetry(BASE_SLEEP_TIME_MS, MAX_SLEEP_TIME_MS, MAX_RETRIES)) + .compressionProvider(new PotentiallyGzippedCompressionProvider(config.getEnableCompression())) + .aclProvider(config.getEnableAcl() ? new SecuredACLProvider() : new DefaultACLProvider()) + .build(); lifecycle.addHandler( new Lifecycle.Handler() diff --git a/server/src/test/java/io/druid/curator/CuratorConfigTest.java b/server/src/test/java/io/druid/curator/CuratorConfigTest.java index 4e5ad354ec3..9b45eb25459 100644 --- a/server/src/test/java/io/druid/curator/CuratorConfigTest.java +++ b/server/src/test/java/io/druid/curator/CuratorConfigTest.java @@ -19,10 +19,11 @@ package io.druid.curator; -import io.druid.guice.JsonConfigTesterBase; import org.junit.Assert; import org.junit.Test; +import io.druid.guice.JsonConfigTesterBase; + public class CuratorConfigTest extends JsonConfigTesterBase { @Test @@ -30,10 +31,16 @@ public class CuratorConfigTest extends JsonConfigTesterBase { propertyValues.put(getPropertyKey("host"), "fooHost"); propertyValues.put(getPropertyKey("acl"), "true"); + propertyValues.put(getPropertyKey("user"), "test-zk-user"); + propertyValues.put(getPropertyKey("pwd"), "test-zk-pwd"); + propertyValues.put(getPropertyKey("authScheme"), "auth"); testProperties.putAll(propertyValues); configProvider.inject(testProperties, configurator); CuratorConfig config = configProvider.get().get(); Assert.assertEquals("fooHost", config.getZkHosts()); Assert.assertEquals(true, config.getEnableAcl()); + Assert.assertEquals("test-zk-user", config.getZkUser()); + Assert.assertEquals("test-zk-pwd", config.getZkPwd()); + Assert.assertEquals("auth", config.getAuthScheme()); } }