|
@@ -17,11 +17,23 @@
|
|
|
*/
|
|
|
package org.apache.ambari.server.security.authorization;
|
|
|
|
|
|
-import java.util.*;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.HashSet;
|
|
|
+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;
|
|
|
import org.apache.ambari.server.orm.dao.MemberDAO;
|
|
|
import org.apache.ambari.server.orm.dao.PermissionDAO;
|
|
@@ -47,7 +59,6 @@ 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;
|
|
@@ -83,7 +94,13 @@ public class Users {
|
|
|
@Inject
|
|
|
protected Configuration configuration;
|
|
|
@Inject
|
|
|
- private AmbariLdapAuthenticationProvider ldapAuthenticationProvider;
|
|
|
+ private AmbariLdapAuthenticationProvider ldapAuthenticationProvider;
|
|
|
+
|
|
|
+ @Inject
|
|
|
+ private Provider<HookService> hookServiceProvider;
|
|
|
+
|
|
|
+ @Inject
|
|
|
+ private HookContextFactory hookContextFactory;
|
|
|
|
|
|
public List<User> getAllUsers() {
|
|
|
List<UserEntity> userEntities = userDAO.findAll();
|
|
@@ -98,6 +115,7 @@ public class Users {
|
|
|
|
|
|
/**
|
|
|
* This method works incorrectly, userName is not unique if users have different types
|
|
|
+ *
|
|
|
* @return One user. Priority is LOCAL -> LDAP -> JWT
|
|
|
*/
|
|
|
@Deprecated
|
|
@@ -125,6 +143,7 @@ public class Users {
|
|
|
/**
|
|
|
* 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.
|
|
|
+ *
|
|
|
* @param userName
|
|
|
* @return User if userName is unique in DB, null otherwise
|
|
|
*/
|
|
@@ -147,6 +166,7 @@ public class Users {
|
|
|
|
|
|
/**
|
|
|
* Modifies password of local user
|
|
|
+ *
|
|
|
* @throws AmbariException
|
|
|
*/
|
|
|
public synchronized void modifyPassword(String userName, String currentUserPassword, String newPassword) throws AmbariException {
|
|
@@ -166,14 +186,14 @@ public class Users {
|
|
|
try {
|
|
|
ldapAuthenticationProvider.authenticate(
|
|
|
new UsernamePasswordAuthenticationToken(currentUserName, currentUserPassword));
|
|
|
- isLdapUser = true;
|
|
|
+ isLdapUser = true;
|
|
|
} catch (InvalidUsernamePasswordCombinationException ex) {
|
|
|
throw new AmbariException(ex.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
boolean isCurrentUserAdmin = false;
|
|
|
- for (PrivilegeEntity privilegeEntity: currentUserEntity.getPrincipal().getPrivileges()) {
|
|
|
+ for (PrivilegeEntity privilegeEntity : currentUserEntity.getPrincipal().getPrivileges()) {
|
|
|
if (privilegeEntity.getPermission().getPermissionName().equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION_NAME)) {
|
|
|
isCurrentUserAdmin = true;
|
|
|
break;
|
|
@@ -270,8 +290,8 @@ public class Users {
|
|
|
* @param userName user name
|
|
|
* @param password password
|
|
|
* @param userType user type
|
|
|
- * @param active is user active
|
|
|
- * @param admin is user admin
|
|
|
+ * @param active is user active
|
|
|
+ * @param admin is user admin
|
|
|
* @throws AmbariException if user already exists
|
|
|
*/
|
|
|
public synchronized void createUser(String userName, String password, UserType userType, Boolean active, Boolean
|
|
@@ -319,14 +339,17 @@ public class Users {
|
|
|
if (admin != null && admin) {
|
|
|
grantAdminPrivilege(userEntity.getUserId());
|
|
|
}
|
|
|
+
|
|
|
+ // execute user initialization hook if required ()
|
|
|
+ hookServiceProvider.get().execute(hookContextFactory.createUserHookContext(userName));
|
|
|
}
|
|
|
|
|
|
public synchronized void removeUser(User user) throws AmbariException {
|
|
|
UserEntity userEntity = userDAO.findByPK(user.getUserId());
|
|
|
if (userEntity != null) {
|
|
|
- if (!isUserCanBeRemoved(userEntity)){
|
|
|
+ if (!isUserCanBeRemoved(userEntity)) {
|
|
|
throw new AmbariException("Could not remove user " + userEntity.getUserName() +
|
|
|
- ". System should have at least one administrator.");
|
|
|
+ ". System should have at least one administrator.");
|
|
|
}
|
|
|
userDAO.remove(userEntity);
|
|
|
} else {
|
|
@@ -357,12 +380,12 @@ public class Users {
|
|
|
return null;
|
|
|
} else {
|
|
|
final Set<User> users = new HashSet<User>();
|
|
|
- for (MemberEntity memberEntity: groupEntity.getMemberEntities()) {
|
|
|
+ for (MemberEntity memberEntity : groupEntity.getMemberEntities()) {
|
|
|
if (memberEntity.getUser() != null) {
|
|
|
users.add(new User(memberEntity.getUser()));
|
|
|
} else {
|
|
|
LOG.error("Wrong state, not found user for member '{}' (group: '{}')",
|
|
|
- memberEntity.getMemberId(), memberEntity.getGroup().getGroupName());
|
|
|
+ memberEntity.getMemberId(), memberEntity.getGroup().getGroupName());
|
|
|
}
|
|
|
}
|
|
|
return users;
|
|
@@ -402,7 +425,7 @@ public class Users {
|
|
|
final List<GroupEntity> groupEntities = groupDAO.findAll();
|
|
|
final List<Group> groups = new ArrayList<Group>(groupEntities.size());
|
|
|
|
|
|
- for (GroupEntity groupEntity: groupEntities) {
|
|
|
+ for (GroupEntity groupEntity : groupEntities) {
|
|
|
groups.add(new Group(groupEntity));
|
|
|
}
|
|
|
|
|
@@ -421,7 +444,7 @@ public class Users {
|
|
|
if (groupEntity == null) {
|
|
|
throw new AmbariException("Group " + groupName + " doesn't exist");
|
|
|
}
|
|
|
- for (MemberEntity member: groupEntity.getMemberEntities()) {
|
|
|
+ for (MemberEntity member : groupEntity.getMemberEntities()) {
|
|
|
members.add(member.getUser().getUserName());
|
|
|
}
|
|
|
return members;
|
|
@@ -463,7 +486,7 @@ public class Users {
|
|
|
*/
|
|
|
public synchronized void revokeAdminPrivilege(Integer userId) {
|
|
|
final UserEntity user = userDAO.findByPK(userId);
|
|
|
- for (PrivilegeEntity privilege: user.getPrincipal().getPrivileges()) {
|
|
|
+ for (PrivilegeEntity privilege : user.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
|
|
@@ -518,7 +541,7 @@ public class Users {
|
|
|
|
|
|
if (isUserInGroup(userEntity, groupEntity)) {
|
|
|
MemberEntity memberEntity = null;
|
|
|
- for (MemberEntity entity: userEntity.getMemberEntities()) {
|
|
|
+ for (MemberEntity entity : userEntity.getMemberEntities()) {
|
|
|
if (entity.getGroup().equals(groupEntity)) {
|
|
|
memberEntity = entity;
|
|
|
break;
|
|
@@ -541,7 +564,7 @@ public class Users {
|
|
|
* @param userEntity user to be checked
|
|
|
* @return true if user can be removed
|
|
|
*/
|
|
|
- public synchronized boolean isUserCanBeRemoved(UserEntity userEntity){
|
|
|
+ public synchronized boolean isUserCanBeRemoved(UserEntity userEntity) {
|
|
|
List<PrincipalEntity> adminPrincipals = principalDAO.findByPermissionId(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION);
|
|
|
Set<UserEntity> userEntitysSet = new HashSet<UserEntity>(userDAO.findUsersByPrincipal(adminPrincipals));
|
|
|
return (userEntitysSet.contains(userEntity) && userEntitysSet.size() < 2) ? false : true;
|
|
@@ -550,12 +573,12 @@ public class Users {
|
|
|
/**
|
|
|
* Performs a check if given user belongs to given group.
|
|
|
*
|
|
|
- * @param userEntity user entity
|
|
|
+ * @param userEntity user entity
|
|
|
* @param groupEntity group entity
|
|
|
* @return true if user presents in group
|
|
|
*/
|
|
|
private boolean isUserInGroup(UserEntity userEntity, GroupEntity groupEntity) {
|
|
|
- for (MemberEntity memberEntity: userEntity.getMemberEntities()) {
|
|
|
+ for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
|
|
|
if (memberEntity.getGroup().equals(groupEntity)) {
|
|
|
return true;
|
|
|
}
|
|
@@ -574,11 +597,11 @@ public class Users {
|
|
|
|
|
|
// prefetch all user and group data to avoid heavy queries in membership creation
|
|
|
|
|
|
- for (UserEntity userEntity: userDAO.findAll()) {
|
|
|
+ for (UserEntity userEntity : userDAO.findAll()) {
|
|
|
allUsers.put(userEntity.getUserName(), userEntity);
|
|
|
}
|
|
|
|
|
|
- for (GroupEntity groupEntity: groupDAO.findAll()) {
|
|
|
+ for (GroupEntity groupEntity : groupDAO.findAll()) {
|
|
|
allGroups.put(groupEntity.getGroupName(), groupEntity);
|
|
|
}
|
|
|
|
|
@@ -589,7 +612,7 @@ public class Users {
|
|
|
|
|
|
// remove users
|
|
|
final Set<UserEntity> usersToRemove = new HashSet<UserEntity>();
|
|
|
- for (String userName: batchInfo.getUsersToBeRemoved()) {
|
|
|
+ for (String userName : batchInfo.getUsersToBeRemoved()) {
|
|
|
UserEntity userEntity = userDAO.findUserByName(userName);
|
|
|
if (userEntity == null) {
|
|
|
continue;
|
|
@@ -601,7 +624,7 @@ public class Users {
|
|
|
|
|
|
// remove groups
|
|
|
final Set<GroupEntity> groupsToRemove = new HashSet<GroupEntity>();
|
|
|
- for (String groupName: batchInfo.getGroupsToBeRemoved()) {
|
|
|
+ for (String groupName : batchInfo.getGroupsToBeRemoved()) {
|
|
|
final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
|
|
|
allGroups.remove(groupEntity.getGroupName());
|
|
|
groupsToRemove.add(groupEntity);
|
|
@@ -610,7 +633,7 @@ public class Users {
|
|
|
|
|
|
// update users
|
|
|
final Set<UserEntity> usersToBecomeLdap = new HashSet<UserEntity>();
|
|
|
- for (String userName: batchInfo.getUsersToBecomeLdap()) {
|
|
|
+ for (String userName : batchInfo.getUsersToBecomeLdap()) {
|
|
|
UserEntity userEntity = userDAO.findLocalUserByName(userName);
|
|
|
if (userEntity == null) {
|
|
|
userEntity = userDAO.findLdapUserByName(userName);
|
|
@@ -626,7 +649,7 @@ public class Users {
|
|
|
|
|
|
// update groups
|
|
|
final Set<GroupEntity> groupsToBecomeLdap = new HashSet<GroupEntity>();
|
|
|
- for (String groupName: batchInfo.getGroupsToBecomeLdap()) {
|
|
|
+ for (String groupName : batchInfo.getGroupsToBecomeLdap()) {
|
|
|
final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
|
|
|
groupEntity.setLdapGroup(true);
|
|
|
allGroups.put(groupEntity.getGroupName(), groupEntity);
|
|
@@ -639,7 +662,7 @@ public class Users {
|
|
|
|
|
|
// prepare create users
|
|
|
final Set<UserEntity> usersToCreate = new HashSet<UserEntity>();
|
|
|
- for (String userName: batchInfo.getUsersToBeCreated()) {
|
|
|
+ for (String userName : batchInfo.getUsersToBeCreated()) {
|
|
|
final PrincipalEntity principalEntity = new PrincipalEntity();
|
|
|
principalEntity.setPrincipalType(userPrincipalType);
|
|
|
principalsToCreate.add(principalEntity);
|
|
@@ -656,7 +679,7 @@ public class Users {
|
|
|
|
|
|
// prepare create groups
|
|
|
final Set<GroupEntity> groupsToCreate = new HashSet<GroupEntity>();
|
|
|
- for (String groupName: batchInfo.getGroupsToBeCreated()) {
|
|
|
+ for (String groupName : batchInfo.getGroupsToBeCreated()) {
|
|
|
final PrincipalEntity principalEntity = new PrincipalEntity();
|
|
|
principalEntity.setPrincipalType(groupPrincipalType);
|
|
|
principalsToCreate.add(principalEntity);
|
|
@@ -678,7 +701,7 @@ public class Users {
|
|
|
// create membership
|
|
|
final Set<MemberEntity> membersToCreate = new HashSet<MemberEntity>();
|
|
|
final Set<GroupEntity> groupsToUpdate = new HashSet<GroupEntity>();
|
|
|
- for (LdapUserGroupMemberDto member: batchInfo.getMembershipToAdd()) {
|
|
|
+ for (LdapUserGroupMemberDto member : batchInfo.getMembershipToAdd()) {
|
|
|
final MemberEntity memberEntity = new MemberEntity();
|
|
|
final GroupEntity groupEntity = allGroups.get(member.getGroupName());
|
|
|
memberEntity.setGroup(groupEntity);
|
|
@@ -692,7 +715,7 @@ public class Users {
|
|
|
|
|
|
// remove membership
|
|
|
final Set<MemberEntity> membersToRemove = new HashSet<MemberEntity>();
|
|
|
- for (LdapUserGroupMemberDto member: batchInfo.getMembershipToRemove()) {
|
|
|
+ for (LdapUserGroupMemberDto member : batchInfo.getMembershipToRemove()) {
|
|
|
MemberEntity memberEntity = memberDAO.findByUserAndGroup(member.getUserName(), member.getGroupName());
|
|
|
if (memberEntity != null) {
|
|
|
membersToRemove.add(memberEntity);
|
|
@@ -702,6 +725,36 @@ 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)));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Assembles a map where the keys are usernames and values are Lists with groups associated with users.
|
|
|
+ *
|
|
|
+ * @param usersToCreate a list with user entities
|
|
|
+ * @return the a populated map instance
|
|
|
+ */
|
|
|
+ private Map<String, Set<String>> getUsersToGroupMap(Set<UserEntity> usersToCreate) {
|
|
|
+ Map<String, Set<String>> usersToGroups = new HashMap<>();
|
|
|
+
|
|
|
+ for (UserEntity userEntity : usersToCreate) {
|
|
|
+
|
|
|
+ // make sure user entities are refreshed so that membership is updated
|
|
|
+ userEntity = userDAO.findByPK(userEntity.getUserId());
|
|
|
+
|
|
|
+ usersToGroups.put(userEntity.getUserName(), new HashSet<String>());
|
|
|
+
|
|
|
+ for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
|
|
|
+ usersToGroups.get(userEntity.getUserName()).add(memberEntity.getGroup().getGroupName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return usersToGroups;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -740,10 +793,9 @@ public class Users {
|
|
|
List<PrivilegeEntity> implicitPrivilegeEntities = getImplicitPrivileges(explicitPrivilegeEntities);
|
|
|
List<PrivilegeEntity> privilegeEntities;
|
|
|
|
|
|
- if(implicitPrivilegeEntities.isEmpty()) {
|
|
|
+ if (implicitPrivilegeEntities.isEmpty()) {
|
|
|
privilegeEntities = explicitPrivilegeEntities;
|
|
|
- }
|
|
|
- else {
|
|
|
+ } else {
|
|
|
privilegeEntities = new LinkedList<PrivilegeEntity>();
|
|
|
privilegeEntities.addAll(explicitPrivilegeEntities);
|
|
|
privilegeEntities.addAll(implicitPrivilegeEntities);
|
|
@@ -782,10 +834,9 @@ public class Users {
|
|
|
List<PrivilegeEntity> implicitPrivilegeEntities = getImplicitPrivileges(explicitPrivilegeEntities);
|
|
|
List<PrivilegeEntity> privilegeEntities;
|
|
|
|
|
|
- if(implicitPrivilegeEntities.isEmpty()) {
|
|
|
+ if (implicitPrivilegeEntities.isEmpty()) {
|
|
|
privilegeEntities = explicitPrivilegeEntities;
|
|
|
- }
|
|
|
- else {
|
|
|
+ } else {
|
|
|
privilegeEntities = new LinkedList<PrivilegeEntity>();
|
|
|
privilegeEntities.addAll(explicitPrivilegeEntities);
|
|
|
privilegeEntities.addAll(implicitPrivilegeEntities);
|