You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ol...@apache.org on 2016/03/31 19:12:48 UTC
ambari git commit: AMBARI-15383. Cleanup Ldap Sync Process (oleewere)
Repository: ambari
Updated Branches:
refs/heads/trunk 6f61de093 -> a6f0fbfb4
AMBARI-15383. Cleanup Ldap Sync Process (oleewere)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/a6f0fbfb
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a6f0fbfb
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a6f0fbfb
Branch: refs/heads/trunk
Commit: a6f0fbfb48e27e0199ade5eb4d9cfdfb7d5807c5
Parents: 6f61de0
Author: oleewere <ol...@gmail.com>
Authored: Thu Mar 31 19:10:58 2016 +0200
Committer: oleewere <ol...@gmail.com>
Committed: Thu Mar 31 19:10:58 2016 +0200
----------------------------------------------------------------------
.../security/authorization/AmbariLdapUtils.java | 32 ++++
.../server/security/authorization/Users.java | 7 +-
.../security/ldap/AmbariLdapDataPopulator.java | 73 ++++++---
.../server/security/AmbariLdapUtilsTest.java | 64 ++++++++
.../ldap/AmbariLdapDataPopulatorTest.java | 156 +++++++++++++++++--
5 files changed, 300 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6f0fbfb/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapUtils.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapUtils.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapUtils.java
index ffebd45..6d20de3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapUtils.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapUtils.java
@@ -18,6 +18,14 @@
package org.apache.ambari.server.security.authorization;
+import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.ldap.core.DirContextAdapter;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.security.ldap.LdapUtils;
+
+import javax.naming.Name;
import java.util.regex.Pattern;
/**
@@ -25,6 +33,8 @@ import java.util.regex.Pattern;
*/
public class AmbariLdapUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(AmbariLdapUtils.class);
+
/**
* Regexp to verify if user login name beside user contains domain information as well (User principal name format).
*/
@@ -40,4 +50,26 @@ public class AmbariLdapUtils {
}
+ /**
+ * Determine that the full DN of an LDAP object is in/out of the base DN scope.
+ * @param adapter used for get the full dn from the ldap query response
+ * @param baseDn
+ * @return
+ */
+ public static boolean isLdapObjectOutOfScopeFromBaseDn(DirContextAdapter adapter, String baseDn) {
+ boolean isOutOfScope = true;
+ try {
+ Name dn = adapter.getDn();
+ Preconditions.checkArgument(dn != null, "DN cannot be null in LDAP response object");
+
+ DistinguishedName full = LdapUtils.getFullDn((DistinguishedName) dn, adapter);
+ DistinguishedName base = new DistinguishedName(baseDn);
+ if (full.startsWith(base)) {
+ isOutOfScope = false;
+ }
+ } catch (Exception e) {
+ LOG.error(e.getMessage());
+ }
+ return isOutOfScope;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6f0fbfb/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
index c2bc22f..d80edf3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
@@ -360,7 +360,12 @@ public class Users {
} else {
final Set<User> users = new HashSet<User>();
for (MemberEntity memberEntity: groupEntity.getMemberEntities()) {
- users.add(new User(memberEntity.getUser()));
+ if (memberEntity.getUser() != null) {
+ users.add(new User(memberEntity.getUser()));
+ } else {
+ LOG.error("Wrong state, not found user for member '{}' (group: '{}')",
+ memberEntity.getMemberId(), memberEntity.getGroup().getGroupName());
+ }
}
return users;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6f0fbfb/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java b/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
index 75df9cc..9a66456 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
@@ -25,19 +25,22 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.regex.Pattern;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
+import com.google.common.collect.Lists;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.security.authorization.AmbariLdapUtils;
import org.apache.ambari.server.security.authorization.Group;
import org.apache.ambari.server.security.authorization.LdapServerProperties;
import org.apache.ambari.server.security.authorization.User;
import org.apache.ambari.server.security.authorization.Users;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import org.springframework.ldap.control.PagedResultsDirContextProcessor;
@@ -62,7 +65,7 @@ public class AmbariLdapDataPopulator {
/**
* Log.
*/
- private static final Log LOG = LogFactory.getLog(AmbariLdapDataPopulator.class);
+ private static final Logger LOG = LoggerFactory.getLogger(AmbariLdapDataPopulator.class);
/**
* Ambari configuration.
@@ -84,11 +87,19 @@ public class AmbariLdapDataPopulator {
*/
private LdapTemplate ldapTemplate;
+ /**
+ * List for organizationUnits from the base DN
+ */
+ private List<String> baseOrganizationUnits = Lists.newArrayList();
+
// Constants
private static final String UID_ATTRIBUTE = "uid";
private static final String OBJECT_CLASS_ATTRIBUTE = "objectClass";
private static final int USERS_PAGE_SIZE = 500;
+ // REGEXP to check member attribute starts with "cn=" or "uid=" - case insensitive
+ private static final String IS_MEMBER_DN_REGEXP = "^(?i)(%s|%s)=.*$";
+
/**
* Construct an AmbariLdapDataPopulator.
*
@@ -169,7 +180,7 @@ public class AmbariLdapDataPopulator {
* @throws AmbariException if synchronization failed for any reason
*/
public LdapBatchDto synchronizeAllLdapGroups(LdapBatchDto batchInfo) throws AmbariException {
-
+ LOG.trace("Synchronize All LDAP groups...");
Set<LdapGroupDto> externalLdapGroupInfo = getExternalLdapGroupInfo();
final Map<String, Group> internalGroupsMap = getInternalGroups();
@@ -178,7 +189,7 @@ public class AmbariLdapDataPopulator {
for (LdapGroupDto groupDto : externalLdapGroupInfo) {
String groupName = groupDto.getGroupName();
addLdapGroup(batchInfo, internalGroupsMap, groupName);
- refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null);
+ refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null, false);
}
for (Entry<String, Group> internalGroup : internalGroupsMap.entrySet()) {
if (internalGroup.getValue().isLdapGroup()) {
@@ -195,7 +206,7 @@ public class AmbariLdapDataPopulator {
* @throws AmbariException if synchronization failed for any reason
*/
public LdapBatchDto synchronizeAllLdapUsers(LdapBatchDto batchInfo) throws AmbariException {
-
+ LOG.trace("Synchronize All LDAP users...");
Set<LdapUserDto> externalLdapUserInfo = getExternalLdapUserInfo();
Map<String, User> internalUsersMap = getInternalUsers();
@@ -205,6 +216,7 @@ public class AmbariLdapDataPopulator {
final User user = internalUsersMap.get(userName);
if (user != null && !user.isLdapUser()) {
batchInfo.getUsersToBecomeLdap().add(userName);
+ LOG.trace("Convert user '{}' to LDAP user.", userName);
}
internalUsersMap.remove(userName);
} else {
@@ -227,7 +239,7 @@ public class AmbariLdapDataPopulator {
* @throws AmbariException if synchronization failed for any reason
*/
public LdapBatchDto synchronizeLdapGroups(Set<String> groups, LdapBatchDto batchInfo) throws AmbariException {
-
+ LOG.trace("Synchronize LDAP groups...");
final Set<LdapGroupDto> specifiedGroups = new HashSet<LdapGroupDto>();
for (String group : groups) {
Set<LdapGroupDto> groupDtos = getLdapGroups(group);
@@ -244,7 +256,7 @@ public class AmbariLdapDataPopulator {
for (LdapGroupDto groupDto : specifiedGroups) {
String groupName = groupDto.getGroupName();
addLdapGroup(batchInfo, internalGroupsMap, groupName);
- refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null);
+ refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null, true);
}
return batchInfo;
@@ -257,7 +269,7 @@ public class AmbariLdapDataPopulator {
* @throws AmbariException if synchronization failed for any reason
*/
public LdapBatchDto synchronizeLdapUsers(Set<String> users, LdapBatchDto batchInfo) throws AmbariException {
-
+ LOG.trace("Synchronize LDAP users...");
final Set<LdapUserDto> specifiedUsers = new HashSet<LdapUserDto>();
for (String user : users) {
@@ -292,6 +304,7 @@ public class AmbariLdapDataPopulator {
* @throws AmbariException if synchronization failed for any reason
*/
public LdapBatchDto synchronizeExistingLdapGroups(LdapBatchDto batchInfo) throws AmbariException {
+ LOG.trace("Synchronize Existing LDAP groups...");
final Map<String, Group> internalGroupsMap = getInternalGroups();
final Map<String, User> internalUsersMap = getInternalUsers();
@@ -304,7 +317,7 @@ public class AmbariLdapDataPopulator {
batchInfo.getGroupsToBeRemoved().add(group.getGroupName());
} else {
LdapGroupDto groupDto = groupDtos.iterator().next();
- refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null);
+ refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null, true);
}
}
}
@@ -318,6 +331,7 @@ public class AmbariLdapDataPopulator {
* @throws AmbariException if synchronization failed for any reason
*/
public LdapBatchDto synchronizeExistingLdapUsers(LdapBatchDto batchInfo) throws AmbariException {
+ LOG.trace("Synchronize Existing LDAP users...");
final Map<String, User> internalUsersMap = getInternalUsers();
for (User user : internalUsersMap.values()) {
@@ -339,10 +353,11 @@ public class AmbariLdapDataPopulator {
* @param group ldap group
* @param internalUsers map of internal users
* @param groupMemberAttributes set of group member attributes that have already been refreshed
+ * @param recursive if disabled, it won't refresh members recursively (its not needed in case of all groups are processed)
* @throws AmbariException if group refresh failed
*/
protected void refreshGroupMembers(LdapBatchDto batchInfo, LdapGroupDto group, Map<String, User> internalUsers,
- Map<String, Group> internalGroupsMap, Set<String> groupMemberAttributes)
+ Map<String, Group> internalGroupsMap, Set<String> groupMemberAttributes, boolean recursive)
throws AmbariException {
Set<String> externalMembers = new HashSet<String>();
@@ -356,13 +371,13 @@ public class AmbariLdapDataPopulator {
externalMembers.add(groupMember.getUserName());
} else {
// if we haven't already processed this group
- if (!groupMemberAttributes.contains(memberAttributeValue)) {
+ if (recursive && !groupMemberAttributes.contains(memberAttributeValue)) {
// if the member is another group then add all of its members
LdapGroupDto subGroup = getLdapGroupByMemberAttr(memberAttributeValue);
if (subGroup != null) {
groupMemberAttributes.add(memberAttributeValue);
addLdapGroup(batchInfo, internalGroupsMap, subGroup.getGroupName());
- refreshGroupMembers(batchInfo, subGroup, internalUsers, internalGroupsMap, groupMemberAttributes);
+ refreshGroupMembers(batchInfo, subGroup, internalUsers, internalGroupsMap, groupMemberAttributes, true);
}
}
}
@@ -434,9 +449,11 @@ public class AmbariLdapDataPopulator {
protected LdapUserDto getLdapUserByMemberAttr(String memberAttributeValue) {
Set<LdapUserDto> filteredLdapUsers = new HashSet<LdapUserDto>();
if (memberAttributeValue!= null && isMemberAttributeBaseDn(memberAttributeValue)) {
+ LOG.trace("Member can be used as baseDn: {}", memberAttributeValue);
Filter filter = new EqualsFilter(OBJECT_CLASS_ATTRIBUTE, ldapServerProperties.getUserObjectClass());
filteredLdapUsers = getFilteredLdapUsers(memberAttributeValue, filter);
} else {
+ LOG.trace("Member cannot be used as baseDn: {}", memberAttributeValue);
Filter filter = new AndFilter()
.and(new EqualsFilter(OBJECT_CLASS_ATTRIBUTE, ldapServerProperties.getUserObjectClass()))
.and(new EqualsFilter(ldapServerProperties.getUsernameAttribute(), memberAttributeValue));
@@ -455,9 +472,11 @@ public class AmbariLdapDataPopulator {
protected LdapGroupDto getLdapGroupByMemberAttr(String memberAttributeValue) {
Set<LdapGroupDto> filteredLdapGroups = new HashSet<LdapGroupDto>();
if (memberAttributeValue != null && isMemberAttributeBaseDn(memberAttributeValue)) {
+ LOG.trace("Member can be used as baseDn: {}", memberAttributeValue);
Filter filter = new EqualsFilter(OBJECT_CLASS_ATTRIBUTE, ldapServerProperties.getGroupObjectClass());
filteredLdapGroups = getFilteredLdapGroups(memberAttributeValue, filter);
} else {
+ LOG.trace("Member cannot be used as baseDn: {}", memberAttributeValue);
filteredLdapGroups = getFilteredLdapGroups(ldapServerProperties.getBaseDN(),
new EqualsFilter(OBJECT_CLASS_ATTRIBUTE, ldapServerProperties.getGroupObjectClass()),
getMemberFilter(memberAttributeValue));
@@ -482,11 +501,12 @@ public class AmbariLdapDataPopulator {
// Utility methods
- private void addLdapGroup(LdapBatchDto batchInfo, Map<String, Group> internalGroupsMap, String groupName) {
+ protected void addLdapGroup(LdapBatchDto batchInfo, Map<String, Group> internalGroupsMap, String groupName) {
if (internalGroupsMap.containsKey(groupName)) {
final Group group = internalGroupsMap.get(groupName);
if (!group.isLdapGroup()) {
batchInfo.getGroupsToBecomeLdap().add(groupName);
+ LOG.trace("Convert group '{}' to LDAP group.", groupName);
}
internalGroupsMap.remove(groupName);
batchInfo.getGroupsProcessedInternal().add(groupName);
@@ -500,9 +520,10 @@ public class AmbariLdapDataPopulator {
/**
* Determines that the member attribute can be used as a 'dn'
*/
- private boolean isMemberAttributeBaseDn(String memberAttributeValue) {
- return memberAttributeValue.startsWith(ldapServerProperties.getUsernameAttribute() + "=")
- || memberAttributeValue.startsWith(ldapServerProperties.getGroupNamingAttr() + "=");
+ protected boolean isMemberAttributeBaseDn(String memberAttributeValue) {
+ Pattern pattern = Pattern.compile(String.format(IS_MEMBER_DN_REGEXP,
+ ldapServerProperties.getUsernameAttribute(), ldapServerProperties.getGroupNamingAttr()));
+ return pattern.matcher(memberAttributeValue).find();
}
/**
@@ -535,7 +556,9 @@ public class AmbariLdapDataPopulator {
private Set<LdapGroupDto> getFilteredLdapGroups(String baseDn, Filter filter) {
final Set<LdapGroupDto> groups = new HashSet<LdapGroupDto>();
final LdapTemplate ldapTemplate = loadLdapTemplate();
- ldapTemplate.search(baseDn, filter.encode(), new LdapGroupContextMapper(groups, ldapServerProperties));
+ LOG.trace("LDAP Group Query - Base DN: '{}' ; Filter: '{}'", baseDn, filter.encode());
+ ldapTemplate.search(baseDn, filter.encode(),
+ new LdapGroupContextMapper(groups, ldapServerProperties));
return groups;
}
@@ -572,6 +595,7 @@ public class AmbariLdapDataPopulator {
List dtos = configuration.getLdapServerProperties().isPaginationEnabled() ?
ldapTemplate.search(baseDn, encodedFilter, searchControls, ldapUserContextMapper, processor) :
ldapTemplate.search(baseDn, encodedFilter, searchControls, ldapUserContextMapper);
+ LOG.trace("LDAP User Query - Base DN: '{}' ; Filter: '{}'", baseDn, encodedFilter);
for (Object dto : dtos) {
if (dto != null) {
users.add((LdapUserDto)dto);
@@ -604,6 +628,7 @@ public class AmbariLdapDataPopulator {
protected Map<String, User> getInternalUsers() {
final List<User> internalUsers = users.getAllUsers();
final Map<String, User> internalUsersMap = new HashMap<String, User>();
+ LOG.trace("Get all users from Ambari Server.");
for (User user : internalUsers) {
internalUsersMap.put(user.getUserName(), user);
}
@@ -716,6 +741,11 @@ public class AmbariLdapDataPopulator {
public Object mapFromContext(Object ctx) {
final DirContextAdapter adapter = (DirContextAdapter) ctx;
final String groupNameAttribute = adapter.getStringAttribute(ldapServerProperties.getGroupNamingAttr());
+ boolean outOfScope = AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, ldapServerProperties.getBaseDN());
+ if (outOfScope) {
+ LOG.warn("Group '{}' is out of scope of the base DN. It will be skipped.", groupNameAttribute);
+ return null;
+ }
if (groupNameAttribute != null) {
final LdapGroupDto group = new LdapGroupDto();
group.setGroupName(groupNameAttribute.toLowerCase());
@@ -744,6 +774,13 @@ public class AmbariLdapDataPopulator {
final DirContextAdapter adapter = (DirContextAdapter) ctx;
final String usernameAttribute = adapter.getStringAttribute(ldapServerProperties.getUsernameAttribute());
final String uidAttribute = adapter.getStringAttribute(UID_ATTRIBUTE);
+
+ boolean outOfScope = AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, ldapServerProperties.getBaseDN());
+ if (outOfScope) {
+ LOG.warn("User '{}' is out of scope of the base DN. It will be skipped.", usernameAttribute);
+ return null;
+ }
+
if (usernameAttribute != null || uidAttribute != null) {
final LdapUserDto user = new LdapUserDto();
user.setUserName(usernameAttribute != null ? usernameAttribute.toLowerCase() : null);
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6f0fbfb/ambari-server/src/test/java/org/apache/ambari/server/security/AmbariLdapUtilsTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/AmbariLdapUtilsTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/AmbariLdapUtilsTest.java
index b2778ae..5bcdf48 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/AmbariLdapUtilsTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/AmbariLdapUtilsTest.java
@@ -19,12 +19,30 @@ package org.apache.ambari.server.security;
import org.apache.ambari.server.security.authorization.AmbariLdapUtils;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.ldap.core.DirContextAdapter;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.security.ldap.LdapUtils;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(LdapUtils.class)
public class AmbariLdapUtilsTest {
+ private static final String USER_DN = "uid=myuser,ou=hdp,ou=Users,dc=apache,dc=org";
+
@Test
public void testIsUserPrincipalNameFormat_True() throws Exception {
// Given
@@ -84,4 +102,50 @@ public class AmbariLdapUtilsTest {
// Then
assertFalse(isUserPrincipalNameFormat);
}
+
+ @Test
+ public void testIsLdapObjectOutOfScopeFromBaseDn() throws NamingException {
+ // GIVEN
+ DistinguishedName fullDn = new DistinguishedName(USER_DN);
+ Context context = createNiceMock(Context.class);
+ DirContextAdapter adapter = createNiceMock(DirContextAdapter.class);
+
+ PowerMock.mockStatic(LdapUtils.class);
+ expect(LdapUtils.getFullDn(anyObject(DistinguishedName.class), anyObject(Context.class)))
+ .andReturn(fullDn).anyTimes();
+
+ expect(adapter.getDn()).andReturn(fullDn);
+ expect(context.getNameInNamespace()).andReturn(USER_DN);
+
+ replay(adapter, context);
+ PowerMock.replayAll();
+
+ // WHEN
+ boolean isOutOfScopeFromBaseDN = AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, "dc=apache,dc=org");
+ // THEN
+ assertFalse(isOutOfScopeFromBaseDN);
+ }
+
+ @Test
+ public void testIsLdapObjectOutOfScopeFromBaseDn_dnOutOfScope() throws NamingException {
+ // GIVEN
+ DistinguishedName fullDn = new DistinguishedName(USER_DN);
+ Context context = createNiceMock(Context.class);
+ DirContextAdapter adapter = createNiceMock(DirContextAdapter.class);
+
+ PowerMock.mockStatic(LdapUtils.class);
+ expect(LdapUtils.getFullDn(anyObject(DistinguishedName.class), anyObject(Context.class)))
+ .andReturn(fullDn).anyTimes();
+
+ expect(adapter.getDn()).andReturn(fullDn);
+ expect(context.getNameInNamespace()).andReturn(USER_DN);
+
+ replay(adapter, context);
+ PowerMock.replayAll();
+
+ // WHEN
+ boolean isOutOfScopeFromBaseDN = AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, "dc=apache,dc=org,ou=custom");
+ // THEN
+ assertTrue(isOutOfScopeFromBaseDN);
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6f0fbfb/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
index ffff3ea..eef91c1 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
@@ -36,6 +36,7 @@ import org.apache.ambari.server.orm.entities.MemberEntity;
import org.apache.ambari.server.orm.entities.PrincipalEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.security.authorization.AmbariLdapUtils;
import org.apache.ambari.server.security.authorization.Group;
import org.apache.ambari.server.security.authorization.LdapServerProperties;
import org.apache.ambari.server.security.authorization.User;
@@ -44,6 +45,10 @@ import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.ldap.control.PagedResultsCookie;
import org.springframework.ldap.control.PagedResultsDirContextProcessor;
import org.springframework.ldap.core.AttributesMapper;
@@ -56,8 +61,11 @@ import javax.naming.directory.SearchControls;
import static junit.framework.Assert.*;
import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.anyBoolean;
import static org.easymock.EasyMock.createNiceMock;
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(AmbariLdapUtils.class)
public class AmbariLdapDataPopulatorTest {
public static class AmbariLdapDataPopulatorTestInstance extends TestAmbariLdapDataPopulator {
public AmbariLdapDataPopulatorTestInstance(Configuration configuration, Users users) {
@@ -250,7 +258,7 @@ public class AmbariLdapDataPopulatorTest {
expect(populator.getLdapGroups("group2")).andReturn(Collections.EMPTY_SET);
LdapGroupDto externalGroup1 = createNiceMock(LdapGroupDto.class);
LdapBatchDto batchInfo = new LdapBatchDto();
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup1), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup1), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
expect(populator.getLdapGroups("group4")).andReturn(Collections.singleton(externalGroup1));
expect(populator.getLdapGroups("group5")).andReturn(Collections.EMPTY_SET);
@@ -373,12 +381,15 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup3, externalGroup4);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup),
+ anyObject(Map.class), anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
}
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup1), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup1),
+ anyObject(Map.class), anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup2), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup2), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
expect(populator.getLdapGroups("x*")).andReturn(externalGroups);
expect(populator.getLdapGroups("group1")).andReturn(Collections.singleton(externalGroup1));
@@ -456,10 +467,12 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup3, externalGroup4);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class),
+ anyObject(Set.class), anyBoolean());
expectLastCall();
}
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup2), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup2), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
expect(populator.getLdapGroups("x*")).andReturn(externalGroups);
expect(populator.getLdapGroups("group2")).andReturn(Collections.singleton(externalGroup2));
@@ -530,7 +543,8 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2, externalGroup3, externalGroup4);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
}
expect(populator.getLdapGroups("group*")).andReturn(externalGroups);
@@ -660,7 +674,8 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2, externalGroup3, externalGroup4);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
}
@@ -721,7 +736,8 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
}
expect(populator.getExternalLdapGroupInfo()).andReturn(externalGroups);
@@ -785,7 +801,8 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup1);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
}
expect(populator.getExternalLdapGroupInfo()).andReturn(externalGroups);
@@ -848,7 +865,8 @@ public class AmbariLdapDataPopulatorTest {
LdapBatchDto batchInfo = new LdapBatchDto();
Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2);
for (LdapGroupDto externalGroup : externalGroups) {
- populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class), anyObject(Map.class), anyObject(Set.class));
+ populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), anyObject(Map.class),
+ anyObject(Map.class), anyObject(Set.class), anyBoolean());
expectLastCall();
}
expect(populator.getExternalLdapGroupInfo()).andReturn(externalGroups);
@@ -1461,7 +1479,7 @@ public class AmbariLdapDataPopulatorTest {
Map<String, Group> internalGroups = new HashMap<String, Group>();
internalGroups.put("group2", group2);
- populator.refreshGroupMembers(batchInfo, externalGroup, internalUsers, internalGroups, null);
+ populator.refreshGroupMembers(batchInfo, externalGroup, internalUsers, internalGroups, null, true);
Set<String> groupMembersToAdd = new HashSet<String>();
for (LdapUserGroupMemberDto ldapUserGroupMemberDto : batchInfo.getMembershipToAdd()) {
@@ -1624,12 +1642,18 @@ public class AmbariLdapDataPopulatorTest {
public void testLdapUserContextMapper_uidIsNull() throws Exception {
LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
expect(ldapServerProperties.getUsernameAttribute()).andReturn("cn").once();
+ expect(ldapServerProperties.getBaseDN()).andReturn("dc=SME,dc=support,dc=com").anyTimes();
DirContextAdapter adapter = createNiceMock(DirContextAdapter.class);
expect(adapter.getStringAttribute("cn")).andReturn("testUser");
expect(adapter.getStringAttribute("uid")).andReturn(null);
expect(adapter.getNameInNamespace()).andReturn("cn=testUser,ou=Ambari,dc=SME,dc=support,dc=com");
- replay(ldapServerProperties, adapter);
+ PowerMock.mockStatic(AmbariLdapUtils.class);
+ expect(AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, "dc=SME,dc=support,dc=com"))
+ .andReturn(false).anyTimes();
+
+ replay(adapter, ldapServerProperties);
+ PowerMock.replayAll();
AmbariLdapDataPopulator.LdapUserContextMapper ldapUserContextMapper = new AmbariLdapDataPopulator.LdapUserContextMapper(ldapServerProperties);
LdapUserDto userDto = (LdapUserDto) ldapUserContextMapper.mapFromContext(adapter);
@@ -1659,12 +1683,18 @@ public class AmbariLdapDataPopulatorTest {
public void testLdapUserContextMapper() throws Exception {
LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
expect(ldapServerProperties.getUsernameAttribute()).andReturn("cn").once();
+ expect(ldapServerProperties.getBaseDN()).andReturn("dc=SME,dc=support,dc=com").anyTimes();
DirContextAdapter adapter = createNiceMock(DirContextAdapter.class);
expect(adapter.getStringAttribute("cn")).andReturn("testUser");
expect(adapter.getStringAttribute("uid")).andReturn("UID1");
expect(adapter.getNameInNamespace()).andReturn("cn=testUser,ou=Ambari,dc=SME,dc=support,dc=com");
+ PowerMock.mockStatic(AmbariLdapUtils.class);
+ expect(AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, "dc=SME,dc=support,dc=com"))
+ .andReturn(false).anyTimes();
+
replay(ldapServerProperties, adapter);
+ PowerMock.replayAll();
AmbariLdapDataPopulator.LdapUserContextMapper ldapUserContextMapper = new AmbariLdapDataPopulator.LdapUserContextMapper(ldapServerProperties);
LdapUserDto userDto = (LdapUserDto) ldapUserContextMapper.mapFromContext(adapter);
@@ -1675,6 +1705,106 @@ public class AmbariLdapDataPopulatorTest {
assertEquals("cn=testuser,ou=ambari,dc=sme,dc=support,dc=com", userDto.getDn());
}
+ @Test
+ public void testIsMemberAttributeBaseDn() {
+ // GIVEN
+ Configuration configuration = createNiceMock(Configuration.class);
+ Users users = createNiceMock(Users.class);
+ LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
+
+ expect(configuration.getLdapServerProperties()).andReturn(ldapServerProperties).anyTimes();
+ expect(ldapServerProperties.getUsernameAttribute()).andReturn("UID");
+ expect(ldapServerProperties.getGroupNamingAttr()).andReturn("CN");
+
+ replay(configuration, users, ldapServerProperties);
+
+ // WHEN
+ AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
+ boolean result = populator.isMemberAttributeBaseDn("CN=mygroupname,OU=myOrganizationUnit,DC=apache,DC=org");
+ // THEN
+ assertTrue(result);
+ }
+
+ @Test
+ public void testIsMemberAttributeBaseDn_withUidMatch() {
+ // GIVEN
+ Configuration configuration = createNiceMock(Configuration.class);
+ Users users = createNiceMock(Users.class);
+ LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
+
+ expect(configuration.getLdapServerProperties()).andReturn(ldapServerProperties).anyTimes();
+ expect(ldapServerProperties.getUsernameAttribute()).andReturn("UID");
+ expect(ldapServerProperties.getGroupNamingAttr()).andReturn("CN");
+
+ replay(configuration, users, ldapServerProperties);
+
+ // WHEN
+ AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
+ boolean result = populator.isMemberAttributeBaseDn("uid=myuid,OU=myOrganizationUnit,DC=apache,DC=org");
+ // THEN
+ assertTrue(result);
+ }
+
+ @Test
+ public void testIsMemberAttributeBaseDn_withLowerAndUpperCaseValue() {
+ // GIVEN
+ Configuration configuration = createNiceMock(Configuration.class);
+ Users users = createNiceMock(Users.class);
+ LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
+
+ expect(configuration.getLdapServerProperties()).andReturn(ldapServerProperties).anyTimes();
+ expect(ldapServerProperties.getUsernameAttribute()).andReturn("uid");
+ expect(ldapServerProperties.getGroupNamingAttr()).andReturn("CN");
+
+ replay(configuration, users, ldapServerProperties);
+
+ // WHEN
+ AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
+ boolean result = populator.isMemberAttributeBaseDn("cn=mygroupname,OU=myOrganizationUnit,DC=apache,DC=org");
+ // THEN
+ assertTrue(result);
+ }
+
+ @Test
+ public void testIsMemberAttributeBaseDn_withWrongAttribute() {
+ // GIVEN
+ Configuration configuration = createNiceMock(Configuration.class);
+ Users users = createNiceMock(Users.class);
+ LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
+
+ expect(configuration.getLdapServerProperties()).andReturn(ldapServerProperties).anyTimes();
+ expect(ldapServerProperties.getUsernameAttribute()).andReturn("uid");
+ expect(ldapServerProperties.getGroupNamingAttr()).andReturn("CN");
+
+ replay(configuration, users, ldapServerProperties);
+
+ // WHEN
+ AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
+ boolean result = populator.isMemberAttributeBaseDn("cnn=mygroupname,OU=myOrganizationUnit,DC=apache,DC=org");
+ // THEN
+ assertFalse(result);
+ }
+
+ @Test
+ public void testIsMemberAttributeBaseDn_withEmptyValues() {
+ // GIVEN
+ Configuration configuration = createNiceMock(Configuration.class);
+ Users users = createNiceMock(Users.class);
+ LdapServerProperties ldapServerProperties = createNiceMock(LdapServerProperties.class);
+
+ expect(configuration.getLdapServerProperties()).andReturn(ldapServerProperties).anyTimes();
+ expect(ldapServerProperties.getUsernameAttribute()).andReturn("");
+ expect(ldapServerProperties.getGroupNamingAttr()).andReturn(null);
+
+ replay(configuration, users, ldapServerProperties);
+
+ // WHEN
+ AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
+ boolean result = populator.isMemberAttributeBaseDn("cnn=mygroupname,OU=myOrganizationUnit,DC=apache,DC=org");
+ // THEN
+ assertFalse(result);
+ }
+
private static int userIdCounter = 1;
private User createUser(String name, boolean ldapUser, GroupEntity group) {