You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2017/11/29 19:42:03 UTC

ambari git commit: AMBARI-21222. Update LDAP sync process to work with improved user management facility. (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-20859 deb180036 -> d459d1304


AMBARI-21222. Update LDAP sync process to work with improved user management facility. (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d459d130
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d459d130
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d459d130

Branch: refs/heads/branch-feature-AMBARI-20859
Commit: d459d1304e5efd1c9d64a65342ecf0696b9d329f
Parents: deb1800
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Nov 29 14:41:56 2017 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Nov 29 14:41:56 2017 -0500

----------------------------------------------------------------------
 .../internal/UserPrivilegeResourceProvider.java |   1 -
 .../server/orm/dao/UserAuthenticationDAO.java   |   7 +
 .../orm/entities/UserAuthenticationEntity.java  |   4 +-
 .../server/security/authorization/Users.java    | 299 ++++++++++++-------
 .../security/ldap/AmbariLdapDataPopulator.java  |  74 +++--
 .../server/security/ldap/LdapBatchDto.java      |  32 +-
 .../ldap/AmbariLdapDataPopulatorTest.java       | 225 +++++++-------
 7 files changed, 376 insertions(+), 266 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
index 816767e..eeabc10 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
@@ -286,7 +286,6 @@ public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
         }
 
         if (userEntity == null) {
-          LOG.debug("User {} was not found", userName);
           throw new SystemException("User was not found");
         }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
index 13c17f9..513e782 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserAuthenticationDAO.java
@@ -25,6 +25,7 @@ import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 
 import com.google.inject.Inject;
@@ -66,6 +67,12 @@ public class UserAuthenticationDAO {
     return daoUtils.selectList(query);
   }
 
+  public List<UserAuthenticationEntity> findByUser(UserEntity userEntity) {
+    TypedQuery<UserAuthenticationEntity> query = entityManagerProvider.get().createNamedQuery("UserAuthenticationEntity.findByUser", UserAuthenticationEntity.class);
+    query.setParameter("userId", userEntity.getUserId());
+    return daoUtils.selectList(query);
+  }
+
   @Transactional
   public void create(UserAuthenticationEntity entity) {
     entityManagerProvider.get().persist(entity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
index bba8cf2..27514f6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java
@@ -52,7 +52,9 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
     @NamedQuery(name = "UserAuthenticationEntity.findByType",
         query = "SELECT entity FROM UserAuthenticationEntity entity where lower(entity.authenticationType)=lower(:authenticationType)"),
     @NamedQuery(name = "UserAuthenticationEntity.findByTypeAndKey",
-        query = "SELECT entity FROM UserAuthenticationEntity entity where lower(entity.authenticationType)=lower(:authenticationType) and entity.authenticationKey=:authenticationKey")
+        query = "SELECT entity FROM UserAuthenticationEntity entity where lower(entity.authenticationType)=lower(:authenticationType) and entity.authenticationKey=:authenticationKey"),
+    @NamedQuery(name = "UserAuthenticationEntity.findByUser",
+        query = "SELECT entity FROM UserAuthenticationEntity entity where entity.user.userId=:userId")
 })
 @TableGenerator(name = "user_authentication_id_generator",
     table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"

http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/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 ec05641..ebe26a2 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
@@ -57,6 +57,8 @@ import org.apache.ambari.server.security.authentication.AccountDisabledException
 import org.apache.ambari.server.security.authentication.TooManyLoginFailuresException;
 import org.apache.ambari.server.security.authentication.UserNotFoundException;
 import org.apache.ambari.server.security.ldap.LdapBatchDto;
+import org.apache.ambari.server.security.ldap.LdapGroupDto;
+import org.apache.ambari.server.security.ldap.LdapUserDto;
 import org.apache.ambari.server.security.ldap.LdapUserGroupMemberDto;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
@@ -694,9 +696,6 @@ public class Users {
    *
    * @param batchInfo DTO with batch information
    */
-  // TODO: ************
-  // TODO: This is to be revisited for AMBARI-21222 (Update LDAP sync process to work with improved user management facility)
-  // TODO: ************
   public void processLdapSync(LdapBatchDto batchInfo) {
     final Map<String, UserEntity> allUsers = new HashMap<>();
     final Map<String, GroupEntity> allGroups = new HashMap<>();
@@ -712,7 +711,7 @@ public class Users {
     }
 
     final PrincipalTypeEntity groupPrincipalType = principalTypeDAO
-      .ensurePrincipalTypeCreated(PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE);
+        .ensurePrincipalTypeCreated(PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE);
 
     /* *****
      * Remove users
@@ -721,17 +720,21 @@ public class Users {
      * ***** */
     final Set<UserEntity> usersToRemove = new HashSet<>();
     final Set<UserAuthenticationEntity> authenticationEntitiesToRemove = new HashSet<>();
-    for (String userName : batchInfo.getUsersToBeRemoved()) {
-      UserEntity userEntity = userDAO.findUserByName(userName);
+    for (LdapUserDto user : batchInfo.getUsersToBeRemoved()) {
+      UserEntity userEntity = userDAO.findUserByName(user.getUserName());
       if (userEntity != null) {
-        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+        List<UserAuthenticationEntity> authenticationEntities = userAuthenticationDAO.findByUser(userEntity);
         Iterator<UserAuthenticationEntity> iterator = authenticationEntities.iterator();
         while (iterator.hasNext()) {
           UserAuthenticationEntity authenticationEntity = iterator.next();
 
           if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.LDAP) {
-            // TODO: Determine if this is the _relevant_ LDAP authentication entry - for now there will only be one..
-            authenticationEntitiesToRemove.add(authenticationEntity);
+            String dn = user.getDn();
+            String authenticationKey = authenticationEntity.getAuthenticationKey();
+
+            if (StringUtils.isEmpty(dn) || StringUtils.isEmpty(authenticationKey) || dn.equals(authenticationKey)) {
+              authenticationEntitiesToRemove.add(authenticationEntity);
+            }
             iterator.remove();
           }
         }
@@ -747,8 +750,8 @@ public class Users {
 
     // remove groups
     final Set<GroupEntity> groupsToRemove = new HashSet<>();
-    for (String groupName : batchInfo.getGroupsToBeRemoved()) {
-      final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
+    for (LdapGroupDto group : batchInfo.getGroupsToBeRemoved()) {
+      final GroupEntity groupEntity = groupDAO.findGroupByName(group.getGroupName());
       allGroups.remove(groupEntity.getGroupName());
       groupsToRemove.add(groupEntity);
     }
@@ -758,36 +761,18 @@ public class Users {
      * Update users
      * ***** */
     final Set<UserEntity> userEntitiesToUpdate = new HashSet<>();
-    for (String userName : batchInfo.getUsersToBecomeLdap()) {
+    for (LdapUserDto user : batchInfo.getUsersToBecomeLdap()) {
       // Ensure the username is all lowercase
-      userName = userName.toLowerCase();
+      String userName = user.getUserName();
 
       UserEntity userEntity = userDAO.findUserByName(userName);
       if (userEntity != null) {
         LOG.trace("Enabling LDAP authentication for the user account with the username {}.", userName);
-        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
-        boolean createNew = true;
-
-        for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
-          if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.LDAP) {
-            // TODO: check for the relevant LDAP entry... for now there will be only one.
-            LOG.debug("Found existing LDAP authentication record for the user account with the username {}.", userName);
-            createNew = false;
-            break;
-          }
-        }
-
-        if (createNew) {
-          LOG.debug("Creating new LDAP authentication record for the user account with the username {}.", userName);
-
-          UserAuthenticationEntity authenticationEntity = new UserAuthenticationEntity();
-          authenticationEntity.setUser(userEntity);
-          authenticationEntity.setAuthenticationType(UserAuthenticationType.LDAP);
-          authenticationEntity.setAuthenticationKey("DN to be set");
-          authenticationEntities.add(authenticationEntity);
-
-          userEntity.setAuthenticationEntities(authenticationEntities);
+        try {
+          addLdapAuthentication(userEntity, user.getDn(), false);
           userEntitiesToUpdate.add(userEntity);
+        } catch (AmbariException e) {
+          LOG.warn(String.format("Failed to enable LDAP authentication for the user account with the username %s: %s", userName, e.getLocalizedMessage()), e);
         }
       } else {
         LOG.warn("Failed to find user account for {} while enabling LDAP authentication for the user.", userName);
@@ -797,8 +782,8 @@ public class Users {
 
     // update groups
     final Set<GroupEntity> groupsToBecomeLdap = new HashSet<>();
-    for (String groupName : batchInfo.getGroupsToBecomeLdap()) {
-      final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
+    for (LdapGroupDto group : batchInfo.getGroupsToBecomeLdap()) {
+      final GroupEntity groupEntity = groupDAO.findGroupByName(group.getGroupName());
       groupEntity.setGroupType(GroupType.LDAP);
       allGroups.put(groupEntity.getGroupName(), groupEntity);
       groupsToBecomeLdap.add(groupEntity);
@@ -809,7 +794,8 @@ public class Users {
     final List<PrincipalEntity> principalsToCreate = new ArrayList<>();
 
     // Create users
-    for (String userName : batchInfo.getUsersToBeCreated()) {
+    for (LdapUserDto user : batchInfo.getUsersToBeCreated()) {
+      String userName = user.getUserName();
       UserEntity userEntity;
 
       try {
@@ -820,24 +806,29 @@ public class Users {
       }
 
       if (userEntity != null) {
-        UserAuthenticationEntity authenticationEntity = new UserAuthenticationEntity();
-        authenticationEntity.setUser(userEntity);
-        authenticationEntity.setAuthenticationType(UserAuthenticationType.LDAP);
-        authenticationEntity.setAuthenticationKey("DN to be set");
-        userEntity.setAuthenticationEntities(Collections.singletonList(authenticationEntity));
+        LOG.trace("Enabling LDAP authentication for the user account with the username {}.", userName);
+        try {
+          addLdapAuthentication(userEntity, user.getDn(), false);
+        } catch (AmbariException e) {
+          LOG.warn(String.format("Failed to enable LDAP authentication for the user account with the username %s: %s", userName, e.getLocalizedMessage()), e);
+        }
+
         userDAO.merge(userEntity);
+
+        // Add the new user to the allUsers map.
+        allUsers.put(userEntity.getUserName(), userEntity);
       }
     }
 
     // prepare create groups
     final Set<GroupEntity> groupsToCreate = new HashSet<>();
-    for (String groupName : batchInfo.getGroupsToBeCreated()) {
+    for (LdapGroupDto group: batchInfo.getGroupsToBeCreated()) {
       final PrincipalEntity principalEntity = new PrincipalEntity();
       principalEntity.setPrincipalType(groupPrincipalType);
       principalsToCreate.add(principalEntity);
 
       final GroupEntity groupEntity = new GroupEntity();
-      groupEntity.setGroupName(groupName);
+      groupEntity.setGroupName(group.getGroupName());
       groupEntity.setPrincipal(principalEntity);
       groupEntity.setGroupType(GroupType.LDAP);
 
@@ -1284,55 +1275,112 @@ public class Users {
    * Adds the ability for a user to authenticate using a JWT token.
    * <p>
    * The key for this authentication mechanism is the username expected to be in the JWT token.
+   * <p>
+   * The created {@link UserAuthenticationEntity} and the supplied {@link UserEntity} are persisted.
    *
    * @param userEntity the user
    * @param key        the relevant key
    * @throws AmbariException
+   * @see #addJWTAuthentication(UserEntity, String, boolean)
    */
   public void addJWTAuthentication(UserEntity userEntity, String key) throws AmbariException {
-    addAuthentication(userEntity, UserAuthenticationType.JWT, key, new Validator() {
-      public void validate(UserEntity userEntity, String key) throws AmbariException {
-        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
-
-        // Ensure only one UserAuthenticationEntity exists for JWT for the user...
-        for (UserAuthenticationEntity entity : authenticationEntities) {
-          if ((entity.getAuthenticationType() == UserAuthenticationType.JWT) &&
-              ((key == null) ? (entity.getAuthenticationKey() == null) : key.equals(entity.getAuthenticationKey()))) {
-            throw new AmbariException("The authentication type already exists for this user");
+    addJWTAuthentication(userEntity, key, true);
+  }
+
+  /**
+   * Adds the ability for a user to authenticate using a JWT token.
+   * <p>
+   * The key for this authentication mechanism is the username expected to be in the JWT token.
+   *
+   * @param userEntity the user
+   * @param key        the relevant key
+   * @param persist    true, to persist the created entity; false, to not persist the created entity
+   * @throws AmbariException
+   */
+  public void addJWTAuthentication(UserEntity userEntity, String key, boolean persist) throws AmbariException {
+    addAuthentication(userEntity,
+        UserAuthenticationType.JWT,
+        key,
+        new Validator() {
+          public void validate(UserEntity userEntity, String key) throws AmbariException {
+            List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+
+            // Ensure only one UserAuthenticationEntity exists for JWT for the user...
+            for (UserAuthenticationEntity entity : authenticationEntities) {
+              if ((entity.getAuthenticationType() == UserAuthenticationType.JWT) &&
+                  ((key == null) ? (entity.getAuthenticationKey() == null) : key.equals(entity.getAuthenticationKey()))) {
+                throw new AmbariException("The authentication type already exists for this user");
+              }
+            }
           }
-        }
-      }
-    });
+        },
+        persist);
   }
 
   /**
    * Adds the ability for a user to authenticate using a Kerberos token.
+   * <p>
+   * The created {@link UserAuthenticationEntity} and the supplied {@link UserEntity} are persisted.
    *
    * @param userEntity    the user
    * @param principalName the user's principal name
    * @throws AmbariException
+   * @see #addKerberosAuthentication(UserEntity, String, boolean)
    */
   public void addKerberosAuthentication(UserEntity userEntity, String principalName) throws AmbariException {
-    addAuthentication(userEntity, UserAuthenticationType.KERBEROS, principalName, new Validator() {
-      public void validate(UserEntity userEntity, String key) throws AmbariException {
-        // Ensure no other authentication entries exist for the same principal...
-        if (!CollectionUtils.isEmpty(userAuthenticationDAO.findByTypeAndKey(UserAuthenticationType.KERBEROS, key))) {
-          throw new AmbariException("The authentication type already exists for this principal");
-        }
-      }
-    });
+    addKerberosAuthentication(userEntity, principalName, true);
+  }
+
+  /**
+   * Adds the ability for a user to authenticate using a Kerberos token.
+   *
+   * @param userEntity    the user
+   * @param principalName the user's principal name
+   * @param persist       true, to persist the created entity; false, to not persist the created entity
+   * @throws AmbariException
+   */
+  public void addKerberosAuthentication(UserEntity userEntity, String principalName, boolean persist) throws AmbariException {
+    addAuthentication(userEntity,
+        UserAuthenticationType.KERBEROS,
+        principalName,
+        new Validator() {
+          public void validate(UserEntity userEntity, String key) throws AmbariException {
+            // Ensure no other authentication entries exist for the same principal...
+            if (!CollectionUtils.isEmpty(userAuthenticationDAO.findByTypeAndKey(UserAuthenticationType.KERBEROS, key))) {
+              throw new AmbariException("The authentication type already exists for this principal");
+            }
+          }
+        },
+        persist);
   }
 
   /**
    * Adds the ability for a user to authenticate using a password stored in Ambari's database
    * <p>
    * The supplied plaintext password will be encoded before storing.
+   * <p>
+   * The created {@link UserAuthenticationEntity} and the supplied {@link UserEntity} are persisted.
    *
    * @param userEntity the user
    * @param password   the user's plaintext password
    * @throws AmbariException
+   * @see #addLocalAuthentication(UserEntity, String, boolean)
    */
   public void addLocalAuthentication(UserEntity userEntity, String password) throws AmbariException {
+    addLocalAuthentication(userEntity, password, true);
+  }
+
+  /**
+   * Adds the ability for a user to authenticate using a password stored in Ambari's database
+   * <p>
+   * The supplied plaintext password will be encoded before storing.
+   *
+   * @param userEntity the user
+   * @param password   the user's plaintext password
+   * @param persist    true, to persist the created entity; false, to not persist the created entity
+   * @throws AmbariException
+   */
+  public void addLocalAuthentication(UserEntity userEntity, String password, boolean persist) throws AmbariException {
 
     // Ensure the password meets configured minimal requirements, if any
     validatePassword(password);
@@ -1340,64 +1388,105 @@ public class Users {
     // Encode the password..
     String encodedPassword = passwordEncoder.encode(password);
 
-    addAuthentication(userEntity, UserAuthenticationType.LOCAL, encodedPassword, new Validator() {
-      public void validate(UserEntity userEntity, String key) throws AmbariException {
-        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
-
-        // Ensure only one UserAuthenticationEntity exists for LOCAL for the user...
-        for (UserAuthenticationEntity entity : authenticationEntities) {
-          if (entity.getAuthenticationType() == UserAuthenticationType.LOCAL) {
-            throw new AmbariException("The authentication type already exists for this user");
+    addAuthentication(userEntity,
+        UserAuthenticationType.LOCAL,
+        encodedPassword,
+        new Validator() {
+          public void validate(UserEntity userEntity, String key) throws AmbariException {
+            List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+
+            // Ensure only one UserAuthenticationEntity exists for LOCAL for the user...
+            for (UserAuthenticationEntity entity : authenticationEntities) {
+              if (entity.getAuthenticationType() == UserAuthenticationType.LOCAL) {
+                throw new AmbariException("The authentication type already exists for this user");
+              }
+            }
           }
-        }
-      }
-    });
+        },
+        persist);
   }
 
   /**
    * Adds the ability for a user to authenticate using Pam
+   * <p>
+   * The created {@link UserAuthenticationEntity} and the supplied {@link UserEntity} are persisted.
    *
    * @param userEntity the user
    * @param userName   the user's os-level username
    * @throws AmbariException
+   * @see #addPamAuthentication(UserEntity, String, boolean)
    */
   public void addPamAuthentication(UserEntity userEntity, String userName) throws AmbariException {
-    addAuthentication(userEntity, UserAuthenticationType.PAM, userName, new Validator() {
-      public void validate(UserEntity userEntity, String key) throws AmbariException {
-        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
-
-        // Ensure only one UserAuthenticationEntity exists for PAM for the user...
-        for (UserAuthenticationEntity entity : authenticationEntities) {
-          if (entity.getAuthenticationType() == UserAuthenticationType.PAM) {
-            throw new AmbariException("The authentication type already exists for this user");
+    addPamAuthentication(userEntity, userName, true);
+  }
+
+  /**
+   * Adds the ability for a user to authenticate using Pam
+   *
+   * @param userEntity the user
+   * @param userName   the user's os-level username
+   * @param persist    true, to persist the created entity; false, to not persist the created entity
+   * @throws AmbariException
+   */
+  public void addPamAuthentication(UserEntity userEntity, String userName, boolean persist) throws AmbariException {
+    addAuthentication(userEntity,
+        UserAuthenticationType.PAM,
+        userName,
+        new Validator() {
+          public void validate(UserEntity userEntity, String key) throws AmbariException {
+            List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+
+            // Ensure only one UserAuthenticationEntity exists for PAM for the user...
+            for (UserAuthenticationEntity entity : authenticationEntities) {
+              if (entity.getAuthenticationType() == UserAuthenticationType.PAM) {
+                throw new AmbariException("The authentication type already exists for this user");
+              }
+            }
           }
-        }
-      }
-    });
+        },
+        persist);
   }
 
   /**
-   * TODO: This is to be revisited for AMBARI-21219 (Update LDAP Authentication process to work with improved user management facility)
    * Adds the ability for a user to authenticate using a remote LDAP server
+   * <p>
+   * The created {@link UserAuthenticationEntity} and the supplied {@link UserEntity} are persisted.
    *
    * @param userEntity the user
    * @param dn         the user's distinguished name
    * @throws AmbariException
+   * @see #addLdapAuthentication(UserEntity, String, boolean)
    */
   public void addLdapAuthentication(UserEntity userEntity, String dn) throws AmbariException {
-    addAuthentication(userEntity, UserAuthenticationType.LDAP, dn, new Validator() {
-      public void validate(UserEntity userEntity, String key) throws AmbariException {
-        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
-
-        // Ensure only one UserAuthenticationEntity exists for PAM for the user...
-        for (UserAuthenticationEntity entity : authenticationEntities) {
-          if ((entity.getAuthenticationType() == UserAuthenticationType.LDAP) &&
-              ((key == null) ? (entity.getAuthenticationKey() == null) : key.equalsIgnoreCase(entity.getAuthenticationKey()))) {
-            throw new AmbariException("The authentication type already exists for this user");
+    addLdapAuthentication(userEntity, dn, true);
+  }
+
+  /**
+   * Adds the ability for a user to authenticate using a remote LDAP server
+   *
+   * @param userEntity the user
+   * @param dn         the user's distinguished name
+   * @param persist    true, to persist the created entity; false, to not persist the created entity
+   * @throws AmbariException
+   */
+  public void addLdapAuthentication(UserEntity userEntity, String dn, boolean persist) throws AmbariException {
+    addAuthentication(userEntity,
+        UserAuthenticationType.LDAP,
+        dn,
+        new Validator() {
+          public void validate(UserEntity userEntity, String key) throws AmbariException {
+            List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+
+            // Ensure only one UserAuthenticationEntity exists for LDAP for the user...
+            for (UserAuthenticationEntity entity : authenticationEntities) {
+              if ((entity.getAuthenticationType() == UserAuthenticationType.LDAP) &&
+                  ((key == null) ? (entity.getAuthenticationKey() == null) : key.equalsIgnoreCase(entity.getAuthenticationKey()))) {
+                throw new AmbariException("The authentication type already exists for this user");
+              }
+            }
           }
-        }
-      }
-    });
+        },
+        persist);
   }
 
   /**
@@ -1407,9 +1496,12 @@ public class Users {
    * @param type       the authentication type
    * @param key        the authentication type specific metadata
    * @param validator  the authentication type specific validator
+   * @param persist    true, to persist the created entity; false, to not persist the created entity
    * @throws AmbariException
    */
-  private void addAuthentication(UserEntity userEntity, UserAuthenticationType type, String key, Validator validator) throws AmbariException {
+  private void addAuthentication(UserEntity userEntity, UserAuthenticationType type, String key,
+                                 Validator validator, boolean persist)
+      throws AmbariException {
 
     if (userEntity == null) {
       throw new AmbariException("Missing user");
@@ -1426,7 +1518,10 @@ public class Users {
     authenticationEntities.add(authenticationEntity);
 
     userEntity.setAuthenticationEntities(authenticationEntities);
-    userDAO.merge(userEntity);
+
+    if (persist) {
+      userDAO.merge(userEntity);
+    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/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 c3451dd..001b5fe 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
@@ -187,13 +187,14 @@ public class AmbariLdapDataPopulator {
     final Map<String, User> internalUsersMap = getInternalUsers();
 
     for (LdapGroupDto groupDto : externalLdapGroupInfo) {
-      String groupName = groupDto.getGroupName();
-      addLdapGroup(batchInfo, internalGroupsMap, groupName);
+      addLdapGroup(batchInfo, internalGroupsMap, groupDto);
       refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null, false);
     }
     for (Entry<String, Group> internalGroup : internalGroupsMap.entrySet()) {
       if (internalGroup.getValue().isLdapGroup()) {
-        batchInfo.getGroupsToBeRemoved().add(internalGroup.getValue().getGroupName());
+        LdapGroupDto groupDto = new LdapGroupDto();
+        groupDto.setGroupName(internalGroup.getValue().getGroupName());
+        batchInfo.getGroupsToBeRemoved().add(groupDto);
       }
     }
 
@@ -217,20 +218,23 @@ public class AmbariLdapDataPopulator {
         if (user != null && !user.isLdapUser()) {
           if (Configuration.LdapUsernameCollisionHandlingBehavior.SKIP == configuration.getLdapSyncCollisionHandlingBehavior()) {
             LOG.info("User '{}' skipped because it is local user", userName);
-            batchInfo.getUsersSkipped().add(userName);
+            batchInfo.getUsersSkipped().add(userDto);
           } else {
-            batchInfo.getUsersToBecomeLdap().add(userName);
+            batchInfo.getUsersToBecomeLdap().add(userDto);
             LOG.trace("Convert user '{}' to LDAP user.", userName);
           }
         }
         internalUsersMap.remove(userName);
       } else {
-        batchInfo.getUsersToBeCreated().add(userName);
+        batchInfo.getUsersToBeCreated().add(userDto);
       }
     }
     for (Entry<String, User> internalUser : internalUsersMap.entrySet()) {
       if (internalUser.getValue().isLdapUser()) {
-        batchInfo.getUsersToBeRemoved().add(internalUser.getValue().getUserName());
+        LdapUserDto userDto = new LdapUserDto();
+        userDto.setUserName(internalUser.getValue().getUserName());
+        userDto.setDn(null);  // Setting to null since we do not know what the DN for this user was.
+        batchInfo.getUsersToBeRemoved().add(userDto);
       }
     }
 
@@ -259,8 +263,7 @@ public class AmbariLdapDataPopulator {
     final Map<String, User> internalUsersMap = getInternalUsers();
 
     for (LdapGroupDto groupDto : specifiedGroups) {
-      String groupName = groupDto.getGroupName();
-      addLdapGroup(batchInfo, internalGroupsMap, groupName);
+      addLdapGroup(batchInfo, internalGroupsMap, groupDto);
       refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null, true);
     }
 
@@ -294,14 +297,14 @@ public class AmbariLdapDataPopulator {
         if (user != null && !user.isLdapUser()) {
           if (Configuration.LdapUsernameCollisionHandlingBehavior.SKIP == configuration.getLdapSyncCollisionHandlingBehavior()) {
             LOG.info("User '{}' skipped because it is local user", userName);
-            batchInfo.getUsersSkipped().add(userName);
+            batchInfo.getUsersSkipped().add(userDto);
           } else {
-            batchInfo.getUsersToBecomeLdap().add(userName);
+            batchInfo.getUsersToBecomeLdap().add(userDto);
           }
         }
         internalUsersMap.remove(userName);
       } else {
-        batchInfo.getUsersToBeCreated().add(userName);
+        batchInfo.getUsersToBeCreated().add(userDto);
       }
     }
 
@@ -324,7 +327,9 @@ public class AmbariLdapDataPopulator {
       if (group.isLdapGroup()) {
         Set<LdapGroupDto> groupDtos = getLdapGroups(group.getGroupName());
         if (groupDtos.isEmpty()) {
-          batchInfo.getGroupsToBeRemoved().add(group.getGroupName());
+          LdapGroupDto groupDto = new LdapGroupDto();
+          groupDto.setGroupName(group.getGroupName());
+          batchInfo.getGroupsToBeRemoved().add(groupDto);
         } else {
           LdapGroupDto groupDto = groupDtos.iterator().next();
           refreshGroupMembers(batchInfo, groupDto, internalUsersMap, internalGroupsMap, null, true);
@@ -348,7 +353,10 @@ public class AmbariLdapDataPopulator {
       if (user.isLdapUser()) {
         Set<LdapUserDto> userDtos = getLdapUsers(user.getUserName());
         if (userDtos.isEmpty()) {
-          batchInfo.getUsersToBeRemoved().add(user.getUserName());
+          LdapUserDto userDto = new LdapUserDto();
+          userDto.setUserName(user.getUserName());
+          userDto.setDn(null);  // Setting to null since we do not know what the DN for this user was.
+          batchInfo.getUsersToBeRemoved().add(userDto);
         }
       }
     }
@@ -369,7 +377,7 @@ public class AmbariLdapDataPopulator {
   protected void refreshGroupMembers(LdapBatchDto batchInfo, LdapGroupDto group, Map<String, User> internalUsers,
                                      Map<String, Group> internalGroupsMap, Set<String> groupMemberAttributes, boolean recursive)
       throws AmbariException {
-    Set<String> externalMembers = new HashSet<>();
+    Set<LdapUserDto> externalMembers = new HashSet<>();
 
     if (groupMemberAttributes == null) {
       groupMemberAttributes = new HashSet<>();
@@ -378,7 +386,7 @@ public class AmbariLdapDataPopulator {
     for (String memberAttributeValue : group.getMemberAttributes()) {
       LdapUserDto groupMember = getLdapUserByMemberAttr(memberAttributeValue);
       if (groupMember != null) {
-        externalMembers.add(groupMember.getUserName());
+        externalMembers.add(groupMember);
       } else {
         // if we haven't already processed this group
         if (recursive && !groupMemberAttributes.contains(memberAttributeValue)) {
@@ -386,7 +394,7 @@ public class AmbariLdapDataPopulator {
           LdapGroupDto subGroup = getLdapGroupByMemberAttr(memberAttributeValue);
           if (subGroup != null) {
             groupMemberAttributes.add(memberAttributeValue);
-            addLdapGroup(batchInfo, internalGroupsMap, subGroup.getGroupName());
+            addLdapGroup(batchInfo, internalGroupsMap, subGroup);
             refreshGroupMembers(batchInfo, subGroup, internalUsers, internalGroupsMap, groupMemberAttributes, true);
           }
         }
@@ -394,33 +402,34 @@ public class AmbariLdapDataPopulator {
     }
     String groupName = group.getGroupName();
     final Map<String, User> internalMembers = getInternalMembers(groupName);
-    for (String externalMember : externalMembers) {
-      if (internalUsers.containsKey(externalMember)) {
-        final User user = internalUsers.get(externalMember);
+    for (LdapUserDto externalMember : externalMembers) {
+      String userName = externalMember.getUserName();
+      if (internalUsers.containsKey(userName)) {
+        final User user = internalUsers.get(userName);
         if (user == null) {
           // user is fresh and is already added to batch info
-          if (!internalMembers.containsKey(externalMember)) {
-            batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto(groupName, externalMember));
+          if (!internalMembers.containsKey(userName)) {
+            batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto(groupName, externalMember.getUserName()));
           }
           continue;
         }
         if (!user.isLdapUser()) {
           if (Configuration.LdapUsernameCollisionHandlingBehavior.SKIP == configuration.getLdapSyncCollisionHandlingBehavior()) {
             // existing user can not be converted to ldap user, so skip it
-            LOG.info("User '{}' skipped because it is local user", externalMember);
+            LOG.info("User '{}' skipped because it is local user", userName);
             batchInfo.getUsersSkipped().add(externalMember);
             continue; // and remove from group
           } else {
             batchInfo.getUsersToBecomeLdap().add(externalMember);
           }
         }
-        if (!internalMembers.containsKey(externalMember)) {
-          batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto(groupName, externalMember));
+        if (!internalMembers.containsKey(userName)) {
+          batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto(groupName, externalMember.getUserName()));
         }
-        internalMembers.remove(externalMember);
+        internalMembers.remove(userName);
       } else {
         batchInfo.getUsersToBeCreated().add(externalMember);
-        batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto(groupName, externalMember));
+        batchInfo.getMembershipToAdd().add(new LdapUserGroupMemberDto(groupName, externalMember.getUserName()));
       }
     }
     for (Entry<String, User> userToBeUnsynced : internalMembers.entrySet()) {
@@ -570,18 +579,19 @@ public class AmbariLdapDataPopulator {
 
   // Utility methods
 
-  protected void addLdapGroup(LdapBatchDto batchInfo, Map<String, Group> internalGroupsMap, String groupName) {
+  protected void addLdapGroup(LdapBatchDto batchInfo, Map<String, Group> internalGroupsMap, LdapGroupDto groupDto) {
+    String groupName = groupDto.getGroupName();
     if (internalGroupsMap.containsKey(groupName)) {
       final Group group = internalGroupsMap.get(groupName);
       if (!group.isLdapGroup()) {
-        batchInfo.getGroupsToBecomeLdap().add(groupName);
+        batchInfo.getGroupsToBecomeLdap().add(groupDto);
         LOG.trace("Convert group '{}' to LDAP group.", groupName);
       }
       internalGroupsMap.remove(groupName);
-      batchInfo.getGroupsProcessedInternal().add(groupName);
+      batchInfo.getGroupsProcessedInternal().add(groupDto);
     } else {
-      if (!batchInfo.getGroupsProcessedInternal().contains(groupName)) {
-        batchInfo.getGroupsToBeCreated().add(groupName);
+      if (!batchInfo.getGroupsProcessedInternal().contains(groupDto)) {
+        batchInfo.getGroupsToBeCreated().add(groupDto);
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/LdapBatchDto.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/LdapBatchDto.java b/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/LdapBatchDto.java
index 0f9089a..8025a5a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/LdapBatchDto.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/LdapBatchDto.java
@@ -24,34 +24,34 @@ import java.util.Set;
  * Contains information for batch database update on LDAP synchronization.
  */
 public class LdapBatchDto {
-  private final Set<String> groupsToBecomeLdap = new HashSet<>();
-  private final Set<String> groupsToBeCreated = new HashSet<>();
-  private final Set<String> groupsToBeRemoved = new HashSet<>();
-  private final Set<String> groupsProcessedInternal = new HashSet<>();
-  private final Set<String> usersSkipped = new HashSet<>();
-  private final Set<String> usersToBecomeLdap = new HashSet<>();
-  private final Set<String> usersToBeCreated = new HashSet<>();
-  private final Set<String> usersToBeRemoved = new HashSet<>();
+  private final Set<LdapGroupDto> groupsToBecomeLdap = new HashSet<>();
+  private final Set<LdapGroupDto> groupsToBeCreated = new HashSet<>();
+  private final Set<LdapGroupDto> groupsToBeRemoved = new HashSet<>();
+  private final Set<LdapGroupDto> groupsProcessedInternal = new HashSet<>();
+  private final Set<LdapUserDto> usersSkipped = new HashSet<>();
+  private final Set<LdapUserDto> usersToBecomeLdap = new HashSet<>();
+  private final Set<LdapUserDto> usersToBeCreated = new HashSet<>();
+  private final Set<LdapUserDto> usersToBeRemoved = new HashSet<>();
   private final Set<LdapUserGroupMemberDto> membershipToAdd = new HashSet<>();
   private final Set<LdapUserGroupMemberDto> membershipToRemove = new HashSet<>();
 
-  public Set<String> getUsersSkipped() {
+  public Set<LdapUserDto> getUsersSkipped() {
     return usersSkipped;
   }
 
-  public Set<String> getGroupsToBecomeLdap() {
+  public Set<LdapGroupDto> getGroupsToBecomeLdap() {
     return groupsToBecomeLdap;
   }
 
-  public Set<String> getGroupsToBeCreated() {
+  public Set<LdapGroupDto> getGroupsToBeCreated() {
     return groupsToBeCreated;
   }
 
-  public Set<String> getUsersToBecomeLdap() {
+  public Set<LdapUserDto> getUsersToBecomeLdap() {
     return usersToBecomeLdap;
   }
 
-  public Set<String> getUsersToBeCreated() {
+  public Set<LdapUserDto> getUsersToBeCreated() {
     return usersToBeCreated;
   }
 
@@ -63,15 +63,15 @@ public class LdapBatchDto {
     return membershipToRemove;
   }
 
-  public Set<String> getGroupsToBeRemoved() {
+  public Set<LdapGroupDto> getGroupsToBeRemoved() {
     return groupsToBeRemoved;
   }
 
-  public Set<String> getUsersToBeRemoved() {
+  public Set<LdapUserDto> getUsersToBeRemoved() {
     return usersToBeRemoved;
   }
 
-  public Set<String> getGroupsProcessedInternal() {
+  public Set<LdapGroupDto> getGroupsProcessedInternal() {
     return groupsProcessedInternal;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d459d130/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 34bbe97..81d73d2 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
@@ -40,6 +40,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -232,7 +233,7 @@ public class AmbariLdapDataPopulatorTest {
     verify(populator.loadLdapTemplate(), populator.getLdapServerProperties(), configuration);
   }
 
-  private <T> Set<T> createSet(T...elements) {
+  private <T> Set<T> createSet(T... elements) {
     return new HashSet<>(Arrays.asList(elements));
   }
 
@@ -287,9 +288,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeExistingLdapGroups(batchInfo);
 
-    assertEquals(2, result.getGroupsToBeRemoved().size());
-    assertTrue(result.getGroupsToBeRemoved().contains("group2"));
-    assertTrue(result.getGroupsToBeRemoved().contains("group5"));
+    verifyGroupsInSet(result.getGroupsToBeRemoved(), Sets.newHashSet("group2", "group5"));
     assertTrue(result.getGroupsToBecomeLdap().isEmpty());
     assertTrue(result.getGroupsToBeCreated().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
@@ -334,11 +333,11 @@ public class AmbariLdapDataPopulatorTest {
     LdapBatchDto batchInfo = new LdapBatchDto();
     replay(configuration, users, group1, group2);
     AmbariLdapDataPopulator dataPopulator = createMockBuilder(AmbariLdapDataPopulatorTestInstance.class)
-      .withConstructor(configuration, users)
-      .addMockedMethod("getLdapGroups")
-      .addMockedMethod("getLdapUserByMemberAttr")
-      .addMockedMethod("getLdapGroupByMemberAttr")
-      .createNiceMock();
+        .withConstructor(configuration, users)
+        .addMockedMethod("getLdapGroups")
+        .addMockedMethod("getLdapUserByMemberAttr")
+        .addMockedMethod("getLdapGroupByMemberAttr")
+        .createNiceMock();
 
     expect(dataPopulator.getLdapUserByMemberAttr(anyString())).andReturn(null).anyTimes();
     expect(dataPopulator.getLdapGroupByMemberAttr("group2")).andReturn(group2Dto);
@@ -401,14 +400,14 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup3, externalGroup4);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup),
-        EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
     populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup1),
-      EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+        EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
     expectLastCall();
     populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup2), EasyMock.anyObject(),
-      EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
     expectLastCall();
     expect(populator.getLdapGroups("x*")).andReturn(externalGroups);
     expect(populator.getLdapGroups("group1")).andReturn(Collections.singleton(externalGroup1));
@@ -420,21 +419,15 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeLdapGroups(createSet("x*", "group1", "group2"), batchInfo);
 
-    assertEquals(1, result.getGroupsToBecomeLdap().size());
-    assertTrue(result.getGroupsToBecomeLdap().contains("group1"));
-    assertEquals(2, result.getGroupsToBeCreated().size());
-    assertTrue(result.getGroupsToBeCreated().contains("xgroup1"));
-    assertTrue(result.getGroupsToBeCreated().contains("xgroup2"));
+    verifyGroupsInSet(result.getGroupsToBecomeLdap(), Sets.newHashSet("group1"));
+    verifyGroupsInSet(result.getGroupsToBeCreated(), Sets.newHashSet("xgroup1", "xgroup2"));
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getMembershipToAdd().isEmpty());
     assertTrue(result.getMembershipToRemove().isEmpty());
     assertTrue(result.getUsersToBecomeLdap().isEmpty());
     assertTrue(result.getUsersToBeRemoved().isEmpty());
-    assertTrue(result.getGroupsProcessedInternal().contains("group1"));
-    assertTrue(result.getGroupsProcessedInternal().contains("group2"));
-    assertTrue(!result.getGroupsProcessedInternal().contains("xgroup1"));
-    assertTrue(!result.getGroupsProcessedInternal().contains("xgroup2"));
+    verifyGroupsInSet(result.getGroupsProcessedInternal(), Sets.newHashSet("group1", "group2"));
     verify(populator.loadLdapTemplate(), populator);
   }
 
@@ -487,11 +480,11 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup3, externalGroup4);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), EasyMock.anyObject(), EasyMock.anyObject(),
-        EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
     populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup2), EasyMock.anyObject(),
-      EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
     expectLastCall();
     expect(populator.getLdapGroups("x*")).andReturn(externalGroups);
     expect(populator.getLdapGroups("group2")).andReturn(Collections.singleton(externalGroup2));
@@ -502,9 +495,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeLdapGroups(createSet("x*", "group2"), batchInfo);
 
-    assertEquals(2, result.getGroupsToBeCreated().size());
-    assertTrue(result.getGroupsToBeCreated().contains("xgroup1"));
-    assertTrue(result.getGroupsToBeCreated().contains("xgroup2"));
+    verifyGroupsInSet(result.getGroupsToBeCreated(), Sets.newHashSet("xgroup1", "xgroup2"));
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBecomeLdap().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
@@ -563,7 +554,7 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2, externalGroup3, externalGroup4);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), EasyMock.anyObject(),
-        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
     expect(populator.getLdapGroups("group*")).andReturn(externalGroups);
@@ -574,9 +565,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeLdapGroups(createSet("group*"), batchInfo);
 
-    assertEquals(2, result.getGroupsToBecomeLdap().size());
-    assertTrue(result.getGroupsToBecomeLdap().contains("group1"));
-    assertTrue(result.getGroupsToBecomeLdap().contains("group4"));
+    verifyGroupsInSet(result.getGroupsToBecomeLdap(), Sets.newHashSet("group1", "group4"));
     assertTrue(result.getGroupsToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
@@ -694,7 +683,7 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2, externalGroup3, externalGroup4);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), EasyMock.anyObject(),
-        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
 
@@ -707,13 +696,9 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapGroups(batchInfo);
 
-    assertEquals(1, result.getGroupsToBeRemoved().size());
-    assertTrue(result.getGroupsToBeRemoved().contains("group2"));
-    assertEquals(1, result.getGroupsToBecomeLdap().size());
-    assertTrue(result.getGroupsToBecomeLdap().contains("group3"));
-    assertEquals(2, result.getGroupsToBeCreated().size());
-    assertTrue(result.getGroupsToBeCreated().contains("group6"));
-    assertTrue(result.getGroupsToBeCreated().contains("group7"));
+    verifyGroupsInSet(result.getGroupsToBeRemoved(), Sets.newHashSet("group2"));
+    verifyGroupsInSet(result.getGroupsToBecomeLdap(), Sets.newHashSet("group3"));
+    verifyGroupsInSet(result.getGroupsToBeCreated(), Sets.newHashSet("group6", "group7"));
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getMembershipToAdd().isEmpty());
     assertTrue(result.getMembershipToRemove().isEmpty());
@@ -756,7 +741,7 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), EasyMock.anyObject(),
-        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
     expect(populator.getExternalLdapGroupInfo()).andReturn(externalGroups);
@@ -768,9 +753,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapGroups(batchInfo);
 
-    assertEquals(2, result.getGroupsToBeCreated().size());
-    assertTrue(result.getGroupsToBeCreated().contains("group3"));
-    assertTrue(result.getGroupsToBeCreated().contains("group4"));
+    verifyGroupsInSet(result.getGroupsToBeCreated(), Sets.newHashSet("group3", "group4"));
     assertTrue(result.getGroupsToBecomeLdap().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
@@ -821,7 +804,7 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup1);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), EasyMock.anyObject(),
-        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
     expect(populator.getExternalLdapGroupInfo()).andReturn(externalGroups);
@@ -833,9 +816,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapGroups(batchInfo);
 
-    assertEquals(2, result.getGroupsToBeRemoved().size());
-    assertTrue(result.getGroupsToBeRemoved().contains("group2"));
-    assertTrue(result.getGroupsToBeRemoved().contains("group4"));
+    verifyGroupsInSet(result.getGroupsToBeRemoved(), Sets.newHashSet("group2", "group4"));
     assertTrue(result.getGroupsToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBecomeLdap().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
@@ -885,7 +866,7 @@ public class AmbariLdapDataPopulatorTest {
     Set<LdapGroupDto> externalGroups = createSet(externalGroup1, externalGroup2);
     for (LdapGroupDto externalGroup : externalGroups) {
       populator.refreshGroupMembers(eq(batchInfo), eq(externalGroup), EasyMock.anyObject(),
-        EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
+          EasyMock.anyObject(), EasyMock.anyObject(), anyBoolean());
       expectLastCall();
     }
     expect(populator.getExternalLdapGroupInfo()).andReturn(externalGroups);
@@ -897,9 +878,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapGroups(batchInfo);
 
-    assertEquals(2, result.getGroupsToBecomeLdap().size());
-    assertTrue(result.getGroupsToBecomeLdap().contains("group2"));
-    assertTrue(result.getGroupsToBecomeLdap().contains("group3"));
+    verifyGroupsInSet(result.getGroupsToBecomeLdap(), Sets.newHashSet("group2", "group3"));
     assertTrue(result.getGroupsToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
@@ -961,13 +940,9 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapUsers(new LdapBatchDto());
 
-    assertEquals(1, result.getUsersToBeRemoved().size());
-    assertTrue(result.getUsersToBeRemoved().contains("synced_user1"));
-    assertEquals(2, result.getUsersToBeCreated().size());
-    assertTrue(result.getUsersToBeCreated().contains("external_user1"));
-    assertTrue(result.getUsersToBeCreated().contains("external_user2"));
-    assertEquals(1, result.getUsersToBecomeLdap().size());
-    assertTrue(result.getUsersToBecomeLdap().contains("unsynced_user2"));
+    verifyUsersInSet(result.getUsersToBeRemoved(), Sets.newHashSet("synced_user1"));
+    verifyUsersInSet(result.getUsersToBeCreated(), Sets.newHashSet("external_user1", "external_user2"));
+    verifyUsersInSet(result.getUsersToBecomeLdap(), Sets.newHashSet("unsynced_user2"));
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBecomeLdap().isEmpty());
@@ -1022,9 +997,8 @@ public class AmbariLdapDataPopulatorTest {
     populator.setLdapServerProperties(ldapServerProperties);
 
     LdapBatchDto result = populator.synchronizeAllLdapUsers(new LdapBatchDto());
-    assertEquals(2, result.getUsersSkipped().size());
-    assertTrue(result.getUsersSkipped().contains("local1"));
-    assertTrue(result.getUsersSkipped().contains("local2"));
+
+    verifyUsersInSet(result.getUsersSkipped(), Sets.newHashSet("local1", "local2"));
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeCreated().isEmpty());
@@ -1075,9 +1049,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapUsers(new LdapBatchDto());
 
-    assertEquals(2, result.getUsersToBeCreated().size());
-    assertTrue(result.getUsersToBeCreated().contains("user3"));
-    assertTrue(result.getUsersToBeCreated().contains("user4"));
+    verifyUsersInSet(result.getUsersToBeCreated(), Sets.newHashSet("user3", "user4"));
     assertTrue(result.getUsersToBecomeLdap().isEmpty());
     assertTrue(result.getUsersToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
@@ -1126,9 +1098,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapUsers(new LdapBatchDto());
 
-    assertEquals(2, result.getUsersToBeRemoved().size());
-    assertTrue(result.getUsersToBeRemoved().contains("user3"));
-    assertTrue(result.getUsersToBeRemoved().contains("user1"));
+    verifyUsersInSet(result.getUsersToBeRemoved(), Sets.newHashSet("user3", "user1"));
     assertTrue(result.getUsersToBecomeLdap().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
@@ -1185,8 +1155,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeAllLdapUsers(new LdapBatchDto());
 
-    assertEquals(1, result.getUsersToBecomeLdap().size());
-    assertTrue(result.getUsersToBecomeLdap().contains("user3"));
+    verifyUsersInSet(result.getUsersToBecomeLdap(), Sets.newHashSet("user3"));
     assertTrue(result.getUsersToBeRemoved().isEmpty());
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
@@ -1238,8 +1207,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeExistingLdapUsers(new LdapBatchDto());
 
-    assertEquals(1, result.getUsersToBeRemoved().size());
-    assertTrue(result.getUsersToBeRemoved().contains("synced_user1"));
+    verifyUsersInSet(result.getUsersToBeRemoved(), Sets.newHashSet("synced_user1"));
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getUsersToBecomeLdap().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
@@ -1303,11 +1271,8 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeLdapUsers(createSet("user1", "user2", "xuser*"), new LdapBatchDto());
 
-    assertEquals(2, result.getUsersToBeCreated().size());
-    assertTrue(result.getUsersToBeCreated().contains("xuser3"));
-    assertTrue(result.getUsersToBeCreated().contains("xuser4"));
-    assertEquals(1, result.getUsersToBecomeLdap().size());
-    assertTrue(result.getUsersToBecomeLdap().contains("user1"));
+    verifyUsersInSet(result.getUsersToBeCreated(), Sets.newHashSet("xuser3", "xuser4"));
+    verifyUsersInSet(result.getUsersToBecomeLdap(), Sets.newHashSet("user1"));
     assertTrue(result.getUsersToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeCreated().isEmpty());
@@ -1367,9 +1332,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeLdapUsers(createSet("user2", "xuser*"), new LdapBatchDto());
 
-    assertEquals(2, result.getUsersToBeCreated().size());
-    assertTrue(result.getUsersToBeCreated().contains("xuser3"));
-    assertTrue(result.getUsersToBeCreated().contains("xuser4"));
+    verifyUsersInSet(result.getUsersToBeCreated(), Sets.newHashSet("xuser3", "xuser4"));
     assertTrue(result.getUsersToBecomeLdap().isEmpty());
     assertTrue(result.getUsersToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
@@ -1431,9 +1394,7 @@ public class AmbariLdapDataPopulatorTest {
 
     LdapBatchDto result = populator.synchronizeLdapUsers(createSet("user2", "user1", "user6"), new LdapBatchDto());
 
-    assertEquals(2, result.getUsersToBecomeLdap().size());
-    assertTrue(result.getUsersToBecomeLdap().contains("user1"));
-    assertTrue(result.getUsersToBecomeLdap().contains("user6"));
+    verifyUsersInSet(result.getUsersToBecomeLdap(), Sets.newHashSet("user1", "user6"));
     assertTrue(result.getUsersToBeCreated().isEmpty());
     assertTrue(result.getUsersToBeRemoved().isEmpty());
     assertTrue(result.getGroupsToBeRemoved().isEmpty());
@@ -1513,11 +1474,11 @@ public class AmbariLdapDataPopulatorTest {
     replay(group1, group2);
 
     AmbariLdapDataPopulatorTestInstance populator = createMockBuilder(AmbariLdapDataPopulatorTestInstance.class)
-      .addMockedMethod("getLdapUserByMemberAttr")
-      .addMockedMethod("getLdapGroupByMemberAttr")
-      .addMockedMethod("getInternalMembers")
-      .withConstructor(configuration, users)
-      .createNiceMock();
+        .addMockedMethod("getLdapUserByMemberAttr")
+        .addMockedMethod("getLdapGroupByMemberAttr")
+        .addMockedMethod("getInternalMembers")
+        .withConstructor(configuration, users)
+        .createNiceMock();
 
     LdapGroupDto externalGroup = createNiceMock(LdapGroupDto.class);
     expect(externalGroup.getGroupName()).andReturn("group1").anyTimes();
@@ -1558,26 +1519,12 @@ public class AmbariLdapDataPopulatorTest {
 
     populator.refreshGroupMembers(batchInfo, externalGroup, internalUsers, internalGroups, null, true);
 
-    Set<String> groupMembersToAdd = new HashSet<>();
-    for (LdapUserGroupMemberDto ldapUserGroupMemberDto : batchInfo.getMembershipToAdd()) {
-      groupMembersToAdd.add(ldapUserGroupMemberDto.getUserName());
-    }
-    assertEquals(3, groupMembersToAdd.size());
-    assertTrue(groupMembersToAdd.contains("user2"));
-    assertTrue(groupMembersToAdd.contains("user6"));
-    Set<String> groupMembersToRemove = new HashSet<>();
-    for (LdapUserGroupMemberDto ldapUserGroupMemberDto : batchInfo.getMembershipToRemove()) {
-      groupMembersToRemove.add(ldapUserGroupMemberDto.getUserName());
-    }
-    assertEquals(2, groupMembersToRemove.size());
-    assertTrue(groupMembersToRemove.contains("user3"));
-    assertEquals(1, batchInfo.getUsersToBeCreated().size());
-    assertTrue(batchInfo.getUsersToBeCreated().contains("user6"));
-    assertEquals(1, batchInfo.getUsersToBecomeLdap().size());
-    assertTrue(batchInfo.getUsersToBecomeLdap().contains("user1"));
-    assertTrue(!batchInfo.getUsersToBecomeLdap().contains("user4"));
+    verifyMembershipInSet(batchInfo.getMembershipToAdd(), Sets.newHashSet("user1", "user2", "user6"));
+    verifyMembershipInSet(batchInfo.getMembershipToRemove(), Sets.newHashSet("user3", "user4"));
+    verifyUsersInSet(batchInfo.getUsersToBeCreated(), Sets.newHashSet("user6"));
+    verifyUsersInSet(batchInfo.getUsersToBecomeLdap(), Sets.newHashSet("user1"));
     assertTrue(batchInfo.getGroupsToBecomeLdap().isEmpty());
-    assertEquals(1, batchInfo.getGroupsToBeCreated().size());
+    verifyGroupsInSet(batchInfo.getGroupsToBeCreated(), Sets.newHashSet("group1"));
     assertTrue(batchInfo.getGroupsToBeRemoved().isEmpty());
     assertTrue(batchInfo.getUsersToBeRemoved().isEmpty());
     verify(populator.loadLdapTemplate(), populator);
@@ -1701,7 +1648,7 @@ public class AmbariLdapDataPopulatorTest {
     expect(ldapServerProperties.getDnAttribute()).andReturn("dn").anyTimes();
     expect(ldapServerProperties.getBaseDN()).andReturn("cn=testUser,ou=Ambari,dc=SME,dc=support,dc=com").anyTimes();
 
-    expect(ldapTemplate.search(eq(LdapUtils.newLdapName("cn=testUser,ou=Ambari,dc=SME,dc=support,dc=com") ), eq("(&(objectClass=objectClass)(uid=foo))"), anyObject(SearchControls.class), capture(contextMapperCapture))).andReturn(list);
+    expect(ldapTemplate.search(eq(LdapUtils.newLdapName("cn=testUser,ou=Ambari,dc=SME,dc=support,dc=com")), eq("(&(objectClass=objectClass)(uid=foo))"), anyObject(SearchControls.class), capture(contextMapperCapture))).andReturn(list);
 
     replay(ldapTemplate, ldapServerProperties, users, configuration, processor, cookie);
 
@@ -1727,7 +1674,7 @@ public class AmbariLdapDataPopulatorTest {
 
     PowerMock.mockStatic(AmbariLdapUtils.class);
     expect(AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, "dc=SME,dc=support,dc=com"))
-      .andReturn(false).anyTimes();
+        .andReturn(false).anyTimes();
 
     replay(adapter, ldapServerProperties);
     PowerMock.replayAll();
@@ -1768,7 +1715,7 @@ public class AmbariLdapDataPopulatorTest {
 
     PowerMock.mockStatic(AmbariLdapUtils.class);
     expect(AmbariLdapUtils.isLdapObjectOutOfScopeFromBaseDn(adapter, "dc=SME,dc=support,dc=com"))
-      .andReturn(false).anyTimes();
+        .andReturn(false).anyTimes();
 
     replay(ldapServerProperties, adapter);
     PowerMock.replayAll();
@@ -1906,7 +1853,7 @@ public class AmbariLdapDataPopulatorTest {
     // GIVEN
     Configuration configuration = createNiceMock(Configuration.class);
     Users users = createNiceMock(Users.class);
-    String  syncUserMemberPattern = "(?<sid>.*);(?<guid>.*);(?<member>.*)";
+    String syncUserMemberPattern = "(?<sid>.*);(?<guid>.*);(?<member>.*)";
     String memberAttribute = "<SID=...>;<GUID=...>;cn=member,dc=apache,dc=org";
     AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
     // WHEN
@@ -1920,7 +1867,7 @@ public class AmbariLdapDataPopulatorTest {
     // GIVEN
     Configuration configuration = createNiceMock(Configuration.class);
     Users users = createNiceMock(Users.class);
-    String  syncUserMemberPattern = "(?<sid>.*);(?<guid>.*);(?<mem>.*)";
+    String syncUserMemberPattern = "(?<sid>.*);(?<guid>.*);(?<mem>.*)";
     String memberAttribute = "<SID=...>;<GUID=...>;cn=member,dc=apache,dc=org";
     AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
     // WHEN
@@ -1947,7 +1894,7 @@ public class AmbariLdapDataPopulatorTest {
     // GIVEN
     Configuration configuration = createNiceMock(Configuration.class);
     Users users = createNiceMock(Users.class);
-    String  syncUserMemberPattern = "(?<sid>.*);(?<guid>.*);(?<member>.*)";
+    String syncUserMemberPattern = "(?<sid>.*);(?<guid>.*);(?<member>.*)";
     AmbariLdapDataPopulatorTestInstance populator = new AmbariLdapDataPopulatorTestInstance(configuration, users);
     // WHEN
     String result = populator.getUniqueIdByMemberPattern(null, syncUserMemberPattern);
@@ -1990,11 +1937,10 @@ public class AmbariLdapDataPopulatorTest {
     }
 
     UserAuthenticationEntity userAuthenticationEntity = new UserAuthenticationEntity();
-    if(ldapUser) {
+    if (ldapUser) {
       userAuthenticationEntity.setAuthenticationType(UserAuthenticationType.LDAP);
       userAuthenticationEntity.setAuthenticationKey("some dn");
-    }
-    else {
+    } else {
       userAuthenticationEntity.setAuthenticationType(UserAuthenticationType.LOCAL);
       userAuthenticationEntity.setAuthenticationKey("some password (normally encoded)");
     }
@@ -2018,4 +1964,55 @@ public class AmbariLdapDataPopulatorTest {
   private User createLocalUserWithGroup(GroupEntity group) {
     return createUser("LocalUserWithGroup", false, group);
   }
+
+  private void verifyUsersInSet(Set<LdapUserDto> usersToVerify, HashSet<String> expectedUserNames) {
+    assertEquals(expectedUserNames.size(), usersToVerify.size());
+
+    HashSet<LdapUserDto> usersToBeVerified = new HashSet<>(usersToVerify);
+    Set<String> expected = new HashSet<>(expectedUserNames);
+
+    Iterator<LdapUserDto> iterator = usersToBeVerified.iterator();
+    while (iterator.hasNext()) {
+      LdapUserDto user = iterator.next();
+      if (expected.remove(user.getUserName())) {
+        iterator.remove();
+      }
+    }
+
+    assertTrue(usersToBeVerified.isEmpty());
+  }
+
+  private void verifyMembershipInSet(Set<LdapUserGroupMemberDto> membershipsToVerify, HashSet<String> expectedUserNames) {
+    assertEquals(expectedUserNames.size(), membershipsToVerify.size());
+
+    HashSet<LdapUserGroupMemberDto> membershipsToBeVerified = new HashSet<>(membershipsToVerify);
+    Set<String> expected = new HashSet<>(expectedUserNames);
+
+    Iterator<LdapUserGroupMemberDto> iterator = membershipsToBeVerified.iterator();
+    while (iterator.hasNext()) {
+      LdapUserGroupMemberDto membership = iterator.next();
+      if (expected.remove(membership.getUserName())) {
+        iterator.remove();
+      }
+    }
+
+    assertTrue(membershipsToBeVerified.isEmpty());
+  }
+
+  private void verifyGroupsInSet(Set<LdapGroupDto> groupsToVerify, HashSet<String> expectedGroupNames) {
+    assertEquals(expectedGroupNames.size(), groupsToVerify.size());
+
+    HashSet<LdapGroupDto> groupsToBeVerified = new HashSet<>(groupsToVerify);
+    Set<String> expected = new HashSet<>(expectedGroupNames);
+
+    Iterator<LdapGroupDto> iterator = groupsToBeVerified.iterator();
+    while (iterator.hasNext()) {
+      LdapGroupDto group = iterator.next();
+      if (expected.remove(group.getGroupName())) {
+        iterator.remove();
+      }
+    }
+
+    assertTrue(groupsToBeVerified.isEmpty());
+  }
 }