You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by se...@apache.org on 2016/10/01 01:09:01 UTC
[19/44] hive git commit: HIVE-14713: LDAP Authentication Provider
should be covered with unit tests (Illya Yalovyy, reviewed by Chaoyu Tang,
Szehon Ho)
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/java/org/apache/hive/service/auth/ldap/UserSearchFilterFactory.java
----------------------------------------------------------------------
diff --git a/service/src/java/org/apache/hive/service/auth/ldap/UserSearchFilterFactory.java b/service/src/java/org/apache/hive/service/auth/ldap/UserSearchFilterFactory.java
new file mode 100644
index 0000000..3218875
--- /dev/null
+++ b/service/src/java/org/apache/hive/service/auth/ldap/UserSearchFilterFactory.java
@@ -0,0 +1,65 @@
+/**
+ * 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.ldap;
+
+import java.util.Collection;
+import javax.naming.NamingException;
+import javax.security.sasl.AuthenticationException;
+import org.apache.hadoop.hive.conf.HiveConf;
+
+/**
+ * A factory for a {@link Filter} that check whether provided user could be found in the directory.
+ * <br>
+ * The produced filter object filters out all users that are not found in the directory.
+ */
+public final class UserSearchFilterFactory implements FilterFactory {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Filter getInstance(HiveConf conf) {
+ Collection<String> groupFilter = conf.getStringCollection(
+ HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER.varname);
+ Collection<String> userFilter = conf.getStringCollection(
+ HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER.varname);
+
+ if (groupFilter.isEmpty() && userFilter.isEmpty()) {
+ return null;
+ }
+
+ return new UserSearchFilter();
+ }
+
+ private static final class UserSearchFilter implements Filter {
+ @Override
+ public void apply(DirSearch client, String user) throws AuthenticationException {
+ try {
+ String userDn = client.findUserDn(user);
+
+ // This should not be null because we were allowed to bind with this username
+ // safe check in case we were able to bind anonymously.
+ if (userDn == null) {
+ throw new AuthenticationException("Authentication failed: User search failed");
+ }
+ } catch (NamingException e) {
+ throw new AuthenticationException("LDAP Authentication failed for user", e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithMiniDS.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithMiniDS.java b/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithMiniDS.java
index 089a059..23a048a 100644
--- a/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithMiniDS.java
+++ b/service/src/test/org/apache/hive/service/auth/TestLdapAtnProviderWithMiniDS.java
@@ -225,7 +225,6 @@ public class TestLdapAtnProviderWithMiniDS extends AbstractLdapTestUnit {
hiveConf = new HiveConf();
ldapProvider = new LdapAuthenticationProviderImpl(hiveConf);
- ldapProvider.init(hiveConf);
}
@AfterClass
@@ -259,7 +258,7 @@ public class TestLdapAtnProviderWithMiniDS extends AbstractLdapTestUnit {
}
}
- ldapProvider.init(hiveConf);
+ ldapProvider = new LdapAuthenticationProviderImpl(hiveConf);
}
@Test
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/TestLdapAuthenticationProviderImpl.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/TestLdapAuthenticationProviderImpl.java b/service/src/test/org/apache/hive/service/auth/TestLdapAuthenticationProviderImpl.java
index f276906..4fad755 100644
--- a/service/src/test/org/apache/hive/service/auth/TestLdapAuthenticationProviderImpl.java
+++ b/service/src/test/org/apache/hive/service/auth/TestLdapAuthenticationProviderImpl.java
@@ -15,51 +15,260 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.hive.service.auth;
+import java.io.IOException;
+import java.util.Arrays;
+import javax.naming.NamingException;
import javax.security.sasl.AuthenticationException;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-
-import junit.framework.TestCase;
import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hive.service.auth.ldap.DirSearch;
+import org.apache.hive.service.auth.ldap.DirSearchFactory;
+import org.apache.hive.service.auth.ldap.LdapSearchFactory;
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestLdapAuthenticationProviderImpl {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
-public class TestLdapAuthenticationProviderImpl extends TestCase {
+ public HiveConf conf;
+ public LdapAuthenticationProviderImpl auth;
- private static HiveConf hiveConf;
- private static byte[] hiveConfBackup;
+ @Mock
+ public DirSearchFactory factory;
- @Override
- public void setUp() throws Exception {
- hiveConf = new HiveConf();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- hiveConf.writeXml(baos);
- baos.close();
- hiveConfBackup = baos.toByteArray();
- hiveConf.set("hive.server2.authentication.ldap.url", "localhost");
- FileOutputStream fos = new FileOutputStream(new File(hiveConf.getHiveSiteLocation().toURI()));
- hiveConf.writeXml(fos);
- fos.close();
+ @Mock
+ public DirSearch search;
+
+ @Before
+ public void setup() throws AuthenticationException {
+ conf = new HiveConf();
+ conf.set("hive.root.logger", "DEBUG,console");
+ conf.set("hive.server2.authentication.ldap.url", "localhost");
+ when(factory.getInstance(any(HiveConf.class), anyString(), anyString())).thenReturn(search);
}
- public void testLdapEmptyPassword() {
- LdapAuthenticationProviderImpl ldapImpl = new LdapAuthenticationProviderImpl(hiveConf);
- try {
- ldapImpl.Authenticate("user", "");
- assertFalse(true);
- } catch (AuthenticationException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("a null or blank password has been provided"));
- }
+ @Test
+ public void authenticateGivenBlankPassword() throws Exception {
+ auth = new LdapAuthenticationProviderImpl(conf, new LdapSearchFactory());
+ expectAuthenticationExceptionForInvalidPassword();
+ auth.Authenticate("user", "");
+ }
+
+ @Test
+ public void authenticateGivenStringWithNullCharacterForPassword() throws Exception {
+ auth = new LdapAuthenticationProviderImpl(conf, new LdapSearchFactory());
+ expectAuthenticationExceptionForInvalidPassword();
+ auth.Authenticate("user", "\0");
+ }
+
+ @Test
+ public void authenticateGivenNullForPassword() throws Exception {
+ auth = new LdapAuthenticationProviderImpl(conf, new LdapSearchFactory());
+ expectAuthenticationExceptionForInvalidPassword();
+ auth.Authenticate("user", null);
+ }
+
+ @Test
+ public void testAuthenticateNoUserOrGroupFilter() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "cn=%s,ou=Users,dc=mycorp,dc=com:cn=%s,ou=PowerUsers,dc=mycorp,dc=com");
+
+ DirSearchFactory factory = mock(DirSearchFactory.class);
+
+ when(search.findUserDn("user1")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+
+ when(factory.getInstance(conf, "cn=user1,ou=PowerUsers,dc=mycorp,dc=com", "Blah")).thenReturn(search);
+ when(factory.getInstance(conf, "cn=user1,ou=Users,dc=mycorp,dc=com", "Blah")).thenThrow(AuthenticationException.class);
+
+ auth = new LdapAuthenticationProviderImpl(conf, factory);
+ auth.Authenticate("user1", "Blah");
+
+ verify(factory, times(2)).getInstance(isA(HiveConf.class), anyString(), eq("Blah"));
+ verify(search, atLeastOnce()).close();
}
- @Override
- public void tearDown() throws Exception {
- if(hiveConf != null && hiveConfBackup != null) {
- FileOutputStream fos = new FileOutputStream(new File(hiveConf.getHiveSiteLocation().toURI()));
- fos.write(hiveConfBackup);
- fos.close();
+ @Test
+ public void testAuthenticateWhenUserFilterPasses() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER,
+ "user1,user2");
+
+ when(search.findUserDn("user1")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+ when(search.findUserDn("user2")).thenReturn("cn=user2,ou=PowerUsers,dc=mycorp,dc=com");
+
+ authenticateUserAndCheckSearchIsClosed("user1");
+ authenticateUserAndCheckSearchIsClosed("user2");
+ }
+
+ @Test
+ public void testAuthenticateWhenLoginWithDomainAndUserFilterPasses() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER,
+ "user1");
+
+ when(search.findUserDn("user1")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+
+ authenticateUserAndCheckSearchIsClosed("user1@mydomain.com");
+ }
+
+ @Test
+ public void testAuthenticateWhenLoginWithDnAndUserFilterPasses() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER,
+ "user1");
+
+ when(search.findUserDn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+
+ authenticateUserAndCheckSearchIsClosed("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+ }
+
+ @Test
+ public void testAuthenticateWhenUserSearchFails() throws NamingException, AuthenticationException, IOException {
+ thrown.expect(AuthenticationException.class);
+
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "user1,user2");
+
+ when(search.findUserDn("user1")).thenReturn(null);
+
+ authenticateUserAndCheckSearchIsClosed("user1");
+ }
+
+ @Test
+ public void testAuthenticateWhenUserFilterFails() throws NamingException, AuthenticationException, IOException {
+ thrown.expect(AuthenticationException.class);
+
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "user1,user2");
+
+ when(search.findUserDn("user3")).thenReturn("cn=user3,ou=PowerUsers,dc=mycorp,dc=com");
+
+ authenticateUserAndCheckSearchIsClosed("user3");
+ }
+
+ @Test
+ public void testAuthenticateWhenGroupFilterPasses() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "group1,group2");
+
+ when(search.findUserDn("user1")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+ when(search.findUserDn("user2")).thenReturn("cn=user2,ou=PowerUsers,dc=mycorp,dc=com");
+
+ when(search.findGroupsForUser("cn=user1,ou=PowerUsers,dc=mycorp,dc=com"))
+ .thenReturn(Arrays.asList(
+ "cn=testGroup,ou=Groups,dc=mycorp,dc=com",
+ "cn=group1,ou=Groups,dc=mycorp,dc=com"));
+ when(search.findGroupsForUser("cn=user2,ou=PowerUsers,dc=mycorp,dc=com"))
+ .thenReturn(Arrays.asList(
+ "cn=testGroup,ou=Groups,dc=mycorp,dc=com",
+ "cn=group2,ou=Groups,dc=mycorp,dc=com"));
+
+ authenticateUserAndCheckSearchIsClosed("user1");
+ authenticateUserAndCheckSearchIsClosed("user2");
+ }
+
+ @Test
+ public void testAuthenticateWhenUserAndGroupFiltersPass() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "group1,group2");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "user1,user2");
+
+ when(search.findUserDn("user1")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+ when(search.findUserDn("user2")).thenReturn("cn=user2,ou=PowerUsers,dc=mycorp,dc=com");
+
+ when(search.findGroupsForUser("cn=user1,ou=PowerUsers,dc=mycorp,dc=com"))
+ .thenReturn(Arrays.asList(
+ "cn=testGroup,ou=Groups,dc=mycorp,dc=com",
+ "cn=group1,ou=Groups,dc=mycorp,dc=com"));
+ when(search.findGroupsForUser("cn=user2,ou=PowerUsers,dc=mycorp,dc=com"))
+ .thenReturn(Arrays.asList(
+ "cn=testGroup,ou=Groups,dc=mycorp,dc=com",
+ "cn=group2,ou=Groups,dc=mycorp,dc=com"));
+
+ authenticateUserAndCheckSearchIsClosed("user1");
+ authenticateUserAndCheckSearchIsClosed("user2");
+ }
+
+ @Test
+ public void testAuthenticateWhenUserFilterPassesAndGroupFilterFails()
+ throws NamingException, AuthenticationException, IOException {
+ thrown.expect(AuthenticationException.class);
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "group1,group2");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "user1,user2");
+
+ when(search.findUserDn("user1")).thenReturn("cn=user1,ou=PowerUsers,dc=mycorp,dc=com");
+
+ when(search.findGroupsForUser("cn=user1,ou=PowerUsers,dc=mycorp,dc=com"))
+ .thenReturn(Arrays.asList(
+ "cn=testGroup,ou=Groups,dc=mycorp,dc=com",
+ "cn=OtherGroup,ou=Groups,dc=mycorp,dc=com"));
+
+ authenticateUserAndCheckSearchIsClosed("user1");
+ }
+
+ @Test
+ public void testAuthenticateWhenUserFilterFailsAndGroupFilterPasses()
+ throws NamingException, AuthenticationException, IOException {
+ thrown.expect(AuthenticationException.class);
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "group3");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "user1,user2");
+
+ when(search.findUserDn("user3")).thenReturn("cn=user3,ou=PowerUsers,dc=mycorp,dc=com");
+
+ when(search.findGroupsForUser("cn=user3,ou=PowerUsers,dc=mycorp,dc=com"))
+ .thenReturn(Arrays.asList(
+ "cn=testGroup,ou=Groups,dc=mycorp,dc=com",
+ "cn=group3,ou=Groups,dc=mycorp,dc=com"));
+
+ authenticateUserAndCheckSearchIsClosed("user3");
+ }
+
+ @Test
+ public void testAuthenticateWhenCustomQueryFilterPasses() throws NamingException, AuthenticationException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN, "dc=mycorp,dc=com");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_CUSTOMLDAPQUERY,
+ "(&(objectClass=person)(|(memberOf=CN=Domain Admins,CN=Users,DC=apache,DC=org)(memberOf=CN=Administrators,CN=Builtin,DC=apache,DC=org)))");
+
+ when(search.executeCustomQuery(anyString())).thenReturn(Arrays.asList(
+ "cn=user1,ou=PowerUsers,dc=mycorp,dc=com",
+ "cn=user2,ou=PowerUsers,dc=mycorp,dc=com"));
+
+ authenticateUserAndCheckSearchIsClosed("user1");
+ }
+
+ @Test
+ public void testAuthenticateWhenCustomQueryFilterFailsAndUserFilterPasses() throws NamingException, AuthenticationException, IOException {
+ thrown.expect(AuthenticationException.class);
+
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN, "dc=mycorp,dc=com");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_CUSTOMLDAPQUERY,
+ "(&(objectClass=person)(|(memberOf=CN=Domain Admins,CN=Users,DC=apache,DC=org)(memberOf=CN=Administrators,CN=Builtin,DC=apache,DC=org)))");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "user3");
+
+ when(search.findUserDn("user3")).thenReturn("cn=user3,ou=PowerUsers,dc=mycorp,dc=com");
+ when(search.executeCustomQuery(anyString())).thenReturn(Arrays.asList(
+ "cn=user1,ou=PowerUsers,dc=mycorp,dc=com",
+ "cn=user2,ou=PowerUsers,dc=mycorp,dc=com"));
+
+ authenticateUserAndCheckSearchIsClosed("user3");
+ }
+
+ private void expectAuthenticationExceptionForInvalidPassword() {
+ thrown.expect(AuthenticationException.class);
+ thrown.expectMessage("a null or blank password has been provided");
+ }
+
+ private void authenticateUserAndCheckSearchIsClosed(String user) throws IOException {
+ auth = new LdapAuthenticationProviderImpl(conf, factory);
+ try {
+ auth.Authenticate(user, "password doesn't matter");
+ } finally {
+ verify(search, atLeastOnce()).close();
}
}
}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/Credentials.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/Credentials.java b/service/src/test/org/apache/hive/service/auth/ldap/Credentials.java
new file mode 100644
index 0000000..ce22b8e
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/Credentials.java
@@ -0,0 +1,41 @@
+/**
+ * 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.ldap;
+
+public final class Credentials {
+
+ private final String user;
+ private final String password;
+
+ private Credentials(String user, String password) {
+ this.user = user;
+ this.password = password;
+ }
+
+ public static Credentials of(String user, String password) {
+ return new Credentials(user, password);
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/LdapTestUtils.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/LdapTestUtils.java b/service/src/test/org/apache/hive/service/auth/ldap/LdapTestUtils.java
new file mode 100644
index 0000000..d4e034f
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/LdapTestUtils.java
@@ -0,0 +1,126 @@
+/**
+ * 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.ldap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.SearchResult;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.mockito.stubbing.OngoingStubbing;
+
+public final class LdapTestUtils {
+
+ private LdapTestUtils() {
+ }
+
+ public static NamingEnumeration<SearchResult> mockEmptyNamingEnumeration() throws NamingException {
+ return mockNamingEnumeration(new SearchResult[0]);
+ }
+
+ public static NamingEnumeration<SearchResult> mockNamingEnumeration(String... dns) throws NamingException {
+ return mockNamingEnumeration(mockSearchResults(dns).toArray(new SearchResult[0]));
+ }
+
+ public static NamingEnumeration<SearchResult> mockNamingEnumeration(SearchResult... searchResults) throws NamingException {
+ NamingEnumeration<SearchResult> ne =
+ (NamingEnumeration<SearchResult>) mock(NamingEnumeration.class);
+ mockHasMoreMethod(ne, searchResults.length);
+ if (searchResults.length > 0) {
+ List<SearchResult> mockedResults = Arrays.asList(searchResults);
+ mockNextMethod(ne, mockedResults);
+ }
+ return ne;
+ }
+
+ public static void mockHasMoreMethod(NamingEnumeration<SearchResult> ne, int length) throws NamingException {
+ OngoingStubbing<Boolean> hasMoreStub = when(ne.hasMore());
+ for (int i = 0; i < length; i++) {
+ hasMoreStub = hasMoreStub.thenReturn(true);
+ }
+ hasMoreStub.thenReturn(false);
+ }
+
+ public static void mockNextMethod(NamingEnumeration<SearchResult> ne, List<SearchResult> searchResults) throws NamingException {
+ OngoingStubbing<SearchResult> nextStub = when(ne.next());
+ for (SearchResult searchResult : searchResults) {
+ nextStub = nextStub.thenReturn(searchResult);
+ }
+ }
+
+ public static List<SearchResult> mockSearchResults(String[] dns) {
+ List<SearchResult> list = new ArrayList<>();
+ for (String dn : dns) {
+ list.add(mockSearchResult(dn, null));
+ }
+ return list;
+ }
+
+ public static SearchResult mockSearchResult(String dn, Attributes attributes) {
+ SearchResult searchResult = mock(SearchResult.class);
+ when(searchResult.getNameInNamespace()).thenReturn(dn);
+ when(searchResult.getAttributes()).thenReturn(attributes);
+ return searchResult;
+ }
+
+ public static Attributes mockEmptyAttributes() throws NamingException {
+ return mockAttributes();
+ }
+
+ public static Attributes mockAttributes(String name, String value) throws NamingException {
+ return mockAttributes(new NameValues(name, value));
+ }
+
+ public static Attributes mockAttributes(String name1, String value1, String name2, String value2) throws NamingException {
+ if (name1.equals(name2)) {
+ return mockAttributes(new NameValues(name1, value1, value2));
+ } else {
+ return mockAttributes(new NameValues(name1, value1), new NameValues(name2, value2));
+ }
+ }
+
+ private static Attributes mockAttributes(NameValues... namedValues) throws NamingException {
+ Attributes attributes = new BasicAttributes();
+ for (NameValues namedValue : namedValues) {
+ Attribute attr = new BasicAttribute(namedValue.name);
+ for (String value : namedValue.values) {
+ attr.add(value);
+ }
+ attributes.put(attr);
+ }
+ return attributes;
+ }
+
+ private static final class NameValues {
+ final String name;
+ final String[] values;
+
+ public NameValues(String name, String... values) {
+ this.name = name;
+ this.values = values;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestChainFilter.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestChainFilter.java b/service/src/test/org/apache/hive/service/auth/ldap/TestChainFilter.java
new file mode 100644
index 0000000..9caa233
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestChainFilter.java
@@ -0,0 +1,103 @@
+/**
+ * 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.ldap;
+
+import java.io.IOException;
+import javax.naming.NamingException;
+import javax.security.sasl.AuthenticationException;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestChainFilter {
+
+ private FilterFactory factory;
+ private HiveConf conf;
+
+ @Mock
+ public Filter filter1;
+
+ @Mock
+ public Filter filter2;
+
+ @Mock
+ public Filter filter3;
+
+ @Mock
+ public FilterFactory factory1;
+
+ @Mock
+ public FilterFactory factory2;
+
+ @Mock
+ public FilterFactory factory3;
+
+ @Mock
+ private DirSearch search;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ factory = new ChainFilterFactory(factory1, factory2, factory3);
+ }
+
+ @Test
+ public void testFactoryAllNull() {
+ assertNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testFactoryAllEmpty() {
+ FilterFactory emptyFactory = new ChainFilterFactory();
+ assertNull(emptyFactory.getInstance(conf));
+ }
+
+ @Test
+ public void testFactory() throws AuthenticationException {
+ when(factory1.getInstance(any(HiveConf.class))).thenReturn(filter1);
+ when(factory2.getInstance(any(HiveConf.class))).thenReturn(filter2);
+ when(factory3.getInstance(any(HiveConf.class))).thenReturn(filter3);
+
+ Filter filter = factory.getInstance(conf);
+
+ filter.apply(search, "User");
+ verify(filter1, times(1)).apply(search, "User");
+ verify(filter2, times(1)).apply(search, "User");
+ verify(filter3, times(1)).apply(search, "User");
+ }
+
+ @Test(expected = AuthenticationException.class)
+ public void testApplyNegative() throws AuthenticationException, NamingException, IOException {
+ doThrow(AuthenticationException.class).when(filter3).apply((DirSearch) anyObject(), anyString());
+
+ when(factory1.getInstance(any(HiveConf.class))).thenReturn(filter1);
+ when(factory3.getInstance(any(HiveConf.class))).thenReturn(filter3);
+
+ Filter filter = factory.getInstance(conf);
+
+ filter.apply(search, "User");
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestCustomQueryFilter.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestCustomQueryFilter.java b/service/src/test/org/apache/hive/service/auth/ldap/TestCustomQueryFilter.java
new file mode 100644
index 0000000..fd4b898
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestCustomQueryFilter.java
@@ -0,0 +1,85 @@
+/**
+ * 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.ldap;
+
+import java.io.IOException;
+import java.util.Arrays;
+import javax.naming.NamingException;
+import javax.security.sasl.AuthenticationException;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestCustomQueryFilter {
+
+ private static final String USER2_DN = "uid=user2,ou=People,dc=example,dc=com";
+ private static final String USER1_DN = "uid=user1,ou=People,dc=example,dc=com";
+ private static final String CUSTOM_QUERY = "(&(objectClass=person)(|(uid=user1)(uid=user2)))";
+
+ private FilterFactory factory;
+ private HiveConf conf;
+
+ @Mock
+ private DirSearch search;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ conf.set("hive.root.logger", "DEBUG,console");
+ factory = new CustomQueryFilterFactory();
+ }
+
+ @Test
+ public void testFactory() {
+ conf.unset(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_CUSTOMLDAPQUERY.varname);
+ assertNull(factory.getInstance(conf));
+
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_CUSTOMLDAPQUERY, CUSTOM_QUERY);
+ assertNotNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testApplyPositive() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_CUSTOMLDAPQUERY, CUSTOM_QUERY);
+
+ when(search.executeCustomQuery(eq(CUSTOM_QUERY))).thenReturn(Arrays.asList(USER1_DN, USER2_DN));
+
+ Filter filter = factory.getInstance(conf);
+ filter.apply(search, "user1");
+ filter.apply(search, "user2");
+ }
+
+
+ @Test(expected = AuthenticationException.class)
+ public void testApplyNegative() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_CUSTOMLDAPQUERY, CUSTOM_QUERY);
+
+ when(search.executeCustomQuery(eq(CUSTOM_QUERY))).thenReturn(Arrays.asList(USER1_DN, USER2_DN));
+
+ Filter filter = factory.getInstance(conf);
+ filter.apply(search, "user3");
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestGroupFilter.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestGroupFilter.java b/service/src/test/org/apache/hive/service/auth/ldap/TestGroupFilter.java
new file mode 100644
index 0000000..0cc2ead
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestGroupFilter.java
@@ -0,0 +1,101 @@
+/**
+ * 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.ldap;
+
+import java.io.IOException;
+import java.util.Arrays;
+import javax.naming.NamingException;
+import javax.security.sasl.AuthenticationException;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestGroupFilter {
+
+ private FilterFactory factory;
+ private HiveConf conf;
+
+ @Mock
+ private DirSearch search;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ conf.set("hive.root.logger", "DEBUG,console");
+ factory = new GroupFilterFactory();
+ }
+
+ @Test
+ public void testFactory() {
+ conf.unset(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER.varname);
+ assertNull(factory.getInstance(conf));
+
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "G1");
+ assertNotNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testApplyPositive() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "HiveUsers");
+
+ when(search.findUserDn(eq("user1")))
+ .thenReturn("cn=user1,ou=People,dc=example,dc=com");
+ when(search.findUserDn(eq("cn=user2,dc=example,dc=com")))
+ .thenReturn("cn=user2,ou=People,dc=example,dc=com");
+ when(search.findUserDn(eq("user3@mydomain.com")))
+ .thenReturn("cn=user3,ou=People,dc=example,dc=com");
+
+ when(search.findGroupsForUser(eq("cn=user1,ou=People,dc=example,dc=com")))
+ .thenReturn(Arrays.asList(
+ "cn=SuperUsers,ou=Groups,dc=example,dc=com",
+ "cn=Office1,ou=Groups,dc=example,dc=com",
+ "cn=HiveUsers,ou=Groups,dc=example,dc=com",
+ "cn=G1,ou=Groups,dc=example,dc=com"));
+ when(search.findGroupsForUser(eq("cn=user2,ou=People,dc=example,dc=com")))
+ .thenReturn(Arrays.asList(
+ "cn=HiveUsers,ou=Groups,dc=example,dc=com"));
+ when(search.findGroupsForUser(eq("cn=user3,ou=People,dc=example,dc=com")))
+ .thenReturn(Arrays.asList(
+ "cn=HiveUsers,ou=Groups,dc=example,dc=com",
+ "cn=G1,ou=Groups,dc=example,dc=com",
+ "cn=G2,ou=Groups,dc=example,dc=com"));
+
+ Filter filter = factory.getInstance(conf);
+ filter.apply(search, "user1");
+ filter.apply(search, "cn=user2,dc=example,dc=com");
+ filter.apply(search, "user3@mydomain.com");
+ }
+
+ @Test(expected = AuthenticationException.class)
+ public void testApplyNegative() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "HiveUsers");
+
+ when(search.findGroupsForUser(eq("user1"))).thenReturn(Arrays.asList("SuperUsers", "Office1", "G1", "G2"));
+
+ Filter filter = factory.getInstance(conf);
+ filter.apply(search, "user1");
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestLdapSearch.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestLdapSearch.java b/service/src/test/org/apache/hive/service/auth/ldap/TestLdapSearch.java
new file mode 100644
index 0000000..499b624
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestLdapSearch.java
@@ -0,0 +1,209 @@
+/**
+ * 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.ldap;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import static org.apache.hive.service.auth.ldap.LdapTestUtils.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestLdapSearch {
+
+ @Mock
+ private DirContext ctx;
+
+ private HiveConf conf;
+ private LdapSearch search;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ }
+
+ @Test
+ public void testClose() throws NamingException {
+ search = new LdapSearch(conf, ctx);
+ search.close();
+ verify(ctx, atLeastOnce()).close();
+ }
+
+ @Test
+ public void testFindUserDnWhenUserDnPositive() throws NamingException {
+ NamingEnumeration<SearchResult> searchResult = mockNamingEnumeration("CN=User1,OU=org1,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class)))
+ .thenReturn(searchResult)
+ .thenThrow(NamingException.class);
+ search = new LdapSearch(conf, ctx);
+ String expected = "CN=User1,OU=org1,DC=foo,DC=bar";
+ String actual = search.findUserDn("CN=User1,OU=org1");
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testFindUserDnWhenUserDnNegativeDuplicates() throws NamingException {
+ NamingEnumeration<SearchResult> searchResult = mockNamingEnumeration(
+ "CN=User1,OU=org1,DC=foo,DC=bar",
+ "CN=User1,OU=org2,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class))).thenReturn(searchResult);
+ search = new LdapSearch(conf, ctx);
+ assertNull(search.findUserDn("CN=User1,DC=foo,DC=bar"));
+ }
+
+ @Test
+ public void testFindUserDnWhenUserDnNegativeNone() throws NamingException {
+ NamingEnumeration<SearchResult> searchResult = mockEmptyNamingEnumeration();
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class))).thenReturn(searchResult);
+ search = new LdapSearch(conf, ctx);
+ assertNull(search.findUserDn("CN=User1,DC=foo,DC=bar"));
+ }
+
+ @Test
+ public void testFindUserDnWhenUserPatternFoundBySecondPattern() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "CN=%s,OU=org1,DC=foo,DC=bar:CN=%s,OU=org2,DC=foo,DC=bar");
+ NamingEnumeration<SearchResult> emptyResult = mockEmptyNamingEnumeration();
+ NamingEnumeration<SearchResult> validResult = mockNamingEnumeration("CN=User1,OU=org2,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class)))
+ .thenReturn(emptyResult)
+ .thenReturn(validResult);
+ search = new LdapSearch(conf, ctx);
+ String expected = "CN=User1,OU=org2,DC=foo,DC=bar";
+ String actual = search.findUserDn("User1");
+ assertEquals(expected, actual);
+ verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class));
+ verify(ctx).search(eq("OU=org2,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class));
+ }
+
+ @Test
+ public void testFindUserDnWhenUserPatternFoundByFirstPattern() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "CN=%s,OU=org1,DC=foo,DC=bar:CN=%s,OU=org2,DC=foo,DC=bar");
+ NamingEnumeration<SearchResult> emptyResult = mockEmptyNamingEnumeration();
+ NamingEnumeration<SearchResult> validResult = mockNamingEnumeration("CN=User1,OU=org2,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class)))
+ .thenReturn(validResult)
+ .thenReturn(emptyResult);
+ search = new LdapSearch(conf, ctx);
+ String expected = "CN=User1,OU=org2,DC=foo,DC=bar";
+ String actual = search.findUserDn("User1");
+ assertEquals(expected, actual);
+ verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class));
+ }
+
+ @Test
+ public void testFindUserDnWhenUserPatternFoundByUniqueIdentifier() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "CN=%s,OU=org1,DC=foo,DC=bar");
+ NamingEnumeration<SearchResult> validResult = mockNamingEnumeration("CN=User1,OU=org1,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class)))
+ .thenReturn(null)
+ .thenReturn(validResult);
+ search = new LdapSearch(conf, ctx);
+ String expected = "CN=User1,OU=org1,DC=foo,DC=bar";
+ String actual = search.findUserDn("User1");
+ assertEquals(expected, actual);
+ verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class));
+ verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("uid=User1"), any(SearchControls.class));
+ }
+
+ @Test
+ public void testFindUserDnWhenUserPatternFoundByUniqueIdentifierNegativeNone() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "CN=%s,OU=org1,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class)))
+ .thenReturn(null)
+ .thenReturn(null);
+ search = new LdapSearch(conf, ctx);
+ assertNull(search.findUserDn("User1"));
+ }
+
+ @Test
+ public void testFindUserDnWhenUserPatternFoundByUniqueIdentifierNegativeMany() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "CN=%s,OU=org1,DC=foo,DC=bar");
+ NamingEnumeration<SearchResult> manyResult = mockNamingEnumeration(
+ "CN=User1,OU=org1,DC=foo,DC=bar",
+ "CN=User12,OU=org1,DC=foo,DC=bar");
+ when(ctx.search(anyString(), anyString(), any(SearchControls.class)))
+ .thenReturn(null)
+ .thenReturn(manyResult);
+ search = new LdapSearch(conf, ctx);
+ assertNull(search.findUserDn("User1"));
+ }
+
+ @Test
+ public void testFindGroupsForUser() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPDNPATTERN,
+ "CN=%s,OU=org1,DC=foo,DC=bar");
+
+ NamingEnumeration<SearchResult> groupsResult = mockNamingEnumeration("CN=Group1,OU=org1,DC=foo,DC=bar");
+ when(ctx.search(eq("OU=org1,DC=foo,DC=bar"), contains("User1"), any(SearchControls.class)))
+ .thenReturn(groupsResult);
+
+ search = new LdapSearch(conf, ctx);
+
+ List<String> expected = Arrays.asList("CN=Group1,OU=org1,DC=foo,DC=bar");
+ List<String> actual = search.findGroupsForUser("CN=User1,OU=org1,DC=foo,DC=bar");
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testExecuteCustomQuery() throws NamingException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN, "dc=example,dc=com");
+
+ NamingEnumeration<SearchResult> customQueryResult = mockNamingEnumeration(
+ mockSearchResult(
+ "uid=group1,ou=Groups,dc=example,dc=com",
+ mockAttributes("member", "uid=user1,ou=People,dc=example,dc=com")),
+ mockSearchResult(
+ "uid=group2,ou=Groups,dc=example,dc=com",
+ mockAttributes("member", "uid=user2,ou=People,dc=example,dc=com"))
+ );
+
+ when(ctx.search(eq("dc=example,dc=com"), anyString(), any(SearchControls.class)))
+ .thenReturn(customQueryResult);
+
+ search = new LdapSearch(conf, ctx);
+
+ List<String> expected = Arrays.asList(
+ "uid=group1,ou=Groups,dc=example,dc=com",
+ "uid=user1,ou=People,dc=example,dc=com",
+ "uid=group2,ou=Groups,dc=example,dc=com",
+ "uid=user2,ou=People,dc=example,dc=com");
+ List<String> actual = search.executeCustomQuery("(&(objectClass=groupOfNames)(|(cn=group1)(cn=group2)))");
+ Collections.sort(expected);
+ Collections.sort(actual);
+ assertEquals(expected, actual);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestLdapUtils.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestLdapUtils.java b/service/src/test/org/apache/hive/service/auth/ldap/TestLdapUtils.java
new file mode 100644
index 0000000..661aff4
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestLdapUtils.java
@@ -0,0 +1,103 @@
+/**
+ * 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.ldap;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestLdapUtils {
+
+ @Test
+ public void testCreateCandidatePrincipalsForUserDn() {
+ HiveConf conf = new HiveConf();
+ String userDn = "cn=user1,ou=CORP,dc=mycompany,dc=com";
+ List<String> expected = Arrays.asList(userDn);
+ List<String> actual = LdapUtils.createCandidatePrincipals(conf, userDn);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testCreateCandidatePrincipalsForUserWithDomain() {
+ HiveConf conf = new HiveConf();
+ String userWithDomain = "user1@mycompany.com";
+ List<String> expected = Arrays.asList(userWithDomain);
+ List<String> actual = LdapUtils.createCandidatePrincipals(conf, userWithDomain);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testCreateCandidatePrincipalsLdapDomain() {
+ HiveConf conf = new HiveConf();
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_DOMAIN, "mycompany.com");
+ List<String> expected = Arrays.asList("user1@mycompany.com");
+ List<String> actual = LdapUtils.createCandidatePrincipals(conf, "user1");
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testCreateCandidatePrincipalsUserPatternsDefaultBaseDn() {
+ HiveConf conf = new HiveConf();
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GUIDKEY, "sAMAccountName");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN, "dc=mycompany,dc=com");
+ List<String> expected = Arrays.asList("sAMAccountName=user1,dc=mycompany,dc=com");
+ List<String> actual = LdapUtils.createCandidatePrincipals(conf, "user1");
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testCreateCandidatePrincipals() {
+ HiveConf conf = new HiveConf();
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN, "dc=mycompany,dc=com");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN,
+ "cn=%s,ou=CORP1,dc=mycompany,dc=com:cn=%s,ou=CORP2,dc=mycompany,dc=com");
+ List<String> expected = Arrays.asList(
+ "cn=user1,ou=CORP1,dc=mycompany,dc=com",
+ "cn=user1,ou=CORP2,dc=mycompany,dc=com");
+ List<String> actual = LdapUtils.createCandidatePrincipals(conf, "user1");
+ Collections.sort(expected);
+ Collections.sort(actual);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testExtractFirstRdn() {
+ String dn = "cn=user1,ou=CORP1,dc=mycompany,dc=com";
+ String expected = "cn=user1";
+ String actual = LdapUtils.extractFirstRdn(dn);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testExtractBaseDn() {
+ String dn = "cn=user1,ou=CORP1,dc=mycompany,dc=com";
+ String expected = "ou=CORP1,dc=mycompany,dc=com";
+ String actual = LdapUtils.extractBaseDn(dn);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testExtractBaseDnNegative() {
+ String dn = "cn=user1";
+ assertNull(LdapUtils.extractBaseDn(dn));
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestQuery.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestQuery.java b/service/src/test/org/apache/hive/service/auth/ldap/TestQuery.java
new file mode 100644
index 0000000..1f4bb1a
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestQuery.java
@@ -0,0 +1,59 @@
+/**
+ * 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.ldap;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestQuery {
+
+ @Test
+ public void testQueryBuilderFilter() {
+ Query q = Query.builder()
+ .filter("test <uid_attr>=<value> query")
+ .map("uid_attr", "uid")
+ .map("value", "Hello!")
+ .build();
+ assertEquals("test uid=Hello! query", q.getFilter());
+ assertEquals(0, q.getControls().getCountLimit());
+ }
+
+ @Test
+ public void testQueryBuilderLimit() {
+ Query q = Query.builder()
+ .filter("<key1>,<key2>")
+ .map("key1", "value1")
+ .map("key2", "value2")
+ .limit(8)
+ .build();
+ assertEquals("value1,value2", q.getFilter());
+ assertEquals(8, q.getControls().getCountLimit());
+ }
+
+ @Test
+ public void testQueryBuilderReturningAttributes() {
+ Query q = Query.builder()
+ .filter("(query)")
+ .returnAttribute("attr1")
+ .returnAttribute("attr2")
+ .build();
+ assertEquals("(query)", q.getFilter());
+ assertArrayEquals(new String[] {"attr1", "attr2"}, q.getControls().getReturningAttributes());
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestQueryFactory.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestQueryFactory.java b/service/src/test/org/apache/hive/service/auth/ldap/TestQueryFactory.java
new file mode 100644
index 0000000..3054e33
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestQueryFactory.java
@@ -0,0 +1,79 @@
+/**
+ * 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.ldap;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestQueryFactory {
+
+ private QueryFactory queries;
+ private HiveConf conf;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GUIDKEY, "guid");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPCLASS_KEY, "superGroups");
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPMEMBERSHIP_KEY, "member");
+ queries = new QueryFactory(conf);
+ }
+
+ @Test
+ public void testFindGroupDnById() {
+ Query q = queries.findGroupDnById("unique_group_id");
+ String expected = "(&(objectClass=superGroups)(guid=unique_group_id))";
+ String actual = q.getFilter();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testFindUserDnByRdn() {
+ Query q = queries.findUserDnByRdn("cn=User1");
+ String expected = "(&(|(objectClass=person)(objectClass=user)(objectClass=inetOrgPerson))(cn=User1))";
+ String actual = q.getFilter();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testFindDnByPattern() {
+ Query q = queries.findDnByPattern("cn=User1");
+ String expected = "(cn=User1)";
+ String actual = q.getFilter();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testFindUserDnByName() {
+ Query q = queries.findUserDnByName("unique_user_id");
+ String expected = "(&(|(objectClass=person)(objectClass=user)(objectClass=inetOrgPerson))(|(uid=unique_user_id)(sAMAccountName=unique_user_id)))";
+ String actual = q.getFilter();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testFindGroupsForUser() {
+ Query q = queries.findGroupsForUser("user_name", "user_Dn");
+ String expected = "(&(objectClass=superGroups)(|(member=user_Dn)(member=user_name)))";
+ String actual = q.getFilter();
+ assertEquals(expected, actual);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestSearchResultHandler.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestSearchResultHandler.java b/service/src/test/org/apache/hive/service/auth/ldap/TestSearchResultHandler.java
new file mode 100644
index 0000000..2615680
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestSearchResultHandler.java
@@ -0,0 +1,222 @@
+/**
+ * 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.ldap;
+
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.SearchResult;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import static org.apache.hive.service.auth.ldap.LdapTestUtils.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestSearchResultHandler {
+
+ SearchResultHandler handler;
+
+ @Test
+ public void testHandle() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addSearchResultWithDns("1")
+ .addSearchResultWithDns("2", "3");
+ handler = new SearchResultHandler(resultCollection);
+ List<String> expected = Arrays.asList("1", "2");
+ final List<String> actual = new ArrayList<>();
+ handler.handle(new SearchResultHandler.RecordProcessor() {
+ @Override
+ public boolean process(SearchResult record) throws NamingException {
+ actual.add(record.getNameInNamespace());
+ return actual.size() < 2;
+ }
+ });
+ assertEquals(expected, actual);
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testGetAllLdapNamesNoRecords() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addEmptySearchResult();
+ handler = new SearchResultHandler(resultCollection);
+ List<String> actual = handler.getAllLdapNames();
+ assertEquals("Resultset size", 0, actual.size());
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testGetAllLdapNamesWithExceptionInNamingEnumerationClose() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addSearchResultWithDns("1")
+ .addSearchResultWithDns("2");
+ doThrow(NamingException.class).when(resultCollection.iterator().next()).close();
+ handler = new SearchResultHandler(resultCollection);
+ List<String> actual = handler.getAllLdapNames();
+ assertEquals("Resultset size", 2, actual.size());
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testGetAllLdapNames() throws NamingException {
+ String objectDn1 = "cn=a1,dc=b,dc=c";
+ String objectDn2 = "cn=a2,dc=b,dc=c";
+ String objectDn3 = "cn=a3,dc=b,dc=c";
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addSearchResultWithDns(objectDn1)
+ .addSearchResultWithDns(objectDn2, objectDn3);
+ handler = new SearchResultHandler(resultCollection);
+ List<String> expected = Arrays.asList(objectDn1, objectDn2, objectDn3);
+ Collections.sort(expected);
+ List<String> actual = handler.getAllLdapNames();
+ Collections.sort(actual);
+ assertEquals(expected, actual);
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testGetAllLdapNamesAndAttributes() throws NamingException {
+ SearchResult searchResult1 = mockSearchResult("cn=a1,dc=b,dc=c",
+ mockAttributes("attr1", "attr1value1"));
+ SearchResult searchResult2 = mockSearchResult("cn=a2,dc=b,dc=c",
+ mockAttributes("attr1", "attr1value2", "attr2", "attr2value1"));
+ SearchResult searchResult3 = mockSearchResult("cn=a3,dc=b,dc=c",
+ mockAttributes("attr1", "attr1value3", "attr1", "attr1value4"));
+ SearchResult searchResult4 = mockSearchResult("cn=a4,dc=b,dc=c",
+ mockEmptyAttributes());
+
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addSearchResults(searchResult1)
+ .addSearchResults(searchResult2, searchResult3)
+ .addSearchResults(searchResult4);
+
+ handler = new SearchResultHandler(resultCollection);
+ List<String> expected = Arrays.asList(
+ "cn=a1,dc=b,dc=c", "attr1value1",
+ "cn=a2,dc=b,dc=c", "attr1value2", "attr2value1",
+ "cn=a3,dc=b,dc=c", "attr1value3", "attr1value4",
+ "cn=a4,dc=b,dc=c");
+ Collections.sort(expected);
+ List<String> actual = handler.getAllLdapNamesAndAttributes();
+ Collections.sort(actual);
+ assertEquals(expected, actual);
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testHasSingleResultNoRecords() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addEmptySearchResult();
+ handler = new SearchResultHandler(resultCollection);
+ assertFalse(handler.hasSingleResult());
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testHasSingleResult() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addSearchResultWithDns("1");
+ handler = new SearchResultHandler(resultCollection);
+ assertTrue(handler.hasSingleResult());
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test
+ public void testHasSingleResultManyRecords() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addSearchResultWithDns("1")
+ .addSearchResultWithDns("2");
+ handler = new SearchResultHandler(resultCollection);
+ assertFalse(handler.hasSingleResult());
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ @Test(expected = NamingException.class)
+ public void testGetSingleLdapNameNoRecords() throws NamingException {
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addEmptySearchResult();
+ handler = new SearchResultHandler(resultCollection);
+ try {
+ handler.getSingleLdapName();
+ } finally {
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+ }
+
+ @Test
+ public void testGetSingleLdapName() throws NamingException {
+ String objectDn = "cn=a,dc=b,dc=c";
+ MockResultCollection resultCollection = MockResultCollection.create()
+ .addEmptySearchResult()
+ .addSearchResultWithDns(objectDn);
+
+ handler = new SearchResultHandler(resultCollection);
+ String expected = objectDn;
+ String actual = handler.getSingleLdapName();
+ assertEquals(expected, actual);
+ assertAllNamingEnumerationsClosed(resultCollection);
+ }
+
+ private void assertAllNamingEnumerationsClosed(MockResultCollection resultCollection) throws NamingException {
+ for (NamingEnumeration<SearchResult> namingEnumeration : resultCollection) {
+ verify(namingEnumeration, atLeastOnce()).close();
+ }
+ }
+
+ private static final class MockResultCollection extends AbstractCollection<NamingEnumeration<SearchResult>> {
+
+ List<NamingEnumeration<SearchResult>> results = new ArrayList<>();
+
+ static MockResultCollection create() {
+ return new MockResultCollection();
+ }
+
+ MockResultCollection addSearchResultWithDns(String... dns) throws NamingException {
+ results.add(mockNamingEnumeration(dns));
+ return this;
+ }
+
+ MockResultCollection addSearchResults(SearchResult... dns) throws NamingException {
+ results.add(mockNamingEnumeration(dns));
+ return this;
+ }
+
+ MockResultCollection addEmptySearchResult() throws NamingException {
+ addSearchResults();
+ return this;
+ }
+
+ @Override
+ public Iterator<NamingEnumeration<SearchResult>> iterator() {
+ return results.iterator();
+ }
+
+ @Override
+ public int size() {
+ return results.size();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestUserFilter.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestUserFilter.java b/service/src/test/org/apache/hive/service/auth/ldap/TestUserFilter.java
new file mode 100644
index 0000000..f941c9c
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestUserFilter.java
@@ -0,0 +1,75 @@
+/**
+ * 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.ldap;
+
+import java.io.IOException;
+import javax.naming.NamingException;
+import javax.security.sasl.AuthenticationException;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestUserFilter {
+
+ private FilterFactory factory;
+ private HiveConf conf;
+
+ @Mock
+ private DirSearch search;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ factory = new UserFilterFactory();
+ }
+
+ @Test
+ public void testFactory() {
+ conf.unset(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER.varname);
+ assertNull(factory.getInstance(conf));
+
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1");
+ assertNotNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testApplyPositive() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1,User2,uSeR3");
+
+ Filter filter = factory.getInstance(conf);
+ filter.apply(search, "User1");
+ filter.apply(search, "uid=user2,ou=People,dc=example,dc=com");
+ filter.apply(search, "User3@mydomain.com");
+ }
+
+ @Test(expected = AuthenticationException.class)
+ public void testApplyNegative() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1,User2");
+
+ Filter filter = factory.getInstance(conf);
+ filter.apply(search, "User3");
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/990927e3/service/src/test/org/apache/hive/service/auth/ldap/TestUserSearchFilter.java
----------------------------------------------------------------------
diff --git a/service/src/test/org/apache/hive/service/auth/ldap/TestUserSearchFilter.java b/service/src/test/org/apache/hive/service/auth/ldap/TestUserSearchFilter.java
new file mode 100644
index 0000000..0f2b509
--- /dev/null
+++ b/service/src/test/org/apache/hive/service/auth/ldap/TestUserSearchFilter.java
@@ -0,0 +1,94 @@
+/**
+ * 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.ldap;
+
+import java.io.IOException;
+import javax.naming.NamingException;
+import javax.security.sasl.AuthenticationException;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestUserSearchFilter {
+
+ private FilterFactory factory;
+ private HiveConf conf;
+
+ @Mock
+ private DirSearch search;
+
+ @Before
+ public void setup() {
+ conf = new HiveConf();
+ factory = new UserSearchFilterFactory();
+ }
+
+ @Test
+ public void testFactoryWhenNoGroupOrUserFilters() {
+ assertNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testFactoryWhenGroupFilter() {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPFILTER, "Grp1,Grp2");
+ assertNotNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testFactoryWhenUserFilter() {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1,User2");
+ assertNotNull(factory.getInstance(conf));
+ }
+
+ @Test
+ public void testApplyPositive() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1");
+ Filter filter = factory.getInstance(conf);
+
+ when(search.findUserDn(anyString())).thenReturn("cn=User1,ou=People,dc=example,dc=com");
+
+ filter.apply(search, "User1");
+ }
+
+ @Test(expected = AuthenticationException.class)
+ public void testApplyWhenNamingException() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1");
+ Filter filter = factory.getInstance(conf);
+
+ when(search.findUserDn(anyString())).thenThrow(NamingException.class);
+
+ filter.apply(search, "User3");
+ }
+
+ @Test(expected = AuthenticationException.class)
+ public void testApplyWhenNotFound() throws AuthenticationException, NamingException, IOException {
+ conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERFILTER, "User1");
+ Filter filter = factory.getInstance(conf);
+
+ when(search.findUserDn(anyString())).thenReturn(null);
+
+ filter.apply(search, "User3");
+ }
+}