http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/util/RemoteRegistryConfigTestUtils.java ---------------------------------------------------------------------- diff --git a/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/util/RemoteRegistryConfigTestUtils.java b/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/util/RemoteRegistryConfigTestUtils.java new file mode 100644 index 0000000..2854998 --- /dev/null +++ b/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/util/RemoteRegistryConfigTestUtils.java @@ -0,0 +1,117 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.service.config.remote.util; + +import java.util.Collection; +import java.util.Map; + +public class RemoteRegistryConfigTestUtils { + + public static final String PROPERTY_TYPE = "type"; + public static final String PROPERTY_NAME = "name"; + public static final String PROPERTY_ADDRESS = "address"; + public static final String PROPERTY_NAMESAPCE = "namespace"; + public static final String PROPERTY_SECURE = "secure"; + public static final String PROPERTY_AUTH_TYPE = "authType"; + public static final String PROPERTY_PRINCIPAL = "principal"; + public static final String PROPERTY_CRED_ALIAS = "credentialAlias"; + public static final String PROPERTY_KEYTAB = "keyTab"; + public static final String PROPERTY_USE_KEYTAB = "useKeyTab"; + public static final String PROPERTY_USE_TICKET_CACHE = "useTicketCache"; + + public static String createRemoteConfigRegistriesXML(Collection<Map<String, String>> configProperties) { + String result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + + "<remote-configuration-registries>\n"; + + for (Map<String, String> props : configProperties) { + String authType = props.get(PROPERTY_AUTH_TYPE); + if ("Kerberos".equalsIgnoreCase(authType)) { + result += + createRemoteConfigRegistryXMLWithKerberosAuth(props.get(PROPERTY_TYPE), + props.get(PROPERTY_NAME), + props.get(PROPERTY_ADDRESS), + props.get(PROPERTY_PRINCIPAL), + props.get(PROPERTY_KEYTAB), + Boolean.valueOf(props.get(PROPERTY_USE_KEYTAB)), + Boolean.valueOf(props.get(PROPERTY_USE_TICKET_CACHE))); + } else if ("Digest".equalsIgnoreCase(authType)) { + result += + createRemoteConfigRegistryXMLWithDigestAuth(props.get(PROPERTY_TYPE), + props.get(PROPERTY_NAME), + props.get(PROPERTY_ADDRESS), + props.get(PROPERTY_PRINCIPAL), + props.get(PROPERTY_CRED_ALIAS)); + } else { + result += createRemoteConfigRegistryXMLNoAuth(props.get(PROPERTY_TYPE), + props.get(PROPERTY_NAME), + props.get(PROPERTY_ADDRESS)); + } + } + + result += "</remote-configuration-registries>\n"; + + return result; + } + + public static String createRemoteConfigRegistryXMLWithKerberosAuth(String type, + String name, + String address, + String principal, + String keyTab, + boolean userKeyTab, + boolean useTicketCache) { + return " <remote-configuration-registry>\n" + + " <name>" + name + "</name>\n" + + " <type>" + type + "</type>\n" + + " <address>" + address + "</address>\n" + + " <secure>true</secure>\n" + + " <auth-type>" + "Kerberos" + "</auth-type>\n" + + " <principal>" + principal + "</principal>\n" + + " <keytab>" + keyTab + "</keytab>\n" + + " <use-keytab>" + String.valueOf(userKeyTab) + "</use-keytab>\n" + + " <use-ticket-cache>" + String.valueOf(useTicketCache) + "</use-ticket-cache>\n" + + " </remote-configuration-registry>\n"; + } + + public static String createRemoteConfigRegistryXMLWithDigestAuth(String type, + String name, + String address, + String principal, + String credentialAlias) { + return " <remote-configuration-registry>\n" + + " <name>" + name + "</name>\n" + + " <type>" + type + "</type>\n" + + " <address>" + address + "</address>\n" + + " <secure>true</secure>\n" + + " <auth-type>" + "Digest" + "</auth-type>\n" + + " <principal>" + principal + "</principal>\n" + + " <credential-alias>" + credentialAlias + "</credential-alias>\n" + + " </remote-configuration-registry>\n"; + } + + + public static String createRemoteConfigRegistryXMLNoAuth(String type, + String name, + String address) { + return " <remote-configuration-registry>\n" + + " <name>" + name + "</name>\n" + + " <type>" + type + "</type>\n" + + " <address>" + address + "</address>\n" + + " </remote-configuration-registry>\n"; + } + +}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryClientServiceTest.java ---------------------------------------------------------------------- diff --git a/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryClientServiceTest.java b/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryClientServiceTest.java new file mode 100644 index 0000000..8a817a4 --- /dev/null +++ b/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryClientServiceTest.java @@ -0,0 +1,424 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.service.config.remote.zk; + +import org.apache.commons.io.FileUtils; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.curator.test.InstanceSpec; +import org.apache.curator.test.TestingCluster; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient.ChildEntryListener; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService; +import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryClientServiceFactory; +import org.apache.knox.gateway.service.config.remote.util.RemoteRegistryConfigTestUtils; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.data.ACL; +import org.apache.zookeeper.data.Id; +import org.easymock.EasyMock; +import org.junit.Test; + +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class RemoteConfigurationRegistryClientServiceTest { + + /** + * Test a configuration for an unsecured remote registry, included in the gateway configuration. + */ + @Test + public void testUnsecuredZooKeeperWithSimpleRegistryConfig() throws Exception { + final String REGISTRY_CLIENT_NAME = "unsecured-zk-registry-name"; + final String PRINCIPAL = null; + final String PWD = null; + final String CRED_ALIAS = null; + + // Configure and start a secure ZK cluster + TestingCluster zkCluster = setupAndStartSecureTestZooKeeper(PRINCIPAL, PWD); + + try { + // Create the setup client for the test cluster, and initialize the test znodes + CuratorFramework setupClient = initializeTestClientAndZNodes(zkCluster, PRINCIPAL); + + // Mock configuration + GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class); + final String registryConfigValue = + GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString(); + EasyMock.expect(config.getRemoteRegistryConfiguration(REGISTRY_CLIENT_NAME)) + .andReturn(registryConfigValue) + .anyTimes(); + EasyMock.expect(config.getRemoteRegistryConfigurationNames()) + .andReturn(Collections.singletonList(REGISTRY_CLIENT_NAME)).anyTimes(); + EasyMock.replay(config); + + doTestZooKeeperClient(setupClient, REGISTRY_CLIENT_NAME, config, CRED_ALIAS, PWD); + } finally { + zkCluster.stop(); + } + } + + /** + * Test multiple configurations for an unsecured remote registry. + */ + @Test + public void testMultipleUnsecuredZooKeeperWithSimpleRegistryConfig() throws Exception { + final String REGISTRY_CLIENT_NAME_1 = "zkclient1"; + final String REGISTRY_CLIENT_NAME_2 = "zkclient2"; + final String PRINCIPAL = null; + final String PWD = null; + final String CRED_ALIAS = null; + + // Configure and start a secure ZK cluster + TestingCluster zkCluster = setupAndStartSecureTestZooKeeper(PRINCIPAL, PWD); + + try { + // Create the setup client for the test cluster, and initialize the test znodes + CuratorFramework setupClient = initializeTestClientAndZNodes(zkCluster, PRINCIPAL); + + // Mock configuration + GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class); + final String registryConfigValue1 = + GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString(); + EasyMock.expect(config.getRemoteRegistryConfiguration(REGISTRY_CLIENT_NAME_1)) + .andReturn(registryConfigValue1).anyTimes(); + final String registryConfigValue2 = + GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString(); + EasyMock.expect(config.getRemoteRegistryConfiguration(REGISTRY_CLIENT_NAME_2)) + .andReturn(registryConfigValue2).anyTimes(); + EasyMock.expect(config.getRemoteRegistryConfigurationNames()) + .andReturn(Arrays.asList(REGISTRY_CLIENT_NAME_1, REGISTRY_CLIENT_NAME_2)).anyTimes(); + EasyMock.replay(config); + + // Create the client service instance + RemoteConfigurationRegistryClientService clientService = + RemoteConfigurationRegistryClientServiceFactory.newInstance(config); + assertEquals("Wrong registry client service type.", clientService.getClass(), CuratorClientService.class); + clientService.setAliasService(null); + clientService.init(config, null); + clientService.start(); + + RemoteConfigurationRegistryClient client1 = clientService.get(REGISTRY_CLIENT_NAME_1); + assertNotNull(client1); + + RemoteConfigurationRegistryClient client2 = clientService.get(REGISTRY_CLIENT_NAME_2); + assertNotNull(client2); + + doTestZooKeeperClient(setupClient, REGISTRY_CLIENT_NAME_1, clientService, false); + doTestZooKeeperClient(setupClient, REGISTRY_CLIENT_NAME_2, clientService, false); + } finally { + zkCluster.stop(); + } + } + + /** + * Test a configuration for a secure remote registry, included in the gateway configuration. + */ + @Test + public void testZooKeeperWithSimpleRegistryConfig() throws Exception { + final String AUTH_TYPE = "digest"; + final String REGISTRY_CLIENT_NAME = "zk-registry-name"; + final String PRINCIPAL = "knox"; + final String PWD = "knoxtest"; + final String CRED_ALIAS = "zkCredential"; + + // Configure and start a secure ZK cluster + TestingCluster zkCluster = setupAndStartSecureTestZooKeeper(PRINCIPAL, PWD); + + try { + // Create the setup client for the test cluster, and initialize the test znodes + CuratorFramework setupClient = initializeTestClientAndZNodes(zkCluster, PRINCIPAL); + + // Mock configuration + GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class); + final String registryConfigValue = + GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=" + AUTH_TYPE + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + PRINCIPAL + ";" + + GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + CRED_ALIAS; + EasyMock.expect(config.getRemoteRegistryConfiguration(REGISTRY_CLIENT_NAME)) + .andReturn(registryConfigValue) + .anyTimes(); + EasyMock.expect(config.getRemoteRegistryConfigurationNames()) + .andReturn(Collections.singletonList(REGISTRY_CLIENT_NAME)).anyTimes(); + EasyMock.replay(config); + + doTestZooKeeperClient(setupClient, REGISTRY_CLIENT_NAME, config, CRED_ALIAS, PWD); + } finally { + zkCluster.stop(); + } + } + + /** + * Test the remote registry configuration external to, and referenced from, the gateway configuration, for a secure + * client. + */ + @Test + public void testZooKeeperWithSingleExternalRegistryConfig() throws Exception { + final String AUTH_TYPE = "digest"; + final String REGISTRY_CLIENT_NAME = "my-zookeeper_registryNAME"; + final String PRINCIPAL = "knox"; + final String PWD = "knoxtest"; + final String CRED_ALIAS = "zkCredential"; + + // Configure and start a secure ZK cluster + TestingCluster zkCluster = setupAndStartSecureTestZooKeeper(PRINCIPAL, PWD); + + File tmpRegConfigFile = null; + + try { + // Create the setup client for the test cluster, and initialize the test znodes + CuratorFramework setupClient = initializeTestClientAndZNodes(zkCluster, PRINCIPAL); + + // Mock configuration + Map<String, String> registryConfigProps = new HashMap<>(); + registryConfigProps.put("type", ZooKeeperClientService.TYPE); + registryConfigProps.put("name", REGISTRY_CLIENT_NAME); + registryConfigProps.put("address", zkCluster.getConnectString()); + registryConfigProps.put("secure", "true"); + registryConfigProps.put("authType", AUTH_TYPE); + registryConfigProps.put("principal", PRINCIPAL); + registryConfigProps.put("credentialAlias", CRED_ALIAS); + String registryConfigXML = + RemoteRegistryConfigTestUtils.createRemoteConfigRegistriesXML(Collections.singleton(registryConfigProps)); + tmpRegConfigFile = File.createTempFile("myRemoteRegistryConfig", "xml"); + FileUtils.writeStringToFile(tmpRegConfigFile, registryConfigXML); + + System.setProperty("org.apache.knox.gateway.remote.registry.config.file", tmpRegConfigFile.getAbsolutePath()); + + GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.replay(config); + + doTestZooKeeperClient(setupClient, REGISTRY_CLIENT_NAME, config, CRED_ALIAS, PWD); + } finally { + zkCluster.stop(); + if (tmpRegConfigFile != null && tmpRegConfigFile.exists()) { + tmpRegConfigFile.delete(); + } + System.clearProperty("org.apache.knox.gateway.remote.registry.config.file"); + } + } + + /** + * Setup and start a secure test ZooKeeper cluster. + */ + private TestingCluster setupAndStartSecureTestZooKeeper(String principal, String digestPassword) throws Exception { + final boolean applyAuthentication = (principal != null); + + // Configure security for the ZK cluster instances + Map<String, Object> customInstanceSpecProps = new HashMap<>(); + + if (applyAuthentication) { + customInstanceSpecProps.put("authProvider.1", "org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + customInstanceSpecProps.put("requireClientAuthScheme", "sasl"); + } + + // Define the test cluster + List<InstanceSpec> instanceSpecs = new ArrayList<>(); + for (int i = 0 ; i < 3 ; i++) { + InstanceSpec is = new InstanceSpec(null, -1, -1, -1, false, (i+1), -1, -1, customInstanceSpecProps); + instanceSpecs.add(is); + } + TestingCluster zkCluster = new TestingCluster(instanceSpecs); + + if (applyAuthentication) { + // Setup ZooKeeper server SASL + Map<String, String> digestOptions = new HashMap<>(); + digestOptions.put("user_" + principal, digestPassword); + final AppConfigurationEntry[] serverEntries = + {new AppConfigurationEntry("org.apache.zookeeper.server.auth.DigestLoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, + digestOptions)}; + Configuration.setConfiguration(new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + return ("Server".equalsIgnoreCase(name)) ? serverEntries : null; + } + }); + } + + // Start the cluster + zkCluster.start(); + + return zkCluster; + } + + /** + * Create a ZooKeeper client with SASL digest auth configured, and initialize the test znodes. + */ + private CuratorFramework initializeTestClientAndZNodes(TestingCluster zkCluster, String principal) throws Exception { + // Create the client for the test cluster + CuratorFramework setupClient = CuratorFrameworkFactory.builder() + .connectString(zkCluster.getConnectString()) + .retryPolicy(new ExponentialBackoffRetry(100, 3)) + .build(); + assertNotNull(setupClient); + setupClient.start(); + + List<ACL> acls = new ArrayList<>(); + if (principal != null) { + acls.add(new ACL(ZooDefs.Perms.ALL, new Id("sasl", principal))); + } else { + acls.add(new ACL(ZooDefs.Perms.ALL, ZooDefs.Ids.ANYONE_ID_UNSAFE)); + } + setupClient.create().creatingParentsIfNeeded().withACL(acls).forPath("/knox/config/descriptors"); + setupClient.create().creatingParentsIfNeeded().withACL(acls).forPath("/knox/config/shared-providers"); + + List<ACL> negativeACLs = new ArrayList<>(); + if (principal != null) { + negativeACLs.add(new ACL(ZooDefs.Perms.ALL, new Id("sasl", "notyou"))); + } else { + negativeACLs.add(new ACL(ZooDefs.Perms.ALL, ZooDefs.Ids.ANYONE_ID_UNSAFE)); + } + setupClient.create().creatingParentsIfNeeded().withACL(negativeACLs).forPath("/someotherconfig"); + + return setupClient; + } + + private void doTestZooKeeperClient(final CuratorFramework setupClient, + final String testClientName, + final GatewayConfig config, + final String credentialAlias, + final String digestPassword) throws Exception { + boolean isSecureTest = (credentialAlias != null && digestPassword != null); + + // Mock alias service + AliasService aliasService = EasyMock.createNiceMock(AliasService.class); + EasyMock.expect(aliasService.getPasswordFromAliasForGateway(credentialAlias)) + .andReturn(isSecureTest ? digestPassword.toCharArray() : null) + .anyTimes(); + EasyMock.replay(aliasService); + + // Create the client service instance + RemoteConfigurationRegistryClientService clientService = + RemoteConfigurationRegistryClientServiceFactory.newInstance(config); + assertEquals("Wrong registry client service type.", clientService.getClass(), CuratorClientService.class); + clientService.setAliasService(aliasService); + clientService.init(config, null); + clientService.start(); + + doTestZooKeeperClient(setupClient, testClientName, clientService, isSecureTest); + } + + /** + * Test secure ZooKeeper client interactions. + * + * @param setupClient The client used for interacting with ZooKeeper independent from the registry client service. + * @param testClientName The name of the client to use from the registry client service. + * @param clientService The RemoteConfigurationRegistryClientService + * @param isSecureTest Flag to indicate whether this is a secure interaction test + */ + private void doTestZooKeeperClient(final CuratorFramework setupClient, + final String testClientName, + final RemoteConfigurationRegistryClientService clientService, + boolean isSecureTest) throws Exception { + + RemoteConfigurationRegistryClient client = clientService.get(testClientName); + assertNotNull(client); + List<String> descriptors = client.listChildEntries("/knox/config/descriptors"); + assertNotNull(descriptors); + for (String descriptor : descriptors) { + System.out.println("Descriptor: " + descriptor); + } + + List<String> providerConfigs = client.listChildEntries("/knox/config/shared-providers"); + assertNotNull(providerConfigs); + for (String providerConfig : providerConfigs) { + System.out.println("Provider config: " + providerConfig); + } + + List<String> someotherConfig = client.listChildEntries("/someotherconfig"); + if (isSecureTest) { + assertNull("Expected null because of the ACL mismatch.", someotherConfig); + } else { + assertNotNull(someotherConfig); + } + + // Test listeners + final String MY_NEW_ZNODE = "/clientServiceTestNode"; + final String MY_NEW_DATA_ZNODE = MY_NEW_ZNODE + "/mydata"; + + if (setupClient.checkExists().forPath(MY_NEW_ZNODE) != null) { + setupClient.delete().deletingChildrenIfNeeded().forPath(MY_NEW_ZNODE); + } + + final List<String> listenerLog = new ArrayList<>(); + client.addChildEntryListener(MY_NEW_ZNODE, (c, type, path) -> { + listenerLog.add("EXTERNAL: " + type.toString() + ":" + path); + if (RemoteConfigurationRegistryClient.ChildEntryListener.Type.ADDED.equals(type)) { + try { + c.addEntryListener(path, (cc, p, d) -> listenerLog.add("EXTERNAL: " + p + ":" + (d != null ? new String(d) : "null"))); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + client.createEntry(MY_NEW_ZNODE); + client.createEntry(MY_NEW_DATA_ZNODE, "more test data"); + String testData = client.getEntryData(MY_NEW_DATA_ZNODE); + assertNotNull(testData); + assertEquals("more test data", testData); + + assertTrue(client.entryExists(MY_NEW_DATA_ZNODE)); + client.setEntryData(MY_NEW_DATA_ZNODE, "still more data"); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // + } + + client.setEntryData(MY_NEW_DATA_ZNODE, "changed completely"); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // + } + + client.deleteEntry(MY_NEW_DATA_ZNODE); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // + } + + assertFalse(listenerLog.isEmpty()); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfigTest.java ---------------------------------------------------------------------- diff --git a/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfigTest.java b/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfigTest.java new file mode 100644 index 0000000..7a123f4 --- /dev/null +++ b/gateway-service-remoteconfig/src/test/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfigTest.java @@ -0,0 +1,255 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.service.config.remote.zk; + +import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig; +import org.apache.knox.gateway.service.config.remote.zk.RemoteConfigurationRegistryJAASConfig; +import org.apache.knox.gateway.services.security.AliasService; +import org.easymock.EasyMock; +import org.junit.Test; + +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class RemoteConfigurationRegistryJAASConfigTest { + + @Test + public void testZooKeeperDigestContextEntry() throws Exception { + List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>(); + final String ENTRY_NAME = "my_digest_context"; + final String DIGEST_PRINCIPAL = "myIdentity"; + final String DIGEST_PWD_ALIAS = "myAlias"; + final String DIGEST_PWD = "mysecret"; + + AliasService aliasService = EasyMock.createNiceMock(AliasService.class); + EasyMock.expect(aliasService.getPasswordFromAliasForGateway(DIGEST_PWD_ALIAS)).andReturn(DIGEST_PWD.toCharArray()).anyTimes(); + EasyMock.replay(aliasService); + + registryConfigs.add(createDigestConfig(ENTRY_NAME, DIGEST_PRINCIPAL, DIGEST_PWD_ALIAS)); + + try { + RemoteConfigurationRegistryJAASConfig jaasConfig = + RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, aliasService); + + // Make sure there are no entries for an invalid context entry name + assertNull(jaasConfig.getAppConfigurationEntry("invalid")); + + // Validate the intended context entry + validateDigestContext(jaasConfig, + ENTRY_NAME, + RemoteConfigurationRegistryJAASConfig.digestLoginModules.get("ZOOKEEPER"), + DIGEST_PRINCIPAL, + DIGEST_PWD); + } finally { + Configuration.setConfiguration(null); + } + } + + @Test + public void testKerberosContextEntry() throws Exception { + List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>(); + final String ENTRY_NAME = "my_kerberos_context"; + final String PRINCIPAL = "myIdentity"; + + File dummyKeyTab = File.createTempFile("my_context", "keytab"); + registryConfigs.add(createKerberosConfig(ENTRY_NAME, PRINCIPAL, dummyKeyTab.getAbsolutePath())); + + try { + RemoteConfigurationRegistryJAASConfig jaasConfig = + RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, null); + + // Make sure there are no entries for an invalid context entry name + assertNull(jaasConfig.getAppConfigurationEntry("invalid")); + + // Validate the intended context entry + validateKerberosContext(jaasConfig, + ENTRY_NAME, + PRINCIPAL, + dummyKeyTab.getAbsolutePath(), + true, + false); + + } finally { + Configuration.setConfiguration(null); + } + } + + @Test + public void testZooKeeperMultipleContextEntries() throws Exception { + List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>(); + final String KERBEROS_ENTRY_NAME = "my_kerberos_context"; + final String KERBEROS_PRINCIPAL = "myKerberosIdentity"; + final String DIGEST_ENTRY_NAME = "my_digest_context"; + final String DIGEST_PRINCIPAL = "myDigestIdentity"; + final String DIGEST_PWD_ALIAS = "myAlias"; + final String DIGEST_PWD = "mysecret"; + + AliasService aliasService = EasyMock.createNiceMock(AliasService.class); + EasyMock.expect(aliasService.getPasswordFromAliasForGateway(DIGEST_PWD_ALIAS)).andReturn(DIGEST_PWD.toCharArray()).anyTimes(); + EasyMock.replay(aliasService); + + File dummyKeyTab = File.createTempFile("my_context", "keytab"); + registryConfigs.add(createKerberosConfig(KERBEROS_ENTRY_NAME, KERBEROS_PRINCIPAL, dummyKeyTab.getAbsolutePath())); + registryConfigs.add(createDigestConfig(DIGEST_ENTRY_NAME, DIGEST_PRINCIPAL, DIGEST_PWD_ALIAS)); + + try { + RemoteConfigurationRegistryJAASConfig jaasConfig = + RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, aliasService); + + // Make sure there are no entries for an invalid context entry name + assertNull(jaasConfig.getAppConfigurationEntry("invalid")); + + // Validate the kerberos context entry + validateKerberosContext(jaasConfig, + KERBEROS_ENTRY_NAME, + KERBEROS_PRINCIPAL, + dummyKeyTab.getAbsolutePath(), + true, + false); + + // Validate the digest context entry + validateDigestContext(jaasConfig, + DIGEST_ENTRY_NAME, + RemoteConfigurationRegistryJAASConfig.digestLoginModules.get("ZOOKEEPER"), + DIGEST_PRINCIPAL, + DIGEST_PWD); + + } finally { + Configuration.setConfiguration(null); + } + } + + @Test + public void testZooKeeperDigestContextEntryWithoutAliasService() throws Exception { + List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>(); + final String ENTRY_NAME = "my_digest_context"; + final String DIGEST_PRINCIPAL = "myIdentity"; + final String DIGEST_PWD_ALIAS = "myAlias"; + + registryConfigs.add(createDigestConfig(ENTRY_NAME, DIGEST_PRINCIPAL, DIGEST_PWD_ALIAS)); + + try { + RemoteConfigurationRegistryJAASConfig jaasConfig = + RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, null); + fail("Expected IllegalArgumentException because the AliasService is not available."); + } catch (IllegalArgumentException e) { + // Expected + assertTrue(e.getMessage().contains("AliasService")); + } catch (Throwable e) { + fail("Wrong exception encountered: " + e.getClass().getName() + ", " + e.getMessage()); + } finally { + Configuration.setConfiguration(null); + } + } + + private static RemoteConfigurationRegistryConfig createDigestConfig(String entryName, + String principal, + String credentialAlias) { + return createDigestConfig(entryName, principal, credentialAlias, "ZooKeeper"); + } + + private static RemoteConfigurationRegistryConfig createDigestConfig(String entryName, + String principal, + String credentialAlias, + String registryType) { + RemoteConfigurationRegistryConfig rc = EasyMock.createNiceMock(RemoteConfigurationRegistryConfig.class); + EasyMock.expect(rc.getRegistryType()).andReturn(registryType).anyTimes(); + EasyMock.expect(rc.getName()).andReturn(entryName).anyTimes(); + EasyMock.expect(rc.isSecureRegistry()).andReturn(true).anyTimes(); + EasyMock.expect(rc.getAuthType()).andReturn("digest").anyTimes(); + EasyMock.expect(rc.getPrincipal()).andReturn(principal).anyTimes(); + EasyMock.expect(rc.getCredentialAlias()).andReturn(credentialAlias).anyTimes(); + EasyMock.replay(rc); + return rc; + } + + + private static RemoteConfigurationRegistryConfig createKerberosConfig(String entryName, + String principal, + String keyTabPath) { + return createKerberosConfig(entryName, principal, keyTabPath, "ZooKeeper"); + } + + private static RemoteConfigurationRegistryConfig createKerberosConfig(String entryName, + String principal, + String keyTabPath, + String registryType) { + return createKerberosConfig(entryName, principal, keyTabPath, null, null, registryType); + } + + private static RemoteConfigurationRegistryConfig createKerberosConfig(String entryName, + String principal, + String keyTabPath, + Boolean useKeyTab, + Boolean useTicketCache, + String registryType) { + RemoteConfigurationRegistryConfig rc = EasyMock.createNiceMock(RemoteConfigurationRegistryConfig.class); + EasyMock.expect(rc.getRegistryType()).andReturn(registryType).anyTimes(); + EasyMock.expect(rc.getName()).andReturn(entryName).anyTimes(); + EasyMock.expect(rc.isSecureRegistry()).andReturn(true).anyTimes(); + EasyMock.expect(rc.getAuthType()).andReturn("kerberos").anyTimes(); + EasyMock.expect(rc.getPrincipal()).andReturn(principal).anyTimes(); + EasyMock.expect(rc.getKeytab()).andReturn(keyTabPath).anyTimes(); + EasyMock.expect(rc.isUseKeyTab()).andReturn(useKeyTab != null ? useKeyTab : true).anyTimes(); + EasyMock.expect(rc.isUseTicketCache()).andReturn(useTicketCache != null ? useTicketCache : false).anyTimes(); + EasyMock.replay(rc); + return rc; + } + + private static void validateDigestContext(RemoteConfigurationRegistryJAASConfig config, + String entryName, + String loginModule, + String principal, + String password) throws Exception { + AppConfigurationEntry[] myContextEntries = config.getAppConfigurationEntry(entryName); + assertNotNull(myContextEntries); + assertEquals(1, myContextEntries.length); + AppConfigurationEntry entry = myContextEntries[0]; + assertTrue(entry.getLoginModuleName().equals(loginModule)); + Map<String, ?> entryOpts = entry.getOptions(); + assertEquals(principal, entryOpts.get("username")); + assertEquals(password, entryOpts.get("password")); + } + + private static void validateKerberosContext(RemoteConfigurationRegistryJAASConfig config, + String entryName, + String principal, + String keyTab, + boolean useKeyTab, + boolean useTicketCache) throws Exception { + AppConfigurationEntry[] myContextEntries = config.getAppConfigurationEntry(entryName); + assertNotNull(myContextEntries); + assertEquals(1, myContextEntries.length); + AppConfigurationEntry entry = myContextEntries[0]; + assertTrue(entry.getLoginModuleName().endsWith(".security.auth.module.Krb5LoginModule")); + Map<String, ?> entryOpts = entry.getOptions(); + assertEquals(principal, entryOpts.get("principal")); + assertEquals(keyTab, entryOpts.get("keyTab")); + assertEquals(useKeyTab, Boolean.valueOf((String)entryOpts.get("isUseKeyTab"))); + assertEquals(useTicketCache, Boolean.valueOf((String)entryOpts.get("isUseTicketCache"))); + } +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClient.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClient.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClient.java deleted file mode 100644 index bfb4518..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClient.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.services.config.client; - -import java.util.List; - -public interface RemoteConfigurationRegistryClient { - - String getAddress(); - - boolean isAuthenticationConfigured(); - - boolean entryExists(String path); - - List<EntryACL> getACL(String path); - - void setACL(String path, List<EntryACL> acls); - - List<String> listChildEntries(String path); - - String getEntryData(String path); - - String getEntryData(String path, String encoding); - - void createEntry(String path); - - void createEntry(String path, String data); - - void createEntry(String path, String data, String encoding); - - int setEntryData(String path, String data); - - int setEntryData(String path, String data, String encoding); - - void deleteEntry(String path); - - void addChildEntryListener(String path, ChildEntryListener listener) throws Exception; - - void addEntryListener(String path, EntryListener listener) throws Exception; - - void removeEntryListener(String path) throws Exception; - - interface ChildEntryListener { - - enum Type { - ADDED, - REMOVED, - UPDATED - } - - void childEvent(RemoteConfigurationRegistryClient client, ChildEntryListener.Type type, String path); - } - - interface EntryListener { - void entryChanged(RemoteConfigurationRegistryClient client, String path, byte[] data); - } - - interface EntryACL { - String getId(); - String getType(); - Object getPermissions(); - boolean canRead(); - boolean canWrite(); - } - -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClientService.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClientService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClientService.java deleted file mode 100644 index 1467f75..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/config/client/RemoteConfigurationRegistryClientService.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.services.config.client; - -import org.apache.hadoop.gateway.services.Service; -import org.apache.hadoop.gateway.services.security.AliasService; - -public interface RemoteConfigurationRegistryClientService extends Service { - - void setAliasService(AliasService aliasService); - - RemoteConfigurationRegistryClient get(String l); - -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/ClusterConfigurationMonitorService.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/ClusterConfigurationMonitorService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/ClusterConfigurationMonitorService.java deleted file mode 100644 index 961f2e5..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/ClusterConfigurationMonitorService.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.topology; - -import org.apache.hadoop.gateway.services.Service; -import org.apache.hadoop.gateway.topology.discovery.ClusterConfigurationMonitor; - -/** - * Gateway service for managing cluster configuration monitors. - */ -public interface ClusterConfigurationMonitorService extends Service { - - /** - * - * @param type The type of monitor (e.g., Ambari) - * - * @return The monitor associated with the specified type, or null if there is no such monitor. - */ - ClusterConfigurationMonitor getMonitor(String type); - - - /** - * Register for configuration change notifications from <em>any</em> of the monitors managed by this service. - * - * @param listener The listener to register. - */ - void addListener(ClusterConfigurationMonitor.ConfigurationChangeListener listener); - -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitor.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitor.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitor.java deleted file mode 100644 index fc3614d..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitor.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.topology.discovery; - -public interface ClusterConfigurationMonitor { - - /** - * Start the monitor. - */ - void start(); - - /** - * Stop the monitor. - */ - void stop(); - - /** - * - * @param interval The polling interval, in seconds - */ - void setPollingInterval(int interval); - - /** - * Register for notifications from the monitor. - */ - void addListener(ConfigurationChangeListener listener); - - /** - * Monitor listener interface for receiving notifications that a configuration has changed. - */ - interface ConfigurationChangeListener { - void onConfigurationChange(String source, String clusterName); - } -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java deleted file mode 100644 index a8d5f30..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.topology.discovery; - -import org.apache.hadoop.gateway.config.GatewayConfig; -import org.apache.hadoop.gateway.services.security.AliasService; - -public interface ClusterConfigurationMonitorProvider { - - String getType(); - - ClusterConfigurationMonitor newInstance(GatewayConfig config, AliasService aliasService); -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitor.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitor.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitor.java deleted file mode 100644 index 82c5809..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitor.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.topology.monitor; - -public interface RemoteConfigurationMonitor { - - void start() throws Exception; - - void stop() throws Exception; -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java deleted file mode 100644 index d19dace..0000000 --- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway.topology.monitor; - - -import org.apache.hadoop.gateway.config.GatewayConfig; -import org.apache.hadoop.gateway.services.config.client.RemoteConfigurationRegistryClientService; - -public interface RemoteConfigurationMonitorProvider { - - /** - * - * @param config The gateway configuration. - * @param clientService The RemoteConfigurationRegistryClientService for accessing the remote configuration. - * - * @return A RemoteConfigurationMonitor for keeping the local config in sync with the remote config - */ - RemoteConfigurationMonitor newInstance(GatewayConfig config, RemoteConfigurationRegistryClientService clientService); - -} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClient.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClient.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClient.java new file mode 100644 index 0000000..5afae63 --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClient.java @@ -0,0 +1,80 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.config.client; + +import java.util.List; + +public interface RemoteConfigurationRegistryClient { + + String getAddress(); + + boolean isAuthenticationConfigured(); + + boolean entryExists(String path); + + List<EntryACL> getACL(String path); + + void setACL(String path, List<EntryACL> acls); + + List<String> listChildEntries(String path); + + String getEntryData(String path); + + String getEntryData(String path, String encoding); + + void createEntry(String path); + + void createEntry(String path, String data); + + void createEntry(String path, String data, String encoding); + + int setEntryData(String path, String data); + + int setEntryData(String path, String data, String encoding); + + void deleteEntry(String path); + + void addChildEntryListener(String path, ChildEntryListener listener) throws Exception; + + void addEntryListener(String path, EntryListener listener) throws Exception; + + void removeEntryListener(String path) throws Exception; + + interface ChildEntryListener { + + enum Type { + ADDED, + REMOVED, + UPDATED + } + + void childEvent(RemoteConfigurationRegistryClient client, ChildEntryListener.Type type, String path); + } + + interface EntryListener { + void entryChanged(RemoteConfigurationRegistryClient client, String path, byte[] data); + } + + interface EntryACL { + String getId(); + String getType(); + Object getPermissions(); + boolean canRead(); + boolean canWrite(); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClientService.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClientService.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClientService.java new file mode 100644 index 0000000..77573dd --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/config/client/RemoteConfigurationRegistryClientService.java @@ -0,0 +1,28 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.config.client; + +import org.apache.knox.gateway.services.Service; +import org.apache.knox.gateway.services.security.AliasService; + +public interface RemoteConfigurationRegistryClientService extends Service { + + void setAliasService(AliasService aliasService); + + RemoteConfigurationRegistryClient get(String l); + +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/topology/ClusterConfigurationMonitorService.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/ClusterConfigurationMonitorService.java b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/ClusterConfigurationMonitorService.java new file mode 100644 index 0000000..0bfaa5f --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/ClusterConfigurationMonitorService.java @@ -0,0 +1,43 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.topology; + +import org.apache.knox.gateway.services.Service; +import org.apache.knox.gateway.topology.discovery.ClusterConfigurationMonitor; + +/** + * Gateway service for managing cluster configuration monitors. + */ +public interface ClusterConfigurationMonitorService extends Service { + + /** + * + * @param type The type of monitor (e.g., Ambari) + * + * @return The monitor associated with the specified type, or null if there is no such monitor. + */ + ClusterConfigurationMonitor getMonitor(String type); + + + /** + * Register for configuration change notifications from <em>any</em> of the monitors managed by this service. + * + * @param listener The listener to register. + */ + void addListener(ClusterConfigurationMonitor.ConfigurationChangeListener listener); + +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitor.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitor.java b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitor.java new file mode 100644 index 0000000..641bad5 --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitor.java @@ -0,0 +1,48 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.topology.discovery; + +public interface ClusterConfigurationMonitor { + + /** + * Start the monitor. + */ + void start(); + + /** + * Stop the monitor. + */ + void stop(); + + /** + * + * @param interval The polling interval, in seconds + */ + void setPollingInterval(int interval); + + /** + * Register for notifications from the monitor. + */ + void addListener(ConfigurationChangeListener listener); + + /** + * Monitor listener interface for receiving notifications that a configuration has changed. + */ + interface ConfigurationChangeListener { + void onConfigurationChange(String source, String clusterName); + } +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java new file mode 100644 index 0000000..c84e5c9 --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/discovery/ClusterConfigurationMonitorProvider.java @@ -0,0 +1,27 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.topology.discovery; + +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.services.security.AliasService; + +public interface ClusterConfigurationMonitorProvider { + + String getType(); + + ClusterConfigurationMonitor newInstance(GatewayConfig config, AliasService aliasService); +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java new file mode 100644 index 0000000..0ce1513 --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java @@ -0,0 +1,24 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.topology.monitor; + +public interface RemoteConfigurationMonitor { + + void start() throws Exception; + + void stop() throws Exception; +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java new file mode 100644 index 0000000..cab33f9 --- /dev/null +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorProvider.java @@ -0,0 +1,34 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.topology.monitor; + + +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService; + +public interface RemoteConfigurationMonitorProvider { + + /** + * + * @param config The gateway configuration. + * @param clientService The RemoteConfigurationRegistryClientService for accessing the remote configuration. + * + * @return A RemoteConfigurationMonitor for keeping the local config in sync with the remote config + */ + RemoteConfigurationMonitor newInstance(GatewayConfig config, RemoteConfigurationRegistryClientService clientService); + +} http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-test/src/test/java/org/apache/hadoop/gateway/SimpleDescriptorHandlerFuncTest.java ---------------------------------------------------------------------- diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/SimpleDescriptorHandlerFuncTest.java b/gateway-test/src/test/java/org/apache/hadoop/gateway/SimpleDescriptorHandlerFuncTest.java deleted file mode 100644 index bda8952..0000000 --- a/gateway-test/src/test/java/org/apache/hadoop/gateway/SimpleDescriptorHandlerFuncTest.java +++ /dev/null @@ -1,275 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.hadoop.gateway; - -import org.apache.commons.io.FileUtils; -import org.apache.hadoop.gateway.config.GatewayConfig; -import org.apache.hadoop.gateway.services.GatewayServices; -import org.apache.hadoop.gateway.services.security.AliasService; -import org.apache.hadoop.gateway.services.security.KeystoreService; -import org.apache.hadoop.gateway.services.security.MasterService; -import org.apache.hadoop.gateway.services.topology.TopologyService; -import org.apache.hadoop.gateway.topology.discovery.ServiceDiscovery; -import org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryConfig; -import org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryType; -import org.apache.hadoop.gateway.topology.simple.SimpleDescriptor; -import org.apache.hadoop.gateway.topology.simple.SimpleDescriptorHandler; -import org.apache.hadoop.test.TestUtils; -import org.easymock.Capture; -import org.easymock.EasyMock; -import org.junit.Test; - -import java.io.File; -import java.net.InetSocketAddress; -import java.security.KeyStore; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.capture; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -public class SimpleDescriptorHandlerFuncTest { - - - private static final String TEST_PROVIDER_CONFIG = - " <gateway>\n" + - " <provider>\n" + - " <role>authentication</role>\n" + - " <name>ShiroProvider</name>\n" + - " <enabled>true</enabled>\n" + - " <param>\n" + - " <name>sessionTimeout</name>\n" + - " <value>30</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>main.ldapRealm</name>\n" + - " <value>org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>main.ldapContextFactory</name>\n" + - " <value>org.apache.hadoop.gateway.shirorealm.KnoxLdapContextFactory</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>main.ldapRealm.contextFactory</name>\n" + - " <value>$ldapContextFactory</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>main.ldapRealm.userDnTemplate</name>\n" + - " <value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>main.ldapRealm.contextFactory.url</name>\n" + - " <value>ldap://localhost:33389</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>main.ldapRealm.contextFactory.authenticationMechanism</name>\n" + - " <value>simple</value>\n" + - " </param>\n" + - " <param>\n" + - " <name>urls./**</name>\n" + - " <value>authcBasic</value>\n" + - " </param>\n" + - " </provider>\n" + - "\n" + - " <provider>\n" + - " <role>identity-assertion</role>\n" + - " <name>Default</name>\n" + - " <enabled>true</enabled>\n" + - " </provider>\n" + - "\n" + - " <provider>\n" + - " <role>hostmap</role>\n" + - " <name>static</name>\n" + - " <enabled>true</enabled>\n" + - " <param><name>localhost</name><value>sandbox,sandbox.hortonworks.com</value></param>\n" + - " </provider>\n" + - " </gateway>\n"; - - - /** - * KNOX-1136 - * <p> - * Test that a credential store is created, and a encryptQueryString alias is defined, with a password that is not - * random (but is derived from the master secret and the topology name). - * <p> - * N.B. This test depends on the NoOpServiceDiscovery extension being configured in META-INF/services - */ - @Test - public void testSimpleDescriptorHandlerQueryStringCredentialAliasCreation() throws Exception { - - final String testMasterSecret = "mysecret"; - final String discoveryType = "NO_OP"; - final String clusterName = "dummy"; - - final Map<String, List<String>> serviceURLs = new HashMap<>(); - serviceURLs.put("RESOURCEMANAGER", Collections.singletonList("http://myhost:1234/resource")); - - File testRootDir = TestUtils.createTempDir(getClass().getSimpleName()); - File testConfDir = new File(testRootDir, "conf"); - File testProvDir = new File(testConfDir, "shared-providers"); - File testTopoDir = new File(testConfDir, "topologies"); - File testDeployDir = new File(testConfDir, "deployments"); - - // Write the externalized provider config to a temp file - File providerConfig = new File(testProvDir, "ambari-cluster-policy.xml"); - FileUtils.write(providerConfig, TEST_PROVIDER_CONFIG); - - File topologyFile = null; - try { - File destDir = new File(System.getProperty("java.io.tmpdir")).getCanonicalFile(); - - // Mock out the simple descriptor - SimpleDescriptor testDescriptor = EasyMock.createNiceMock(SimpleDescriptor.class); - EasyMock.expect(testDescriptor.getName()).andReturn("mysimpledescriptor").anyTimes(); - EasyMock.expect(testDescriptor.getDiscoveryAddress()).andReturn(null).anyTimes(); - EasyMock.expect(testDescriptor.getDiscoveryType()).andReturn(discoveryType).anyTimes(); - EasyMock.expect(testDescriptor.getDiscoveryUser()).andReturn(null).anyTimes(); - EasyMock.expect(testDescriptor.getProviderConfig()).andReturn(providerConfig.getAbsolutePath()).anyTimes(); - EasyMock.expect(testDescriptor.getClusterName()).andReturn(clusterName).anyTimes(); - List<SimpleDescriptor.Service> serviceMocks = new ArrayList<>(); - for (String serviceName : serviceURLs.keySet()) { - SimpleDescriptor.Service svc = EasyMock.createNiceMock(SimpleDescriptor.Service.class); - EasyMock.expect(svc.getName()).andReturn(serviceName).anyTimes(); - EasyMock.expect(svc.getURLs()).andReturn(serviceURLs.get(serviceName)).anyTimes(); - EasyMock.expect(svc.getParams()).andReturn(Collections.emptyMap()).anyTimes(); - EasyMock.replay(svc); - serviceMocks.add(svc); - } - EasyMock.expect(testDescriptor.getServices()).andReturn(serviceMocks).anyTimes(); - EasyMock.replay(testDescriptor); - - // Try setting up enough of the GatewayServer to support the test... - GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class); - InetSocketAddress gatewayAddress = new InetSocketAddress(0); - EasyMock.expect(config.getGatewayTopologyDir()).andReturn(testTopoDir.getAbsolutePath()).anyTimes(); - EasyMock.expect(config.getGatewayDeploymentDir()).andReturn(testDeployDir.getAbsolutePath()).anyTimes(); - EasyMock.expect(config.getGatewayAddress()).andReturn(gatewayAddress).anyTimes(); - EasyMock.expect(config.getGatewayPortMappings()).andReturn(Collections.emptyMap()).anyTimes(); - EasyMock.replay(config); - - // Setup the Gateway Services - GatewayServices gatewayServices = EasyMock.createNiceMock(GatewayServices.class); - - // Master Service - MasterService ms = EasyMock.createNiceMock(MasterService.class); - EasyMock.expect(ms.getMasterSecret()).andReturn(testMasterSecret.toCharArray()).anyTimes(); - EasyMock.replay(ms); - EasyMock.expect(gatewayServices.getService("MasterService")).andReturn(ms).anyTimes(); - - // Keystore Service - KeystoreService ks = EasyMock.createNiceMock(KeystoreService.class); - EasyMock.expect(ks.isCredentialStoreForClusterAvailable(testDescriptor.getName())).andReturn(false).once(); - ks.createCredentialStoreForCluster(testDescriptor.getName()); - EasyMock.expectLastCall().once(); - KeyStore credStore = EasyMock.createNiceMock(KeyStore.class); - EasyMock.expect(ks.getCredentialStoreForCluster(testDescriptor.getName())).andReturn(credStore).anyTimes(); - EasyMock.replay(ks); - EasyMock.expect(gatewayServices.getService(GatewayServices.KEYSTORE_SERVICE)).andReturn(ks).anyTimes(); - - // Alias Service - AliasService as = EasyMock.createNiceMock(AliasService.class); - // Captures for validating the alias creation for a generated topology - Capture<String> capturedCluster = EasyMock.newCapture(); - Capture<String> capturedAlias = EasyMock.newCapture(); - Capture<String> capturedPwd = EasyMock.newCapture(); - as.addAliasForCluster(capture(capturedCluster), capture(capturedAlias), capture(capturedPwd)); - EasyMock.expectLastCall().anyTimes(); - EasyMock.replay(as); - EasyMock.expect(gatewayServices.getService(GatewayServices.ALIAS_SERVICE)).andReturn(as).anyTimes(); - - // Topology Service - TopologyService ts = EasyMock.createNiceMock(TopologyService.class); - ts.addTopologyChangeListener(anyObject()); - EasyMock.expectLastCall().anyTimes(); - ts.reloadTopologies(); - EasyMock.expectLastCall().anyTimes(); - EasyMock.expect(ts.getTopologies()).andReturn(Collections.emptyList()).anyTimes(); - EasyMock.replay(ts); - EasyMock.expect(gatewayServices.getService(GatewayServices.TOPOLOGY_SERVICE)).andReturn(ts).anyTimes(); - - EasyMock.replay(gatewayServices); - - // Start a GatewayService with the GatewayServices mock - GatewayServer server = GatewayServer.startGateway(config, gatewayServices); - - // Invoke the simple descriptor handler, which will also create the credential store - // (because it doesn't exist) and the encryptQueryString alias - Map<String, File> files = SimpleDescriptorHandler.handle(testDescriptor, - providerConfig.getParentFile(), - destDir); - topologyFile = files.get("topology"); - - // Validate the AliasService interaction - assertEquals("Unexpected cluster name for the alias (should be the topology name).", - testDescriptor.getName(), capturedCluster.getValue()); - assertEquals("Unexpected alias name.", "encryptQueryString", capturedAlias.getValue()); - assertEquals("Unexpected alias value (should be master secret + topology name.", - testMasterSecret + testDescriptor.getName(), capturedPwd.getValue()); - - } catch (Exception e) { - e.printStackTrace(); - fail(e.getMessage()); - } finally { - FileUtils.forceDelete(testRootDir); - if (topologyFile != null) { - topologyFile.delete(); - } - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////////////////// - // Test classes for effectively "skipping" service discovery for this test. - /////////////////////////////////////////////////////////////////////////////////////////////////////// - - public static final class NoOpServiceDiscoveryType implements ServiceDiscoveryType { - @Override - public String getType() { - return NoOpServiceDiscovery.TYPE; - } - - @Override - public ServiceDiscovery newInstance() { - return new NoOpServiceDiscovery(); - } - } - - private static final class NoOpServiceDiscovery implements ServiceDiscovery { - static final String TYPE = "NO_OP"; - - @Override - public String getType() { - return TYPE; - } - - @Override - public Map<String, Cluster> discover(ServiceDiscoveryConfig config) { - return Collections.emptyMap(); - } - - @Override - public Cluster discover(ServiceDiscoveryConfig config, String clusterName) { - return null; - } - } - -}