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);
}