You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2024/04/02 12:37:48 UTC

(servicecomb-java-chassis) branch master updated: [SCB-2863]support zookeeper authentication (#4292)

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 5ff9fa07b [SCB-2863]support zookeeper authentication (#4292)
5ff9fa07b is described below

commit 5ff9fa07b75151a5c9fac1dd98cb18e399153b69
Author: liubao68 <bi...@qq.com>
AuthorDate: Tue Apr 2 20:37:43 2024 +0800

    [SCB-2863]support zookeeper authentication (#4292)
---
 .../config/zookeeper/ZookeeperClient.java          | 48 +++++++++++++++++++--
 .../config/zookeeper/ZookeeperConfig.java          | 12 ++++++
 .../registry/zookeeper/ZookeeperDiscovery.java     | 48 +++++++++++++++++++--
 .../registry/zookeeper/ZookeeperRegistration.java  | 49 ++++++++++++++++++++--
 .../zookeeper/ZookeeperRegistryProperties.java     | 20 +++++++++
 5 files changed, 168 insertions(+), 9 deletions(-)

diff --git a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java
index 56d9ff7b8..32554923e 100644
--- a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java
+++ b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java
@@ -24,6 +24,9 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -31,6 +34,7 @@ import org.apache.curator.framework.recipes.cache.CuratorCache;
 import org.apache.curator.retry.ExponentialBackoffRetry;
 import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.config.zookeeper.ZookeeperDynamicPropertiesSource.UpdateHandler;
+import org.apache.zookeeper.server.auth.DigestLoginModule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
@@ -38,6 +42,29 @@ import org.springframework.core.env.Environment;
 import org.springframework.core.io.ByteArrayResource;
 
 public class ZookeeperClient {
+  static class ZookeeperSASLConfig extends Configuration {
+    AppConfigurationEntry entry;
+
+    public ZookeeperSASLConfig(String username,
+        String password) {
+      Map<String, String> options = new HashMap<>();
+      options.put("username", username);
+      options.put("password", password);
+      this.entry = new AppConfigurationEntry(
+          DigestLoginModule.class.getName(),
+          AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+          options
+      );
+    }
+
+    @Override
+    public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+      AppConfigurationEntry[] array = new AppConfigurationEntry[1];
+      array[0] = entry;
+      return array;
+    }
+  }
+
   private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperClient.class);
 
   public static final String PATH_ENVIRONMENT = "/servicecomb/config/environment/%s";
@@ -70,6 +97,7 @@ public class ZookeeperClient {
 
   private Map<String, Object> allLast = new HashMap<>();
 
+
   public ZookeeperClient(UpdateHandler updateHandler, Environment environment) {
     this.updateHandler = updateHandler;
     this.zookeeperConfig = new ZookeeperConfig(environment);
@@ -77,9 +105,23 @@ public class ZookeeperClient {
   }
 
   public void refreshZookeeperConfig() throws Exception {
-    CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConfig.getConnectString(),
-        zookeeperConfig.getSessionTimeoutMillis(), zookeeperConfig.getConnectionTimeoutMillis(),
-        new ExponentialBackoffRetry(1000, 3));
+    CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
+        .connectString(zookeeperConfig.getConnectString())
+        .sessionTimeoutMs(zookeeperConfig.getSessionTimeoutMillis())
+        .retryPolicy(new ExponentialBackoffRetry(1000, 3));
+    String authSchema = zookeeperConfig.getAuthSchema();
+    if (StringUtils.isNotEmpty(authSchema)) {
+      if (!"digest".equals(authSchema)) {
+        throw new IllegalStateException("Not supported schema now. " + authSchema);
+      }
+      if (zookeeperConfig.getAuthInfo() == null) {
+        throw new IllegalStateException("Auth info can not be empty. ");
+      }
+
+      String[] authInfo = zookeeperConfig.getAuthInfo().split(":");
+      Configuration.setConfiguration(new ZookeeperSASLConfig(authInfo[0], authInfo[1]));
+    }
+    CuratorFramework client = builder.build();
     client.start();
 
     String env = BootStrapProperties.readServiceEnvironment(environment);
diff --git a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java
index 090ba15f3..074939c58 100644
--- a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java
+++ b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java
@@ -27,6 +27,10 @@ public class ZookeeperConfig {
 
   public static final String PROPERTY_CONNECTION_TIMEOUT = "servicecomb.config.zk.connection-timeout-mills";
 
+  public static final String PROPERTY_AUTH_SCHEMA = "servicecomb.config.zk.authentication-schema";
+
+  public static final String PROPERTY_AUTH_INFO = "servicecomb.config.zk.authentication-info";
+
   private final Environment environment;
 
   public ZookeeperConfig(Environment environment) {
@@ -44,4 +48,12 @@ public class ZookeeperConfig {
   public int getConnectionTimeoutMillis() {
     return environment.getProperty(PROPERTY_CONNECTION_TIMEOUT, int.class, 1000);
   }
+
+  public String getAuthSchema() {
+    return environment.getProperty(PROPERTY_AUTH_SCHEMA);
+  }
+
+  public String getAuthInfo() {
+    return environment.getProperty(PROPERTY_AUTH_INFO);
+  }
 }
diff --git a/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperDiscovery.java b/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperDiscovery.java
index fdd8ce078..4d871b3a1 100644
--- a/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperDiscovery.java
+++ b/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperDiscovery.java
@@ -16,12 +16,16 @@
  */
 package org.apache.servicecomb.registry.zookeeper;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -37,12 +41,36 @@ import org.apache.curator.x.discovery.details.ServiceCacheListener;
 import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.registry.api.Discovery;
+import org.apache.zookeeper.server.auth.DigestLoginModule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 
 public class ZookeeperDiscovery implements Discovery<ZookeeperDiscoveryInstance> {
+  static class ZookeeperSASLConfig extends Configuration {
+    AppConfigurationEntry entry;
+
+    public ZookeeperSASLConfig(String username,
+        String password) {
+      Map<String, String> options = new HashMap<>();
+      options.put("username", username);
+      options.put("password", password);
+      this.entry = new AppConfigurationEntry(
+          DigestLoginModule.class.getName(),
+          AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+          options
+      );
+    }
+
+    @Override
+    public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+      AppConfigurationEntry[] array = new AppConfigurationEntry[1];
+      array[0] = entry;
+      return array;
+    }
+  }
+
   private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperDiscovery.class);
 
   private final Map<String, ServiceCache<ZookeeperInstance>> serviceDiscoveries =
@@ -145,9 +173,23 @@ public class ZookeeperDiscovery implements Discovery<ZookeeperDiscoveryInstance>
 
   @Override
   public void run() {
-    client = CuratorFrameworkFactory.newClient(zookeeperRegistryProperties.getConnectString(),
-        zookeeperRegistryProperties.getSessionTimeoutMillis(), zookeeperRegistryProperties.getConnectionTimeoutMillis(),
-        new ExponentialBackoffRetry(1000, 3));
+    CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
+        .connectString(zookeeperRegistryProperties.getConnectString())
+        .sessionTimeoutMs(zookeeperRegistryProperties.getSessionTimeoutMillis())
+        .retryPolicy(new ExponentialBackoffRetry(1000, 3));
+    String authSchema = zookeeperRegistryProperties.getAuthenticationSchema();
+    if (StringUtils.isNotEmpty(authSchema)) {
+      if (!"digest".equals(authSchema)) {
+        throw new IllegalStateException("Not supported schema now. " + authSchema);
+      }
+      if (zookeeperRegistryProperties.getAuthenticationInfo() == null) {
+        throw new IllegalStateException("Auth info can not be empty. ");
+      }
+
+      String[] authInfo = zookeeperRegistryProperties.getAuthenticationInfo().split(":");
+      Configuration.setConfiguration(new ZookeeperSASLConfig(authInfo[0], authInfo[1]));
+    }
+    client = builder.build();
     client.start();
   }
 
diff --git a/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistration.java b/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistration.java
index e7c8c1aa6..1e819926a 100644
--- a/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistration.java
+++ b/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistration.java
@@ -16,8 +16,13 @@
  */
 package org.apache.servicecomb.registry.zookeeper;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.UUID;
 
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -32,10 +37,34 @@ import org.apache.servicecomb.config.DataCenterProperties;
 import org.apache.servicecomb.registry.api.DataCenterInfo;
 import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus;
 import org.apache.servicecomb.registry.api.Registration;
+import org.apache.zookeeper.server.auth.DigestLoginModule;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 
 public class ZookeeperRegistration implements Registration<ZookeeperRegistrationInstance> {
+  static class ZookeeperSASLConfig extends Configuration {
+    AppConfigurationEntry entry;
+
+    public ZookeeperSASLConfig(String username,
+        String password) {
+      Map<String, String> options = new HashMap<>();
+      options.put("username", username);
+      options.put("password", password);
+      this.entry = new AppConfigurationEntry(
+          DigestLoginModule.class.getName(),
+          AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+          options
+      );
+    }
+
+    @Override
+    public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+      AppConfigurationEntry[] array = new AppConfigurationEntry[1];
+      array[0] = entry;
+      return array;
+    }
+  }
+
   private Environment environment;
 
   private ZookeeperRegistryProperties zookeeperRegistryProperties;
@@ -99,9 +128,23 @@ public class ZookeeperRegistration implements Registration<ZookeeperRegistration
 
   @Override
   public void run() {
-    client = CuratorFrameworkFactory.newClient(zookeeperRegistryProperties.getConnectString(),
-        zookeeperRegistryProperties.getSessionTimeoutMillis(), zookeeperRegistryProperties.getConnectionTimeoutMillis(),
-        new ExponentialBackoffRetry(1000, 3));
+    CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
+        .connectString(zookeeperRegistryProperties.getConnectString())
+        .sessionTimeoutMs(zookeeperRegistryProperties.getSessionTimeoutMillis())
+        .retryPolicy(new ExponentialBackoffRetry(1000, 3));
+    String authSchema = zookeeperRegistryProperties.getAuthenticationSchema();
+    if (StringUtils.isNotEmpty(authSchema)) {
+      if (!"digest".equals(authSchema)) {
+        throw new IllegalStateException("Not supported schema now. " + authSchema);
+      }
+      if (zookeeperRegistryProperties.getAuthenticationInfo() == null) {
+        throw new IllegalStateException("Auth info can not be empty. ");
+      }
+
+      String[] authInfo = zookeeperRegistryProperties.getAuthenticationInfo().split(":");
+      Configuration.setConfiguration(new ZookeeperDiscovery.ZookeeperSASLConfig(authInfo[0], authInfo[1]));
+    }
+    client = builder.build();
     client.start();
     JsonInstanceSerializer<ZookeeperInstance> serializer =
         new JsonInstanceSerializer<>(ZookeeperInstance.class);
diff --git a/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistryProperties.java b/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistryProperties.java
index f1fa0a773..cea946d99 100644
--- a/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistryProperties.java
+++ b/service-registry/registry-zookeeper/src/main/java/org/apache/servicecomb/registry/zookeeper/ZookeeperRegistryProperties.java
@@ -23,6 +23,10 @@ public class ZookeeperRegistryProperties {
 
   private String connectString = "zookeeper://127.0.0.1:2181";
 
+  private String authenticationSchema;
+
+  private String authenticationInfo;
+
   private int connectionTimeoutMillis = 1000;
 
   private int sessionTimeoutMillis = 60000;
@@ -76,4 +80,20 @@ public class ZookeeperRegistryProperties {
   public void setEnableSwaggerRegistration(boolean enableSwaggerRegistration) {
     this.enableSwaggerRegistration = enableSwaggerRegistration;
   }
+
+  public String getAuthenticationSchema() {
+    return authenticationSchema;
+  }
+
+  public void setAuthenticationSchema(String authenticationSchema) {
+    this.authenticationSchema = authenticationSchema;
+  }
+
+  public String getAuthenticationInfo() {
+    return authenticationInfo;
+  }
+
+  public void setAuthenticationInfo(String authenticationInfo) {
+    this.authenticationInfo = authenticationInfo;
+  }
 }