Repository: hive Updated Branches: refs/heads/master a989f6976 -> 8964c1ebc
HIVE-11866 : Add framework to enable testing using LDAPServer using LDAP protocol (Naveen Gangam via Szehon) Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/8964c1eb Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/8964c1eb Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/8964c1eb Branch: refs/heads/master Commit: 8964c1ebc7f14f03c2c5773a785ed50d318798fe Parents: a989f69 Author: Szehon Ho <[email protected]> Authored: Mon Oct 5 10:15:20 2015 -0700 Committer: Szehon Ho <[email protected]> Committed: Mon Oct 5 10:15:20 2015 -0700 ---------------------------------------------------------------------- pom.xml | 1 + service/pom.xml | 6 + .../auth/TestLdapAtnProviderWithLdapServer.java | 215 +++++++++++++++++++ .../org/apache/hive/service/auth/ldapdata.ldif | 59 +++++ 4 files changed, 281 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/8964c1eb/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index b11a405..2ef2a09 100644 --- a/pom.xml +++ b/pom.xml @@ -166,6 +166,7 @@ <scala.version>2.10.4</scala.version> <tempus-fugit.version>1.1</tempus-fugit.version> <snappy.version>0.2</snappy.version> + <unboundid.version>2.3.1</unboundid.version> <wadl-resourcedoc-doclet.version>1.4</wadl-resourcedoc-doclet.version> <velocity.version>1.5</velocity.version> <xerces.version>2.9.1</xerces.version> http://git-wip-us.apache.org/repos/asf/hive/blob/8964c1eb/service/pom.xml ---------------------------------------------------------------------- diff --git a/service/pom.xml b/service/pom.xml index 07eeb9a..d9bf8d1 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -111,6 +111,12 @@ <version>${junit.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>com.unboundid</groupId> + <artifactId>unboundid-ldapsdk</artifactId> + <version>${unboundid.version}</version> + <scope>test</scope> + </dependency> </dependencies> <profiles> http://git-wip-us.apache.org/repos/asf/hive/blob/8964c1eb/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithLdapServer.java ---------------------------------------------------------------------- diff --git a/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithLdapServer.java b/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithLdapServer.java new file mode 100644 index 0000000..8f015b0 --- /dev/null +++ b/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithLdapServer.java @@ -0,0 +1,215 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hive.service.auth; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.ldap.sdk.DN; +import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldif.LDIFReader; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Set; + +import javax.security.sasl.AuthenticationException; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.apache.hadoop.hive.conf.HiveConf; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Tests that use an in-memory LDAP Server (unboundID) to test HS2's + * LDAP Authentication Provider. The ldap server uses a sample ldif + * file to load ldap data into its directory. + * Any of Hive's LDAP Configuration properties are set on the HiveConf + * prior to the initialization of LdapAuthenticationProviderImpl. + * Each test uses a different set of properties to alter the Atn + * provider behavior. + */ +public class TestLdapAtnProviderWithLdapServer { + private static String ldapUrl; + private static InMemoryDirectoryServer server; + private static InMemoryDirectoryServerConfig config; + private static HiveConf hiveConf; + private static byte[] hiveConfBackup; + private static LdapAuthenticationProviderImpl ldapProvider; + private static final int serverPort = 33300; + + @BeforeClass + public static void init() throws Exception { + DN dn = new DN("dc=example, dc=com"); + config = new InMemoryDirectoryServerConfig(dn); + config.setSchema(null); + config.addAdditionalBindCredentials("cn=user1,ou=People,dc=example,dc=com","user1"); + config.addAdditionalBindCredentials("cn=user2,ou=People,dc=example,dc=com","user2"); + + // listener config only necessary if you want to make sure that the + // server listens on port 33300, otherwise a free random port will + // be picked at runtime - which might be even better for tests btw. + config.setListenerConfigs( + new InMemoryListenerConfig("myListener", null, serverPort, null, null, null)); + + server = new InMemoryDirectoryServer(config); + + server.startListening(); + + File ldifFile = new File(Thread.currentThread().getContextClassLoader() + .getResource("org/apache/hive/service/auth/ldapdata.ldif").getFile()); + LDIFReader ldifReader = new LDIFReader(ldifFile); + // import your test data from ldif files + server.importFromLDIF(true, ldifReader); + + LDAPConnection conn = server.getConnection(); + int port = server.getListenPort(); + ldapUrl = new String("ldap://localhost:" + port); + + hiveConf = new HiveConf(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + hiveConf.writeXml(baos); + baos.close(); + hiveConfBackup = baos.toByteArray(); + hiveConf.set("hive.root.logger", "TRACE,console"); + hiveConf.set("hive.server2.authentication.ldap.url", ldapUrl); + hiveConf.set("hive.server2.authentication.ldap.baseDN", "dc=example,dc=com"); + hiveConf.set("hive.server2.authentication.ldap.userDNPattern", "cn=%s,ou=People,dc=example,dc=com"); + FileOutputStream fos = new FileOutputStream(new File(hiveConf.getHiveSiteLocation().toURI())); + hiveConf.writeXml(fos); + fos.close(); + + ldapProvider = new LdapAuthenticationProviderImpl(); + } + + private static void initLdapAtn(Hashtable<String, String> hiveProperties) + throws Exception { + Set<String> keys = hiveProperties.keySet(); + Iterator<String> iter = keys.iterator(); + hiveConf = new HiveConf(); + + try { + boolean deleted = new File(hiveConf.getHiveSiteLocation().toURI()).delete(); + } catch (Exception e) {} + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + hiveConf.writeXml(baos); + baos.close(); + + hiveConf.set("hive.root.logger", "TRACE,console"); + hiveConf.set("hive.server2.authentication.ldap.url", ldapUrl); + hiveConf.set("hive.server2.authentication.ldap.userDNPattern", "cn=%s,ou=People,dc=example,dc=com"); + hiveConf.set("hive.server2.authentication.ldap.groupDNPattern", "cn=%s,ou=Groups,dc=example,dc=com"); + + String key; + String value; + while (iter.hasNext()) { + key = iter.next(); + value = hiveProperties.get(key); + hiveConf.set(key, value); + } + + FileOutputStream fos = new FileOutputStream(new File(hiveConf.getHiveSiteLocation().toURI())); + hiveConf.writeXml(fos); + fos.close(); + + ldapProvider = new LdapAuthenticationProviderImpl(); + } + + @AfterClass + public static void tearDown() throws Exception { + server.shutDown(true); + } + + @Test + public void testRoot() throws Exception { + Hashtable<String, String> ldapProperties = new Hashtable<String, String>(); + initLdapAtn(ldapProperties); + String user; + + user = "cn=user1,ou=People,dc=example,dc=com"; + try { + ldapProvider.Authenticate(user, "user1"); + assertTrue(true); + + user = "cn=user2,ou=People,dc=example,dc=com"; + ldapProvider.Authenticate(user, "user2"); + assertTrue(true); + } catch (AuthenticationException e) { + e.printStackTrace(); + Assert.fail("Authentication failed for user:" + user); + } + } + + @Test + public void testUserBindPositive() throws Exception { + Hashtable<String, String> ldapProperties = new Hashtable<String, String>(); + ldapProperties.put("hive.server2.authentication.ldap.userFilter", "user1,user2"); + initLdapAtn(ldapProperties); + String user; + + user = "cn=user1,ou=People,dc=example,dc=com"; + try { + ldapProvider.Authenticate(user, "user1"); + assertTrue("testUserBindPositive: Authentication succeeded for user1 as expected", true); + } catch (AuthenticationException e) { + Assert.fail("testUserBindPositive: Authentication failed for user:" + user + + " with password user1, expected to succeed"); + } + + user = "cn=user2,ou=People,dc=example,dc=com"; + try { + ldapProvider.Authenticate(user, "user2"); + assertTrue("testUserBindPositive: Authentication succeeded for user2 as expected", true); + } catch (AuthenticationException e) { + Assert.fail("testUserBindPositive: Authentication failed for user:" + user + + " with password user2, expected to succeed"); + } + } + + @Test + public void testUserBindNegative() throws Exception { + Hashtable<String, String> ldapProperties = new Hashtable<String, String>(); + initLdapAtn(ldapProperties); + + try { + ldapProvider.Authenticate("cn=user1,ou=People,dc=example,dc=com", "user2"); + Assert.fail("testUserBindNegative: Authentication succeeded for user1 with password " + + "user2, expected to fail"); + } catch (AuthenticationException e) { + assertTrue("testUserBindNegative: Authentication failed for user1 as expected", true); + } + + try { + ldapProvider.Authenticate("cn=user2,ou=People,dc=example,dc=com", "user"); + Assert.fail("testUserBindNegative: Authentication failed for user2 with password user, " + + "expected to fail"); + } catch (AuthenticationException e) { + assertTrue("testUserBindNegative: Authentication failed for user2 as expected", true); + } + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/8964c1eb/service/src/test/resources/org/apache/hive/service/auth/ldapdata.ldif ---------------------------------------------------------------------- diff --git a/service/src/test/resources/org/apache/hive/service/auth/ldapdata.ldif b/service/src/test/resources/org/apache/hive/service/auth/ldapdata.ldif new file mode 100644 index 0000000..686fb3f --- /dev/null +++ b/service/src/test/resources/org/apache/hive/service/auth/ldapdata.ldif @@ -0,0 +1,59 @@ +dn: dc=example,dc=com +distinguishedName: dc=example,dc=com +objectClass: top +objectClass: domain +dc: example + +dn: ou=People,dc=example,dc=com +distinguishedName: ou=People,dc=example,dc=com +objectClass: top +objectClass: organizationalUnit +ou: People +description: Contains entries which describe persons (seamen) + +dn: ou=Groups,dc=example,dc=com +distinguishedName: ou=Groups,dc=example,dc=com +objectClass: top +objectClass: organizationalUnit +ou: Groups +description: Contains entries which describe groups (crews, for instance) + +dn: cn=group1,ou=Groups,dc=example,dc=com +distinguishedName: cn=group1,ou=Groups,dc=example,dc=com +objectClass: group +objectClass: top +givenName: Group1 +cn: Test Group1 +sn: group1 + +dn: cn=group2,ou=Groups,dc=example,dc=com +distinguishedName: cn=group2,ou=Groups,dc=example,dc=com +objectClass: group +objectClass: top +givenName: Group2 +cn: Test Group2 +sn: group1 + +dn: cn=user1,ou=People,dc=example,dc=com +distinguishedName: cn=user1,ou=People,dc=example,dc=com +objectClass: inetOrgPerson +objectClass: person +objectClass: top +givenName: Test1 +cn: Test User1 +sn: user1 +uid: user1 +userPassword: user1 +memberOf: cn=group1,ou=Groups,dc=example,dc=com + +dn: cn=user2,ou=People,dc=example,dc=com +distinguishedName: cn=user2,ou=People,dc=example,dc=com +objectClass: inetOrgPerson +objectClass: person +objectClass: top +givenName: Test2 +cn: Test User2 +sn: user2 +uid: user2 +userPassword: user2 +memberOf: cn=group2,ou=Groups,dc=example,dc=com
