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/06/15 15:06:17 UTC

[3/8] ambari git commit: AMBARI-21147. Update Database Access Layer to Support New Database Schema for Improved User Account Management (rlevas)

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/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 9cdde8f..35eb255 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
@@ -22,16 +22,15 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.inject.Inject;
 import javax.persistence.EntityManager;
 
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.hooks.HookContextFactory;
 import org.apache.ambari.server.hooks.HookService;
 import org.apache.ambari.server.orm.dao.GroupDAO;
@@ -41,7 +40,7 @@ import org.apache.ambari.server.orm.dao.PrincipalDAO;
 import org.apache.ambari.server.orm.dao.PrincipalTypeDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ResourceDAO;
-import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
+import org.apache.ambari.server.orm.dao.UserAuthenticationDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.entities.GroupEntity;
 import org.apache.ambari.server.orm.entities.MemberEntity;
@@ -50,17 +49,16 @@ import org.apache.ambari.server.orm.entities.PrincipalEntity;
 import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.security.ldap.LdapBatchDto;
 import org.apache.ambari.server.security.ldap.LdapUserGroupMemberDto;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 
+import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
@@ -74,31 +72,37 @@ public class Users {
   private static final Logger LOG = LoggerFactory.getLogger(Users.class);
 
   @Inject
-  Provider<EntityManager> entityManagerProvider;
-  @Inject
-  protected UserDAO userDAO;
-  @Inject
-  protected GroupDAO groupDAO;
+  private Provider<EntityManager> entityManagerProvider;
+
   @Inject
-  protected MemberDAO memberDAO;
+  private UserDAO userDAO;
+
   @Inject
-  protected PrincipalDAO principalDAO;
+  private UserAuthenticationDAO userAuthenticationDAO;
+
   @Inject
-  protected PermissionDAO permissionDAO;
+  private GroupDAO groupDAO;
+
   @Inject
-  protected PrivilegeDAO privilegeDAO;
+  private MemberDAO memberDAO;
+
   @Inject
-  protected ResourceDAO resourceDAO;
+  private PrincipalDAO principalDAO;
+
   @Inject
-  protected ResourceTypeDAO resourceTypeDAO;
+  private PermissionDAO permissionDAO;
+
   @Inject
-  protected PrincipalTypeDAO principalTypeDAO;
+  private PrivilegeDAO privilegeDAO;
+
   @Inject
-  protected PasswordEncoder passwordEncoder;
+  private ResourceDAO resourceDAO;
+
   @Inject
-  protected Configuration configuration;
+  private PrincipalTypeDAO principalTypeDAO;
+
   @Inject
-  private AmbariLdapAuthenticationProvider ldapAuthenticationProvider;
+  private PasswordEncoder passwordEncoder;
 
   @Inject
   private Provider<HookService> hookServiceProvider;
@@ -117,52 +121,38 @@ public class Users {
     return users;
   }
 
-  /**
-   * This method works incorrectly, userName is not unique if users have different types
-   *
-   * @return One user. Priority is LOCAL -> LDAP -> JWT -> PAM
-   */
-  @Deprecated
-  public User getAnyUser(String userName) {
-    UserEntity userEntity = userDAO.findSingleUserByName(userName);
-    return (null == userEntity) ? null : new User(userEntity);
+  public List<UserEntity> getAllUserEntities() {
+    return userDAO.findAll();
+  }
+
+  public UserEntity getUserEntity(String userName) {
+    return (userName == null) ? null : userDAO.findUserByName(userName);
+  }
+
+  public UserEntity getUserEntity(Integer userId) {
+    return (userId == null) ? null : userDAO.findByPK(userId);
   }
 
-  public User getUser(String userName, UserType userType) {
-    UserEntity userEntity = userDAO.findUserByNameAndType(userName, userType);
+  public User getUser(UserEntity userEntity) {
     return (null == userEntity) ? null : new User(userEntity);
   }
 
   public User getUser(Integer userId) {
-    UserEntity userEntity = userDAO.findByPK(userId);
-    return (null == userEntity) ? null : new User(userEntity);
+    return getUser(getUserEntity(userId));
+  }
+
+  public User getUser(String userName) {
+    return getUser(getUserEntity(userName));
   }
 
   /**
-   * Retrieves User then userName is unique in users DB. Will return null if there no user with provided userName or
-   * there are some users with provided userName but with different types.
-   *
-   * <p>User names in the future will likely be unique hence the deprecation.</p>
+   * Modifies password of local user
    *
-   * @param userName
-   * @return User if userName is unique in DB, null otherwise
+   * @throws AmbariException
    */
-  @Deprecated
-  public User getUserIfUnique(String userName) {
-    List<UserEntity> userEntities = new ArrayList<>();
-    UserEntity userEntity = userDAO.findUserByNameAndType(userName, UserType.LOCAL);
-    if (userEntity != null) {
-      userEntities.add(userEntity);
-    }
-    userEntity = userDAO.findUserByNameAndType(userName, UserType.LDAP);
-    if (userEntity != null) {
-      userEntities.add(userEntity);
-    }
-    userEntity = userDAO.findUserByNameAndType(userName, UserType.JWT);
-    if (userEntity != null) {
-      userEntities.add(userEntity);
-    }
-    return (userEntities.isEmpty() || userEntities.size() > 1) ? null : new User(userEntities.get(0));
+  public synchronized void modifyPassword(String userName, String currentUserPassword, String newPassword) throws AmbariException, AuthorizationException {
+    UserEntity userEntity = userDAO.findUserByName(userName);
+    modifyPassword(userEntity, currentUserPassword, newPassword);
   }
 
   /**
@@ -170,59 +160,58 @@ public class Users {
    *
    * @throws AmbariException
    */
-  public synchronized void modifyPassword(String userName, String currentUserPassword, String newPassword) throws AmbariException {
+  public synchronized void modifyPassword(UserEntity userEntity, String currentUserPassword, String newPassword) throws AmbariException, AuthorizationException {
 
-    SecurityContext securityContext = SecurityContextHolder.getContext();
-    String currentUserName = securityContext.getAuthentication().getName();
-    if (currentUserName == null) {
+    String authenticatedUserName = AuthorizationHelper.getAuthenticatedName();
+    if (authenticatedUserName == null) {
       throw new AmbariException("Authentication required. Please sign in.");
     }
 
-    UserEntity currentUserEntity = userDAO.findLocalUserByName(currentUserName);
-
-    //Authenticate LDAP user
-    boolean isLdapUser = false;
-    if (currentUserEntity == null) {
-      currentUserEntity = userDAO.findLdapUserByName(currentUserName);
-      try {
-        ldapAuthenticationProvider.authenticate(
-            new UsernamePasswordAuthenticationToken(currentUserName, currentUserPassword));
-        isLdapUser = true;
-      } catch (InvalidUsernamePasswordCombinationException ex) {
-        throw new AmbariException(ex.getMessage());
-      }
-    }
-
-    boolean isCurrentUserAdmin = false;
-    for (PrivilegeEntity privilegeEntity : currentUserEntity.getPrincipal().getPrivileges()) {
-      if (privilegeEntity.getPermission().getPermissionName().equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION_NAME)) {
-        isCurrentUserAdmin = true;
-        break;
+    if (userEntity != null) {
+    /* **************************************************
+     * Ensure that the authenticated user can change the password for the subject user. at least one
+     * of the following must be true
+     *  * The authenticate user is requesting to change his/her own password
+     *  * The authenticated user has permissions to manage users
+     *  ************************************************** */
+      boolean isSelf = userEntity.getUserName().equalsIgnoreCase(authenticatedUserName);
+      if (!isSelf && !AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null, RoleAuthorization.AMBARI_MANAGE_USERS)) {
+        throw new AuthorizationException("You are not authorized perform this operation");
       }
-    }
 
-    UserEntity userEntity = userDAO.findLocalUserByName(userName);
+      List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+      UserAuthenticationEntity localAuthenticationEntity = null;
 
-    if ((userEntity != null) && (currentUserEntity != null)) {
-      if (!isCurrentUserAdmin && !userName.equals(currentUserName)) {
-        throw new AmbariException("You can't change password of another user");
+      // Find the authentication entity for the local authentication type - only one should exist, if one exists at all.
+      for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+        if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.LOCAL) {
+          localAuthenticationEntity = authenticationEntity;
+          break;
+        }
       }
 
-      if ((isLdapUser && isCurrentUserAdmin) || (StringUtils.isNotEmpty(currentUserPassword) &&
-          passwordEncoder.matches(currentUserPassword, currentUserEntity.getUserPassword()))) {
-        userEntity.setUserPassword(passwordEncoder.encode(newPassword));
-        userDAO.merge(userEntity);
-      } else {
+      if (localAuthenticationEntity == null) {
+        // The user account does not have a local authentication record.  Therefore there is no local
+        // password to change...
+        throw new AmbariException("An Ambari-specific password is not set for this user. The user's password cannot be changed at this time.");
+      } else if (isSelf &&
+          (StringUtils.isEmpty(currentUserPassword) || !passwordEncoder.matches(currentUserPassword, localAuthenticationEntity.getAuthenticationKey()))) {
+        // The authenticated user is the same user as subject user and the correct current password
+        // was not supplied.
         throw new AmbariException("Wrong current password provided");
       }
 
-    } else {
-      userEntity = userDAO.findLdapUserByName(userName);
-      if (userEntity != null) {
-        throw new AmbariException("Password of LDAP user cannot be modified");
-      } else {
-        throw new AmbariException("User " + userName + " not found");
+      // TODO: validate the new password...
+      if (StringUtils.isEmpty(newPassword)) {
+        throw new AmbariException("The new password does not meet the Ambari password requirements");
       }
+
+      // If we get here the authenticated user is authorized to change the password for the subject
+      // user and the correct current password was supplied (if required).
+      localAuthenticationEntity.setAuthenticationKey(passwordEncoder.encode(newPassword));
+      userAuthenticationDAO.merge(localAuthenticationEntity);
+    } else {
+      throw new AmbariException("User not found");
     }
   }
 
@@ -230,32 +219,28 @@ public class Users {
    * Enables/disables user.
    *
    * @param userName user name
+   * @param active   true if active; false if not active
    * @throws AmbariException if user does not exist
    */
   public synchronized void setUserActive(String userName, boolean active) throws AmbariException {
     UserEntity userEntity = userDAO.findUserByName(userName);
     if (userEntity != null) {
-      userEntity.setActive(active);
-      userDAO.merge(userEntity);
+      setUserActive(userEntity, active);
     } else {
       throw new AmbariException("User " + userName + " doesn't exist");
     }
   }
 
   /**
-   * Converts user to LDAP user.
+   * Enables/disables user.
    *
-   * @param userName user name
+   * @param userEntity the user
+   * @param active     true if active; false if not active
    * @throws AmbariException if user does not exist
    */
-  public synchronized void setUserLdap(String userName) throws AmbariException {
-    UserEntity userEntity = userDAO.findUserByName(userName);
-    if (userEntity != null) {
-      userEntity.setLdapUser(true);
-      userDAO.merge(userEntity);
-    } else {
-      throw new AmbariException("User " + userName + " doesn't exist");
-    }
+  public synchronized void setUserActive(UserEntity userEntity, boolean active) throws AmbariException {
+    userEntity.setActive(active);
+    userDAO.merge(userEntity);
   }
 
   /**
@@ -275,40 +260,45 @@ public class Users {
   }
 
   /**
-   * Creates new local user with provided userName and password.
+   * Creates new, active, user with provided userName, local username, and display name.
    *
-   * @param userName user name
-   * @param password password
+   * @param userName      user name
+   * @param localUserName the local username to use; if <code>null</code> or empty, userName will be used
+   * @param displayName   the name to display for presentation; if <code>null</code> or empty, userName will be used
+   * @return the new UserEntity
    * @throws AmbariException if user already exists
    */
-  public void createUser(String userName, String password) throws AmbariException {
-    createUser(userName, password, UserType.LOCAL, true, false);
+  public UserEntity createUser(String userName, String localUserName, String displayName) throws AmbariException {
+    return createUser(userName, localUserName, displayName, true);
   }
 
   /**
-   * Creates new user with provided userName and password.
+   * Creates new, user with provided userName, local username, and display name.
    *
-   * @param userName user name
-   * @param password password
-   * @param userType user type
-   * @param active   is user active
-   * @param admin    is user admin
+   * @param userName      user name
+   * @param localUserName the local username to use; if <code>null</code> or empty, userName will be used
+   * @param displayName   the name to display for presentation; if <code>null</code> or empty, userName will be used
+   * @param active        is user active
+   * @return the new UserEntity
    * @throws AmbariException if user already exists
    */
-  public synchronized void createUser(String userName, String password, UserType userType, Boolean active, Boolean
-      admin) throws AmbariException {
-    // if user type is not provided, assume LOCAL since the default
-    // value of user_type in the users table is LOCAL
-    if (userType == null) {
-      throw new AmbariException("UserType not specified.");
-    }
-
-    User existingUser = getAnyUser(userName);
-    if (existingUser != null) {
-      throw new AmbariException("User " + existingUser.getUserName() + " already exists with type "
-          + existingUser.getUserType());
+  @Transactional
+  public synchronized UserEntity createUser(String userName, String localUserName, String displayName, Boolean active) throws AmbariException {
+
+    String validatedUserName = UserName.fromString(userName).toString();
+    String validatedDisplayName = (StringUtils.isEmpty(displayName))
+        ? validatedUserName
+        : UserName.fromString(displayName).toString();
+    String validatedLocalUserName = (StringUtils.isEmpty(localUserName))
+        ? validatedUserName
+        : UserName.fromString(localUserName).toString();
+
+    // Ensure that the user does not already exist
+    if (userDAO.findUserByName(validatedUserName) != null) {
+      throw new AmbariException("User already exists");
     }
 
+    // Create the PrincipalEntity - needed for assigning privileges/roles
     PrincipalTypeEntity principalTypeEntity = principalTypeDAO.findById(PrincipalTypeEntity.USER_PRINCIPAL_TYPE);
     if (principalTypeEntity == null) {
       principalTypeEntity = new PrincipalTypeEntity();
@@ -320,42 +310,62 @@ public class Users {
     principalEntity.setPrincipalType(principalTypeEntity);
     principalDAO.create(principalEntity);
 
+    // Create the new UserEntity Record
     UserEntity userEntity = new UserEntity();
-    userEntity.setUserName(UserName.fromString(userName));
-    if (userType == UserType.LOCAL) {
-      //passwords should be stored for local users only
-      userEntity.setUserPassword(passwordEncoder.encode(password));
-    }
+    userEntity.setUserName(validatedUserName);
+    userEntity.setDisplayName(validatedDisplayName);
+    userEntity.setLocalUsername(validatedLocalUserName);
+
     userEntity.setPrincipal(principalEntity);
     if (active != null) {
       userEntity.setActive(active);
     }
 
-    userEntity.setUserType(userType);
-    if (userType == UserType.LDAP) {
-      userEntity.setLdapUser(true);
-    }
-
     userDAO.create(userEntity);
 
-    if (admin != null && admin) {
-      grantAdminPrivilege(userEntity.getUserId());
-    }
-
     // execute user initialization hook if required ()
-    hookServiceProvider.get().execute(hookContextFactory.createUserHookContext(userName));
+    hookServiceProvider.get().execute(hookContextFactory.createUserHookContext(validatedUserName));
+
+    return userEntity;
   }
 
+
+  /**
+   * Removes a user from the Ambari database.
+   * <p>
+   * It is expected that the assoicated user authencation records are removed by this operation
+   * as well.
+   *
+   * @param user the user to remove
+   * @throws AmbariException
+   */
+  @Transactional
   public synchronized void removeUser(User user) throws AmbariException {
     UserEntity userEntity = userDAO.findByPK(user.getUserId());
     if (userEntity != null) {
+      removeUser(userEntity);
+    } else {
+      throw new AmbariException("User " + user + " doesn't exist");
+    }
+  }
+
+  /**
+   * Removes a user from the Ambari database.
+   * <p>
+   * It is expected that the assoicated user authencation records are removed by this operation
+   * as well.
+   *
+   * @param userEntity the user to remove
+   * @throws AmbariException
+   */
+  @Transactional
+  public synchronized void removeUser(UserEntity userEntity) throws AmbariException {
+    if (userEntity != null) {
       if (!isUserCanBeRemoved(userEntity)) {
         throw new AmbariException("Could not remove user " + userEntity.getUserName() +
             ". System should have at least one administrator.");
       }
       userDAO.remove(userEntity);
-    } else {
-      throw new AmbariException("User " + user + " doesn't exist");
     }
   }
 
@@ -410,7 +420,7 @@ public class Users {
    * Creates new group with provided name & type
    */
   @Transactional
-  public synchronized void createGroup(String groupName, GroupType groupType) {
+  public synchronized GroupEntity createGroup(String groupName, GroupType groupType) {
     // create an admin principal to represent this group
     PrincipalTypeEntity principalTypeEntity = principalTypeDAO.findById(PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE);
     if (principalTypeEntity == null) {
@@ -429,6 +439,7 @@ public class Users {
     groupEntity.setGroupType(groupType);
 
     groupDAO.create(groupEntity);
+    return groupEntity;
   }
 
   /**
@@ -476,30 +487,66 @@ public class Users {
   }
 
   /**
-   * Grants AMBARI.ADMINISTRATOR privilege to provided user.
+   * Test the user for Ambari Admistrator privileges.
+   *
+   * @param userEntity the user to test
+   * @return true if the user has Ambari Administrator privileges; otherwise false
+   */
+  public synchronized boolean hasAdminPrivilege(UserEntity userEntity) {
+    PrincipalEntity principalEntity = userEntity.getPrincipal();
+    if (principalEntity != null) {
+      Set<PrivilegeEntity> roles = principalEntity.getPrivileges();
+      if (roles != null) {
+        PermissionEntity adminPermission = permissionDAO.findAmbariAdminPermission();
+        Integer adminPermissionId = (adminPermission == null) ? null : adminPermission.getId();
+
+        if (adminPermissionId != null) {
+          for (PrivilegeEntity privilegeEntity : roles) {
+            PermissionEntity rolePermission = privilegeEntity.getPermission();
+            if ((rolePermission != null) && (adminPermissionId.equals(rolePermission.getId()))) {
+              return true;
+            }
+          }
+        }
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Grants Ambari Administrator privilege to provided user.
    *
    * @param userId user id
    */
   public synchronized void grantAdminPrivilege(Integer userId) {
-    final UserEntity user = userDAO.findByPK(userId);
+    grantAdminPrivilege(userDAO.findByPK(userId));
+  }
+
+  /**
+   * Grants Ambari Administrator privilege to provided user.
+   *
+   * @param userEntity the user
+   */
+  public synchronized void grantAdminPrivilege(UserEntity userEntity) {
     final PrivilegeEntity adminPrivilege = new PrivilegeEntity();
     adminPrivilege.setPermission(permissionDAO.findAmbariAdminPermission());
-    adminPrivilege.setPrincipal(user.getPrincipal());
+    adminPrivilege.setPrincipal(userEntity.getPrincipal());
     adminPrivilege.setResource(resourceDAO.findAmbariResource());
-    if (!user.getPrincipal().getPrivileges().contains(adminPrivilege)) {
+    if (!userEntity.getPrincipal().getPrivileges().contains(adminPrivilege)) {
       privilegeDAO.create(adminPrivilege);
-      user.getPrincipal().getPrivileges().add(adminPrivilege);
-      principalDAO.merge(user.getPrincipal()); //explicit merge for Derby support
-      userDAO.merge(user);
+      userEntity.getPrincipal().getPrivileges().add(adminPrivilege);
+      principalDAO.merge(userEntity.getPrincipal()); //explicit merge for Derby support
+      userDAO.merge(userEntity);
     }
   }
 
   /**
    * Grants privilege to provided group.
    *
-   * @param groupId group id
-   * @param resourceId resource id
-   * @param resourceType resource type
+   * @param groupId        group id
+   * @param resourceId     resource id
+   * @param resourceType   resource type
    * @param permissionName permission name
    */
   public synchronized void grantPrivilegeToGroup(Integer groupId, Long resourceId, ResourceType resourceType, String permissionName) {
@@ -508,7 +555,7 @@ public class Users {
     ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
     resourceTypeEntity.setId(resourceType.getId());
     resourceTypeEntity.setName(resourceType.name());
-    privilege.setPermission(permissionDAO.findPermissionByNameAndType(permissionName,resourceTypeEntity));
+    privilege.setPermission(permissionDAO.findPermissionByNameAndType(permissionName, resourceTypeEntity));
     privilege.setPrincipal(group.getPrincipal());
     privilege.setResource(resourceDAO.findById(resourceId));
     if (!group.getPrincipal().getPrivileges().contains(privilege)) {
@@ -521,17 +568,25 @@ public class Users {
   }
 
   /**
-   * Revokes AMBARI.ADMINISTRATOR privilege from provided user.
+   * Revokes Ambari Administrator privileges from provided user.
    *
    * @param userId user id
    */
   public synchronized void revokeAdminPrivilege(Integer userId) {
-    final UserEntity user = userDAO.findByPK(userId);
-    for (PrivilegeEntity privilege : user.getPrincipal().getPrivileges()) {
+    revokeAdminPrivilege(userDAO.findByPK(userId));
+  }
+
+  /**
+   * Revokes Ambari Administrator privileges from provided user.
+   *
+   * @param userEntity the user
+   */
+  public synchronized void revokeAdminPrivilege(UserEntity userEntity) {
+    for (PrivilegeEntity privilege : userEntity.getPrincipal().getPrivileges()) {
       if (privilege.getPermission().getPermissionName().equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION_NAME)) {
-        user.getPrincipal().getPrivileges().remove(privilege);
-        principalDAO.merge(user.getPrincipal()); //explicit merge for Derby support
-        userDAO.merge(user);
+        userEntity.getPrincipal().getPrivileges().remove(privilege);
+        principalDAO.merge(userEntity.getPrincipal()); //explicit merge for Derby support
+        userDAO.merge(userEntity);
         privilegeDAO.remove(privilege);
         break;
       }
@@ -552,9 +607,22 @@ public class Users {
       throw new AmbariException("User " + userName + " doesn't exist");
     }
 
-    if (isUserInGroup(userEntity, groupEntity)) {
-      throw new AmbariException("User " + userName + " is already present in group " + groupName);
-    } else {
+    addMemberToGroup(groupEntity, userEntity);
+  }
+
+  @Transactional
+  public synchronized void addMemberToGroup(GroupEntity groupEntity, UserEntity userEntity)
+      throws AmbariException {
+
+    if (groupEntity == null) {
+      throw new NullPointerException();
+    }
+
+    if (userEntity == null) {
+      throw new NullPointerException();
+    }
+
+    if (!isUserInGroup(userEntity, groupEntity)) {
       final MemberEntity memberEntity = new MemberEntity();
       memberEntity.setGroup(groupEntity);
       memberEntity.setUser(userEntity);
@@ -580,6 +648,13 @@ public class Users {
       throw new AmbariException("User " + userName + " doesn't exist");
     }
 
+    removeMemberFromGroup(groupEntity, userEntity);
+  }
+
+  @Transactional
+  public synchronized void removeMemberFromGroup(GroupEntity groupEntity, UserEntity userEntity)
+      throws AmbariException {
+
     if (isUserInGroup(userEntity, groupEntity)) {
       MemberEntity memberEntity = null;
       for (MemberEntity entity : userEntity.getMemberEntities()) {
@@ -593,10 +668,7 @@ public class Users {
       userDAO.merge(userEntity);
       groupDAO.merge(groupEntity);
       memberDAO.remove(memberEntity);
-    } else {
-      throw new AmbariException("User " + userName + " is not present in group " + groupName);
     }
-
   }
 
   /**
@@ -632,6 +704,9 @@ 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<>();
@@ -646,21 +721,38 @@ public class Users {
       allGroups.put(groupEntity.getGroupName(), groupEntity);
     }
 
-    final PrincipalTypeEntity userPrincipalType = principalTypeDAO
-        .ensurePrincipalTypeCreated(PrincipalTypeEntity.USER_PRINCIPAL_TYPE);
     final PrincipalTypeEntity groupPrincipalType = principalTypeDAO
         .ensurePrincipalTypeCreated(PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE);
 
-    // remove users
+    /* *****
+     * Remove users
+     *   First remove the relevant LDAP entries for this user.
+     *   If no more user authentication items exists for the user, then remove the user.
+     * ***** */
     final Set<UserEntity> usersToRemove = new HashSet<>();
+    final Set<UserAuthenticationEntity> authenticationEntitiesToRemove = new HashSet<>();
     for (String userName : batchInfo.getUsersToBeRemoved()) {
       UserEntity userEntity = userDAO.findUserByName(userName);
-      if (userEntity == null) {
-        continue;
+      if (userEntity != null) {
+        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+        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);
+            iterator.remove();
+          }
+        }
+
+        if (authenticationEntities.isEmpty()) {
+          allUsers.remove(userEntity.getUserName());
+          usersToRemove.add(userEntity);
+        }
       }
-      allUsers.remove(userEntity.getUserName());
-      usersToRemove.add(userEntity);
     }
+    userAuthenticationDAO.remove(authenticationEntitiesToRemove);
     userDAO.remove(usersToRemove);
 
     // remove groups
@@ -672,21 +764,46 @@ public class Users {
     }
     groupDAO.remove(groupsToRemove);
 
-    // update users
-    final Set<UserEntity> usersToBecomeLdap = new HashSet<>();
+    /* *****
+     * Update users
+     * ***** */
+    final Set<UserEntity> userEntitiesToUpdate = new HashSet<>();
     for (String userName : batchInfo.getUsersToBecomeLdap()) {
-      UserEntity userEntity = userDAO.findLocalUserByName(userName);
-      if (userEntity == null) {
-        userEntity = userDAO.findLdapUserByName(userName);
-        if (userEntity == null) {
-          continue;
+      // Ensure the username is all lowercase
+      userName = userName.toLowerCase();
+
+      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);
+          userEntitiesToUpdate.add(userEntity);
         }
+      } else {
+        LOG.warn("Failed to find user account for {} while enabling LDAP authentication for the user.", userName);
       }
-      userEntity.setLdapUser(true);
-      allUsers.put(userEntity.getUserName(), userEntity);
-      usersToBecomeLdap.add(userEntity);
     }
-    userDAO.merge(usersToBecomeLdap);
+    userDAO.merge(userEntitiesToUpdate);
 
     // update groups
     final Set<GroupEntity> groupsToBecomeLdap = new HashSet<>();
@@ -701,21 +818,25 @@ public class Users {
     // prepare create principals
     final List<PrincipalEntity> principalsToCreate = new ArrayList<>();
 
-    // prepare create users
-    final Set<UserEntity> usersToCreate = new HashSet<>();
+    // Create users
     for (String userName : batchInfo.getUsersToBeCreated()) {
-      final PrincipalEntity principalEntity = new PrincipalEntity();
-      principalEntity.setPrincipalType(userPrincipalType);
-      principalsToCreate.add(principalEntity);
+      UserEntity userEntity;
 
-      final UserEntity userEntity = new UserEntity();
-      userEntity.setUserName(UserName.fromString(userName));
-      userEntity.setUserPassword("");
-      userEntity.setPrincipal(principalEntity);
-      userEntity.setLdapUser(true);
+      try {
+        userEntity = createUser(userName, userName, userName, true);
+      } catch (AmbariException e) {
+        LOG.error(String.format("Failed to create new user: %s", userName), e);
+        userEntity = null;
+      }
 
-      allUsers.put(userEntity.getUserName(), userEntity);
-      usersToCreate.add(userEntity);
+      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));
+        userDAO.merge(userEntity);
+      }
     }
 
     // prepare create groups
@@ -734,9 +855,8 @@ public class Users {
       groupsToCreate.add(groupEntity);
     }
 
-    // create users and groups
+    // create groups
     principalDAO.create(principalsToCreate);
-    userDAO.create(usersToCreate);
     groupDAO.create(groupsToCreate);
 
     // create membership
@@ -766,12 +886,6 @@ public class Users {
 
     // clear cached entities
     entityManagerProvider.get().getEntityManagerFactory().getCache().evictAll();
-
-    if (!usersToCreate.isEmpty()) {
-      // entry point in the hook logic
-      hookServiceProvider.get().execute(hookContextFactory.createBatchUserHookContext(getUsersToGroupMap(usersToCreate)));
-    }
-
   }
 
   /**
@@ -900,11 +1014,29 @@ public class Users {
    * granted View User access on that File View instance.
    *
    * @param userName the username for the relevant user
-   * @param userType the user type for the relevant user
    * @return the users collection of implicit and explicit granted authorities
    */
-  public Collection<AmbariGrantedAuthority> getUserAuthorities(String userName, UserType userType) {
-    UserEntity userEntity = userDAO.findUserByNameAndType(userName, userType);
+  public Collection<AmbariGrantedAuthority> getUserAuthorities(String userName) {
+    return getUserAuthorities(getUserEntity(userName));
+  }
+
+  /**
+   * Gets the explicit and implicit authorities for the given user.
+   * <p>
+   * The explicit authorities are the authorities that have be explicitly set by assigning roles to
+   * a user.  For example the Cluster Operator role on a given cluster gives that the ability to
+   * start and stop services in that cluster, among other privileges for that particular cluster.
+   * <p>
+   * The implicit authorities are the authorities that have been given to the roles themselves which
+   * in turn are granted to the users that have been assigned those roles. For example if the
+   * Cluster User role for a given cluster has been given View User access on a specified File View
+   * instance, then all users who have the Cluster User role for that cluster will implicitly be
+   * granted View User access on that File View instance.
+   *
+   * @param userEntity the relevant user
+   * @return the users collection of implicit and explicit granted authorities
+   */
+  public Collection<AmbariGrantedAuthority> getUserAuthorities(UserEntity userEntity) {
     if (userEntity == null) {
       return Collections.emptyList();
     }
@@ -964,4 +1096,175 @@ public class Users {
     return implicitPrivileges;
   }
 
+  /**
+   * TODO: This is to be revisited for AMBARI-21217 (Update JWT Authentication process to work with improved user management facility)
+   * 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
+   * @throws AmbariException
+   */
+  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");
+          }
+        }
+      }
+    });
+  }
+
+  /**
+   * TODO: This is to be revisited for AMBARI-21223 (Update Kerberos Authentication process to work with improved user management facility)
+   * Adds the ability for a user to authenticate using a Kerberos token.
+   *
+   * @param userEntity    the user
+   * @param principalName the user's principal name
+   * @throws AmbariException
+   */
+  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 {
+        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+
+        // Ensure only one UserAuthenticationEntity exists for LOCAL for the user...
+        for (UserAuthenticationEntity entity : authenticationEntities) {
+          if ((entity.getAuthenticationType() == UserAuthenticationType.KERBEROS) &&
+              ((key == null) ? (entity.getAuthenticationKey() == null) : key.equals(entity.getAuthenticationKey()))) {
+            throw new AmbariException("The authentication type already exists for this user");
+          }
+        }
+      }
+    });
+  }
+
+  /**
+   * TODO: This is to be revisited for AMBARI-21220 (Update Local Authentication process to work with improved user management facility)
+   * 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
+   * @throws AmbariException
+   */
+  public void addLocalAuthentication(UserEntity userEntity, String password) throws AmbariException {
+
+    // 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");
+          }
+        }
+      }
+    });
+  }
+
+  /**
+   * TODO: This is to be revisited for AMBARI-21221 (Update Pam Authentication process to work with improved user management facility)
+   * Adds the ability for a user to authenticate using Pam
+   *
+   * @param userEntity the user
+   * @param userName   the user's os-level username
+   * @throws AmbariException
+   */
+  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");
+          }
+        }
+      }
+    });
+  }
+
+  /**
+   * 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
+   *
+   * @param userEntity the user
+   * @param dn         the user's distinguished name
+   * @throws AmbariException
+   */
+  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");
+          }
+        }
+      }
+    });
+  }
+
+  /**
+   * Worker to add a user authentication methods for a user.
+   *
+   * @param userEntity the user
+   * @param type       the authentication type
+   * @param key        the authentication type specific metadata
+   * @param validator  the authentication type specific validator
+   * @throws AmbariException
+   */
+  private void addAuthentication(UserEntity userEntity, UserAuthenticationType type, String key, Validator validator) throws AmbariException {
+
+    if (userEntity == null) {
+      throw new AmbariException("Missing user");
+    }
+
+    validator.validate(userEntity, key);
+
+    List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+
+    UserAuthenticationEntity authenticationEntity = new UserAuthenticationEntity();
+    authenticationEntity.setUser(userEntity);
+    authenticationEntity.setAuthenticationType(type);
+    authenticationEntity.setAuthenticationKey(key);
+    authenticationEntities.add(authenticationEntity);
+
+    userEntity.setAuthenticationEntities(authenticationEntities);
+    userDAO.merge(userEntity);
+  }
+
+  /**
+   * Validator is an interface to be implemented by authentication type specific validators to ensure
+   * new user authentication records meet the specific requirements for the relative authentication
+   * type.
+   */
+  private interface Validator {
+    /**
+     * Valudate the authentication type specific key meets the requirments for the relative user
+     * authentication type.
+     *
+     * @param userEntity the user
+     * @param key        the key (or metadata)
+     * @throws AmbariException
+     */
+    void validate(UserEntity userEntity, String key) throws AmbariException;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
index 383e8fa..c57bdf1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
@@ -40,7 +40,7 @@ public class AmbariInternalAuthenticationProvider implements AuthenticationProvi
     if (internalTokenStorage.isValidInternalToken(token.getCredentials())) {
       token.setAuthenticated(true);
     } else {
-      throw new InvalidUsernamePasswordCombinationException();
+      throw new InvalidUsernamePasswordCombinationException(null);
     }
     return token;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/AuthenticationJwtUserNotFoundException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/AuthenticationJwtUserNotFoundException.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/AuthenticationJwtUserNotFoundException.java
deleted file mode 100644
index f18af10..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/AuthenticationJwtUserNotFoundException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.security.authorization.jwt;
-
-import org.springframework.security.core.AuthenticationException;
-
-/**
- * AuthenticationJwtUserNotFoundException is an AuthenticationException implementation to be thrown
- * when the user specified in a JTW token is not found in the Ambari user database.
- */
-public class AuthenticationJwtUserNotFoundException extends AuthenticationException {
-  private final String username;
-
-  public AuthenticationJwtUserNotFoundException(String username, String message) {
-    super(message);
-    this.username = username;
-  }
-
-  public AuthenticationJwtUserNotFoundException(String username, String message, Throwable throwable) {
-    super(message, throwable);
-    this.username = username;
-  }
-
-  public String getUsername() {
-    return username;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilter.java
index e27afdb..3c3a446 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilter.java
@@ -33,11 +33,14 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.security.authentication.AmbariAuthenticationFilter;
+import org.apache.ambari.server.security.authentication.UserNotFoundException;
 import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
-import org.apache.ambari.server.security.authorization.User;
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -116,6 +119,9 @@ public class JwtAuthenticationFilter implements AmbariAuthenticationFilter {
 
   }
 
+  // TODO: ************
+  // TODO: This is to be revisited for AMBARI-21217 (Update JWT Authentication process to work with improved user management facility)
+  // TODO: ************
   @Override
   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
 
@@ -138,27 +144,50 @@ public class JwtAuthenticationFilter implements AmbariAuthenticationFilter {
 
           if (valid) {
             String userName = jwtToken.getJWTClaimsSet().getSubject();
-            User user = users.getUser(userName, UserType.JWT);
-            //fixme temporary solution for LDAP username conflicts, auth ldap users via JWT
-            if (user == null) {
-              user = users.getUser(userName, UserType.LDAP);
-            }
+            UserEntity userEntity = users.getUserEntity(userName);
 
-            if (user == null) {
-              //TODO this is temporary check for conflicts, until /users API will change to use user_id instead of name as PK
-              User existingUser = users.getUser(userName, UserType.LOCAL);
-              if (existingUser != null) {
-                LOG.error("Access for JWT user [{}] restricted. Detected conflict with local user ", userName);
+            if (userEntity == null) {
+              //TODO we temporary expect that LDAP is configured to same server as JWT source
+              throw new UserNotFoundException(userName, "Cannot find user from JWT. Please, ensure LDAP is configured and users are synced.");
+            } else {
+              // Check to see if the user is allowed to authenticate using JWT or LDAP
+              Collection<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+              boolean hasJWT = false;
+              boolean hasLDAP = false;
+
+              if (authenticationEntities != null) {
+                for (UserAuthenticationEntity entity : authenticationEntities) {
+                  if (entity.getAuthenticationType() == UserAuthenticationType.JWT) {
+                    // TODO: possibly check the authentication key to see if it is relevant
+                    hasJWT = true;
+                    break;
+                  } else if (entity.getAuthenticationType() == UserAuthenticationType.LDAP) {
+                    hasLDAP = true;
+                  }
+                }
               }
 
-              //TODO we temporary expect that LDAP is configured to same server as JWT source
-              throw new AuthenticationJwtUserNotFoundException(userName, "Cannot find user from JWT. Please, ensure LDAP is configured and users are synced.");
+              if(!hasJWT) {
+                if (hasLDAP) {
+                  // TODO: Determine if LDAP users can authenticate using JWT
+                  try {
+                    users.addJWTAuthentication(userEntity, userName);
+                  } catch (AmbariException e) {
+                    LOG.error(String.format("Failed to add the JWT authentication method for %s: %s", userName, e.getLocalizedMessage()), e);
+                  }
+                  hasJWT = true;
+                }
+              }
+
+              if (!hasJWT) {
+                throw new UserNotFoundException(userName, "User is not authorized to authenticate from JWT. Please, ensure LDAP is configured and users are synced.");
+              }
             }
 
-            Collection<AmbariGrantedAuthority> userAuthorities =
-                users.getUserAuthorities(user.getUserName(), user.getUserType());
+            // If we made it this far, the user was found and is authorized to authenticate via JWT
+            Collection<AmbariGrantedAuthority> userAuthorities = users.getUserAuthorities(userEntity);
 
-            JwtAuthentication authentication = new JwtAuthentication(serializedJWT, user, userAuthorities);
+            JwtAuthentication authentication = new JwtAuthentication(serializedJWT, users.getUser(userEntity), userAuthorities);
             authentication.setAuthenticated(true);
 
             SecurityContextHolder.getContext().setAuthentication(authentication);
@@ -221,11 +250,7 @@ public class JwtAuthenticationFilter implements AmbariAuthenticationFilter {
     }
 
     //always try to authenticate in case of anonymous user
-    if (existingAuth instanceof AnonymousAuthenticationToken) {
-      return true;
-    }
-
-    return false;
+    return (existingAuth instanceof AnonymousAuthenticationToken);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
index f413c69..4e4b1b6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
@@ -429,9 +429,10 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
       String createdUserName = requestScheduleEntity.getCreateUser();
 
       if (createdUserName != null) {
-        User user = users.getUserIfUnique(createdUserName);
+        // NOTE: This class is expected to go away in Ambari 3.0.0. Apache JIRA not available.
+        User user = users.getUser(createdUserName);
 
-        if (user != null && StringUtils.equals(user.getUserName(), createdUserName)) {
+        if (user != null && StringUtils.equalsIgnoreCase(user.getUserName(), createdUserName)) {
           requestScheduleEntity.setAuthenticatedUserId(user.getUserId());
           requestScheduleDAO.merge(requestScheduleEntity);
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index e4045ef..fa8e8ab 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -74,6 +74,7 @@
     <class>org.apache.ambari.server.orm.entities.UpgradeItemEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeHistoryEntity</class>
     <class>org.apache.ambari.server.orm.entities.UserEntity</class>
+    <class>org.apache.ambari.server.orm.entities.UserAuthenticationEntity</class>
     <class>org.apache.ambari.server.orm.entities.WidgetEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntityEntity</class>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
index 1b8de79..2b78f79 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
@@ -44,7 +44,7 @@ import org.apache.ambari.server.configuration.Configuration.DatabaseType;
 import org.apache.ambari.server.controller.metrics.ThreadPoolEnabledPropertyProvider;
 import org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationProperties;
 import org.apache.ambari.server.security.authorization.LdapServerProperties;
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 import org.apache.ambari.server.state.services.MetricsRetrievalService;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.io.FileUtils;
@@ -905,7 +905,7 @@ public class ConfigurationTest {
     Assert.assertEquals(keytabFile.getAbsolutePath(), kerberosAuthenticationProperties.getSpnegoKeytabFilePath());
     Assert.assertEquals("spnego/principal@REALM", kerberosAuthenticationProperties.getSpnegoPrincipalName());
     Assert.assertEquals("DEFAULT", kerberosAuthenticationProperties.getAuthToLocalRules());
-    Assert.assertEquals(Arrays.asList(UserType.LDAP, UserType.LOCAL), kerberosAuthenticationProperties.getOrderedUserTypes());
+    Assert.assertEquals(Arrays.asList(UserAuthenticationType.LDAP, UserAuthenticationType.LOCAL), kerberosAuthenticationProperties.getOrderedUserTypes());
   }
 
   /**
@@ -930,7 +930,7 @@ public class ConfigurationTest {
     Assert.assertEquals(keytabFile.getAbsolutePath(), kerberosAuthenticationProperties.getSpnegoKeytabFilePath());
     Assert.assertEquals("HTTP/" + StageUtils.getHostName(), kerberosAuthenticationProperties.getSpnegoPrincipalName());
     Assert.assertEquals("DEFAULT", kerberosAuthenticationProperties.getAuthToLocalRules());
-    Assert.assertEquals(Collections.singletonList(UserType.LDAP), kerberosAuthenticationProperties.getOrderedUserTypes());
+    Assert.assertEquals(Collections.singletonList(UserAuthenticationType.LDAP), kerberosAuthenticationProperties.getOrderedUserTypes());
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index 3215e72..c8eb6d6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -4547,80 +4547,7 @@ public class AmbariManagementControllerTest {
     assertEquals("", response.getRequestContext());
   }
 
-  private void createUser(String userName) throws Exception {
-    UserRequest request = new UserRequest(userName);
-    request.setPassword("password");
 
-    controller.createUsers(new HashSet<>(Collections.singleton(request)));
-  }
-
-  @Test
-  public void testCreateAndGetUsers() throws Exception {
-    createUser("user1");
-
-    Set<UserResponse> r =
-        controller.getUsers(Collections.singleton(new UserRequest("user1")));
-
-    Assert.assertEquals(1, r.size());
-    UserResponse resp = r.iterator().next();
-    Assert.assertEquals("user1", resp.getUsername());
-  }
-
-  @Test
-  public void testGetUsers() throws Exception {
-    String user1 = getUniqueName();
-    String user2 = getUniqueName();
-    String user3 = getUniqueName();
-    List<String> users = Arrays.asList(user1, user2, user3);
-
-    for (String user : users) {
-      createUser(user);
-    }
-
-    UserRequest request = new UserRequest(null);
-
-    Set<UserResponse> responses = controller.getUsers(Collections.singleton(request));
-
-    // other tests are making user requests, so let's make sure we have the 3 just made
-    List<String> contained = new ArrayList<>();
-    for (UserResponse ur : responses) {
-      if (users.contains(ur.getUsername())) {
-        contained.add(ur.getUsername());
-      }
-    }
-
-    Assert.assertEquals(3, contained.size());
-  }
-
-  @SuppressWarnings("serial")
-  @Test
-  public void testUpdateUsers() throws Exception {
-    String user1 = getUniqueName();
-    createUser(user1);
-
-    UserRequest request = new UserRequest(user1);
-
-    controller.updateUsers(Collections.singleton(request));
-  }
-
-  @SuppressWarnings("serial")
-  @Ignore
-  @Test
-  public void testDeleteUsers() throws Exception {
-    String user1 = getUniqueName();
-    createUser(user1);
-
-    UserRequest request = new UserRequest(user1);
-    controller.updateUsers(Collections.singleton(request));
-
-    request = new UserRequest(user1);
-    controller.deleteUsers(Collections.singleton(request));
-
-    Set<UserResponse> responses = controller.getUsers(
-        Collections.singleton(new UserRequest(null)));
-
-    Assert.assertEquals(0, responses.size());
-  }
 
   @Test
   public void testUpdateConfigForRunningService() throws Exception {

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractPrivilegeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractPrivilegeResourceProviderTest.java
deleted file mode 100644
index 547bba5..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractPrivilegeResourceProviderTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.controller.internal;
-
-import org.apache.ambari.server.orm.dao.MemberDAO;
-import org.apache.ambari.server.orm.dao.PrivilegeDAO;
-import org.apache.ambari.server.security.authorization.Users;
-import org.easymock.EasyMockSupport;
-
-class AbstractPrivilegeResourceProviderTest extends EasyMockSupport {
-
-  static class TestUsers extends Users {
-
-    void setPrivilegeDAO(PrivilegeDAO privilegeDAO) {
-      this.privilegeDAO = privilegeDAO;
-    }
-
-    public void setMemberDAO(MemberDAO memberDAO) {
-      this.memberDAO = memberDAO;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
index 4dc06b9..487c02a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
@@ -64,7 +64,6 @@ import org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity;
 import org.apache.ambari.server.scheduler.ExecutionScheduler;
 import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
-import org.apache.ambari.server.security.authorization.UserType;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
 import org.apache.ambari.server.security.encryption.CredentialStoreServiceImpl;
@@ -172,7 +171,7 @@ public class ActiveWidgetLayoutResourceProviderTest extends EasyMockSupport {
     UserEntity userEntity = createMockUserEntity(requestedUsername);
 
     UserDAO userDAO = injector.getInstance(UserDAO.class);
-    expect(userDAO.findSingleUserByName(requestedUsername)).andReturn(userEntity).atLeastOnce();
+    expect(userDAO.findUserByName(requestedUsername)).andReturn(userEntity).atLeastOnce();
 
     WidgetLayoutDAO widgetLayoutDAO = injector.getInstance(WidgetLayoutDAO.class);
     expect(widgetLayoutDAO.findById(1L)).andReturn(createMockWidgetLayout(1L, requestedUsername)).atLeastOnce();
@@ -368,7 +367,6 @@ public class ActiveWidgetLayoutResourceProviderTest extends EasyMockSupport {
     UserEntity userEntity = createMock(UserEntity.class);
     expect(userEntity.getUserId()).andReturn(username.hashCode()).anyTimes();
     expect(userEntity.getUserName()).andReturn(username).anyTimes();
-    expect(userEntity.getUserType()).andReturn(UserType.LOCAL).anyTimes();
     expect(userEntity.getActiveWidgetLayouts()).andReturn("[{\"id\":\"1\"},{\"id\":\"2\"}]").anyTimes();
 
     return userEntity;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java
index 36f6a1e..ea981e2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupPrivilegeResourceProviderTest.java
@@ -27,6 +27,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
+import javax.persistence.EntityManager;
+
 import org.apache.ambari.server.controller.GroupPrivilegeResponse;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Request;
@@ -34,6 +36,9 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.hooks.HookContextFactory;
+import org.apache.ambari.server.hooks.HookService;
+import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.GroupDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
@@ -52,16 +57,22 @@ import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.Users;
+import org.easymock.EasyMockSupport;
 import org.junit.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
 
 import junit.framework.Assert;
 
 /**
  * GroupPrivilegeResourceProvider tests.
  */
-public class GroupPrivilegeResourceProviderTest extends AbstractPrivilegeResourceProviderTest {
+public class GroupPrivilegeResourceProviderTest extends EasyMockSupport{
 
   @Test(expected = SystemException.class)
   public void testCreateResources() throws Exception {
@@ -79,7 +90,7 @@ public class GroupPrivilegeResourceProviderTest extends AbstractPrivilegeResourc
   public void testGetResources_NonAdministrator() throws Exception {
     getResourcesTest(TestAuthenticationFactory.createClusterAdministrator("user1", 2L), "Group1");
   }
-  
+
   @Test(expected = SystemException.class)
   public void testUpdateResources() throws Exception {
     SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createClusterAdministrator("user1", 2L));
@@ -230,7 +241,7 @@ public class GroupPrivilegeResourceProviderTest extends AbstractPrivilegeResourc
     expect(groupEntity.getGroupName()).andReturn("group1").atLeastOnce();
 
     ClusterDAO clusterDAO = createMock(ClusterDAO.class);
-    
+
     ViewInstanceDAO viewInstanceDAO = createMock(ViewInstanceDAO.class);
     expect(viewInstanceDAO.findByResourceId(1L)).andReturn(viewInstanceEntity).atLeastOnce();
 
@@ -328,8 +339,31 @@ public class GroupPrivilegeResourceProviderTest extends AbstractPrivilegeResourc
     final ResourceTypeEntity resourceTypeEntity = createNiceMock(ResourceTypeEntity.class);
     final PrivilegeDAO privilegeDAO = createMock(PrivilegeDAO.class);
 
-    final TestUsers users = new TestUsers();
-    users.setPrivilegeDAO(privilegeDAO);
+    final Injector injector = Guice.createInjector(new AbstractModule() {
+                                                     @Override
+                                                     protected void configure() {
+                                                       bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+                                                       bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+                                                       bind(PasswordEncoder.class).toInstance(createNiceMock(PasswordEncoder.class));
+                                                       bind(HookService.class).toInstance(createMock(HookService.class));
+                                                       bind(HookContextFactory.class).toInstance(createMock(HookContextFactory.class));
+
+                                                       bind(GroupDAO.class).toInstance(groupDAO);
+                                                       bind(ClusterDAO.class).toInstance(clusterDAO);
+                                                       bind(ViewInstanceDAO.class).toInstance(viewInstanceDAO);
+                                                       bind(GroupEntity.class).toInstance(groupEntity);
+                                                       bind(PrincipalEntity.class).toInstance(principalEntity);
+                                                       bind(PrivilegeEntity.class).toInstance(privilegeEntity);
+                                                       bind(PermissionEntity.class).toInstance(permissionEntity);
+                                                       bind(PrincipalTypeEntity.class).toInstance(principalTypeEntity);
+                                                       bind(ResourceEntity.class).toInstance(resourceEntity);
+                                                       bind(ResourceTypeEntity.class).toInstance(resourceTypeEntity);
+                                                       bind(PrivilegeDAO.class).toInstance(privilegeDAO);
+                                                     }
+                                                   }
+    );
+
+    final Users users = injector.getInstance(Users.class);
 
     List<PrincipalEntity> groupPrincipals = new LinkedList<>();
     groupPrincipals.add(principalEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java
index 9ccbc11..499354f 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java
@@ -28,6 +28,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
+import javax.persistence.EntityManager;
+
 import org.apache.ambari.server.controller.UserPrivilegeResponse;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Request;
@@ -35,6 +37,9 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.hooks.HookContextFactory;
+import org.apache.ambari.server.hooks.HookService;
+import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.GroupDAO;
 import org.apache.ambari.server.orm.dao.MemberDAO;
@@ -56,16 +61,22 @@ import org.apache.ambari.server.security.TestAuthenticationFactory;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.Users;
+import org.easymock.EasyMockSupport;
 import org.junit.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
 
 import junit.framework.Assert;
 
 /**
  * UserPrivilegeResourceProvider tests.
  */
-public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResourceProviderTest {
+public class UserPrivilegeResourceProviderTest extends EasyMockSupport {
 
   @Test(expected = SystemException.class)
   public void testCreateResources() throws Exception {
@@ -334,45 +345,56 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
   public void testToResource_SpecificVIEW_WithClusterInheritedPermission() throws Exception {
     SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createClusterAdministrator("jdoe", 2L));
 
-    PrincipalTypeEntity rolePrincipalTypeEntity = createMock(PrincipalTypeEntity.class);
+    Injector injector = createInjector();
+
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    final UserDAO userDAO = injector.getInstance(UserDAO.class);
+    final GroupDAO groupDAO = injector.getInstance(GroupDAO.class);
+    final ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+    final ViewInstanceDAO viewInstanceDAO = injector.getInstance(ViewInstanceDAO.class);
+    final PrivilegeDAO privilegeDAO = injector.getInstance(PrivilegeDAO.class);
+    final MemberDAO memberDAO = injector.getInstance(MemberDAO.class);
+
+
+    final PrincipalTypeEntity rolePrincipalTypeEntity = createMock(PrincipalTypeEntity.class);
     expect(rolePrincipalTypeEntity.getName()).andReturn("ROLE").atLeastOnce();
 
-    PrincipalEntity rolePrincipalEntity = createMock(PrincipalEntity.class);
+    final PrincipalEntity rolePrincipalEntity = createMock(PrincipalEntity.class);
     expect(rolePrincipalEntity.getPrincipalType()).andReturn(rolePrincipalTypeEntity).atLeastOnce();
 
-    PermissionEntity permissionEntity = createMock(PermissionEntity.class);
+    final PermissionEntity permissionEntity = createMock(PermissionEntity.class);
     expect(permissionEntity.getPrincipal()).andReturn(rolePrincipalEntity).atLeastOnce();
     expect(permissionEntity.getPermissionName()).andReturn("CLUSTER.ADMINISTRATOR").atLeastOnce();
     expect(permissionEntity.getPermissionLabel()).andReturn("Cluster Administrator").atLeastOnce();
 
-    PrincipalTypeEntity principalTypeEntity = createMock(PrincipalTypeEntity.class);
+    final PrincipalTypeEntity principalTypeEntity = createMock(PrincipalTypeEntity.class);
     expect(principalTypeEntity.getName()).andReturn("USER").atLeastOnce();
 
-    PrincipalEntity principalEntity = createMock(PrincipalEntity.class);
+    final PrincipalEntity principalEntity = createMock(PrincipalEntity.class);
     expect(principalEntity.getPrincipalType()).andReturn(principalTypeEntity).atLeastOnce();
 
-    ViewEntity viewEntity = createMock(ViewEntity.class);
+    final ViewEntity viewEntity = createMock(ViewEntity.class);
     expect(viewEntity.getCommonName()).andReturn("TestView").atLeastOnce();
     expect(viewEntity.getVersion()).andReturn("1.2.3.4").atLeastOnce();
 
-    ResourceTypeEntity resourceTypeEntity = createMock(ResourceTypeEntity.class);
+    final ResourceTypeEntity resourceTypeEntity = createMock(ResourceTypeEntity.class);
     expect(resourceTypeEntity.getName()).andReturn("TestView{1.2.3.4}").atLeastOnce();
 
-    ResourceEntity resourceEntity = createMock(ResourceEntity.class);
+    final ResourceEntity resourceEntity = createMock(ResourceEntity.class);
     expect(resourceEntity.getId()).andReturn(1L).anyTimes();
     expect(resourceEntity.getResourceType()).andReturn(resourceTypeEntity).anyTimes();
 
-    ViewInstanceEntity viewInstanceEntity = createMock(ViewInstanceEntity.class);
+    final ViewInstanceEntity viewInstanceEntity = createMock(ViewInstanceEntity.class);
     expect(viewInstanceEntity.getViewEntity()).andReturn(viewEntity).atLeastOnce();
     expect(viewInstanceEntity.getName()).andReturn("Test View").atLeastOnce();
 
-    PrivilegeEntity explicitPrivilegeEntity = createMock(PrivilegeEntity.class);
+    final PrivilegeEntity explicitPrivilegeEntity = createMock(PrivilegeEntity.class);
     expect(explicitPrivilegeEntity.getId()).andReturn(1).atLeastOnce();
     expect(explicitPrivilegeEntity.getPermission()).andReturn(permissionEntity).atLeastOnce();
     expect(explicitPrivilegeEntity.getPrincipal()).andReturn(principalEntity).atLeastOnce();
     expect(explicitPrivilegeEntity.getResource()).andReturn(resourceEntity).atLeastOnce();
 
-    PrivilegeEntity implicitPrivilegeEntity = createMock(PrivilegeEntity.class);
+    final PrivilegeEntity implicitPrivilegeEntity = createMock(PrivilegeEntity.class);
     expect(implicitPrivilegeEntity.getId()).andReturn(2).atLeastOnce();
     expect(implicitPrivilegeEntity.getPermission()).andReturn(permissionEntity).atLeastOnce();
     expect(implicitPrivilegeEntity.getPrincipal()).andReturn(rolePrincipalEntity).atLeastOnce();
@@ -382,23 +404,13 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
     expect(userEntity.getUserName()).andReturn("jdoe").atLeastOnce();
     expect(userEntity.getPrincipal()).andReturn(principalEntity).atLeastOnce();
 
-    ClusterDAO clusterDAO = createMock(ClusterDAO.class);
-    GroupDAO groupDAO = createMock(GroupDAO.class);
-
-    ViewInstanceDAO viewInstanceDAO = createMock(ViewInstanceDAO.class);
     expect(viewInstanceDAO.findByResourceId(1L)).andReturn(viewInstanceEntity).atLeastOnce();
 
-    final UserDAO userDAO = createNiceMock(UserDAO.class);
-    expect(userDAO.findLocalUserByName("jdoe")).andReturn(userEntity).anyTimes();
+    expect(userDAO.findUserByName("jdoe")).andReturn(userEntity).anyTimes();
     expect(userDAO.findUserByPrincipal(anyObject(PrincipalEntity.class))).andReturn(userEntity).anyTimes();
     expect(userDAO.findAll()).andReturn(Collections.<UserEntity>emptyList()).anyTimes();
 
-    final PrivilegeDAO privilegeDAO = createMock(PrivilegeDAO.class);
-    final MemberDAO memberDAO = createMock(MemberDAO.class);
-
-    final TestUsers users = new TestUsers();
-    users.setPrivilegeDAO(privilegeDAO);
-    users.setMemberDAO(memberDAO);
+    final Users users = injector.getInstance(Users.class);
 
     List<PrincipalEntity> rolePrincipals = new LinkedList<>();
     rolePrincipals.add(rolePrincipalEntity);
@@ -422,9 +434,9 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
     final Set<String> propertyIds = new HashSet<>();
     propertyIds.add(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);
     final Predicate predicate = new PredicateBuilder()
-      .property(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID)
-      .equals("jdoe")
-      .toPredicate();
+        .property(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID)
+        .equals("jdoe")
+        .toPredicate();
     TestAuthenticationFactory.createClusterAdministrator("jdoe", 2L);
     Request request = PropertyHelper.getReadRequest(propertyIds);
 
@@ -443,11 +455,16 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
 
   //  @SuppressWarnings("serial")
   private void getResourcesTest(Authentication authentication, String requestedUsername) throws Exception {
+    Injector injector = createInjector();
+
     final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
-    final UserDAO userDAO = createNiceMock(UserDAO.class);
-    final GroupDAO groupDAO = createNiceMock(GroupDAO.class);
-    final ClusterDAO clusterDAO = createNiceMock(ClusterDAO.class);
-    final ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
+    final UserDAO userDAO = injector.getInstance(UserDAO.class);
+    final GroupDAO groupDAO = injector.getInstance(GroupDAO.class);
+    final ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+    final ViewInstanceDAO viewInstanceDAO = injector.getInstance(ViewInstanceDAO.class);
+    final PrivilegeDAO privilegeDAO = injector.getInstance(PrivilegeDAO.class);
+    final MemberDAO memberDAO = injector.getInstance(MemberDAO.class);
+
     final UserEntity userEntity = createNiceMock(UserEntity.class);
     final PrincipalEntity principalEntity = createNiceMock(PrincipalEntity.class);
     final PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
@@ -455,12 +472,8 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
     final PrincipalTypeEntity principalTypeEntity = createNiceMock(PrincipalTypeEntity.class);
     final ResourceEntity resourceEntity = createNiceMock(ResourceEntity.class);
     final ResourceTypeEntity resourceTypeEntity = createNiceMock(ResourceTypeEntity.class);
-    final PrivilegeDAO privilegeDAO = createMock(PrivilegeDAO.class);
-    final MemberDAO memberDAO = createMock(MemberDAO.class);
 
-    final TestUsers users = new TestUsers();
-    users.setPrivilegeDAO(privilegeDAO);
-    users.setMemberDAO(memberDAO);
+    final Users users = injector.getInstance(Users.class);
 
     List<PrincipalEntity> userPrincipals = new LinkedList<>();
     userPrincipals.add(principalEntity);
@@ -471,7 +484,7 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
     expect(memberDAO.findAllMembersByUser(userEntity)).
         andReturn(Collections.<MemberEntity>emptyList())
         .atLeastOnce();
-    expect(userDAO.findLocalUserByName(requestedUsername)).andReturn(userEntity).anyTimes();
+    expect(userDAO.findUserByName(requestedUsername)).andReturn(userEntity).anyTimes();
     expect(userDAO.findAll()).andReturn(Collections.<UserEntity>emptyList()).anyTimes();
     expect(userEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
     expect(userEntity.getMemberEntities()).andReturn(Collections.<MemberEntity>emptySet()).anyTimes();
@@ -518,4 +531,24 @@ public class UserPrivilegeResourceProviderTest extends AbstractPrivilegeResource
     verifyAll();
   }
 
+  private Injector createInjector() {
+    return Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+        bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+        bind(PasswordEncoder.class).toInstance(createNiceMock(PasswordEncoder.class));
+        bind(HookService.class).toInstance(createMock(HookService.class));
+        bind(HookContextFactory.class).toInstance(createMock(HookContextFactory.class));
+
+        bind(UserDAO.class).toInstance(createNiceMock(UserDAO.class));
+        bind(GroupDAO.class).toInstance(createNiceMock(GroupDAO.class));
+        bind(ClusterDAO.class).toInstance(createNiceMock(ClusterDAO.class));
+        bind(ViewInstanceDAO.class).toInstance(createNiceMock(ViewInstanceDAO.class));
+        bind(PrivilegeDAO.class).toInstance(createMock(PrivilegeDAO.class));
+        bind(MemberDAO.class).toInstance(createMock(MemberDAO.class));
+      }
+    });
+  }
+
 }