You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2018/01/11 17:39:08 UTC
[41/53] [abbrv] knox git commit: KNOX-998 - Merge from trunk 0.14.0
code
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-test/src/test/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorTest.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorTest.java b/gateway-test/src/test/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorTest.java
deleted file mode 100644
index dd75028..0000000
--- a/gateway-test/src/test/java/org/apache/hadoop/gateway/topology/monitor/RemoteConfigurationMonitorTest.java
+++ /dev/null
@@ -1,603 +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.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.hadoop.gateway.config.GatewayConfig;
-import org.apache.hadoop.gateway.service.config.remote.zk.ZooKeeperClientService;
-import org.apache.hadoop.gateway.service.config.remote.zk.ZooKeeperClientServiceProvider;
-import org.apache.hadoop.gateway.services.config.client.RemoteConfigurationRegistryClientService;
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.hadoop.test.TestUtils;
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.data.ACL;
-import org.apache.zookeeper.data.Id;
-import org.easymock.EasyMock;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileWriter;
-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;
-import static org.junit.Assert.fail;
-
-/**
- * Test the RemoteConfigurationMonitor functionality with SASL configured, and znode ACLs applied.
- *
- * The expected implementation is org.apache.hadoop.gateway.topology.monitor.zk.ZooKeeperConfigMonitor
- *
- * Digest-based SASL is used for this test, but since that is dictated solely by the JAAS config, Kerberos-based SASL
- * should work in exactly the same way, simply by modifying the SASL config.
- */
-public class RemoteConfigurationMonitorTest {
-
- private static final String PATH_KNOX = "/knox";
- private static final String PATH_KNOX_CONFIG = PATH_KNOX + "/config";
- private static final String PATH_KNOX_PROVIDERS = PATH_KNOX_CONFIG + "/shared-providers";
- private static final String PATH_KNOX_DESCRIPTORS = PATH_KNOX_CONFIG + "/descriptors";
-
- private static final String PATH_AUTH_TEST = "/auth_test/child_node";
-
-
- private static final String ALT_USERNAME = "notyou";
- private static final String ZK_USERNAME = "testsasluser";
- private static final String ZK_PASSWORD = "testsaslpwd";
-
- private static final ACL ANY_AUTHENTICATED_USER_ALL = new ACL(ZooDefs.Perms.ALL, new Id("auth", ""));
- private static final ACL SASL_TESTUSER_ALL = new ACL(ZooDefs.Perms.ALL, new Id("sasl", ZK_USERNAME));
-
- private static File testTmp;
- private static File providersDir;
- private static File descriptorsDir;
-
- private static TestingCluster zkCluster;
-
- private static CuratorFramework client;
-
- @BeforeClass
- public static void setupSuite() throws Exception {
- testTmp = TestUtils.createTempDir(RemoteConfigurationMonitorTest.class.getName());
- File confDir = TestUtils.createTempDir(testTmp + "/conf");
- providersDir = TestUtils.createTempDir(confDir + "/shared-providers");
- descriptorsDir = TestUtils.createTempDir(confDir + "/descriptors");
- }
-
- @AfterClass
- public static void tearDownSuite() throws Exception {
- // Delete the working dir
- testTmp.delete();
- }
-
- @Before
- public void setupTest() throws Exception {
- configureAndStartZKCluster();
- }
-
- @After
- public void tearDownTest() throws Exception {
- // Clean up the ZK nodes, and close the client
- if (client != null) {
- if (client.checkExists().forPath(PATH_KNOX) != null) {
- client.delete().deletingChildrenIfNeeded().forPath(PATH_KNOX);
- }
- client.close();
- }
-
- // Shutdown the ZK cluster
- zkCluster.close();
- }
-
- /**
- * Create and persist a JAAS configuration file, defining the SASL config for both the ZooKeeper cluster instances
- * and ZooKeeper clients.
- *
- * @param username The digest username
- * @param password The digest password
- *
- * @return The JAAS configuration file
- */
- private static File setupDigestSaslConfig(String username, String password) throws Exception {
- File saslConfigFile = new File(testTmp, "server-jaas.conf");
- FileWriter fw = new FileWriter(saslConfigFile);
- fw.write("Server {\n" +
- " org.apache.zookeeper.server.auth.DigestLoginModule required\n" +
- " user_" + username + " =\"" + password + "\";\n" +
- "};\n" +
- "Client {\n" +
- " org.apache.zookeeper.server.auth.DigestLoginModule required\n" +
- " username=\"" + username + "\"\n" +
- " password=\"" + password + "\";\n" +
- "};\n");
- fw.close();
- return saslConfigFile;
- }
-
- /**
- * Configure and start the ZooKeeper test cluster, and create the znodes monitored by the RemoteConfigurationMonitor.
- */
- private static void configureAndStartZKCluster() throws Exception {
- // Configure security for the ZK cluster instances
- Map<String, Object> customInstanceSpecProps = new HashMap<>();
- 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);
- }
- zkCluster = new TestingCluster(instanceSpecs);
-
- // Configure auth for the ZooKeeper servers and the clients
- File saslConfigFile = setupDigestSaslConfig(ZK_USERNAME, ZK_PASSWORD);
-
- // This system property is used by the ZooKeeper cluster instances, the test driver client, and the
- // RemoteConfigurationMonitor implementation for SASL authentication/authorization
- System.setProperty("java.security.auth.login.config", saslConfigFile.getAbsolutePath());
-
- // Start the cluster
- zkCluster.start();
-
- // Create the client for the test cluster
- client = CuratorFrameworkFactory.builder()
- .connectString(zkCluster.getConnectString())
- .retryPolicy(new ExponentialBackoffRetry(100, 3))
- .build();
- assertNotNull(client);
- client.start();
-
- // Create test config nodes with an ACL for a sasl user that is NOT configured for the test client
- List<ACL> acls = Arrays.asList(new ACL(ZooDefs.Perms.ALL, new Id("sasl", ALT_USERNAME)),
- new ACL(ZooDefs.Perms.READ, ZooDefs.Ids.ANYONE_ID_UNSAFE));
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_AUTH_TEST);
- assertNotNull("Failed to create node:" + PATH_AUTH_TEST,
- client.checkExists().forPath(PATH_AUTH_TEST));
- }
-
-
- private static void validateKnoxConfigNodeACLs(List<ACL> expectedACLS, List<ACL> actualACLs) throws Exception {
- assertEquals(expectedACLS.size(), actualACLs.size());
- int matchedCount = 0;
- for (ACL expected : expectedACLS) {
- for (ACL actual : actualACLs) {
- Id expectedId = expected.getId();
- Id actualId = actual.getId();
- if (actualId.getScheme().equals(expectedId.getScheme()) && actualId.getId().equals(expectedId.getId())) {
- matchedCount++;
- assertEquals(expected.getPerms(), actual.getPerms());
- break;
- }
- }
- }
- assertEquals("ACL mismatch despite being same quantity.", expectedACLS.size(), matchedCount);
- }
-
-
- @Test
- public void testZooKeeperConfigMonitorSASLNodesExistWithUnacceptableACL() throws Exception {
- final String configMonitorName = "zkConfigClient";
- final String alias = "zkPass";
-
- // Setup the base GatewayConfig mock
- GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
- EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(gc.getRemoteRegistryConfigurationNames())
- .andReturn(Collections.singletonList(configMonitorName))
- .anyTimes();
- final String registryConfig =
- GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + ZK_USERNAME + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=Digest;" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + alias;
- EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName))
- .andReturn(registryConfig).anyTimes();
- EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes();
- EasyMock.replay(gc);
-
- AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
- EasyMock.expect(aliasService.getPasswordFromAliasForGateway(alias))
- .andReturn(ZK_PASSWORD.toCharArray())
- .anyTimes();
- EasyMock.replay(aliasService);
-
- RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance();
- clientService.setAliasService(aliasService);
- clientService.init(gc, Collections.emptyMap());
- clientService.start();
-
- RemoteConfigurationMonitorFactory.setClientService(clientService);
-
- RemoteConfigurationMonitor cm = RemoteConfigurationMonitorFactory.get(gc);
- assertNotNull("Failed to load RemoteConfigurationMonitor", cm);
-
- final ACL ANY_AUTHENTICATED_USER_ALL = new ACL(ZooDefs.Perms.ALL, new Id("auth", ""));
- List<ACL> acls = Arrays.asList(ANY_AUTHENTICATED_USER_ALL, new ACL(ZooDefs.Perms.WRITE, ZooDefs.Ids.ANYONE_ID_UNSAFE));
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_CONFIG);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_PROVIDERS);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_DESCRIPTORS);
-
- // Make sure both ACLs were applied
- List<ACL> preACLs = client.getACL().forPath(PATH_KNOX);
- assertEquals(2, preACLs.size());
-
- // Check that the config nodes really do exist (the monitor will NOT create them if they're present)
- assertNotNull(client.checkExists().forPath(PATH_KNOX));
- assertNotNull(client.checkExists().forPath(PATH_KNOX_CONFIG));
- assertNotNull(client.checkExists().forPath(PATH_KNOX_PROVIDERS));
- assertNotNull(client.checkExists().forPath(PATH_KNOX_DESCRIPTORS));
-
- try {
- cm.start();
- } catch (Exception e) {
- fail("Failed to start monitor: " + e.getMessage());
- }
-
- // Validate the expected ACLs on the Knox config znodes (make sure the monitor removed the world:anyone ACL)
- List<ACL> expectedACLs = Collections.singletonList(SASL_TESTUSER_ALL);
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_CONFIG));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_PROVIDERS));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_DESCRIPTORS));
- }
-
-
- @Test
- public void testZooKeeperConfigMonitorSASLNodesExistWithAcceptableACL() throws Exception {
- final String configMonitorName = "zkConfigClient";
- final String alias = "zkPass";
-
- // Setup the base GatewayConfig mock
- GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
- EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(gc.getRemoteRegistryConfigurationNames())
- .andReturn(Collections.singletonList(configMonitorName))
- .anyTimes();
- final String registryConfig =
- GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + ZK_USERNAME + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=Digest;" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + alias;
- EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName))
- .andReturn(registryConfig).anyTimes();
- EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes();
- EasyMock.replay(gc);
-
- AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
- EasyMock.expect(aliasService.getPasswordFromAliasForGateway(alias))
- .andReturn(ZK_PASSWORD.toCharArray())
- .anyTimes();
- EasyMock.replay(aliasService);
-
- RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance();
- clientService.setAliasService(aliasService);
- clientService.init(gc, Collections.emptyMap());
- clientService.start();
-
- RemoteConfigurationMonitorFactory.setClientService(clientService);
-
- RemoteConfigurationMonitor cm = RemoteConfigurationMonitorFactory.get(gc);
- assertNotNull("Failed to load RemoteConfigurationMonitor", cm);
-
- List<ACL> acls = Arrays.asList(ANY_AUTHENTICATED_USER_ALL);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_CONFIG);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_PROVIDERS);
- client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_DESCRIPTORS);
-
- // Check that the config nodes really do exist (the monitor will NOT create them if they're present)
- assertNotNull(client.checkExists().forPath(PATH_KNOX));
- assertNotNull(client.checkExists().forPath(PATH_KNOX_CONFIG));
- assertNotNull(client.checkExists().forPath(PATH_KNOX_PROVIDERS));
- assertNotNull(client.checkExists().forPath(PATH_KNOX_DESCRIPTORS));
-
- try {
- cm.start();
- } catch (Exception e) {
- fail("Failed to start monitor: " + e.getMessage());
- }
-
- // Test auth violation
- clientService.get(configMonitorName).createEntry("/auth_test/child_node/test1");
- assertNull("Creation should have been prevented since write access is not granted to the test client.",
- client.checkExists().forPath("/auth_test/child_node/test1"));
- assertTrue("Creation should have been prevented since write access is not granted to the test client.",
- client.getChildren().forPath("/auth_test/child_node").isEmpty());
-
- // Validate the expected ACLs on the Knox config znodes (make sure the monitor didn't change them)
- List<ACL> expectedACLs = Collections.singletonList(SASL_TESTUSER_ALL);
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_CONFIG));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_PROVIDERS));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_DESCRIPTORS));
- }
-
-
- @Test
- public void testZooKeeperConfigMonitorSASLCreateNodes() throws Exception {
- final String configMonitorName = "zkConfigClient";
- final String alias = "zkPass";
-
- // Setup the base GatewayConfig mock
- GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
- EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(gc.getRemoteRegistryConfigurationNames())
- .andReturn(Collections.singletonList(configMonitorName))
- .anyTimes();
- final String registryConfig =
- GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + ZK_USERNAME + ";" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=Digest;" +
- GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + alias;
- EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName))
- .andReturn(registryConfig).anyTimes();
- EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes();
- EasyMock.replay(gc);
-
- AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
- EasyMock.expect(aliasService.getPasswordFromAliasForGateway(alias))
- .andReturn(ZK_PASSWORD.toCharArray())
- .anyTimes();
- EasyMock.replay(aliasService);
-
- RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance();
- clientService.setAliasService(aliasService);
- clientService.init(gc, Collections.emptyMap());
- clientService.start();
-
- RemoteConfigurationMonitorFactory.setClientService(clientService);
-
- RemoteConfigurationMonitor cm = RemoteConfigurationMonitorFactory.get(gc);
- assertNotNull("Failed to load RemoteConfigurationMonitor", cm);
-
- // Check that the config nodes really don't yet exist (the monitor will create them if they're not present)
- assertNull(client.checkExists().forPath(PATH_KNOX));
- assertNull(client.checkExists().forPath(PATH_KNOX_CONFIG));
- assertNull(client.checkExists().forPath(PATH_KNOX_PROVIDERS));
- assertNull(client.checkExists().forPath(PATH_KNOX_DESCRIPTORS));
-
- try {
- cm.start();
- } catch (Exception e) {
- fail("Failed to start monitor: " + e.getMessage());
- }
-
- // Test auth violation
- clientService.get(configMonitorName).createEntry("/auth_test/child_node/test1");
- assertNull("Creation should have been prevented since write access is not granted to the test client.",
- client.checkExists().forPath("/auth_test/child_node/test1"));
- assertTrue("Creation should have been prevented since write access is not granted to the test client.",
- client.getChildren().forPath("/auth_test/child_node").isEmpty());
-
- // Validate the expected ACLs on the Knox config znodes (make sure the monitor created them correctly)
- List<ACL> expectedACLs = Collections.singletonList(SASL_TESTUSER_ALL);
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_CONFIG));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_PROVIDERS));
- validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_DESCRIPTORS));
-
- // Test the Knox config nodes, for which authentication should be sufficient for access
- try {
- final String pc_one_znode = getProviderPath("providers-config1.xml");
- final File pc_one = new File(providersDir, "providers-config1.xml");
- final String pc_two_znode = getProviderPath("providers-config2.xml");
- final File pc_two = new File(providersDir, "providers-config2.xml");
-
- client.create().withMode(CreateMode.PERSISTENT).forPath(pc_one_znode, TEST_PROVIDERS_CONFIG_1.getBytes());
- Thread.sleep(100);
- assertTrue(pc_one.exists());
- assertEquals(TEST_PROVIDERS_CONFIG_1, FileUtils.readFileToString(pc_one));
-
- client.create().withMode(CreateMode.PERSISTENT).forPath(getProviderPath("providers-config2.xml"), TEST_PROVIDERS_CONFIG_2.getBytes());
- Thread.sleep(100);
- assertTrue(pc_two.exists());
- assertEquals(TEST_PROVIDERS_CONFIG_2, FileUtils.readFileToString(pc_two));
-
- client.setData().forPath(pc_two_znode, TEST_PROVIDERS_CONFIG_1.getBytes());
- Thread.sleep(100);
- assertTrue(pc_two.exists());
- assertEquals(TEST_PROVIDERS_CONFIG_1, FileUtils.readFileToString(pc_two));
-
- client.delete().forPath(pc_two_znode);
- Thread.sleep(100);
- assertFalse(pc_two.exists());
-
- client.delete().forPath(pc_one_znode);
- Thread.sleep(100);
- assertFalse(pc_one.exists());
-
- final String desc_one_znode = getDescriptorPath("test1.json");
- final String desc_two_znode = getDescriptorPath("test2.json");
- final String desc_three_znode = getDescriptorPath("test3.json");
- final File desc_one = new File(descriptorsDir, "test1.json");
- final File desc_two = new File(descriptorsDir, "test2.json");
- final File desc_three = new File(descriptorsDir, "test3.json");
-
- client.create().withMode(CreateMode.PERSISTENT).forPath(desc_one_znode, TEST_DESCRIPTOR_1.getBytes());
- Thread.sleep(100);
- assertTrue(desc_one.exists());
- assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_one));
-
- client.create().withMode(CreateMode.PERSISTENT).forPath(desc_two_znode, TEST_DESCRIPTOR_1.getBytes());
- Thread.sleep(100);
- assertTrue(desc_two.exists());
- assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_two));
-
- client.setData().forPath(desc_two_znode, TEST_DESCRIPTOR_2.getBytes());
- Thread.sleep(100);
- assertTrue(desc_two.exists());
- assertEquals(TEST_DESCRIPTOR_2, FileUtils.readFileToString(desc_two));
-
- client.create().withMode(CreateMode.PERSISTENT).forPath(desc_three_znode, TEST_DESCRIPTOR_1.getBytes());
- Thread.sleep(100);
- assertTrue(desc_three.exists());
- assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_three));
-
- client.delete().forPath(desc_two_znode);
- Thread.sleep(100);
- assertFalse("Expected test2.json to have been deleted.", desc_two.exists());
-
- client.delete().forPath(desc_three_znode);
- Thread.sleep(100);
- assertFalse(desc_three.exists());
-
- client.delete().forPath(desc_one_znode);
- Thread.sleep(100);
- assertFalse(desc_one.exists());
- } finally {
- cm.stop();
- }
- }
-
- private static String getDescriptorPath(String descriptorName) {
- return PATH_KNOX_DESCRIPTORS + "/" + descriptorName;
- }
-
- private static String getProviderPath(String providerConfigName) {
- return PATH_KNOX_PROVIDERS + "/" + providerConfigName;
- }
-
-
- private static final String TEST_PROVIDERS_CONFIG_1 =
- "<gateway>\n" +
- " <provider>\n" +
- " <role>identity-assertion</role>\n" +
- " <name>Default</name>\n" +
- " <enabled>true</enabled>\n" +
- " </provider>\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";
-
- private static final String TEST_PROVIDERS_CONFIG_2 =
- "<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" +
- "</gateway>\n";
-
- private static final String TEST_DESCRIPTOR_1 =
- "{\n" +
- " \"discovery-type\":\"AMBARI\",\n" +
- " \"discovery-address\":\"http://sandbox.hortonworks.com:8080\",\n" +
- " \"discovery-user\":\"maria_dev\",\n" +
- " \"discovery-pwd-alias\":\"sandbox.ambari.discovery.password\",\n" +
- " \"provider-config-ref\":\"sandbox-providers.xml\",\n" +
- " \"cluster\":\"Sandbox\",\n" +
- " \"services\":[\n" +
- " {\"name\":\"NODEUI\"},\n" +
- " {\"name\":\"YARNUI\"},\n" +
- " {\"name\":\"HDFSUI\"},\n" +
- " {\"name\":\"OOZIEUI\"},\n" +
- " {\"name\":\"HBASEUI\"},\n" +
- " {\"name\":\"NAMENODE\"},\n" +
- " {\"name\":\"JOBTRACKER\"},\n" +
- " {\"name\":\"WEBHDFS\"},\n" +
- " {\"name\":\"WEBHCAT\"},\n" +
- " {\"name\":\"OOZIE\"},\n" +
- " {\"name\":\"WEBHBASE\"},\n" +
- " {\"name\":\"RESOURCEMANAGER\"},\n" +
- " {\"name\":\"AMBARI\", \"urls\":[\"http://c6401.ambari.apache.org:8080\"]},\n" +
- " {\"name\":\"AMBARIUI\", \"urls\":[\"http://c6401.ambari.apache.org:8080\"]}\n" +
- " ]\n" +
- "}\n";
-
- private static final String TEST_DESCRIPTOR_2 =
- "{\n" +
- " \"discovery-type\":\"AMBARI\",\n" +
- " \"discovery-address\":\"http://sandbox.hortonworks.com:8080\",\n" +
- " \"discovery-user\":\"maria_dev\",\n" +
- " \"discovery-pwd-alias\":\"sandbox.ambari.discovery.password\",\n" +
- " \"provider-config-ref\":\"sandbox-providers.xml\",\n" +
- " \"cluster\":\"Sandbox\",\n" +
- " \"services\":[\n" +
- " {\"name\":\"NAMENODE\"},\n" +
- " {\"name\":\"JOBTRACKER\"},\n" +
- " {\"name\":\"WEBHDFS\"},\n" +
- " {\"name\":\"WEBHCAT\"},\n" +
- " {\"name\":\"OOZIE\"},\n" +
- " {\"name\":\"WEBHBASE\"},\n" +
- " {\"name\":\"RESOURCEMANAGER\"}\n" +
- " ]\n" +
- "}\n";
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-test/src/test/java/org/apache/knox/gateway/SimpleDescriptorHandlerFuncTest.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/knox/gateway/SimpleDescriptorHandlerFuncTest.java b/gateway-test/src/test/java/org/apache/knox/gateway/SimpleDescriptorHandlerFuncTest.java
new file mode 100644
index 0000000..5b29e19
--- /dev/null
+++ b/gateway-test/src/test/java/org/apache/knox/gateway/SimpleDescriptorHandlerFuncTest.java
@@ -0,0 +1,275 @@
+/**
+ * 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;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.services.GatewayServices;
+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.apache.knox.gateway.services.topology.TopologyService;
+import org.apache.knox.gateway.topology.discovery.ServiceDiscovery;
+import org.apache.knox.gateway.topology.discovery.ServiceDiscoveryConfig;
+import org.apache.knox.gateway.topology.discovery.ServiceDiscoveryType;
+import org.apache.knox.gateway.topology.simple.SimpleDescriptor;
+import org.apache.knox.gateway.topology.simple.SimpleDescriptorHandler;
+import org.apache.knox.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.knox.gateway.shirorealm.KnoxLdapRealm</value>\n" +
+ " </param>\n" +
+ " <param>\n" +
+ " <name>main.ldapContextFactory</name>\n" +
+ " <value>org.apache.knox.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;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-test/src/test/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorTest.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorTest.java b/gateway-test/src/test/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorTest.java
new file mode 100644
index 0000000..37668a8
--- /dev/null
+++ b/gateway-test/src/test/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitorTest.java
@@ -0,0 +1,603 @@
+/**
+ * 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.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.service.config.remote.zk.ZooKeeperClientService;
+import org.apache.knox.gateway.service.config.remote.zk.ZooKeeperClientServiceProvider;
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.test.TestUtils;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Id;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileWriter;
+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;
+import static org.junit.Assert.fail;
+
+/**
+ * Test the RemoteConfigurationMonitor functionality with SASL configured, and znode ACLs applied.
+ *
+ * The expected implementation is org.apache.knox.gateway.topology.monitor.zk.ZooKeeperConfigMonitor
+ *
+ * Digest-based SASL is used for this test, but since that is dictated solely by the JAAS config, Kerberos-based SASL
+ * should work in exactly the same way, simply by modifying the SASL config.
+ */
+public class RemoteConfigurationMonitorTest {
+
+ private static final String PATH_KNOX = "/knox";
+ private static final String PATH_KNOX_CONFIG = PATH_KNOX + "/config";
+ private static final String PATH_KNOX_PROVIDERS = PATH_KNOX_CONFIG + "/shared-providers";
+ private static final String PATH_KNOX_DESCRIPTORS = PATH_KNOX_CONFIG + "/descriptors";
+
+ private static final String PATH_AUTH_TEST = "/auth_test/child_node";
+
+
+ private static final String ALT_USERNAME = "notyou";
+ private static final String ZK_USERNAME = "testsasluser";
+ private static final String ZK_PASSWORD = "testsaslpwd";
+
+ private static final ACL ANY_AUTHENTICATED_USER_ALL = new ACL(ZooDefs.Perms.ALL, new Id("auth", ""));
+ private static final ACL SASL_TESTUSER_ALL = new ACL(ZooDefs.Perms.ALL, new Id("sasl", ZK_USERNAME));
+
+ private static File testTmp;
+ private static File providersDir;
+ private static File descriptorsDir;
+
+ private static TestingCluster zkCluster;
+
+ private static CuratorFramework client;
+
+ @BeforeClass
+ public static void setupSuite() throws Exception {
+ testTmp = TestUtils.createTempDir(RemoteConfigurationMonitorTest.class.getName());
+ File confDir = TestUtils.createTempDir(testTmp + "/conf");
+ providersDir = TestUtils.createTempDir(confDir + "/shared-providers");
+ descriptorsDir = TestUtils.createTempDir(confDir + "/descriptors");
+ }
+
+ @AfterClass
+ public static void tearDownSuite() throws Exception {
+ // Delete the working dir
+ testTmp.delete();
+ }
+
+ @Before
+ public void setupTest() throws Exception {
+ configureAndStartZKCluster();
+ }
+
+ @After
+ public void tearDownTest() throws Exception {
+ // Clean up the ZK nodes, and close the client
+ if (client != null) {
+ if (client.checkExists().forPath(PATH_KNOX) != null) {
+ client.delete().deletingChildrenIfNeeded().forPath(PATH_KNOX);
+ }
+ client.close();
+ }
+
+ // Shutdown the ZK cluster
+ zkCluster.close();
+ }
+
+ /**
+ * Create and persist a JAAS configuration file, defining the SASL config for both the ZooKeeper cluster instances
+ * and ZooKeeper clients.
+ *
+ * @param username The digest username
+ * @param password The digest password
+ *
+ * @return The JAAS configuration file
+ */
+ private static File setupDigestSaslConfig(String username, String password) throws Exception {
+ File saslConfigFile = new File(testTmp, "server-jaas.conf");
+ FileWriter fw = new FileWriter(saslConfigFile);
+ fw.write("Server {\n" +
+ " org.apache.zookeeper.server.auth.DigestLoginModule required\n" +
+ " user_" + username + " =\"" + password + "\";\n" +
+ "};\n" +
+ "Client {\n" +
+ " org.apache.zookeeper.server.auth.DigestLoginModule required\n" +
+ " username=\"" + username + "\"\n" +
+ " password=\"" + password + "\";\n" +
+ "};\n");
+ fw.close();
+ return saslConfigFile;
+ }
+
+ /**
+ * Configure and start the ZooKeeper test cluster, and create the znodes monitored by the RemoteConfigurationMonitor.
+ */
+ private static void configureAndStartZKCluster() throws Exception {
+ // Configure security for the ZK cluster instances
+ Map<String, Object> customInstanceSpecProps = new HashMap<>();
+ 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);
+ }
+ zkCluster = new TestingCluster(instanceSpecs);
+
+ // Configure auth for the ZooKeeper servers and the clients
+ File saslConfigFile = setupDigestSaslConfig(ZK_USERNAME, ZK_PASSWORD);
+
+ // This system property is used by the ZooKeeper cluster instances, the test driver client, and the
+ // RemoteConfigurationMonitor implementation for SASL authentication/authorization
+ System.setProperty("java.security.auth.login.config", saslConfigFile.getAbsolutePath());
+
+ // Start the cluster
+ zkCluster.start();
+
+ // Create the client for the test cluster
+ client = CuratorFrameworkFactory.builder()
+ .connectString(zkCluster.getConnectString())
+ .retryPolicy(new ExponentialBackoffRetry(100, 3))
+ .build();
+ assertNotNull(client);
+ client.start();
+
+ // Create test config nodes with an ACL for a sasl user that is NOT configured for the test client
+ List<ACL> acls = Arrays.asList(new ACL(ZooDefs.Perms.ALL, new Id("sasl", ALT_USERNAME)),
+ new ACL(ZooDefs.Perms.READ, ZooDefs.Ids.ANYONE_ID_UNSAFE));
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_AUTH_TEST);
+ assertNotNull("Failed to create node:" + PATH_AUTH_TEST,
+ client.checkExists().forPath(PATH_AUTH_TEST));
+ }
+
+
+ private static void validateKnoxConfigNodeACLs(List<ACL> expectedACLS, List<ACL> actualACLs) throws Exception {
+ assertEquals(expectedACLS.size(), actualACLs.size());
+ int matchedCount = 0;
+ for (ACL expected : expectedACLS) {
+ for (ACL actual : actualACLs) {
+ Id expectedId = expected.getId();
+ Id actualId = actual.getId();
+ if (actualId.getScheme().equals(expectedId.getScheme()) && actualId.getId().equals(expectedId.getId())) {
+ matchedCount++;
+ assertEquals(expected.getPerms(), actual.getPerms());
+ break;
+ }
+ }
+ }
+ assertEquals("ACL mismatch despite being same quantity.", expectedACLS.size(), matchedCount);
+ }
+
+
+ @Test
+ public void testZooKeeperConfigMonitorSASLNodesExistWithUnacceptableACL() throws Exception {
+ final String configMonitorName = "zkConfigClient";
+ final String alias = "zkPass";
+
+ // Setup the base GatewayConfig mock
+ GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(gc.getRemoteRegistryConfigurationNames())
+ .andReturn(Collections.singletonList(configMonitorName))
+ .anyTimes();
+ final String registryConfig =
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + ZK_USERNAME + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=Digest;" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + alias;
+ EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName))
+ .andReturn(registryConfig).anyTimes();
+ EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes();
+ EasyMock.replay(gc);
+
+ AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
+ EasyMock.expect(aliasService.getPasswordFromAliasForGateway(alias))
+ .andReturn(ZK_PASSWORD.toCharArray())
+ .anyTimes();
+ EasyMock.replay(aliasService);
+
+ RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance();
+ clientService.setAliasService(aliasService);
+ clientService.init(gc, Collections.emptyMap());
+ clientService.start();
+
+ RemoteConfigurationMonitorFactory.setClientService(clientService);
+
+ RemoteConfigurationMonitor cm = RemoteConfigurationMonitorFactory.get(gc);
+ assertNotNull("Failed to load RemoteConfigurationMonitor", cm);
+
+ final ACL ANY_AUTHENTICATED_USER_ALL = new ACL(ZooDefs.Perms.ALL, new Id("auth", ""));
+ List<ACL> acls = Arrays.asList(ANY_AUTHENTICATED_USER_ALL, new ACL(ZooDefs.Perms.WRITE, ZooDefs.Ids.ANYONE_ID_UNSAFE));
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_CONFIG);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_PROVIDERS);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_DESCRIPTORS);
+
+ // Make sure both ACLs were applied
+ List<ACL> preACLs = client.getACL().forPath(PATH_KNOX);
+ assertEquals(2, preACLs.size());
+
+ // Check that the config nodes really do exist (the monitor will NOT create them if they're present)
+ assertNotNull(client.checkExists().forPath(PATH_KNOX));
+ assertNotNull(client.checkExists().forPath(PATH_KNOX_CONFIG));
+ assertNotNull(client.checkExists().forPath(PATH_KNOX_PROVIDERS));
+ assertNotNull(client.checkExists().forPath(PATH_KNOX_DESCRIPTORS));
+
+ try {
+ cm.start();
+ } catch (Exception e) {
+ fail("Failed to start monitor: " + e.getMessage());
+ }
+
+ // Validate the expected ACLs on the Knox config znodes (make sure the monitor removed the world:anyone ACL)
+ List<ACL> expectedACLs = Collections.singletonList(SASL_TESTUSER_ALL);
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_CONFIG));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_PROVIDERS));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_DESCRIPTORS));
+ }
+
+
+ @Test
+ public void testZooKeeperConfigMonitorSASLNodesExistWithAcceptableACL() throws Exception {
+ final String configMonitorName = "zkConfigClient";
+ final String alias = "zkPass";
+
+ // Setup the base GatewayConfig mock
+ GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(gc.getRemoteRegistryConfigurationNames())
+ .andReturn(Collections.singletonList(configMonitorName))
+ .anyTimes();
+ final String registryConfig =
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + ZK_USERNAME + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=Digest;" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + alias;
+ EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName))
+ .andReturn(registryConfig).anyTimes();
+ EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes();
+ EasyMock.replay(gc);
+
+ AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
+ EasyMock.expect(aliasService.getPasswordFromAliasForGateway(alias))
+ .andReturn(ZK_PASSWORD.toCharArray())
+ .anyTimes();
+ EasyMock.replay(aliasService);
+
+ RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance();
+ clientService.setAliasService(aliasService);
+ clientService.init(gc, Collections.emptyMap());
+ clientService.start();
+
+ RemoteConfigurationMonitorFactory.setClientService(clientService);
+
+ RemoteConfigurationMonitor cm = RemoteConfigurationMonitorFactory.get(gc);
+ assertNotNull("Failed to load RemoteConfigurationMonitor", cm);
+
+ List<ACL> acls = Arrays.asList(ANY_AUTHENTICATED_USER_ALL);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_CONFIG);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_PROVIDERS);
+ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(PATH_KNOX_DESCRIPTORS);
+
+ // Check that the config nodes really do exist (the monitor will NOT create them if they're present)
+ assertNotNull(client.checkExists().forPath(PATH_KNOX));
+ assertNotNull(client.checkExists().forPath(PATH_KNOX_CONFIG));
+ assertNotNull(client.checkExists().forPath(PATH_KNOX_PROVIDERS));
+ assertNotNull(client.checkExists().forPath(PATH_KNOX_DESCRIPTORS));
+
+ try {
+ cm.start();
+ } catch (Exception e) {
+ fail("Failed to start monitor: " + e.getMessage());
+ }
+
+ // Test auth violation
+ clientService.get(configMonitorName).createEntry("/auth_test/child_node/test1");
+ assertNull("Creation should have been prevented since write access is not granted to the test client.",
+ client.checkExists().forPath("/auth_test/child_node/test1"));
+ assertTrue("Creation should have been prevented since write access is not granted to the test client.",
+ client.getChildren().forPath("/auth_test/child_node").isEmpty());
+
+ // Validate the expected ACLs on the Knox config znodes (make sure the monitor didn't change them)
+ List<ACL> expectedACLs = Collections.singletonList(SASL_TESTUSER_ALL);
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_CONFIG));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_PROVIDERS));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_DESCRIPTORS));
+ }
+
+
+ @Test
+ public void testZooKeeperConfigMonitorSASLCreateNodes() throws Exception {
+ final String configMonitorName = "zkConfigClient";
+ final String alias = "zkPass";
+
+ // Setup the base GatewayConfig mock
+ GatewayConfig gc = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(gc.getGatewayProvidersConfigDir()).andReturn(providersDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(gc.getGatewayDescriptorsDir()).andReturn(descriptorsDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(gc.getRemoteRegistryConfigurationNames())
+ .andReturn(Collections.singletonList(configMonitorName))
+ .anyTimes();
+ final String registryConfig =
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE + "=" + ZooKeeperClientService.TYPE + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS + "=" + zkCluster.getConnectString() + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL + "=" + ZK_USERNAME + ";" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE + "=Digest;" +
+ GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS + "=" + alias;
+ EasyMock.expect(gc.getRemoteRegistryConfiguration(configMonitorName))
+ .andReturn(registryConfig).anyTimes();
+ EasyMock.expect(gc.getRemoteConfigurationMonitorClientName()).andReturn(configMonitorName).anyTimes();
+ EasyMock.replay(gc);
+
+ AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
+ EasyMock.expect(aliasService.getPasswordFromAliasForGateway(alias))
+ .andReturn(ZK_PASSWORD.toCharArray())
+ .anyTimes();
+ EasyMock.replay(aliasService);
+
+ RemoteConfigurationRegistryClientService clientService = (new ZooKeeperClientServiceProvider()).newInstance();
+ clientService.setAliasService(aliasService);
+ clientService.init(gc, Collections.emptyMap());
+ clientService.start();
+
+ RemoteConfigurationMonitorFactory.setClientService(clientService);
+
+ RemoteConfigurationMonitor cm = RemoteConfigurationMonitorFactory.get(gc);
+ assertNotNull("Failed to load RemoteConfigurationMonitor", cm);
+
+ // Check that the config nodes really don't yet exist (the monitor will create them if they're not present)
+ assertNull(client.checkExists().forPath(PATH_KNOX));
+ assertNull(client.checkExists().forPath(PATH_KNOX_CONFIG));
+ assertNull(client.checkExists().forPath(PATH_KNOX_PROVIDERS));
+ assertNull(client.checkExists().forPath(PATH_KNOX_DESCRIPTORS));
+
+ try {
+ cm.start();
+ } catch (Exception e) {
+ fail("Failed to start monitor: " + e.getMessage());
+ }
+
+ // Test auth violation
+ clientService.get(configMonitorName).createEntry("/auth_test/child_node/test1");
+ assertNull("Creation should have been prevented since write access is not granted to the test client.",
+ client.checkExists().forPath("/auth_test/child_node/test1"));
+ assertTrue("Creation should have been prevented since write access is not granted to the test client.",
+ client.getChildren().forPath("/auth_test/child_node").isEmpty());
+
+ // Validate the expected ACLs on the Knox config znodes (make sure the monitor created them correctly)
+ List<ACL> expectedACLs = Collections.singletonList(SASL_TESTUSER_ALL);
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_CONFIG));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_PROVIDERS));
+ validateKnoxConfigNodeACLs(expectedACLs, client.getACL().forPath(PATH_KNOX_DESCRIPTORS));
+
+ // Test the Knox config nodes, for which authentication should be sufficient for access
+ try {
+ final String pc_one_znode = getProviderPath("providers-config1.xml");
+ final File pc_one = new File(providersDir, "providers-config1.xml");
+ final String pc_two_znode = getProviderPath("providers-config2.xml");
+ final File pc_two = new File(providersDir, "providers-config2.xml");
+
+ client.create().withMode(CreateMode.PERSISTENT).forPath(pc_one_znode, TEST_PROVIDERS_CONFIG_1.getBytes());
+ Thread.sleep(100);
+ assertTrue(pc_one.exists());
+ assertEquals(TEST_PROVIDERS_CONFIG_1, FileUtils.readFileToString(pc_one));
+
+ client.create().withMode(CreateMode.PERSISTENT).forPath(getProviderPath("providers-config2.xml"), TEST_PROVIDERS_CONFIG_2.getBytes());
+ Thread.sleep(100);
+ assertTrue(pc_two.exists());
+ assertEquals(TEST_PROVIDERS_CONFIG_2, FileUtils.readFileToString(pc_two));
+
+ client.setData().forPath(pc_two_znode, TEST_PROVIDERS_CONFIG_1.getBytes());
+ Thread.sleep(100);
+ assertTrue(pc_two.exists());
+ assertEquals(TEST_PROVIDERS_CONFIG_1, FileUtils.readFileToString(pc_two));
+
+ client.delete().forPath(pc_two_znode);
+ Thread.sleep(100);
+ assertFalse(pc_two.exists());
+
+ client.delete().forPath(pc_one_znode);
+ Thread.sleep(100);
+ assertFalse(pc_one.exists());
+
+ final String desc_one_znode = getDescriptorPath("test1.json");
+ final String desc_two_znode = getDescriptorPath("test2.json");
+ final String desc_three_znode = getDescriptorPath("test3.json");
+ final File desc_one = new File(descriptorsDir, "test1.json");
+ final File desc_two = new File(descriptorsDir, "test2.json");
+ final File desc_three = new File(descriptorsDir, "test3.json");
+
+ client.create().withMode(CreateMode.PERSISTENT).forPath(desc_one_znode, TEST_DESCRIPTOR_1.getBytes());
+ Thread.sleep(100);
+ assertTrue(desc_one.exists());
+ assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_one));
+
+ client.create().withMode(CreateMode.PERSISTENT).forPath(desc_two_znode, TEST_DESCRIPTOR_1.getBytes());
+ Thread.sleep(100);
+ assertTrue(desc_two.exists());
+ assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_two));
+
+ client.setData().forPath(desc_two_znode, TEST_DESCRIPTOR_2.getBytes());
+ Thread.sleep(100);
+ assertTrue(desc_two.exists());
+ assertEquals(TEST_DESCRIPTOR_2, FileUtils.readFileToString(desc_two));
+
+ client.create().withMode(CreateMode.PERSISTENT).forPath(desc_three_znode, TEST_DESCRIPTOR_1.getBytes());
+ Thread.sleep(100);
+ assertTrue(desc_three.exists());
+ assertEquals(TEST_DESCRIPTOR_1, FileUtils.readFileToString(desc_three));
+
+ client.delete().forPath(desc_two_znode);
+ Thread.sleep(100);
+ assertFalse("Expected test2.json to have been deleted.", desc_two.exists());
+
+ client.delete().forPath(desc_three_znode);
+ Thread.sleep(100);
+ assertFalse(desc_three.exists());
+
+ client.delete().forPath(desc_one_znode);
+ Thread.sleep(100);
+ assertFalse(desc_one.exists());
+ } finally {
+ cm.stop();
+ }
+ }
+
+ private static String getDescriptorPath(String descriptorName) {
+ return PATH_KNOX_DESCRIPTORS + "/" + descriptorName;
+ }
+
+ private static String getProviderPath(String providerConfigName) {
+ return PATH_KNOX_PROVIDERS + "/" + providerConfigName;
+ }
+
+
+ private static final String TEST_PROVIDERS_CONFIG_1 =
+ "<gateway>\n" +
+ " <provider>\n" +
+ " <role>identity-assertion</role>\n" +
+ " <name>Default</name>\n" +
+ " <enabled>true</enabled>\n" +
+ " </provider>\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";
+
+ private static final String TEST_PROVIDERS_CONFIG_2 =
+ "<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.knox.gateway.shirorealm.KnoxLdapRealm</value>\n" +
+ " </param>\n" +
+ " <param>\n" +
+ " <name>main.ldapContextFactory</name>\n" +
+ " <value>org.apache.knox.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" +
+ "</gateway>\n";
+
+ private static final String TEST_DESCRIPTOR_1 =
+ "{\n" +
+ " \"discovery-type\":\"AMBARI\",\n" +
+ " \"discovery-address\":\"http://sandbox.hortonworks.com:8080\",\n" +
+ " \"discovery-user\":\"maria_dev\",\n" +
+ " \"discovery-pwd-alias\":\"sandbox.ambari.discovery.password\",\n" +
+ " \"provider-config-ref\":\"sandbox-providers.xml\",\n" +
+ " \"cluster\":\"Sandbox\",\n" +
+ " \"services\":[\n" +
+ " {\"name\":\"NODEUI\"},\n" +
+ " {\"name\":\"YARNUI\"},\n" +
+ " {\"name\":\"HDFSUI\"},\n" +
+ " {\"name\":\"OOZIEUI\"},\n" +
+ " {\"name\":\"HBASEUI\"},\n" +
+ " {\"name\":\"NAMENODE\"},\n" +
+ " {\"name\":\"JOBTRACKER\"},\n" +
+ " {\"name\":\"WEBHDFS\"},\n" +
+ " {\"name\":\"WEBHCAT\"},\n" +
+ " {\"name\":\"OOZIE\"},\n" +
+ " {\"name\":\"WEBHBASE\"},\n" +
+ " {\"name\":\"RESOURCEMANAGER\"},\n" +
+ " {\"name\":\"AMBARI\", \"urls\":[\"http://c6401.ambari.apache.org:8080\"]},\n" +
+ " {\"name\":\"AMBARIUI\", \"urls\":[\"http://c6401.ambari.apache.org:8080\"]}\n" +
+ " ]\n" +
+ "}\n";
+
+ private static final String TEST_DESCRIPTOR_2 =
+ "{\n" +
+ " \"discovery-type\":\"AMBARI\",\n" +
+ " \"discovery-address\":\"http://sandbox.hortonworks.com:8080\",\n" +
+ " \"discovery-user\":\"maria_dev\",\n" +
+ " \"discovery-pwd-alias\":\"sandbox.ambari.discovery.password\",\n" +
+ " \"provider-config-ref\":\"sandbox-providers.xml\",\n" +
+ " \"cluster\":\"Sandbox\",\n" +
+ " \"services\":[\n" +
+ " {\"name\":\"NAMENODE\"},\n" +
+ " {\"name\":\"JOBTRACKER\"},\n" +
+ " {\"name\":\"WEBHDFS\"},\n" +
+ " {\"name\":\"WEBHCAT\"},\n" +
+ " {\"name\":\"OOZIE\"},\n" +
+ " {\"name\":\"WEBHBASE\"},\n" +
+ " {\"name\":\"RESOURCEMANAGER\"}\n" +
+ " ]\n" +
+ "}\n";
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-test/src/test/resources/META-INF/services/org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryType
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/resources/META-INF/services/org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryType b/gateway-test/src/test/resources/META-INF/services/org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryType
deleted file mode 100644
index 0c5fe09..0000000
--- a/gateway-test/src/test/resources/META-INF/services/org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryType
+++ /dev/null
@@ -1,19 +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
-#
-# 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.
-##########################################################################
-
-org.apache.hadoop.gateway.SimpleDescriptorHandlerFuncTest$NoOpServiceDiscoveryType
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-test/src/test/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.ServiceDiscoveryType
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.ServiceDiscoveryType b/gateway-test/src/test/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.ServiceDiscoveryType
new file mode 100644
index 0000000..8d72813
--- /dev/null
+++ b/gateway-test/src/test/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.ServiceDiscoveryType
@@ -0,0 +1,19 @@
+##########################################################################
+# 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.
+##########################################################################
+
+org.apache.knox.gateway.SimpleDescriptorHandlerFuncTest$NoOpServiceDiscoveryType