HADOOP-12001. Fixed LdapGroupsMapping to include configurable Posix UID and GID attributes during the search. Contributed by Patrick White.

(cherry picked from commit 722aa1db1f)
This commit is contained in:
Vinod Kumar Vavilapalli 2015-06-15 14:22:34 -07:00
parent ea9a9b3d7e
commit 58d3a9aaf6
4 changed files with 60 additions and 15 deletions

View File

@ -415,6 +415,9 @@ Release 2.7.1 - UNRELEASED
HADOOP-12078. The default retry policy does not handle RetriableException HADOOP-12078. The default retry policy does not handle RetriableException
correctly. (Arpit Agarwal) correctly. (Arpit Agarwal)
HADOOP-12001. Fixed LdapGroupsMapping to include configurable Posix UID and
GID attributes during the search. (Patrick White via vinodkv)
Release 2.7.0 - 2015-04-20 Release 2.7.0 - 2015-04-20
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -149,11 +149,18 @@ public class LdapGroupsMapping
public static final String GROUP_NAME_ATTR_KEY = LDAP_CONFIG_PREFIX + ".search.attr.group.name"; public static final String GROUP_NAME_ATTR_KEY = LDAP_CONFIG_PREFIX + ".search.attr.group.name";
public static final String GROUP_NAME_ATTR_DEFAULT = "cn"; public static final String GROUP_NAME_ATTR_DEFAULT = "cn";
/*
* LDAP attribute names to use when doing posix-like lookups
*/
public static final String POSIX_UID_ATTR_KEY = LDAP_CONFIG_PREFIX + ".posix.attr.uid.name";
public static final String POSIX_UID_ATTR_DEFAULT = "uidNumber";
public static final String POSIX_GID_ATTR_KEY = LDAP_CONFIG_PREFIX + ".posix.attr.gid.name";
public static final String POSIX_GID_ATTR_DEFAULT = "gidNumber";
/* /*
* Posix attributes * Posix attributes
*/ */
public static final String POSIX_UIDNUMBER = "uidNumber";
public static final String POSIX_GIDNUMBER = "gidNumber";
public static final String POSIX_GROUP = "posixGroup"; public static final String POSIX_GROUP = "posixGroup";
public static final String POSIX_ACCOUNT = "posixAccount"; public static final String POSIX_ACCOUNT = "posixAccount";
@ -186,6 +193,8 @@ public class LdapGroupsMapping
private String userSearchFilter; private String userSearchFilter;
private String groupMemberAttr; private String groupMemberAttr;
private String groupNameAttr; private String groupNameAttr;
private String posixUidAttr;
private String posixGidAttr;
private boolean isPosix; private boolean isPosix;
public static int RECONNECT_RETRY_COUNT = 3; public static int RECONNECT_RETRY_COUNT = 3;
@ -256,8 +265,8 @@ public class LdapGroupsMapping
if (isPosix) { if (isPosix) {
String gidNumber = null; String gidNumber = null;
String uidNumber = null; String uidNumber = null;
Attribute gidAttribute = result.getAttributes().get(POSIX_GIDNUMBER); Attribute gidAttribute = result.getAttributes().get(posixGidAttr);
Attribute uidAttribute = result.getAttributes().get(POSIX_UIDNUMBER); Attribute uidAttribute = result.getAttributes().get(posixUidAttr);
if (gidAttribute != null) { if (gidAttribute != null) {
gidNumber = gidAttribute.get().toString(); gidNumber = gidAttribute.get().toString();
} }
@ -267,7 +276,7 @@ public class LdapGroupsMapping
if (uidNumber != null && gidNumber != null) { if (uidNumber != null && gidNumber != null) {
groupResults = groupResults =
ctx.search(baseDN, ctx.search(baseDN,
"(&"+ groupSearchFilter + "(|(" + POSIX_GIDNUMBER + "={0})" + "(&"+ groupSearchFilter + "(|(" + posixGidAttr + "={0})" +
"(" + groupMemberAttr + "={1})))", "(" + groupMemberAttr + "={1})))",
new Object[] { gidNumber, uidNumber }, new Object[] { gidNumber, uidNumber },
SEARCH_CONTROLS); SEARCH_CONTROLS);
@ -374,11 +383,17 @@ public class LdapGroupsMapping
conf.get(GROUP_MEMBERSHIP_ATTR_KEY, GROUP_MEMBERSHIP_ATTR_DEFAULT); conf.get(GROUP_MEMBERSHIP_ATTR_KEY, GROUP_MEMBERSHIP_ATTR_DEFAULT);
groupNameAttr = groupNameAttr =
conf.get(GROUP_NAME_ATTR_KEY, GROUP_NAME_ATTR_DEFAULT); conf.get(GROUP_NAME_ATTR_KEY, GROUP_NAME_ATTR_DEFAULT);
posixUidAttr =
conf.get(POSIX_UID_ATTR_KEY, POSIX_UID_ATTR_DEFAULT);
posixGidAttr =
conf.get(POSIX_GID_ATTR_KEY, POSIX_GID_ATTR_DEFAULT);
int dirSearchTimeout = conf.getInt(DIRECTORY_SEARCH_TIMEOUT, DIRECTORY_SEARCH_TIMEOUT_DEFAULT); int dirSearchTimeout = conf.getInt(DIRECTORY_SEARCH_TIMEOUT, DIRECTORY_SEARCH_TIMEOUT_DEFAULT);
SEARCH_CONTROLS.setTimeLimit(dirSearchTimeout); SEARCH_CONTROLS.setTimeLimit(dirSearchTimeout);
// Limit the attributes returned to only those required to speed up the search. See HADOOP-10626 for more details. // Limit the attributes returned to only those required to speed up the search.
SEARCH_CONTROLS.setReturningAttributes(new String[] {groupNameAttr}); // See HADOOP-10626 and HADOOP-12001 for more details.
SEARCH_CONTROLS.setReturningAttributes(
new String[] {groupNameAttr, posixUidAttr, posixGidAttr});
this.conf = conf; this.conf = conf;
} }

View File

@ -330,6 +330,24 @@ for ldap providers in the same way as above does.
</description> </description>
</property> </property>
<property>
<name>hadoop.security.group.mapping.ldap.posix.attr.uid.name</name>
<value>uidNumber</value>
<description>
The attribute of posixAccount to use when groups for membership.
Mostly useful for schemas wherein groups have memberUids that use an
attribute other than uidNumber.
</description>
</property>
<property>
<name>hadoop.security.group.mapping.ldap.posix.attr.gid.name</name>
<value>gidNumber</value>
<description>
The attribute of posixAccount indicating the group id.
</description>
</property>
<property> <property>
<name>hadoop.security.group.mapping.ldap.directory.search.timeout</name> <name>hadoop.security.group.mapping.ldap.directory.search.timeout</name>
<value>10000</value> <value>10000</value>

View File

@ -52,14 +52,17 @@ public class TestLdapGroupsMappingWithPosixGroup
SearchResult mockUserResult = mock(SearchResult.class); SearchResult mockUserResult = mock(SearchResult.class);
when(mockUserNamingEnum.nextElement()).thenReturn(mockUserResult); when(mockUserNamingEnum.nextElement()).thenReturn(mockUserResult);
Attribute mockUidNumberAttr = mock(Attribute.class);
Attribute mockGidNumberAttr = mock(Attribute.class);
Attribute mockUidAttr = mock(Attribute.class); Attribute mockUidAttr = mock(Attribute.class);
Attribute mockGidAttr = mock(Attribute.class);
Attributes mockAttrs = mock(Attributes.class); Attributes mockAttrs = mock(Attributes.class);
when(mockUidAttr.get()).thenReturn("700"); when(mockUidAttr.get()).thenReturn("some_user");
when(mockGidAttr.get()).thenReturn("600"); when(mockUidNumberAttr.get()).thenReturn("700");
when(mockAttrs.get(eq("uidNumber"))).thenReturn(mockUidAttr); when(mockGidNumberAttr.get()).thenReturn("600");
when(mockAttrs.get(eq("gidNumber"))).thenReturn(mockGidAttr); when(mockAttrs.get(eq("uid"))).thenReturn(mockUidAttr);
when(mockAttrs.get(eq("uidNumber"))).thenReturn(mockUidNumberAttr);
when(mockAttrs.get(eq("gidNumber"))).thenReturn(mockGidNumberAttr);
when(mockUserResult.getAttributes()).thenReturn(mockAttrs); when(mockUserResult.getAttributes()).thenReturn(mockAttrs);
} }
@ -85,6 +88,8 @@ public class TestLdapGroupsMappingWithPosixGroup
conf.set(LdapGroupsMapping.USER_SEARCH_FILTER_KEY, conf.set(LdapGroupsMapping.USER_SEARCH_FILTER_KEY,
"(objectClass=posixAccount)"); "(objectClass=posixAccount)");
conf.set(LdapGroupsMapping.GROUP_MEMBERSHIP_ATTR_KEY, "memberUid"); conf.set(LdapGroupsMapping.GROUP_MEMBERSHIP_ATTR_KEY, "memberUid");
conf.set(LdapGroupsMapping.POSIX_UID_ATTR_KEY, "uidNumber");
conf.set(LdapGroupsMapping.POSIX_GID_ATTR_KEY, "gidNumber");
conf.set(LdapGroupsMapping.GROUP_NAME_ATTR_KEY, "cn"); conf.set(LdapGroupsMapping.GROUP_NAME_ATTR_KEY, "cn");
mappingSpy.setConf(conf); mappingSpy.setConf(conf);
@ -94,6 +99,10 @@ public class TestLdapGroupsMappingWithPosixGroup
Assert.assertEquals(expectedGroups, groups); Assert.assertEquals(expectedGroups, groups);
mappingSpy.getConf().set(LdapGroupsMapping.POSIX_UID_ATTR_KEY, "uid");
Assert.assertEquals(expectedGroups, groups);
// We should have searched for a user, and then two groups // We should have searched for a user, and then two groups
verify(mockContext, times(searchTimes)).search(anyString(), verify(mockContext, times(searchTimes)).search(anyString(),
anyString(), anyString(),