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:18 UTC
[4/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/authentication/kerberos/AmbariAuthToLocalUserDetailsService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariAuthToLocalUserDetailsService.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariAuthToLocalUserDetailsService.java
index 1e4f6ea..261b94e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariAuthToLocalUserDetailsService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariAuthToLocalUserDetailsService.java
@@ -19,19 +19,21 @@
package org.apache.ambari.server.security.authentication.kerberos;
import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.security.authentication.AuthenticationMethodNotAllowedException;
+import org.apache.ambari.server.security.authentication.UserNotFoundException;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
import org.apache.ambari.server.security.authorization.Users;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -47,8 +49,6 @@ public class AmbariAuthToLocalUserDetailsService implements UserDetailsService {
private final Users users;
- private final List<UserType> userTypeOrder;
-
private final String authToLocalRules;
/**
@@ -63,14 +63,12 @@ public class AmbariAuthToLocalUserDetailsService implements UserDetailsService {
*/
public AmbariAuthToLocalUserDetailsService(Configuration configuration, Users users) throws AmbariException {
String authToLocalRules = null;
- List<UserType> orderedUserTypes = null;
if (configuration != null) {
AmbariKerberosAuthenticationProperties properties = configuration.getKerberosAuthenticationProperties();
if (properties != null) {
authToLocalRules = properties.getAuthToLocalRules();
- orderedUserTypes = properties.getOrderedUserTypes();
}
}
@@ -78,12 +76,7 @@ public class AmbariAuthToLocalUserDetailsService implements UserDetailsService {
authToLocalRules = "DEFAULT";
}
- if ((orderedUserTypes == null) || orderedUserTypes.isEmpty()) {
- orderedUserTypes = Collections.singletonList(UserType.LDAP);
- }
-
this.users = users;
- this.userTypeOrder = orderedUserTypes;
this.authToLocalRules = authToLocalRules;
}
@@ -107,7 +100,9 @@ public class AmbariAuthToLocalUserDetailsService implements UserDetailsService {
}
LOG.info("Translated {} to {} using auth-to-local rules during Kerberos authentication.", principal, username);
- return createUser(username);
+ return createUser(username, principal);
+ } catch (UserNotFoundException e) {
+ throw new UsernameNotFoundException(e.getMessage(), e);
} catch (IOException e) {
String message = String.format("Failed to translate %s to a local username during Kerberos authentication: %s", principal, e.getLocalizedMessage());
LOG.warn(message);
@@ -121,26 +116,83 @@ public class AmbariAuthToLocalUserDetailsService implements UserDetailsService {
* User accounts are searched in order of preferred user type as specified in the Ambari configuration
* ({@link Configuration#KERBEROS_AUTH_USER_TYPES}).
*
- * @param username a username
+ * @param username a username
+ * @param principal the user's principal
* @return the user details of the found user, or <code>null</code> if an appropriate user was not found
*/
- private UserDetails createUser(String username) {
- // Iterate over the ordered user types... when an account for the username/type combination is
- // found, build the related AmbariUserAuthentication instance and return it. Only the first
- // match matters... this may be an issue and cause some ambiguity in the event multiple user
- // types are specified in the configuration and multiple accounts for the same username, but
- // different types (LOCAL vs LDAP, etc...).
- for (UserType userType : userTypeOrder) {
- org.apache.ambari.server.security.authorization.User user = users.getUser(username, userType);
-
- if (user != null) {
- Collection<AmbariGrantedAuthority> userAuthorities = users.getUserAuthorities(user.getUserName(), user.getUserType());
- return new User(username, "", userAuthorities);
+ private UserDetails createUser(String username, String principal) throws AuthenticationException {
+ UserEntity userEntity = users.getUserEntity(username);
+
+ if (userEntity == null) {
+ throw new UserNotFoundException(username, String.format("Cannot find user using Kerberos ticket (%s).", principal));
+ } else if (!userEntity.getActive()) {
+ LOG.debug("User account is disabled");
+ throw new UserNotFoundException(username, "User account is disabled");
+ } else {
+
+ // Check to see if the user is allowed to authenticate using KERBEROS or LDAP
+ List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+ boolean hasKerberos = false;
+ boolean hasLDAP = false;
+ boolean hasLocal = false;
+
+ for (UserAuthenticationEntity entity : authenticationEntities) {
+ UserAuthenticationType authenticationType = entity.getAuthenticationType();
+
+ switch (authenticationType) {
+ case KERBEROS:
+ if (principal.equalsIgnoreCase(entity.getAuthenticationKey())) {
+ LOG.trace("Found KERBEROS authentication method for {} using principal {}", username, principal);
+ hasKerberos = true;
+ }
+ break;
+
+ case LDAP:
+ hasLDAP = true;
+ break;
+
+ case LOCAL:
+ hasLocal = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (hasKerberos) {
+ break;
+ }
+ }
+
+ if (!hasKerberos) {
+ if (hasLDAP) {
+ // TODO: Determine if LDAP users can authenticate using Kerberos
+ try {
+ users.addKerberosAuthentication(userEntity, principal);
+ LOG.trace("Added KERBEROS authentication method for {} using principal {}", username, principal);
+ } catch (AmbariException e) {
+ LOG.error(String.format("Failed to add the KERBEROS authentication method for %s: %s", principal, e.getLocalizedMessage()), e);
+ }
+ hasKerberos = true;
+ }
+
+ if (!hasKerberos && hasLocal) {
+ // TODO: Determine if LOCAL users can authenticate using Kerberos
+ try {
+ users.addKerberosAuthentication(userEntity, username);
+ LOG.trace("Added KERBEROS authentication method for {} using principal {}", username, principal);
+ } catch (AmbariException e) {
+ LOG.error(String.format("Failed to add the KERBEROS authentication method for %s: %s", username, e.getLocalizedMessage()), e);
+ }
+ hasKerberos = true;
+ }
+ }
+
+ if (!hasKerberos) {
+ throw new AuthenticationMethodNotAllowedException(username, UserAuthenticationType.KERBEROS);
}
}
- String message = String.format("Failed find user account for user with username of %s during Kerberos authentication.", username);
- LOG.warn(message);
- throw new UsernameNotFoundException(message);
+ return new User(username, "", users.getUserAuthorities(userEntity));
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
index 09422e5..3e31e0d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.apache.ambari.server.security.authorization.UserType;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
/**
* AmbariKerberosAuthenticationProperties is a container for Kerberos authentication-related
@@ -51,10 +51,10 @@ public class AmbariKerberosAuthenticationProperties {
private String spnegoKeytabFilePath = null;
/**
- * A list of {@link UserType}s in order of preference for use when looking up user accounts in the
+ * A list of {@link UserAuthenticationType}s in order of preference for use when looking up user accounts in the
* Ambari database
*/
- private List<UserType> orderedUserTypes = Collections.emptyList();
+ private List<UserAuthenticationType> orderedUserTypes = Collections.emptyList();
/**
* Auth-to-local rules to use to feed to an auth-to-local rules processor used to translate
@@ -119,11 +119,11 @@ public class AmbariKerberosAuthenticationProperties {
}
/**
- * Sets the list of {@link UserType}s (in preference order) to use to look up uer accounts in the Ambari database.
+ * Sets the list of {@link UserAuthenticationType}s (in preference order) to use to look up uer accounts in the Ambari database.
*
- * @param orderedUserTypes a list of {@link UserType}s
+ * @param orderedUserTypes a list of {@link UserAuthenticationType}s
*/
- public void setOrderedUserTypes(List<UserType> orderedUserTypes) {
+ public void setOrderedUserTypes(List<UserAuthenticationType> orderedUserTypes) {
if (orderedUserTypes == null) {
this.orderedUserTypes = Collections.emptyList();
} else {
@@ -132,11 +132,11 @@ public class AmbariKerberosAuthenticationProperties {
}
/**
- * Gets the list of {@link UserType}s (in preference order) to use to look up uer accounts in the Ambari database.
+ * Gets the list of {@link UserAuthenticationType}s (in preference order) to use to look up uer accounts in the Ambari database.
*
- * @return a list of {@link UserType}s
+ * @return a list of {@link UserAuthenticationType}s
*/
- public List<UserType> getOrderedUserTypes() {
+ public List<UserAuthenticationType> getOrderedUserTypes() {
return orderedUserTypes;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index ce9a790..a31e951 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -300,7 +300,7 @@ public class AmbariAuthorizationFilter implements Filter {
String username = configuration.getDefaultApiAuthenticatedUser();
if (!StringUtils.isEmpty(username)) {
- final User user = users.getUser(username, UserType.LOCAL);
+ final User user = users.getUser(username);
if (user != null) {
Principal principal = new Principal() {
@@ -311,7 +311,7 @@ public class AmbariAuthorizationFilter implements Filter {
};
defaultUser = new UsernamePasswordAuthenticationToken(principal, null,
- users.getUserAuthorities(user.getUserName(), user.getUserType()));
+ users.getUserAuthorities(user.getUserName()));
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProvider.java
index b7ff297..6137b68 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProvider.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
import org.apache.ambari.server.security.ClientSecurityType;
import org.slf4j.Logger;
@@ -61,6 +62,9 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
this.userDAO = userDAO;
}
+ // TODO: ************
+ // TODO: This is to be revisited for AMBARI-21219 (Update LDAP Authentication process to work with improved user management facility)
+ // TODO: ************
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (isLdapEnabled()) {
@@ -100,7 +104,6 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
} else {
return null;
}
-
}
@Override
@@ -196,7 +199,7 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
private Integer getUserId(Authentication authentication) {
String userName = AuthorizationHelper.resolveLoginAliasToUserName(authentication.getName());
- UserEntity userEntity = userDAO.findLdapUserByName(userName);
+ UserEntity userEntity = userDAO.findUserByName(userName);
// lookup is case insensitive, so no need for string comparison
if (userEntity == null) {
@@ -206,11 +209,19 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
if (!userEntity.getActive()) {
LOG.debug("User account is disabled ('{}')", userName);
+ } else {
+ List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+ for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+ if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.LDAP) {
+ // TODO: Ensure this is the "correct" LDAP entry..
+ return userEntity.getUserId();
+ }
+ }
- throw new InvalidUsernamePasswordCombinationException();
+ LOG.debug("Failed to find LDAP authentication entry for {})", userName);
}
- return userEntity.getUserId();
+ throw new InvalidUsernamePasswordCombinationException();
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthoritiesPopulator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthoritiesPopulator.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthoritiesPopulator.java
index d38d44c..5c482a1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthoritiesPopulator.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthoritiesPopulator.java
@@ -64,7 +64,7 @@ public class AmbariLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
UserEntity user;
- user = userDAO.findLdapUserByName(username);
+ user = userDAO.findUserByName(username);
if (user == null) {
log.error("Can't get authorities for user " + username + ", he is not present in local DB");
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
index 37d5d49..517efe4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
@@ -17,9 +17,10 @@
*/
package org.apache.ambari.server.security.authorization;
-import java.util.Collection;
+import java.util.List;
import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,47 +53,52 @@ public class AmbariLocalUserProvider extends AbstractUserDetailsAuthenticationPr
// do nothing
}
+ // TODO: ************
+ // TODO: This is to be revisited for AMBARI-21220 (Update Local Authentication process to work with improved user management facility)
+ // TODO: ************
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String userName = authentication.getName().trim();
LOG.info("Loading user by name: " + userName);
- UserEntity userEntity = userDAO.findLocalUserByName(userName);
+ UserEntity userEntity = userDAO.findUserByName(userName);
if (userEntity == null) {
- //TODO case insensitive name comparison is a temporary solution, until users API will change to use id as PK
LOG.info("user not found");
throw new InvalidUsernamePasswordCombinationException();
}
if (!userEntity.getActive()) {
- logger.debug("User account is disabled");
-
+ LOG.debug("User account is disabled");
throw new InvalidUsernamePasswordCombinationException();
}
if (authentication.getCredentials() == null) {
- logger.debug("Authentication failed: no credentials provided");
-
+ LOG.debug("Authentication failed: no credentials provided");
throw new InvalidUsernamePasswordCombinationException();
}
- String password = userEntity.getUserPassword();
- String presentedPassword = authentication.getCredentials().toString();
-
- if (!passwordEncoder.matches(presentedPassword, password)) {
- logger.debug("Authentication failed: password does not match stored value");
-
- throw new InvalidUsernamePasswordCombinationException();
+ List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+ for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+ if (authenticationEntity.getAuthenticationType() == UserAuthenticationType.LOCAL) {
+ // This should only get invoked once...
+ String password = authenticationEntity.getAuthenticationKey();
+ String presentedPassword = authentication.getCredentials().toString();
+
+ if (passwordEncoder.matches(presentedPassword, password)) {
+ // The user was authenticated, return the authenticated user object
+ User user = new User(userEntity);
+ Authentication auth = new AmbariUserAuthentication(password, user, users.getUserAuthorities(userEntity));
+ auth.setAuthenticated(true);
+ return auth;
+ }
+ }
}
- Collection<AmbariGrantedAuthority> userAuthorities =
- users.getUserAuthorities(userEntity.getUserName(), userEntity.getUserType());
- User user = new User(userEntity);
- Authentication auth = new AmbariUserAuthentication(userEntity.getUserPassword(), user, userAuthorities);
- auth.setAuthenticated(true);
- return auth;
+ // The user was not authenticated, fail
+ LOG.debug("Authentication failed: password does not match stored value");
+ throw new InvalidUsernamePasswordCombinationException();
}
@Override
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProvider.java
index 373552e..b9bcff6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProvider.java
@@ -17,7 +17,6 @@
*/
package org.apache.ambari.server.security.authorization;
-import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -51,9 +50,9 @@ public class AmbariPamAuthenticationProvider implements AuthenticationProvider {
@Inject
private Users users;
@Inject
- protected UserDAO userDAO;
+ private UserDAO userDAO;
@Inject
- protected GroupDAO groupDAO;
+ private GroupDAO groupDAO;
private static final Logger LOG = LoggerFactory.getLogger(AmbariPamAuthenticationProvider.class);
@@ -64,97 +63,70 @@ public class AmbariPamAuthenticationProvider implements AuthenticationProvider {
this.configuration = configuration;
}
- /**
- * Performs PAM Initialization
- *
- * @param authentication
- * @return authentication
- */
-
+ // TODO: ************
+ // TODO: This is to be revisited for AMBARI-21221 (Update Pam Authentication process to work with improved user management facility)
+ // TODO: ************
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- if(isPamEnabled()){
- PAM pam;
- String userName = String.valueOf(authentication.getPrincipal());
- UserEntity existingUser = userDAO.findUserByName(userName);
- if ((existingUser != null) && (existingUser.getUserType() != UserType.PAM)) {
- String errorMsg = String.format("%s user exists with the username %s. Cannot authenticate via PAM", existingUser.getUserType(), userName);
- LOG.error(errorMsg);
- return null;
- }
- try{
- //Set PAM configuration file (found under /etc/pam.d)
- String pamConfig = configuration.getPamConfigurationFile();
- pam = new PAM(pamConfig);
-
- } catch(PAMException ex) {
- LOG.error("Unable to Initialize PAM." + ex.getMessage());
- throw new AuthenticationServiceException("Unable to Initialize PAM - ", ex);
- }
+ if (isPamEnabled()) {
+ //Set PAM configuration file (found under /etc/pam.d)
+ String pamConfig = configuration.getPamConfigurationFile();
+ PAM pam;
+ try {
+ //Set PAM configuration file (found under /etc/pam.d)
+ pam = new PAM(pamConfig);
+
+ } catch (PAMException ex) {
+ LOG.error("Unable to Initialize PAM: " + ex.getMessage(), ex);
+ throw new AuthenticationServiceException("Unable to Initialize PAM - ", ex);
+ }
+
+ try {
return authenticateViaPam(pam, authentication);
+ } finally {
+ pam.dispose();
+ }
} else {
- return null;
+ return null;
}
}
- /**
- * Performs PAM Authentication
- *
- * @param pam
- * @param authentication
- * @return authentication
- */
-
- protected Authentication authenticateViaPam(PAM pam, Authentication authentication) throws AuthenticationException{
- if(isPamEnabled()){
- try {
- String userName = String.valueOf(authentication.getPrincipal());
- String passwd = String.valueOf(authentication.getCredentials());
-
- // authenticate using PAM
- UnixUser unixUser = pam.authenticate(userName,passwd);
-
- //Get all the groups that user belongs to
- //Change all group names to lower case.
- Set<String> groups = new HashSet<>();
-
- for(String group: unixUser.getGroups()){
- groups.add(group.toLowerCase());
- }
-
- ambariPamAuthorization(userName,groups);
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
+ }
- Collection<AmbariGrantedAuthority> userAuthorities =
- users.getUserAuthorities(userName, UserType.PAM);
+ Authentication authenticateViaPam(PAM pam, Authentication authentication) {
+ String userName = String.valueOf(authentication.getPrincipal());
+ String password = String.valueOf(authentication.getCredentials());
- final User user = users.getUser(userName, UserType.PAM);
-
- Authentication authToken = new AmbariUserAuthentication(passwd, user, userAuthorities);
- authToken.setAuthenticated(true);
- return authToken;
- } catch (PAMException ex) {
- LOG.error("Unable to sign in. Invalid username/password combination - " + ex.getMessage());
- Throwable t = ex.getCause();
- throw new PamAuthenticationException("Unable to sign in. Invalid username/password combination.",t);
+ UnixUser unixUser;
+ try {
+ // authenticate using PAM
+ unixUser = pam.authenticate(userName, password);
+ } catch (PAMException ex) {
+ LOG.error("Unable to sign in. Invalid username/password combination - " + ex.getMessage());
+ Throwable t = ex.getCause();
+ throw new PamAuthenticationException("Unable to sign in. Invalid username/password combination.", t);
+ }
- } finally {
- pam.dispose();
- }
+ if (unixUser != null) {
+ UserEntity userEntity = ambariPamAuthorization(unixUser);
+ if (userEntity != null) {
+ Authentication authToken = new AmbariUserAuthentication(password, users.getUser(userEntity), users.getUserAuthorities(userEntity));
+ authToken.setAuthenticated(true);
+ return authToken;
}
- else {
- return null;
- }
- }
+ }
- @Override
- public boolean supports(Class<?> authentication) {
- return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
+ return null;
}
/**
* Check if PAM authentication is enabled in server properties
+ *
* @return true if enabled
*/
private boolean isPamEnabled() {
@@ -163,6 +135,7 @@ public class AmbariPamAuthenticationProvider implements AuthenticationProvider {
/**
* Check if PAM authentication is enabled in server properties
+ *
* @return true if enabled
*/
private boolean isAutoGroupCreationAllowed() {
@@ -173,56 +146,64 @@ public class AmbariPamAuthenticationProvider implements AuthenticationProvider {
/**
* Performs PAM authorization by creating user & group(s)
*
- * @param userName user name
- * @param userGroups Collection of groups
- * @return
+ * @param unixUser the user
*/
- private void ambariPamAuthorization(String userName,Set<String> userGroups){
+ private UserEntity ambariPamAuthorization(UnixUser unixUser) {
+ String userName = unixUser.getUserName();
+ UserEntity userEntity = null;
+
try {
- User existingUser = users.getUser(userName,UserType.PAM);
+ userEntity = userDAO.findUserByName(userName);
- if (existingUser == null ) {
- users.createUser(userName, null, UserType.PAM, true, false);
+ // TODO: Ensure automatically creating users when authenticating with PAM is allowed.
+ if (userEntity == null) {
+ userEntity = users.createUser(userName, userName, userName);
+ users.addPamAuthentication(userEntity, userName);
}
- UserEntity userEntity = userDAO.findUserByNameAndType(userName, UserType.PAM);
-
- if(isAutoGroupCreationAllowed()){
- for(String userGroup: userGroups){
- if(users.getGroupByNameAndType(userGroup, GroupType.PAM) == null){
- users.createGroup(userGroup, GroupType.PAM);
- }
-
- final GroupEntity groupEntity = groupDAO.findGroupByNameAndType(userGroup, GroupType.PAM);
-
- if (!isUserInGroup(userEntity, groupEntity)){
- users.addMemberToGroup(userGroup,userName);
+ if (isAutoGroupCreationAllowed()) {
+ //Get all the groups that user belongs to
+ //Change all group names to lower case.
+ Set<String> unixUserGroups = unixUser.getGroups();
+ if (unixUserGroups != null) {
+ for (String group : unixUserGroups) {
+ // Ensure group name is lowercase
+ group = group.toLowerCase();
+
+ GroupEntity groupEntity = groupDAO.findGroupByNameAndType(group, GroupType.PAM);
+ if (groupEntity == null) {
+ groupEntity = users.createGroup(group, GroupType.PAM);
+ }
+
+ if (!isUserInGroup(userEntity, groupEntity)) {
+ users.addMemberToGroup(groupEntity, userEntity);
+ }
}
}
- Set<String> ambariUserGroups = getUserGroups(userName, UserType.PAM);
-
- for(String group: ambariUserGroups){
- if(userGroups == null || !userGroups.contains(group)){
- users.removeMemberFromGroup(group, userName);
+ Set<GroupEntity> ambariUserGroups = getUserGroups(userEntity);
+ for (GroupEntity groupEntity : ambariUserGroups) {
+ if (unixUserGroups == null || !unixUserGroups.contains(groupEntity.getGroupName())) {
+ users.removeMemberFromGroup(groupEntity, userEntity);
}
}
}
-
} catch (AmbariException e) {
e.printStackTrace();
}
+
+ return userEntity;
}
/**
* 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;
}
@@ -233,17 +214,20 @@ public class AmbariPamAuthenticationProvider implements AuthenticationProvider {
/**
* Extracts all groups a user belongs to
*
- * @param userName user name
+ * @param userEntity the user
* @return Collection of group names
*/
- private Set<String> getUserGroups(String userName, UserType userType) {
- UserEntity userEntity = userDAO.findUserByNameAndType(userName, userType);
- Set<String> groups = new HashSet<>();
- for (MemberEntity memberEntity: userEntity.getMemberEntities()) {
- groups.add(memberEntity.getGroup().getGroupName());
+ private Set<GroupEntity> getUserGroups(UserEntity userEntity) {
+ Set<GroupEntity> groups = new HashSet<>();
+ if (userEntity != null) {
+ for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
+ GroupEntity groupEntity = memberEntity.getGroup();
+ if (groupEntity.getGroupType() == GroupType.PAM) {
+ groups.add(memberEntity.getGroup());
+ }
+ }
}
return groups;
}
-
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
index 95e90b3..8fbd816 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
@@ -30,6 +30,7 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.ambari.server.orm.entities.UserEntity;
import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
import org.apache.ambari.server.security.authorization.internal.InternalTokenClientFilter;
import org.apache.ambari.server.security.authorization.internal.InternalTokenStorage;
@@ -70,18 +71,18 @@ public class AmbariUserAuthorizationFilter implements Filter {
return;
}
Integer userId = Integer.parseInt(userToken);
- User user = users.getUser(userId);
- if (user == null) {
+ UserEntity userEntity = users.getUserEntity(userId);
+ if (userEntity == null) {
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Authentication required");
httpResponse.flushBuffer();
return;
- } if (!user.isActive()) {
+ } if (!userEntity.getActive()) {
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not active");
httpResponse.flushBuffer();
return;
} else {
- Collection<AmbariGrantedAuthority> userAuthorities =
- users.getUserAuthorities(user.getUserName(), user.getUserType());
+ Collection<AmbariGrantedAuthority> userAuthorities = users.getUserAuthorities(userEntity);
+ User user = users.getUser(userEntity);
AmbariUserAuthentication authentication = new AmbariUserAuthentication(token, user, userAuthorities);
authentication.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(authentication);
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthenticationMethod.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthenticationMethod.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthenticationMethod.java
new file mode 100644
index 0000000..5670c38
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthenticationMethod.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+public class AuthenticationMethod {
+ private final UserAuthenticationType authenticationType;
+ private final String authenticationKey;
+
+ public AuthenticationMethod(UserAuthenticationType authenticationType, String authenticationKey) {
+ this.authenticationType = authenticationType;
+ this.authenticationKey = authenticationKey;
+ }
+
+ public UserAuthenticationType getAuthenticationType() {
+ return authenticationType;
+ }
+
+ public String getAuthenticationKey() {
+ return authenticationKey;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
index 64d5e61..a0b6029 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
@@ -125,7 +125,7 @@ public class AuthorizationHelper {
* @return true if authorized; otherwise false
* @see #isAuthorized(Authentication, ResourceType, Long, Set)
*/
- public static boolean isAuthorized(ResourceType resourceType, Long resourceId,
+ public static boolean isAuthorized(ResourceType resourceType, Long resourceId,
RoleAuthorization requiredAuthorization) {
return isAuthorized(getAuthentication(), resourceType, resourceId, EnumSet.of(requiredAuthorization));
}
@@ -141,7 +141,7 @@ public class AuthorizationHelper {
* @return true if authorized; otherwise false
* @see #isAuthorized(Authentication, ResourceType, Long, Set)
*/
- public static boolean isAuthorized(ResourceType resourceType, Long resourceId,
+ public static boolean isAuthorized(ResourceType resourceType, Long resourceId,
Set<RoleAuthorization> requiredAuthorizations) {
return isAuthorized(getAuthentication(), resourceType, resourceId, requiredAuthorizations);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
index bff1fd2..a418451 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java
@@ -25,8 +25,8 @@ import java.util.List;
import org.apache.ambari.server.orm.entities.MemberEntity;
import org.apache.ambari.server.orm.entities.PermissionEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
-import org.springframework.security.core.GrantedAuthority;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -37,32 +37,39 @@ import io.swagger.annotations.ApiModelProperty;
*/
@ApiModel
public class User {
- final int userId;
- final String userName;
- final boolean ldapUser;
- final UserType userType;
- final Date createTime;
- final boolean active;
- final Collection<String> groups = new ArrayList<>();
- boolean admin = false;
- final List<GrantedAuthority> authorities = new ArrayList<>();
+ final private int userId;
+ final private String userName;
+ final private Date createTime;
+ final private boolean active;
+ final private Collection<String> groups;
+ final private Collection<AuthenticationMethod> authenticationMethods;
+ final private boolean admin;
public User(UserEntity userEntity) {
userId = userEntity.getUserId();
userName = userEntity.getUserName();
createTime = userEntity.getCreateTime();
- userType = userEntity.getUserType();
- ldapUser = userEntity.getLdapUser();
active = userEntity.getActive();
+
+ groups = new ArrayList<>();
for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
groups.add(memberEntity.getGroup().getGroupName());
}
- for (PrivilegeEntity privilegeEntity: userEntity.getPrincipal().getPrivileges()) {
+
+ authenticationMethods = new ArrayList<>();
+ List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+ for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+ authenticationMethods.add(new AuthenticationMethod(authenticationEntity.getAuthenticationType(), authenticationEntity.getAuthenticationKey()));
+ }
+
+ boolean admin = false;
+ for (PrivilegeEntity privilegeEntity : userEntity.getPrincipal().getPrivileges()) {
if (privilegeEntity.getPermission().getPermissionName().equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION_NAME)) {
admin = true;
break;
}
}
+ this.admin = admin;
}
@ApiModelProperty(hidden = true)
@@ -75,16 +82,6 @@ public class User {
return userName;
}
- @ApiModelProperty(name = "Users/ldap_user")
- public boolean isLdapUser() {
- return ldapUser;
- }
-
- @ApiModelProperty(name = "Users/user_type")
- public UserType getUserType() {
- return userType;
- }
-
@ApiModelProperty(hidden = true)
public Date getCreateTime() {
return createTime;
@@ -105,8 +102,24 @@ public class User {
return groups;
}
+ @ApiModelProperty(name = "Users/authentication_methods")
+ public Collection<AuthenticationMethod> getAuthenticationMethods() {
+ return authenticationMethods;
+ }
+
+ @ApiModelProperty(name = "Users/ldap_user")
+ public boolean isLdapUser() {
+ for (AuthenticationMethod authenticationMethod : authenticationMethods) {
+ if (authenticationMethod.getAuthenticationType() == UserAuthenticationType.LDAP) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public String toString() {
- return "[" + getUserType() + "]" + userName;
+ return userName;
}
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserAuthenticationType.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserAuthenticationType.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserAuthenticationType.java
new file mode 100644
index 0000000..ceeb7f9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserAuthenticationType.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+public enum UserAuthenticationType {
+ LOCAL,
+ LDAP,
+ JWT,
+ PAM,
+ KERBEROS
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f76c87a6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserType.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserType.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserType.java
deleted file mode 100644
index aabd368..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/UserType.java
+++ /dev/null
@@ -1,25 +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;
-
-public enum UserType {
- LOCAL,
- LDAP,
- JWT,
- PAM
-}