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 <[email protected]> Authored: Wed Nov 29 14:41:56 2017 -0500 Committer: Robert Levas <[email protected]> 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()); + } }
