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

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new e28442e  KNOX-2399 - Implemented ZookeeperTokenStateService (#361)
e28442e is described below

commit e28442e277a871a89077f16caaf4dbc486dd30a0
Author: Sandor Molnar <[email protected]>
AuthorDate: Wed Jul 15 15:55:24 2020 +0200

    KNOX-2399 - Implemented ZookeeperTokenStateService (#361)
---
 .../services/factory/AbstractServiceFactory.java   |   4 +-
 .../services/factory/AliasServiceFactory.java      |   2 +-
 .../services/factory/TokenStateServiceFactory.java |   6 +-
 .../security/impl/ZookeeperRemoteAliasService.java |  18 ++-
 .../impl/ZookeeperRemoteAliasServiceProvider.java  |  26 ++--
 .../token/impl/ZookeeperTokenStateService.java     |  57 ++++++++
 .../services/factory/ServiceFactoryTest.java       |   9 +-
 .../factory/TokenStateServiceFactoryTest.java      |  22 +++-
 .../impl/RemoteAliasServiceTestProvider.java       |   6 +
 .../token/impl/ZookeeperTokenStateServiceTest.java | 145 +++++++++++++++++++++
 .../HashicorpVaultRemoteAliasServiceProvider.java  |   6 +
 .../security/RemoteAliasServiceProvider.java       |   3 +
 12 files changed, 275 insertions(+), 29 deletions(-)

diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AbstractServiceFactory.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AbstractServiceFactory.java
index ab02ec0..f855c76 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AbstractServiceFactory.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AbstractServiceFactory.java
@@ -53,10 +53,10 @@ public abstract class AbstractServiceFactory implements 
ServiceFactory {
       if (service == null && StringUtils.isNotBlank(implementation)) {
         // no known service implementation created, try to create the custom 
one
         try {
-          service = 
Service.class.cast(Class.forName(implementation).newInstance());
+          service = (Service) Class.forName(implementation).newInstance();
           logServiceUsage(implementation, serviceType);
         } catch (InstantiationException | IllegalAccessException | 
ClassNotFoundException e) {
-          throw new ServiceLifecycleException("Errror while instantiating " + 
serviceType.getShortName() + " service implementation " + implementation, e);
+          throw new ServiceLifecycleException("Error while instantiating " + 
serviceType.getShortName() + " service implementation " + implementation, e);
         }
       }
     }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AliasServiceFactory.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AliasServiceFactory.java
index d3e3227..e821234 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AliasServiceFactory.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/AliasServiceFactory.java
@@ -54,7 +54,7 @@ public class AliasServiceFactory extends 
AbstractServiceFactory {
       } else if (matchesImplementation(implementation, 
RemoteAliasService.class)) {
         service = new RemoteAliasService(defaultAliasService, 
getMasterService(gatewayServices));
       } else if (matchesImplementation(implementation, 
ZookeeperRemoteAliasService.class)) {
-        service = new 
ZookeeperRemoteAliasServiceProvider().newInstance(defaultAliasService, 
getMasterService(gatewayServices));
+        service = new 
ZookeeperRemoteAliasServiceProvider().newInstance(gatewayServices, 
defaultAliasService, getMasterService(gatewayServices));
       }
 
       logServiceUsage(implementation, serviceType);
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactory.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactory.java
index 800fcb2..affdd64 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactory.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactory.java
@@ -31,6 +31,7 @@ import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.token.impl.AliasBasedTokenStateService;
 import org.apache.knox.gateway.services.token.impl.DefaultTokenStateService;
 import 
org.apache.knox.gateway.services.token.impl.JournalBasedTokenStateService;
+import org.apache.knox.gateway.services.token.impl.ZookeeperTokenStateService;
 
 public class TokenStateServiceFactory extends AbstractServiceFactory {
 
@@ -46,6 +47,8 @@ public class TokenStateServiceFactory extends 
AbstractServiceFactory {
         ((AliasBasedTokenStateService) 
service).setAliasService(getAliasService(gatewayServices));
       } else if (matchesImplementation(implementation, 
JournalBasedTokenStateService.class)) {
         service = new JournalBasedTokenStateService();
+      } else if (matchesImplementation(implementation, 
ZookeeperTokenStateService.class)) {
+        service = new ZookeeperTokenStateService(gatewayServices);
       }
 
       logServiceUsage(implementation, serviceType);
@@ -61,6 +64,7 @@ public class TokenStateServiceFactory extends 
AbstractServiceFactory {
 
   @Override
   protected Collection<String> getKnownImplementations() {
-    return unmodifiableList(asList(DefaultTokenStateService.class.getName(), 
AliasBasedTokenStateService.class.getName(), 
JournalBasedTokenStateService.class.getName()));
+    return unmodifiableList(asList(DefaultTokenStateService.class.getName(), 
AliasBasedTokenStateService.class.getName(), 
JournalBasedTokenStateService.class.getName(),
+        ZookeeperTokenStateService.class.getName()));
   }
 }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasService.java
index 10bd1bf..afbbdf9 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasService.java
@@ -190,13 +190,18 @@ public class ZookeeperRemoteAliasService implements 
AliasService {
      *
      * @param clusterName
      *            cluster name
-     * @return List of all the aliases
+     * @return List of all the aliases (an empty list, in case there is no 
alias for the given cluster)
      */
     @Override
     public List<String> getAliasesForCluster(final String clusterName) throws 
AliasServiceException {
         final List<String> localAliases = 
localAliasService.getAliasesForCluster(clusterName);
         if (localAliases == null || localAliases.isEmpty()) {
-          return remoteClient == null ? new ArrayList<>() : 
remoteClient.listChildEntries(buildClusterEntryName(clusterName));
+          if (remoteClient != null) {
+            final List<String> remoteAliases = 
remoteClient.listChildEntries(buildClusterEntryName(clusterName));
+            return remoteAliases == null ? new ArrayList<>() : remoteAliases;
+          } else {
+            return new ArrayList<>();
+          }
         } else {
           return localAliases;
         }
@@ -435,7 +440,6 @@ public class ZookeeperRemoteAliasService implements 
AliasService {
 
         @Override
         public void childEvent(final RemoteConfigurationRegistryClient client, 
final Type type, final String path) {
-
             final String subPath = StringUtils.substringAfter(path, 
PATH_KNOX_ALIAS_STORE_TOPOLOGY + PATH_SEPARATOR);
             final String[] paths = StringUtils.split(subPath, '/');
 
@@ -494,11 +498,11 @@ public class ZookeeperRemoteAliasService implements 
AliasService {
         @Override
         public void entryChanged(final RemoteConfigurationRegistryClient 
client, final String path, final byte[] data) {
             try {
-                localAliasService.addAliasForCluster(cluster, alias, 
decrypt(new String(data, StandardCharsets.UTF_8)));
+              localAliasService.addAliasForCluster(cluster, alias, decrypt(new 
String(data, StandardCharsets.UTF_8)));
             } catch (final Exception e) {
-                /* log and move on */
-                LOG.errorAddingAliasLocally(cluster, alias, e.toString());
-            }
+              /* log and move on */
+              LOG.errorAddingAliasLocally(cluster, alias, e.toString());
+          }
         }
     }
 }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasServiceProvider.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasServiceProvider.java
index 5232aaf..8e6e53e 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasServiceProvider.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/ZookeeperRemoteAliasServiceProvider.java
@@ -17,6 +17,8 @@
  */
 package org.apache.knox.gateway.services.security.impl;
 
+import java.util.Locale;
+
 import org.apache.knox.gateway.GatewayServer;
 import org.apache.knox.gateway.config.ConfigurationException;
 import org.apache.knox.gateway.security.RemoteAliasServiceProvider;
@@ -28,8 +30,6 @@ import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.MasterService;
 import org.apache.knox.gateway.util.KnoxCLI;
 
-import java.util.Locale;
-
 public class ZookeeperRemoteAliasServiceProvider implements 
RemoteAliasServiceProvider {
   @Override
   public String getType() {
@@ -38,16 +38,24 @@ public class ZookeeperRemoteAliasServiceProvider implements 
RemoteAliasServicePr
 
   @Override
   public AliasService newInstance(AliasService localAliasService, 
MasterService ms) {
+    return newInstance(null, localAliasService, ms);
+  }
 
-    final GatewayServices services = GatewayServer.getGatewayServices() != 
null ? GatewayServer.getGatewayServices() : KnoxCLI.getGatewayServices();
+  @Override
+  public AliasService newInstance(GatewayServices gatewayServices, 
AliasService localAliasService, MasterService masterService) {
+    final RemoteConfigurationRegistryClientService registryClientService = 
getRemoteConfigRegistryClientService(gatewayServices);
+    if (registryClientService != null) {
+      return new ZookeeperRemoteAliasService(localAliasService, masterService, 
registryClientService);
+    }
 
-    if(services != null) {
-      final RemoteConfigurationRegistryClientService registryClientService = 
services
-          .getService(ServiceType.REMOTE_REGISTRY_CLIENT_SERVICE);
+    throw new ConfigurationException(String.format(Locale.ROOT, "%s service 
not configured", ZooKeeperClientService.TYPE));
+  }
 
-      return new ZookeeperRemoteAliasService(localAliasService, ms, 
registryClientService);
+  private RemoteConfigurationRegistryClientService 
getRemoteConfigRegistryClientService(GatewayServices gatewayServices) {
+    GatewayServices services = gatewayServices;
+    if (gatewayServices == null) {
+      services = GatewayServer.getGatewayServices() != null ? 
GatewayServer.getGatewayServices() : KnoxCLI.getGatewayServices();
     }
-
-    throw new ConfigurationException(String.format(Locale.ROOT,"%s service not 
configured", ZooKeeperClientService.TYPE));
+    return services == null ? null : 
services.getService(ServiceType.REMOTE_REGISTRY_CLIENT_SERVICE);
   }
 }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/ZookeeperTokenStateService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/ZookeeperTokenStateService.java
new file mode 100644
index 0000000..31d343a
--- /dev/null
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/ZookeeperTokenStateService.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.services.token.impl;
+
+import static org.apache.knox.gateway.services.ServiceType.ALIAS_SERVICE;
+
+import java.util.Map;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.factory.AliasServiceFactory;
+import 
org.apache.knox.gateway.services.security.impl.ZookeeperRemoteAliasService;
+
+/**
+ * A Zookeeper Token State Service is actually an Alias based TSS where the 
'alias service' happens to be the 'zookeeper' implementation.
+ * This means the only important thing that should be overridden here is the 
init method where the underlying alias service is configured
+ * properly.
+ */
+public class ZookeeperTokenStateService extends AliasBasedTokenStateService {
+
+  private final GatewayServices gatewayServices;
+  private final AliasServiceFactory aliasServiceFactory;
+
+  public ZookeeperTokenStateService(GatewayServices gatewayServices) {
+    this(gatewayServices, new AliasServiceFactory());
+  }
+
+  public ZookeeperTokenStateService(GatewayServices gatewayServices, 
AliasServiceFactory aliasServiceFactory) {
+    this.gatewayServices = gatewayServices;
+    this.aliasServiceFactory = aliasServiceFactory;
+  }
+
+  @Override
+  public void init(GatewayConfig config, Map<String, String> options) throws 
ServiceLifecycleException {
+    final ZookeeperRemoteAliasService zookeeperAliasService = 
(ZookeeperRemoteAliasService) aliasServiceFactory.create(gatewayServices, 
ALIAS_SERVICE, config, options,
+        ZookeeperRemoteAliasService.class.getName());
+    zookeeperAliasService.init(config, options);
+    super.setAliasService(zookeeperAliasService);
+    super.init(config, options);
+  }
+}
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/ServiceFactoryTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/ServiceFactoryTest.java
index c7dbced..8a89a2e 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/ServiceFactoryTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/ServiceFactoryTest.java
@@ -26,7 +26,7 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.lang.reflect.Field;
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
@@ -37,6 +37,7 @@ import org.apache.knox.gateway.services.Service;
 import org.apache.knox.gateway.services.ServiceLifecycleException;
 import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.TestService;
+import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.KeystoreService;
 import org.apache.knox.gateway.services.security.MasterService;
@@ -52,7 +53,7 @@ class ServiceFactoryTest {
 
   protected final GatewayServices gatewayServices = 
EasyMock.createNiceMock(GatewayServices.class);
   protected final GatewayConfig gatewayConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
-  protected final Map<String, String> options = Collections.emptyMap();
+  protected final Map<String, String> options = new HashMap<>();
 
   protected void initConfig() {
     final MasterService masterService = 
EasyMock.createNiceMock(MasterService.class);
@@ -61,6 +62,8 @@ class ServiceFactoryTest {
     
expect(gatewayServices.getService(ServiceType.KEYSTORE_SERVICE)).andReturn(keystoreservice).anyTimes();
     final AliasService aliasService = 
EasyMock.createNiceMock(AliasService.class);
     
expect(gatewayServices.getService(ServiceType.ALIAS_SERVICE)).andReturn(aliasService).anyTimes();
+    final RemoteConfigurationRegistryClientService registryClientService = 
EasyMock.createNiceMock(RemoteConfigurationRegistryClientService.class);
+    
expect(gatewayServices.getService(ServiceType.REMOTE_REGISTRY_CLIENT_SERVICE)).andReturn(registryClientService).anyTimes();
     replay(gatewayServices);
     expect(gatewayConfig.getServiceParameter(anyString(), 
anyString())).andReturn("").anyTimes();
     replay(gatewayConfig);
@@ -85,7 +88,7 @@ class ServiceFactoryTest {
       throws Exception {
     expectedException.expect(ServiceLifecycleException.class);
     final String implementation = "this.is.my.non.existing.Service";
-    expectedException.expectMessage(String.format(Locale.ROOT, "Errror while 
instantiating %s service implementation %s", serviceType.getShortName(), 
implementation));
+    expectedException.expectMessage(String.format(Locale.ROOT, "Error while 
instantiating %s service implementation %s", serviceType.getShortName(), 
implementation));
     expectedException.expectCause(isA(ClassNotFoundException.class));
     serviceFactory.create(gatewayServices, serviceType, null, null, 
implementation);
   }
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactoryTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactoryTest.java
index 7625d50..272593e 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactoryTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/factory/TokenStateServiceFactoryTest.java
@@ -24,6 +24,7 @@ import 
org.apache.knox.gateway.services.security.token.TokenStateService;
 import org.apache.knox.gateway.services.token.impl.AliasBasedTokenStateService;
 import org.apache.knox.gateway.services.token.impl.DefaultTokenStateService;
 import 
org.apache.knox.gateway.services.token.impl.JournalBasedTokenStateService;
+import org.apache.knox.gateway.services.token.impl.ZookeeperTokenStateService;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -42,23 +43,32 @@ public class TokenStateServiceFactoryTest extends 
ServiceFactoryTest {
   }
 
   @Test
-  public void shouldReturnDefaultAliasService() throws Exception {
-    TokenStateService tokenStateService = (TokenStateService) 
serviceFactory.create(gatewayServices, ServiceType.TOKEN_STATE_SERVICE, null, 
null, DefaultTokenStateService.class.getName());
+  public void shouldReturnDefaultTopkenStateService() throws Exception {
+    TokenStateService tokenStateService = (TokenStateService) 
serviceFactory.create(gatewayServices, ServiceType.TOKEN_STATE_SERVICE, 
gatewayConfig, options,
+        DefaultTokenStateService.class.getName());
     assertTrue(tokenStateService instanceof DefaultTokenStateService);
 
-    tokenStateService = (TokenStateService) 
serviceFactory.create(gatewayServices, ServiceType.TOKEN_STATE_SERVICE, null, 
null, "");
+    tokenStateService = (TokenStateService) 
serviceFactory.create(gatewayServices, ServiceType.TOKEN_STATE_SERVICE, 
gatewayConfig, options, "");
     assertTrue(tokenStateService instanceof DefaultTokenStateService);
   }
 
   @Test
   public void shouldReturnAliasBasedTokenStateService() throws Exception {
-    final TokenStateService tokenStateService = (TokenStateService) 
serviceFactory.create(gatewayServices, ServiceType.TOKEN_STATE_SERVICE, null, 
null, AliasBasedTokenStateService.class.getName());
+    final TokenStateService tokenStateService = (TokenStateService) 
serviceFactory.create(gatewayServices, ServiceType.TOKEN_STATE_SERVICE, 
gatewayConfig, options,
+        AliasBasedTokenStateService.class.getName());
     assertTrue(tokenStateService instanceof AliasBasedTokenStateService);
     assertTrue(isAliasServiceSet(tokenStateService));
   }
 
   @Test
-  public void shouldReturnHJournalTokenStateService() throws Exception {
-    assertTrue(serviceFactory.create(gatewayServices, 
ServiceType.TOKEN_STATE_SERVICE, null, null, 
JournalBasedTokenStateService.class.getName()) instanceof 
JournalBasedTokenStateService);
+  public void shouldReturnJournalTokenStateService() throws Exception {
+    assertTrue(serviceFactory.create(gatewayServices, 
ServiceType.TOKEN_STATE_SERVICE, gatewayConfig, options,
+        JournalBasedTokenStateService.class.getName()) instanceof 
JournalBasedTokenStateService);
+  }
+
+  @Test
+  public void shouldReturnZookeeperTokenStateService() throws Exception {
+    assertTrue(serviceFactory.create(gatewayServices, 
ServiceType.TOKEN_STATE_SERVICE, gatewayConfig, options,
+        ZookeeperTokenStateService.class.getName()) instanceof 
ZookeeperTokenStateService);
   }
 }
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/security/impl/RemoteAliasServiceTestProvider.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/security/impl/RemoteAliasServiceTestProvider.java
index 2a0dc05..23560df 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/security/impl/RemoteAliasServiceTestProvider.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/security/impl/RemoteAliasServiceTestProvider.java
@@ -19,6 +19,7 @@ package org.apache.knox.gateway.services.security.impl;
 
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.security.RemoteAliasServiceProvider;
+import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.AliasServiceException;
 import org.apache.knox.gateway.services.security.MasterService;
@@ -43,6 +44,11 @@ public class RemoteAliasServiceTestProvider implements 
RemoteAliasServiceProvide
     return new TestAliasService();
   }
 
+  @Override
+  public AliasService newInstance(GatewayServices gatewayService, AliasService 
localAliasService, MasterService masterService) {
+    return new TestAliasService();
+  }
+
   private class TestAliasService implements AliasService {
     private final Map<String, Map<String, String>> aliases = new HashMap<>();
     private GatewayConfig config;
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/ZookeeperTokenStateServiceTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/ZookeeperTokenStateServiceTest.java
new file mode 100644
index 0000000..f12689c
--- /dev/null
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/ZookeeperTokenStateServiceTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.services.token.impl;
+
+import static 
org.apache.knox.gateway.config.GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.curator.test.InstanceSpec;
+import org.apache.curator.test.TestingCluster;
+import org.apache.curator.test.TestingZooKeeperServer;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.service.config.remote.zk.ZooKeeperClientService;
+import 
org.apache.knox.gateway.service.config.remote.zk.ZooKeeperClientServiceProvider;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceType;
+import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.KeystoreService;
+import org.apache.knox.gateway.services.security.MasterService;
+import org.easymock.EasyMock;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class ZookeeperTokenStateServiceTest {
+
+  @ClassRule
+  public static final TemporaryFolder testFolder = new TemporaryFolder();
+
+  private static final String CONFIG_MONITOR_NAME = 
"remoteConfigMonitorClient";
+  private static final long TOKEN_STATE_ALIAS_PERSISTENCE_INTERVAL = 2L;
+  private static TestingCluster zkNodes;
+
+  @BeforeClass
+  public static void configureAndStartZKCluster() throws Exception {
+    // Configure security for the ZK cluster instances
+    final Map<String, Object> customInstanceSpecProps = new HashMap<>();
+    customInstanceSpecProps.put("authProvider.1", 
"org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
+    customInstanceSpecProps.put("requireClientAuthScheme", "sasl");
+    customInstanceSpecProps.put("admin.enableServer", false);
+
+    // Define the test cluster (with 2 nodes)
+    List<InstanceSpec> instanceSpecs = new ArrayList<>();
+    for (int i = 0; i < 2; i++) {
+      InstanceSpec is = new InstanceSpec(null, -1, -1, -1, false, (i + 1), -1, 
-1, customInstanceSpecProps);
+      instanceSpecs.add(is);
+    }
+    zkNodes = new TestingCluster(instanceSpecs);
+
+    // Start the cluster
+    zkNodes.start();
+  }
+
+  @AfterClass
+  public static void tearDownSuite() throws Exception {
+    // Shutdown the ZK cluster
+    zkNodes.close();
+  }
+
+  @Test
+  public void testStoringTokenAliasesInZookeeper() throws Exception {
+    // mocking GatewayConfig
+    final GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
+    
expect(gc.getRemoteRegistryConfigurationNames()).andReturn(Collections.singletonList(CONFIG_MONITOR_NAME)).anyTimes();
+    final String registryConfig = REMOTE_CONFIG_REGISTRY_TYPE + "=" + 
ZooKeeperClientService.TYPE + ";" + REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + 
zkNodes.getConnectString();
+    
expect(gc.getRemoteRegistryConfiguration(CONFIG_MONITOR_NAME)).andReturn(registryConfig).anyTimes();
+    
expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(CONFIG_MONITOR_NAME).anyTimes();
+    expect(gc.getAlgorithm()).andReturn("AES").anyTimes();
+    expect(gc.isRemoteAliasServiceEnabled()).andReturn(true).anyTimes();
+    
expect(gc.getKnoxTokenStateAliasPersistenceInterval()).andReturn(TOKEN_STATE_ALIAS_PERSISTENCE_INTERVAL).anyTimes();
+    final Path baseFolder = 
Paths.get(testFolder.newFolder().getAbsolutePath());
+    expect(gc.getGatewayDataDir()).andReturn(Paths.get(baseFolder.toString(), 
"data").toString()).anyTimes();
+    
expect(gc.getGatewayKeystoreDir()).andReturn(Paths.get(baseFolder.toString(), 
"data", "keystores").toString()).anyTimes();
+    replay(gc);
+
+    // mocking GatewayServices
+    final GatewayServices gatewayServices = 
EasyMock.createNiceMock(GatewayServices.class);
+    final char[] masterSecret = 
"ThisIsMySup3rS3cr3tM4sterPassW0rd!".toCharArray();
+    final MasterService masterService = 
EasyMock.createNiceMock(MasterService.class);
+    expect(masterService.getMasterSecret()).andReturn(masterSecret).anyTimes();
+    
expect(gatewayServices.getService(ServiceType.MASTER_SERVICE)).andReturn(masterService).anyTimes();
+    final KeystoreService keystoreservice = 
EasyMock.createNiceMock(KeystoreService.class);
+    
expect(gatewayServices.getService(ServiceType.KEYSTORE_SERVICE)).andReturn(keystoreservice).anyTimes();
+    final AliasService aliasService = 
EasyMock.createNiceMock(AliasService.class);
+    
expect(gatewayServices.getService(ServiceType.ALIAS_SERVICE)).andReturn(aliasService).anyTimes();
+    final RemoteConfigurationRegistryClientService clientService = (new 
ZooKeeperClientServiceProvider()).newInstance();
+    clientService.setAliasService(aliasService);
+    clientService.init(gc, Collections.emptyMap());
+    
expect(gatewayServices.getService(ServiceType.REMOTE_REGISTRY_CLIENT_SERVICE)).andReturn(clientService).anyTimes();
+    replay(gatewayServices, masterService);
+
+    final ZookeeperTokenStateService zktokenStateService = new 
ZookeeperTokenStateService(gatewayServices);
+    zktokenStateService.init(gc, new HashMap<>());
+    zktokenStateService.start();
+
+    assertFalse(zkNodeExists("/knox/security/topology/__gateway/token1"));
+    assertFalse(zkNodeExists("/knox/security/topology/__gateway/token1--max"));
+
+    zktokenStateService.addToken("token1", 1L, 2L);
+
+    // give some time for the token state service to persist the token aliases 
in ZK (doubled the persistence interval)
+    Thread.sleep(2 * TOKEN_STATE_ALIAS_PERSISTENCE_INTERVAL * 1000);
+
+    assertTrue(zkNodeExists("/knox/security/topology/__gateway/token1"));
+    assertTrue(zkNodeExists("/knox/security/topology/__gateway/token1--max"));
+  }
+
+  private boolean zkNodeExists(String nodeName) {
+    for (TestingZooKeeperServer server : zkNodes.getServers()) {
+      if 
(server.getQuorumPeer().getActiveServer().getZKDatabase().getNode(nodeName) != 
null) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git 
a/gateway-service-hashicorp-vault/src/main/java/org/apache/knox/gateway/backend/hashicorp/vault/HashicorpVaultRemoteAliasServiceProvider.java
 
b/gateway-service-hashicorp-vault/src/main/java/org/apache/knox/gateway/backend/hashicorp/vault/HashicorpVaultRemoteAliasServiceProvider.java
index 894e510..3e5c32e 100644
--- 
a/gateway-service-hashicorp-vault/src/main/java/org/apache/knox/gateway/backend/hashicorp/vault/HashicorpVaultRemoteAliasServiceProvider.java
+++ 
b/gateway-service-hashicorp-vault/src/main/java/org/apache/knox/gateway/backend/hashicorp/vault/HashicorpVaultRemoteAliasServiceProvider.java
@@ -18,6 +18,7 @@
 package org.apache.knox.gateway.backend.hashicorp.vault;
 
 import org.apache.knox.gateway.security.RemoteAliasServiceProvider;
+import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.MasterService;
 
@@ -29,6 +30,11 @@ public class HashicorpVaultRemoteAliasServiceProvider 
implements RemoteAliasServ
 
   @Override
   public AliasService newInstance(AliasService localAliasService, 
MasterService ms) {
+    return newInstance(null, localAliasService, ms);
+  }
+
+  @Override
+  public AliasService newInstance(GatewayServices gatewayServices, 
AliasService localAliasService, MasterService masterService) {
     return new HashicorpVaultAliasService(localAliasService);
   }
 }
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/security/RemoteAliasServiceProvider.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/security/RemoteAliasServiceProvider.java
index 6980a56..bd80679 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/security/RemoteAliasServiceProvider.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/security/RemoteAliasServiceProvider.java
@@ -16,6 +16,7 @@
  */
 package org.apache.knox.gateway.security;
 
+import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.MasterService;
 
@@ -23,4 +24,6 @@ public interface RemoteAliasServiceProvider {
   String getType();
 
   AliasService newInstance(AliasService localAliasService, MasterService 
masterService);
+
+  AliasService newInstance(GatewayServices gatewayServices, AliasService 
localAliasService, MasterService masterService);
 }

Reply via email to