Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-20859 d57ebbc2d -> d6b271e6b


AMBARI-21221.  Update Pam Authentication process to work with improved user 
management facility (rlevas)


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

Branch: refs/heads/branch-feature-AMBARI-20859
Commit: d6b271e6bbcafbe57831890c9f8aa5386a57c8c3
Parents: d57ebbc
Author: Robert Levas <[email protected]>
Authored: Fri Oct 20 10:03:32 2017 -0400
Committer: Robert Levas <[email protected]>
Committed: Fri Oct 20 10:03:32 2017 -0400

----------------------------------------------------------------------
 ambari-server/docs/configuration/index.md       |   2 +-
 .../server/configuration/Configuration.java     |   2 +-
 .../ambari/server/controller/AmbariServer.java  |   2 +-
 .../AccountDisabledException.java               |   2 +-
 .../AmbariAuthenticationEventHandlerImpl.java   |   5 +-
 .../AmbariAuthenticationException.java          |  17 +-
 .../AmbariAuthenticationProvider.java           |  55 ++--
 .../AmbariBasicAuthenticationFilter.java        |   2 +-
 .../AmbariLocalAuthenticationProvider.java      |  52 ++--
 ...lidUsernamePasswordCombinationException.java |  12 +-
 .../TooManyLoginFailuresException.java          |   2 +-
 .../authentication/UserNotFoundException.java   |   8 +-
 .../jwt/AmbariJwtAuthenticationFilter.java      |   2 +-
 .../jwt/AmbariJwtAuthenticationProvider.java    |  50 +--
 .../AmbariKerberosAuthenticationFilter.java     |   2 +-
 .../pam/AmbariPamAuthenticationProvider.java    | 302 +++++++++++++++++++
 .../pam/PamAuthenticationFactory.java           |  21 +-
 .../AmbariPamAuthenticationProvider.java        | 237 ---------------
 .../PamAuthenticationException.java             |  36 ---
 .../server/security/authorization/Users.java    |  17 +-
 .../AmbariPamAuthenticationProviderTest.java    | 277 +++++++++++++++++
 .../AmbariPamAuthenticationProviderTest.java    | 177 -----------
 22 files changed, 736 insertions(+), 546 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/docs/configuration/index.md
----------------------------------------------------------------------
diff --git a/ambari-server/docs/configuration/index.md 
b/ambari-server/docs/configuration/index.md
index 73d6fd0..514e9ed 100644
--- a/ambari-server/docs/configuration/index.md
+++ b/ambari-server/docs/configuration/index.md
@@ -129,7 +129,7 @@ The following are the properties which can be used to 
configure Ambari.
 | client.api.ssl.port | The port that client connections will use with the 
REST API when using SSL. The Ambari Web client runs on this port if SSL is 
enabled. |`8443` | 
 | client.api.ssl.truststore_name | The name of the truststore used when the 
Ambari Server REST API is protected by SSL. |`https.keystore.p12` | 
 | client.api.ssl.truststore_type | The type of the keystore file specified in 
`client.api.ssl.truststore_name`. Self-signed certificates can be `PKCS12` 
while CA signed certificates are `JKS` |`PKCS12` | 
-| client.security | The type of authentication mechanism used by 
Ambari.<br/><br/>The following are examples of valid 
values:<ul><li>`local`<li>`ldap`</ul> | | 
+| client.security | The type of authentication mechanism used by 
Ambari.<br/><br/>The following are examples of valid 
values:<ul><li>`local`<li>`ldap`<li>`pam`</ul> | | 
 | client.threadpool.size.max | The size of the Jetty connection pool used for 
handling incoming REST API requests. This should be large enough to handle 
requests from both web browsers and embedded Views. |`25` | 
 | common.services.path | The location on the Ambari Server where common 
service resources exist. Stack services share the common service 
files.<br/><br/>The following are examples of valid 
values:<ul><li>`/var/lib/ambari-server/resources/common-services`</ul> | | 
 | custom.action.definitions | The location on the Ambari Server where custom 
actions are defined. 
|`/var/lib/ambari-server/resources/custom_action_definitions` | 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 2b14b4d..205debc 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -813,7 +813,7 @@ public class Configuration {
    * @see ClientSecurityType
    */
   @Markdown(
-      examples = { "local", "ldap" },
+      examples = { "local", "ldap", "pam" },
       description = "The type of authentication mechanism used by Ambari.")
   public static final ConfigurationProperty<String> CLIENT_SECURITY = new 
ConfigurationProperty<>(
       "client.security", null);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index bb8e0fe..b29cfc3 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -102,8 +102,8 @@ import org.apache.ambari.server.security.SecurityFilter;
 import 
org.apache.ambari.server.security.authentication.AmbariAuthenticationEventHandlerImpl;
 import 
org.apache.ambari.server.security.authentication.AmbariLocalAuthenticationProvider;
 import 
org.apache.ambari.server.security.authentication.jwt.AmbariJwtAuthenticationProvider;
+import 
org.apache.ambari.server.security.authentication.pam.AmbariPamAuthenticationProvider;
 import 
org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
-import 
org.apache.ambari.server.security.authorization.AmbariPamAuthenticationProvider;
 import 
org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter;
 import org.apache.ambari.server.security.authorization.PermissionHelper;
 import org.apache.ambari.server.security.authorization.Users;

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AccountDisabledException.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AccountDisabledException.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AccountDisabledException.java
index 4a88f46..18551c3 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AccountDisabledException.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AccountDisabledException.java
@@ -22,6 +22,6 @@ package org.apache.ambari.server.security.authentication;
  */
 public class AccountDisabledException extends AmbariAuthenticationException {
   public AccountDisabledException(String username) {
-    super(username, "The account is disabled");
+    super(username, "The account is disabled", false);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationEventHandlerImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationEventHandlerImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationEventHandlerImpl.java
index e651d22..8ff39e0 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationEventHandlerImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationEventHandlerImpl.java
@@ -97,19 +97,22 @@ public class AmbariAuthenticationEventHandlerImpl 
implements AmbariAuthenticatio
     String message;
     String logMessage;
     Integer consecutiveFailures = null;
+    boolean incrementFailureCount;
 
     if (cause == null) {
       username = null;
       message = "Unknown cause";
+      incrementFailureCount = false;
     } else {
       username = cause.getUsername();
       message = cause.getLocalizedMessage();
+      incrementFailureCount = cause.isCredentialFailure();
     }
 
     if (!StringUtils.isEmpty(username)) {
       // Only increment the authentication failure count if the authentication 
filter declares to
       // do so.
-      if(filter.shouldIncrementFailureCount()) {
+      if(incrementFailureCount && filter.shouldIncrementFailureCount()) {
         // Increment the user's consecutive authentication failure count.
         consecutiveFailures = 
users.incrementConsecutiveAuthenticationFailures(username);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationException.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationException.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationException.java
index fb18b9c..f659f19 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationException.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationException.java
@@ -27,17 +27,30 @@ import 
org.springframework.security.core.AuthenticationException;
 public class AmbariAuthenticationException extends AuthenticationException {
   private final String username;
 
-  public AmbariAuthenticationException(String username, String message) {
+  /**
+   * A boolean value indicating whether the faulire was due to invalid 
credentials (<code>true</code>) or not (<code>false</code>)
+   * <p>
+   * An invalid credential failure will count towards a user's authentication 
failure count.
+   */
+  private final boolean credentialFailure;
+
+  public AmbariAuthenticationException(String username, String message, 
boolean credentialFailure) {
     super(message);
     this.username = username;
+    this.credentialFailure = credentialFailure;
   }
 
-  public AmbariAuthenticationException(String username, String message, 
Throwable throwable) {
+  public AmbariAuthenticationException(String username, String message, 
boolean credentialFailure, Throwable throwable) {
     super(message, throwable);
     this.username = username;
+    this.credentialFailure = credentialFailure;
   }
 
   public String getUsername() {
     return username;
   }
+
+  public boolean isCredentialFailure() {
+    return credentialFailure;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationProvider.java
index d3d5b88..71fa175 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariAuthenticationProvider.java
@@ -37,8 +37,12 @@ import 
org.springframework.security.authentication.AuthenticationProvider;
 public abstract class AmbariAuthenticationProvider implements 
AuthenticationProvider {
   private static final Logger LOG = 
LoggerFactory.getLogger(AmbariAuthenticationProvider.class);
 
-  private Users users;
-  private Configuration configuration;
+  /**
+   * Helper object to provide logic for working with users.
+   */
+  private final Users users;
+
+  private final Configuration configuration;
 
   protected AmbariAuthenticationProvider(Users users, Configuration 
configuration) {
     this.users = users;
@@ -46,40 +50,28 @@ public abstract class AmbariAuthenticationProvider 
implements AuthenticationProv
   }
 
   /**
-   * Gets the {@link UserEntity} for the user with the specified username.
-   * <p>
-   * The entity is validated such that the account is allowed to log in before 
returning. For example,
-   * if the account is not active, no user may not login as that account.
+   * Validates the user account such that the user is allowed to log in.
    *
-   * @param userName
-   * @return
+   * @param userEntity the user entity
+   * @param userName   the Ambari username
    */
-  protected UserEntity getUserEntity(String userName) {
-    LOG.debug("Loading user by name: {}", userName);
-    UserEntity userEntity = users.getUserEntity(userName);
-
+  protected void validateLogin(UserEntity userEntity, String userName) {
     if (userEntity == null) {
-      LOG.info("User not found: {}", userName);
+      LOG.info("User not found");
       throw new UserNotFoundException(userName);
-    }
-
-    if (!userEntity.getActive()) {
-      LOG.info("User account is disabled: {}", userName);
-      throw new AccountDisabledException(userName);
-    }
+    } else {
+      if (!userEntity.getActive()) {
+        LOG.info("User account is disabled: {}", userName);
+        throw new AccountDisabledException(userName);
+      }
 
-    int maxConsecutiveFailures = configuration.getMaxAuthenticationFailures();
-    if (maxConsecutiveFailures > 0 && userEntity.getConsecutiveFailures() >= 
maxConsecutiveFailures) {
-      LOG.info("User account is locked out due to too many authentication 
failures ({}/{}): {}",
-          userEntity.getConsecutiveFailures(), maxConsecutiveFailures, 
userName);
-      if (configuration.showLockedOutUserMessage()) {
+      int maxConsecutiveFailures = 
configuration.getMaxAuthenticationFailures();
+      if (maxConsecutiveFailures > 0 && userEntity.getConsecutiveFailures() >= 
maxConsecutiveFailures) {
+        LOG.info("User account is locked out due to too many authentication 
failures ({}/{}): {}",
+            userEntity.getConsecutiveFailures(), maxConsecutiveFailures, 
userName);
         throw new TooManyLoginFailuresException(userName);
-      } else {
-        throw new InvalidUsernamePasswordCombinationException(userName);
       }
     }
-
-    return userEntity;
   }
 
   /**
@@ -103,4 +95,11 @@ public abstract class AmbariAuthenticationProvider 
implements AuthenticationProv
     return null;
   }
 
+  protected Users getUsers() {
+    return users;
+  }
+
+  protected Configuration getConfiguration() {
+    return configuration;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariBasicAuthenticationFilter.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariBasicAuthenticationFilter.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariBasicAuthenticationFilter.java
index f617a60..faa5116 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariBasicAuthenticationFilter.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariBasicAuthenticationFilter.java
@@ -159,7 +159,7 @@ public class AmbariBasicAuthenticationFilter extends 
BasicAuthenticationFilter i
           LOG.warn("Error occurred during decoding authorization header.", e);
         }
 
-        cause = new AmbariAuthenticationException(username, 
authException.getMessage(), authException);
+        cause = new AmbariAuthenticationException(username, 
authException.getMessage(), false, authException);
       }
 
       eventHandler.onUnsuccessfulAuthentication(this, servletRequest, 
servletResponse, cause);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariLocalAuthenticationProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariLocalAuthenticationProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariLocalAuthenticationProvider.java
index 7ef6524..3ffa3e8 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariLocalAuthenticationProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/AmbariLocalAuthenticationProvider.java
@@ -42,49 +42,37 @@ import com.google.inject.Inject;
 public class AmbariLocalAuthenticationProvider extends 
AmbariAuthenticationProvider {
   private static final Logger LOG = 
LoggerFactory.getLogger(AmbariLocalAuthenticationProvider.class);
 
-  private Users users;
   private PasswordEncoder passwordEncoder;
-  private Configuration configuration;
 
   @Inject
   public AmbariLocalAuthenticationProvider(Users users, PasswordEncoder 
passwordEncoder, Configuration configuration) {
     super(users, configuration);
-    this.users = users;
     this.passwordEncoder = passwordEncoder;
-    this.configuration = configuration;
   }
 
   @Override
   public Authentication authenticate(Authentication authentication) throws 
AuthenticationException {
-    String userName = authentication.getName().trim();
-
-    UserEntity userEntity;
-    try {
-      userEntity = getUserEntity(userName);
-
-      if (userEntity == null) {
-        LOG.info("User not found: {}", userName);
-        throw new InvalidUsernamePasswordCombinationException(userName);
-      }
-    }
-    catch(UserNotFoundException e) {
-      // Do not give away information about the existence or status of a user
-      throw new InvalidUsernamePasswordCombinationException(userName, e);
-    }
-    catch (AccountDisabledException | TooManyLoginFailuresException e) {
-      if (configuration.showLockedOutUserMessage()) {
-        throw e;
-      } else {
-        // Do not give away information about the existence or status of a user
-        throw new InvalidUsernamePasswordCombinationException(userName, e);
-      }
+    if (authentication.getName() == null) {
+      LOG.info("Authentication failed: no username provided");
+      throw new InvalidUsernamePasswordCombinationException("");
     }
 
+    String userName = authentication.getName().trim();
+
     if (authentication.getCredentials() == null) {
       LOG.info("Authentication failed: no credentials provided: {}", userName);
       throw new InvalidUsernamePasswordCombinationException(userName);
     }
 
+    Users users = getUsers();
+
+    UserEntity userEntity = users.getUserEntity(userName);
+
+    if (userEntity == null) {
+      LOG.info("User not found: {}", userName);
+      throw new InvalidUsernamePasswordCombinationException(userName);
+    }
+
     UserAuthenticationEntity authenticationEntity = 
getAuthenticationEntity(userEntity, UserAuthenticationType.LOCAL);
     if (authenticationEntity != null) {
       String password = authenticationEntity.getAuthenticationKey();
@@ -94,6 +82,18 @@ public class AmbariLocalAuthenticationProvider extends 
AmbariAuthenticationProvi
         // The user was  authenticated, return the authenticated user object
         LOG.debug("Authentication succeeded - a matching username and password 
were found: {}", userName);
 
+        try {
+          validateLogin(userEntity, userName);
+        }
+        catch (AccountDisabledException | TooManyLoginFailuresException e) {
+          if (getConfiguration().showLockedOutUserMessage()) {
+            throw e;
+          } else {
+            // Do not give away information about the existence or status of a 
user
+            throw new InvalidUsernamePasswordCombinationException(userName, 
false, e);
+          }
+        }
+
         User user = new User(userEntity);
         Authentication auth = new AmbariUserAuthentication(password, user, 
users.getUserAuthorities(userEntity));
         auth.setAuthenticated(true);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/InvalidUsernamePasswordCombinationException.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/InvalidUsernamePasswordCombinationException.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/InvalidUsernamePasswordCombinationException.java
index cb1babd..640c4cc 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/InvalidUsernamePasswordCombinationException.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/InvalidUsernamePasswordCombinationException.java
@@ -23,10 +23,18 @@ public class InvalidUsernamePasswordCombinationException 
extends AmbariAuthentic
   public static final String MESSAGE = "Unable to sign in. Invalid 
username/password combination.";
 
   public InvalidUsernamePasswordCombinationException(String username) {
-    super(username, MESSAGE);
+    super(username, MESSAGE, true);
+  }
+
+  public InvalidUsernamePasswordCombinationException(String username, boolean 
incrementFailureCount) {
+    super(username, MESSAGE, incrementFailureCount);
   }
 
   public InvalidUsernamePasswordCombinationException(String username, 
Throwable t) {
-    super(username, MESSAGE, t);
+    super(username, MESSAGE, true, t);
+  }
+
+  public InvalidUsernamePasswordCombinationException(String username, boolean 
incrementFailureCount, Throwable t) {
+    super(username, MESSAGE, incrementFailureCount, t);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/TooManyLoginFailuresException.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/TooManyLoginFailuresException.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/TooManyLoginFailuresException.java
index b172079..1a111d8 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/TooManyLoginFailuresException.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/TooManyLoginFailuresException.java
@@ -22,6 +22,6 @@ package org.apache.ambari.server.security.authentication;
  */
 public class TooManyLoginFailuresException extends 
AmbariAuthenticationException {
   public TooManyLoginFailuresException(String username) {
-    super(username, "Too many authentication failures");
+    super(username, "Too many authentication failures", false);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
index 0760d9b..683312e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/UserNotFoundException.java
@@ -26,18 +26,18 @@ public class UserNotFoundException extends 
AmbariAuthenticationException {
   public static final String MESSAGE = "User does not exist.";
 
   public UserNotFoundException(String userName) {
-    super(userName, MESSAGE);
+    super(userName, MESSAGE, false);
   }
 
   public UserNotFoundException(String userName, Throwable cause) {
-    super(userName, MESSAGE, cause);
+    super(userName, MESSAGE, false, cause);
   }
 
   public UserNotFoundException(String username, String message) {
-    super(username, message);
+    super(username, message, false);
   }
 
   public UserNotFoundException(String username, String message, Throwable 
throwable) {
-    super(username, message, throwable);
+    super(username, message, false, throwable);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java
index dcaf3e8..72796ff 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilter.java
@@ -235,7 +235,7 @@ public class AmbariJwtAuthenticationFilter implements 
AmbariAuthenticationFilter
         if (e instanceof AmbariAuthenticationException) {
           cause = (AmbariAuthenticationException) e;
         } else {
-          cause = new AmbariAuthenticationException(null, e.getMessage(), e);
+          cause = new AmbariAuthenticationException(null, e.getMessage(), 
false, e);
         }
 
         eventHandler.onUnsuccessfulAuthentication(this, httpServletRequest, 
httpServletResponse, cause);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationProvider.java
index 9a5b825..672444e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationProvider.java
@@ -21,9 +21,11 @@ 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.AccountDisabledException;
 import 
org.apache.ambari.server.security.authentication.AmbariAuthenticationException;
 import 
org.apache.ambari.server.security.authentication.AmbariAuthenticationProvider;
 import 
org.apache.ambari.server.security.authentication.AmbariUserAuthentication;
+import 
org.apache.ambari.server.security.authentication.TooManyLoginFailuresException;
 import org.apache.ambari.server.security.authentication.UserNotFoundException;
 import org.apache.ambari.server.security.authorization.User;
 import org.apache.ambari.server.security.authorization.UserAuthenticationType;
@@ -46,11 +48,6 @@ public class AmbariJwtAuthenticationProvider extends 
AmbariAuthenticationProvide
   private static final Logger LOG = 
LoggerFactory.getLogger(AmbariJwtAuthenticationProvider.class);
 
   /**
-   * Helper object to provide logic for working with users.
-   */
-  private Users users;
-
-  /**
    * Constructor.
    *
    * @param users         the users helper
@@ -59,28 +56,28 @@ public class AmbariJwtAuthenticationProvider extends 
AmbariAuthenticationProvide
   @Inject
   public AmbariJwtAuthenticationProvider(Users users, Configuration 
configuration) {
     super(users, configuration);
-    this.users = users;
   }
 
   @Override
   public Authentication authenticate(Authentication authentication) throws 
AuthenticationException {
-    String userName = authentication.getName().trim();
+    if (authentication.getName() == null) {
+      LOG.info("Authentication failed: no username provided");
+      throw new AmbariAuthenticationException(null, "Unexpected error due to 
missing username", false);
+    }
 
-    UserEntity userEntity;
-    try {
-      userEntity = getUserEntity(userName);
+    String userName = authentication.getName().trim();
 
-      if (userEntity == null) {
-        LOG.info("User not found: {}", userName);
-        throw new UserNotFoundException(userName, "Cannot find user from JWT. 
Please, ensure LDAP is configured and users are synced.");
-      }
-    } catch (UserNotFoundException e) {
-      throw new UserNotFoundException(userName, "Cannot find user from JWT. 
Please, ensure LDAP is configured and users are synced.", e);
+    if (authentication.getCredentials() == null) {
+      LOG.info("Authentication failed: no credentials provided: {}", userName);
+      throw new AmbariAuthenticationException(userName, "Unexpected error due 
to missing JWT token", false);
     }
 
-    if (authentication.getCredentials() == null) {
-      LOG.info("Authentication failed: no token provided: {}", userName);
-      throw new AmbariAuthenticationException(userName, "Unexpected error due 
to missing JWT token");
+    Users users = getUsers();
+    UserEntity userEntity = users.getUserEntity(userName);
+
+    if (userEntity == null) {
+      LOG.info("User not found: {}", userName);
+      throw new UserNotFoundException(userName, "Cannot find user from JWT. 
Please, ensure LDAP is configured and users are synced.");
     }
 
     // If the user was found and allowed to log in, make sure that user is 
allowed to authentcate using a JWT token.
@@ -100,7 +97,7 @@ public class AmbariJwtAuthenticationProvider extends 
AmbariAuthenticationProvide
           authOK = true;
         } catch (AmbariException e) {
           LOG.error(String.format("Failed to add the JWT authentication method 
for %s: %s", userName, e.getLocalizedMessage()), e);
-          throw new AmbariAuthenticationException(userName, "Unexpected error 
has occurred", e);
+          throw new AmbariAuthenticationException(userName, "Unexpected error 
has occurred", false, e);
         }
       }
     }
@@ -108,6 +105,19 @@ public class AmbariJwtAuthenticationProvider extends 
AmbariAuthenticationProvide
     if (authOK) {
       // The user was  authenticated, return the authenticated user object
       LOG.debug("Authentication succeeded - a matching user was found: {}", 
userName);
+
+      // Ensure the user account is allowed to log in
+      try {
+        validateLogin(userEntity, userName);
+      } catch (AccountDisabledException | TooManyLoginFailuresException e) {
+        if (getConfiguration().showLockedOutUserMessage()) {
+          throw e;
+        } else {
+          // Do not give away information about the existence or status of a 
user
+          throw new AmbariAuthenticationException(userName, "Unexpected error 
due to missing JWT token", false);
+        }
+      }
+
       User user = new User(userEntity);
       Authentication auth = new 
AmbariUserAuthentication(authentication.getCredentials().toString(), user, 
users.getUserAuthorities(userEntity));
       auth.setAuthenticated(true);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationFilter.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationFilter.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationFilter.java
index 41275a5..0e59ad2 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationFilter.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationFilter.java
@@ -95,7 +95,7 @@ public class AmbariKerberosAuthenticationFilter extends 
SpnegoAuthenticationProc
           if (e instanceof AmbariAuthenticationException) {
             cause = (AmbariAuthenticationException) e;
           } else {
-            cause = new AmbariAuthenticationException(null, 
e.getLocalizedMessage(), e);
+            cause = new AmbariAuthenticationException(null, 
e.getLocalizedMessage(), false, e);
           }
           
eventHandler.onUnsuccessfulAuthentication(AmbariKerberosAuthenticationFilter.this,
 httpServletRequest, httpServletResponse, cause);
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProvider.java
new file mode 100644
index 0000000..824fbdf
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProvider.java
@@ -0,0 +1,302 @@
+/*
+ * 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.authentication.pam;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+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.apache.ambari.server.security.authentication.AccountDisabledException;
+import 
org.apache.ambari.server.security.authentication.AmbariAuthenticationException;
+import 
org.apache.ambari.server.security.authentication.AmbariAuthenticationProvider;
+import 
org.apache.ambari.server.security.authentication.AmbariUserAuthentication;
+import 
org.apache.ambari.server.security.authentication.InvalidUsernamePasswordCombinationException;
+import 
org.apache.ambari.server.security.authentication.TooManyLoginFailuresException;
+import org.apache.ambari.server.security.authorization.GroupType;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.apache.ambari.server.security.authorization.Users;
+import org.apache.commons.lang.StringUtils;
+import org.jvnet.libpam.PAM;
+import org.jvnet.libpam.PAMException;
+import org.jvnet.libpam.UnixUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+import com.google.inject.Inject;
+
+/**
+ * Provides PAM user authentication logic for Ambari Server
+ * <p>
+ * It is expected that PAM is properly configured in the underlying operating 
system for this
+ * authentication provider to work properly.
+ */
+public class AmbariPamAuthenticationProvider extends 
AmbariAuthenticationProvider {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(AmbariPamAuthenticationProvider.class);
+
+  private final PamAuthenticationFactory pamAuthenticationFactory;
+
+  @Inject
+  public AmbariPamAuthenticationProvider(Users users, PamAuthenticationFactory 
pamAuthenticationFactory, Configuration configuration) {
+    super(users, configuration);
+    this.pamAuthenticationFactory = pamAuthenticationFactory;
+  }
+
+  @Override
+  public Authentication authenticate(Authentication authentication) throws 
AuthenticationException {
+    if (isPamEnabled()) {
+      if (authentication.getName() == null) {
+        LOG.info("Authentication failed: no username provided");
+        throw new InvalidUsernamePasswordCombinationException("");
+      }
+
+      String userName = authentication.getName().trim();
+
+      if (authentication.getCredentials() == null) {
+        LOG.info("Authentication failed: no credentials provided: {}", 
userName);
+        throw new InvalidUsernamePasswordCombinationException(userName);
+      }
+
+      Users users = getUsers();
+
+      UserEntity userEntity = users.getUserEntity(userName);
+      String password = String.valueOf(authentication.getCredentials());
+      String ambariUsername;
+      String localUsername;
+
+      // Determine what the Ambari and local username values are.  Most of the 
time these should be
+      // the same, however it is possible for the user names to be different 
in the event a user has
+      // multiple authentication sources.
+      if (userEntity == null) {
+        ambariUsername = userName;
+        localUsername = userName;
+      } else {
+        // If the user exists, the username to be used with PAM may be stored 
with the PAM-specific UserAuthenticationEntity
+        // Else, use the UserEntity#getLocalUsername value
+        // Else, use the UserEntity#getUserName value
+        UserAuthenticationEntity authenticationEntity = 
getAuthenticationEntity(userEntity, UserAuthenticationType.PAM);
+
+        ambariUsername = userEntity.getUserName();
+
+        if (authenticationEntity == null) {
+          localUsername = userEntity.getLocalUsername();
+        } else {
+          localUsername = authenticationEntity.getAuthenticationKey();
+
+          if (StringUtils.isEmpty(localUsername)) {
+            localUsername = userEntity.getLocalUsername();
+          }
+        }
+
+        if (StringUtils.isEmpty(localUsername)) {
+          localUsername = ambariUsername;
+        }
+      }
+
+      // Perform authentication....
+      UnixUser unixUser = performPAMAuthentication(ambariUsername, 
localUsername, password);
+
+      if (unixUser != null) {
+        // Authentication was successful via PAM.  Make sure that the user 
exists and has a PAM
+        // authentication entry.
+        if (userEntity == null) {
+          // TODO: Ensure automatically creating users when authenticating 
with PAM is allowed.
+          try {
+            userEntity = users.createUser(ambariUsername, 
unixUser.getUserName(), ambariUsername, true);
+          } catch (AmbariException e) {
+            LOG.error(String.format("Failed to add the user, %s: %s", 
ambariUsername, e.getLocalizedMessage()), e);
+            throw new AmbariAuthenticationException(ambariUsername, 
"Unexpected error has occurred", false, e);
+          }
+        } else {
+          // Ensure the user is allowed to login....
+          try {
+            validateLogin(userEntity, ambariUsername);
+          } catch (AccountDisabledException | TooManyLoginFailuresException e) 
{
+            if (getConfiguration().showLockedOutUserMessage()) {
+              throw e;
+            } else {
+              // Do not give away information about the existence or status of 
a user
+              throw new InvalidUsernamePasswordCombinationException(userName, 
false, e);
+            }
+          }
+        }
+
+        UserAuthenticationEntity authenticationEntity = 
getAuthenticationEntity(userEntity, UserAuthenticationType.PAM);
+        // TODO: Ensure automatically adding the PAM authentication method for 
users when authenticating is allowed.
+        if (authenticationEntity == null) {
+          try {
+            users.addPamAuthentication(userEntity, unixUser.getUserName());
+          } catch (AmbariException e) {
+            LOG.error(String.format("Failed to add the PAM authentication 
method for %s: %s", ambariUsername, e.getLocalizedMessage()), e);
+            throw new AmbariAuthenticationException(ambariUsername, 
"Unexpected error has occurred", false, e);
+          }
+        }
+
+        if (isAutoGroupCreationAllowed()) {
+          synchronizeGroups(unixUser, userEntity);
+        }
+
+        Authentication authToken = new AmbariUserAuthentication(password, 
users.getUser(userEntity), users.getUserAuthorities(userEntity));
+        authToken.setAuthenticated(true);
+        return authToken;
+      }
+
+
+      // The user was not authenticated, catch-all fail
+      LOG.debug(String.format("Authentication failed: password does not match 
stored value: %s", localUsername));
+      throw new InvalidUsernamePasswordCombinationException(ambariUsername);
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * Perform the OS-level PAM authentication routine.
+   *
+   * @param ambariUsername the Ambari username, used for logging and 
notifications
+   * @param localUsername  the username to use for authenticating
+   * @param password       the password to use for authenticating
+   * @return the resulting user object
+   */
+  private UnixUser performPAMAuthentication(String ambariUsername, String 
localUsername, String password) {
+    PAM pam = pamAuthenticationFactory.createInstance(getConfiguration());
+
+    if (pam == null) {
+      String message = "Failed to authenticate the user using the PAM 
authentication method: unexpected error";
+      LOG.error(message);
+      throw new AmbariAuthenticationException(ambariUsername, message, false);
+    } else {
+      if (LOG.isDebugEnabled() && !ambariUsername.equals(localUsername)) {
+        LOG.debug("Authenticating Ambari user {} using the local username {}", 
ambariUsername, localUsername);
+      }
+
+      try {
+        // authenticate using PAM
+        return pam.authenticate(localUsername, password);
+      } catch (PAMException e) {
+        // The user was not authenticated, fail
+        LOG.debug(String.format("Authentication failed: password does not 
match stored value: %s", localUsername), e);
+        throw new InvalidUsernamePasswordCombinationException(ambariUsername, 
true, e);
+      } finally {
+        pam.dispose();
+      }
+    }
+  }
+
+  @Override
+  public boolean supports(Class<?> authentication) {
+    return 
UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
+  }
+
+  /**
+   * Check if PAM authentication is enabled in server properties
+   *
+   * @return true if enabled
+   */
+  private boolean isPamEnabled() {
+    return getConfiguration().getClientSecurityType() == 
ClientSecurityType.PAM;
+  }
+
+  /**
+   * Check if PAM authentication is enabled in server properties
+   *
+   * @return true if enabled
+   */
+  private boolean isAutoGroupCreationAllowed() {
+    return getConfiguration().getAutoGroupCreation().equals("true");
+  }
+
+
+  /**
+   * Synchornizes the OS-level groups assigned to the OS-level user with the 
groups assigned to the
+   * Ambari user in Ambari
+   *
+   * @param unixUser   the user
+   * @param userEntity the ambari user
+   */
+  private void synchronizeGroups(UnixUser unixUser, UserEntity userEntity) {
+    LOG.debug("Synchronizing groups for PAM user: {}", unixUser.getUserName());
+
+    Users users = getUsers();
+
+    try {
+      //Get all the groups that user belongs to
+      //Change all group names to lower case.
+      Set<String> unixUserGroups = convertToLowercase(unixUser.getGroups());
+
+      // Add the user to the specified groups, create the group if needed...
+      for (String group : unixUserGroups) {
+        GroupEntity groupEntity = users.getGroupEntity(group, GroupType.PAM);
+        if (groupEntity == null) {
+          LOG.info("Synchronizing groups for {}, adding new PAM group: {}", 
userEntity.getUserName(), group);
+          groupEntity = users.createGroup(group, GroupType.PAM);
+        }
+
+        if (!users.isUserInGroup(userEntity, groupEntity)) {
+          LOG.info("Synchronizing groups for {}, adding user to PAM group: 
{}", userEntity.getUserName(), group);
+          users.addMemberToGroup(groupEntity, userEntity);
+        }
+      }
+
+      // Remove the user from any other PAM-specific group that the user may 
have been previously
+      // added to. If the user belongs to non-PAM-specific groups, do not 
alter those assignments.
+      Set<MemberEntity> memberEntities = userEntity.getMemberEntities();
+      if (memberEntities != null) {
+        Collection<GroupEntity> groupsToRemove = new ArrayList<>();
+        // Collect the groups to remove...
+        for (MemberEntity memberEntity : memberEntities) {
+          GroupEntity groupEntity = memberEntity.getGroup();
+          if ((groupEntity.getGroupType() == GroupType.PAM) && 
!unixUserGroups.contains(groupEntity.getGroupName())) {
+            groupsToRemove.add(groupEntity);
+          }
+        }
+
+        // Perform the removals...
+        for(GroupEntity groupEntity :groupsToRemove) {
+          LOG.info("Synchronizing groups for {}, removing user from PAM group: 
{}", userEntity.getUserName(), groupEntity.getGroupName());
+          users.removeMemberFromGroup(groupEntity, userEntity);
+        }
+      }
+    } catch (AmbariException e) {
+      e.printStackTrace();
+    }
+  }
+
+  private Set<String> convertToLowercase(Set<String> groups) {
+    Set<String> lowercaseGroups = new HashSet<>();
+
+    if (groups != null) {
+      for (String group : groups) {
+        lowercaseGroups.add(group.toLowerCase());
+      }
+    }
+
+    return lowercaseGroups;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/PamAuthenticationFactory.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/PamAuthenticationFactory.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/PamAuthenticationFactory.java
index 6f423c1..791f055 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/PamAuthenticationFactory.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/pam/PamAuthenticationFactory.java
@@ -20,16 +20,33 @@ package 
org.apache.ambari.server.security.authentication.pam;
 
 import javax.inject.Singleton;
 
+import org.apache.ambari.server.configuration.Configuration;
 import org.jvnet.libpam.PAM;
 import org.jvnet.libpam.PAMException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import 
org.springframework.security.authentication.AuthenticationServiceException;
 
 /**
  * PamAuthenticationFactory returns Pam library instances.
  */
 @Singleton
 public class PamAuthenticationFactory {
+  private static final Logger LOG = 
LoggerFactory.getLogger(PamAuthenticationFactory.class);
 
-  public PAM createInstance(String pamConfig) throws PAMException {
-    return new PAM(pamConfig);
+  public PAM createInstance(Configuration configuration) {
+    String pamConfig = (configuration == null) ? null : 
configuration.getPamConfigurationFile();
+    return createInstance(pamConfig);
+  }
+
+  public PAM createInstance(String pamConfig) {
+    try {
+      //Set PAM configuration file (found under /etc/pam.d)
+      return new PAM(pamConfig);
+    } catch (PAMException e) {
+      String message = String.format("Unable to Initialize PAM: %s", 
e.getMessage());
+      LOG.error(message, e);
+      throw new AuthenticationServiceException(message, e);
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/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
deleted file mode 100644
index a88bcab..0000000
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProvider.java
+++ /dev/null
@@ -1,237 +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;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.orm.dao.GroupDAO;
-import org.apache.ambari.server.orm.dao.UserDAO;
-import org.apache.ambari.server.orm.entities.GroupEntity;
-import org.apache.ambari.server.orm.entities.MemberEntity;
-import org.apache.ambari.server.orm.entities.UserEntity;
-import org.apache.ambari.server.security.ClientSecurityType;
-import 
org.apache.ambari.server.security.authentication.AmbariUserAuthentication;
-import 
org.apache.ambari.server.security.authentication.pam.PamAuthenticationFactory;
-import org.jvnet.libpam.PAM;
-import org.jvnet.libpam.PAMException;
-import org.jvnet.libpam.UnixUser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.authentication.AuthenticationProvider;
-import 
org.springframework.security.authentication.AuthenticationServiceException;
-import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-
-import com.google.inject.Inject;
-
-/**
- * Provides PAM user authentication & authorization logic for Ambari Server
- */
-
-public class AmbariPamAuthenticationProvider implements AuthenticationProvider 
{
-
-  @Inject
-  private Users users;
-  @Inject
-  private UserDAO userDAO;
-  @Inject
-  private GroupDAO groupDAO;
-  @Inject
-  private PamAuthenticationFactory pamAuthenticationFactory;
-
-  private static final Logger LOG = 
LoggerFactory.getLogger(AmbariPamAuthenticationProvider.class);
-
-  private final Configuration configuration;
-
-  @Inject
-  public AmbariPamAuthenticationProvider(Configuration configuration) {
-    this.configuration = configuration;
-  }
-
-  // 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()) {
-      //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;
-    }
-  }
-
-  @Override
-  public boolean supports(Class<?> authentication) {
-    return 
UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
-  }
-
-  Authentication authenticateViaPam(PAM pam, Authentication authentication) {
-    String userName = String.valueOf(authentication.getPrincipal());
-    String password = String.valueOf(authentication.getCredentials());
-
-    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);
-    }
-
-    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;
-      }
-    }
-
-    return null;
-  }
-
-  /**
-   * Check if PAM authentication is enabled in server properties
-   *
-   * @return true if enabled
-   */
-  private boolean isPamEnabled() {
-    return configuration.getClientSecurityType() == ClientSecurityType.PAM;
-  }
-
-  /**
-   * Check if PAM authentication is enabled in server properties
-   *
-   * @return true if enabled
-   */
-  private boolean isAutoGroupCreationAllowed() {
-    return configuration.getAutoGroupCreation().equals("true");
-  }
-
-
-  /**
-   * Performs PAM authorization by creating user & group(s)
-   *
-   * @param unixUser the user
-   */
-  private UserEntity ambariPamAuthorization(UnixUser unixUser) {
-    String userName = unixUser.getUserName();
-    UserEntity userEntity = null;
-
-    try {
-      userEntity = userDAO.findUserByName(userName);
-
-      // TODO: Ensure automatically creating users when authenticating with 
PAM is allowed.
-      if (userEntity == null) {
-        userEntity = users.createUser(userName, userName, userName);
-        users.addPamAuthentication(userEntity, 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<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 groupEntity group entity
-   * @return true if user presents in group
-   */
-  private boolean isUserInGroup(UserEntity userEntity, GroupEntity 
groupEntity) {
-    for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
-      if (memberEntity.getGroup().equals(groupEntity)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Extracts all groups a user belongs to
-   *
-   * @param userEntity the user
-   * @return Collection of group names
-   */
-  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/d6b271e6/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/PamAuthenticationException.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/PamAuthenticationException.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/PamAuthenticationException.java
deleted file mode 100644
index 1588106..0000000
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/PamAuthenticationException.java
+++ /dev/null
@@ -1,36 +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;
-
-import org.springframework.security.core.AuthenticationException;
-
-public class PamAuthenticationException extends AuthenticationException{
-
-   public PamAuthenticationException() {
-        this("The user authentication failed");
-     }
-
-  public PamAuthenticationException(String msg, Throwable t) {
-    super(msg, t);
-  }
-
-  public PamAuthenticationException(String msg) {
-    super(msg);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/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 a5faea1..a268467 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
@@ -337,12 +337,23 @@ public class Users {
    * @param groupType group type
    * @return group
    */
-  public Group getGroupByNameAndType(String groupName, GroupType groupType) {
-    final GroupEntity groupEntity = groupDAO.findGroupByNameAndType(groupName, 
groupType);
+  public Group getGroup(String groupName, GroupType groupType) {
+    final GroupEntity groupEntity = getGroupEntity(groupName, groupType);
     return (null == groupEntity) ? null : new Group(groupEntity);
   }
 
   /**
+   * Gets a {@link GroupEntity} by name and type.
+   *
+   * @param groupName group name
+   * @param groupType group type
+   * @return group
+   */
+  public GroupEntity getGroupEntity(String groupName, GroupType groupType) {
+    return groupDAO.findGroupByNameAndType(groupName, groupType);
+  }
+
+  /**
    * Gets group members.
    *
    * @param groupName group name
@@ -640,7 +651,7 @@ public class Users {
    * @param groupEntity group entity
    * @return true if user presents in group
    */
-  private boolean isUserInGroup(UserEntity userEntity, GroupEntity 
groupEntity) {
+  public boolean isUserInGroup(UserEntity userEntity, GroupEntity groupEntity) 
{
     for (MemberEntity memberEntity : userEntity.getMemberEntities()) {
       if (memberEntity.getGroup().equals(groupEntity)) {
         return true;

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java
new file mode 100644
index 0000000..6908c55
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/pam/AmbariPamAuthenticationProviderTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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.authentication.pam;
+
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+
+import java.util.Collections;
+
+import javax.persistence.EntityManager;
+
+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.DBAccessor;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
+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.apache.ambari.server.security.authentication.AccountDisabledException;
+import 
org.apache.ambari.server.security.authentication.AmbariUserAuthentication;
+import 
org.apache.ambari.server.security.authentication.TooManyLoginFailuresException;
+import org.apache.ambari.server.security.authorization.User;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.apache.ambari.server.security.authorization.UserName;
+import org.apache.ambari.server.security.authorization.Users;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.easymock.EasyMockSupport;
+import org.junit.Before;
+import org.junit.Test;
+import org.jvnet.libpam.PAM;
+import org.jvnet.libpam.PAMException;
+import org.jvnet.libpam.UnixUser;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.crypto.password.StandardPasswordEncoder;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import junit.framework.Assert;
+
+public class AmbariPamAuthenticationProviderTest extends EasyMockSupport {
+
+  private static final String TEST_USER_NAME = "userName";
+  private static final String TEST_USER_PASS = "userPass";
+  private static final String TEST_USER_INCORRECT_PASS = "userIncorrectPass";
+
+  private Injector injector;
+
+  @Before
+  public void setup() {
+    injector = Guice.createInjector(new AbstractModule() {
+
+      @Override
+      protected void configure() {
+        
bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+        bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+        
bind(HookContextFactory.class).toInstance(createNiceMock(HookContextFactory.class));
+        bind(HookService.class).toInstance(createNiceMock(HookService.class));
+        bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
+        
bind(PamAuthenticationFactory.class).toInstance(createMock(PamAuthenticationFactory.class));
+        bind(PasswordEncoder.class).toInstance(new StandardPasswordEncoder());
+        bind(Users.class).toInstance(createMock(Users.class));
+      }
+    });
+
+    Configuration configuration = injector.getInstance(Configuration.class);
+    configuration.setClientSecurityType(ClientSecurityType.PAM);
+    configuration.setProperty(Configuration.PAM_CONFIGURATION_FILE, 
"ambari-pam");
+    configuration.setProperty(Configuration.SHOW_LOCKED_OUT_USER_MESSAGE, 
"true");
+  }
+
+  @Test(expected = AuthenticationException.class)
+  public void testBadCredential() throws Exception {
+
+    PAM pam = createMock(PAM.class);
+    expect(pam.authenticate(eq(TEST_USER_NAME), eq(TEST_USER_INCORRECT_PASS)))
+        .andThrow(new PAMException())
+        .once();
+    pam.dispose();
+    expectLastCall().once();
+
+    PamAuthenticationFactory pamAuthenticationFactory = 
injector.getInstance(PamAuthenticationFactory.class);
+    
expect(pamAuthenticationFactory.createInstance(injector.getInstance(Configuration.class))).andReturn(pam).once();
+
+    Users users = injector.getInstance(Users.class);
+    expect(users.getUserEntity(TEST_USER_NAME)).andReturn(null).once();
+
+    replayAll();
+
+    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_INCORRECT_PASS);
+
+    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
+    authenticationProvider.authenticate(authentication);
+
+    verifyAll();
+  }
+
+  @Test
+  public void testAuthenticateExistingUser() throws Exception {
+
+    UnixUser unixUser = createNiceMock(UnixUser.class);
+
+    PAM pam = createMock(PAM.class);
+    expect(pam.authenticate(eq(TEST_USER_NAME), 
eq(TEST_USER_PASS))).andReturn(unixUser).once();
+    pam.dispose();
+    expectLastCall().once();
+
+    PamAuthenticationFactory pamAuthenticationFactory = 
injector.getInstance(PamAuthenticationFactory.class);
+    
expect(pamAuthenticationFactory.createInstance(injector.getInstance(Configuration.class))).andReturn(pam).once();
+
+    UserEntity userEntity = combineUserEntity(true, true, 0);
+
+    Users users = injector.getInstance(Users.class);
+    expect(users.getUserEntity(TEST_USER_NAME)).andReturn(userEntity).once();
+    expect(users.getUser(userEntity)).andReturn(new User(userEntity)).once();
+    expect(users.getUserAuthorities(userEntity)).andReturn(null).once();
+
+    replayAll();
+
+    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
+    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
+
+    Authentication result = 
authenticationProvider.authenticate(authentication);
+    Assert.assertNotNull(result);
+    Assert.assertEquals(true, result.isAuthenticated());
+    Assert.assertTrue(result instanceof AmbariUserAuthentication);
+
+    verifyAll();
+  }
+
+  @Test(expected = AccountDisabledException.class)
+  public void testAuthenticateDisabledUser() throws Exception {
+
+    UnixUser unixUser = createNiceMock(UnixUser.class);
+
+    PAM pam = createMock(PAM.class);
+    expect(pam.authenticate(eq(TEST_USER_NAME), 
eq(TEST_USER_PASS))).andReturn(unixUser).once();
+    pam.dispose();
+    expectLastCall().once();
+
+    PamAuthenticationFactory pamAuthenticationFactory = 
injector.getInstance(PamAuthenticationFactory.class);
+    
expect(pamAuthenticationFactory.createInstance(injector.getInstance(Configuration.class))).andReturn(pam).once();
+
+    UserEntity userEntity = combineUserEntity(true, false, 0);
+
+    Users users = injector.getInstance(Users.class);
+    expect(users.getUserEntity(TEST_USER_NAME)).andReturn(userEntity).once();
+
+    replayAll();
+
+    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
+    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
+    authenticationProvider.authenticate(authentication);
+
+    verifyAll();
+  }
+
+  @Test(expected = TooManyLoginFailuresException.class)
+  public void testAuthenticateLockedUser() throws Exception {
+
+    UnixUser unixUser = createNiceMock(UnixUser.class);
+
+    PAM pam = createMock(PAM.class);
+    expect(pam.authenticate(eq(TEST_USER_NAME), 
eq(TEST_USER_PASS))).andReturn(unixUser).once();
+    pam.dispose();
+    expectLastCall().once();
+
+    PamAuthenticationFactory pamAuthenticationFactory = 
injector.getInstance(PamAuthenticationFactory.class);
+    
expect(pamAuthenticationFactory.createInstance(injector.getInstance(Configuration.class))).andReturn(pam).once();
+
+    UserEntity userEntity = combineUserEntity(true, true, 11);
+
+    Users users = injector.getInstance(Users.class);
+    expect(users.getUserEntity(TEST_USER_NAME)).andReturn(userEntity).once();
+
+    replayAll();
+
+    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
+    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
+    authenticationProvider.authenticate(authentication);
+
+    verifyAll();
+  }
+
+  @Test
+  public void testAuthenticateNewUser() throws Exception {
+
+    UnixUser unixUser = createNiceMock(UnixUser.class);
+    
expect(unixUser.getUserName()).andReturn(TEST_USER_NAME.toLowerCase()).atLeastOnce();
+
+    PAM pam = createMock(PAM.class);
+    expect(pam.authenticate(eq(TEST_USER_NAME), 
eq(TEST_USER_PASS))).andReturn(unixUser).once();
+    pam.dispose();
+    expectLastCall().once();
+
+    PamAuthenticationFactory pamAuthenticationFactory = 
injector.getInstance(PamAuthenticationFactory.class);
+    
expect(pamAuthenticationFactory.createInstance(injector.getInstance(Configuration.class))).andReturn(pam).once();
+
+    UserEntity userEntity = combineUserEntity(false, true, 0);
+
+    Users users = injector.getInstance(Users.class);
+    expect(users.getUserEntity(TEST_USER_NAME)).andReturn(null).once();
+    expect(users.createUser(TEST_USER_NAME, TEST_USER_NAME.toLowerCase(), 
TEST_USER_NAME, true)).andReturn(userEntity).once();
+    users.addPamAuthentication(userEntity, TEST_USER_NAME.toLowerCase());
+    expectLastCall().once();
+    expect(users.getUser(userEntity)).andReturn(new User(userEntity)).once();
+    expect(users.getUserAuthorities(userEntity)).andReturn(null).once();
+
+    replayAll();
+
+    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
+    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
+
+    Authentication result = 
authenticationProvider.authenticate(authentication);
+    Assert.assertNotNull(result);
+    Assert.assertEquals(true, result.isAuthenticated());
+    Assert.assertTrue(result instanceof AmbariUserAuthentication);
+
+    verifyAll();
+  }
+
+  @Test
+  public void testDisabled() throws Exception {
+
+    Configuration configuration = injector.getInstance(Configuration.class);
+    configuration.setClientSecurityType(ClientSecurityType.LOCAL);
+
+    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
+
+    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
+    Authentication auth = authenticationProvider.authenticate(authentication);
+    Assert.assertTrue(auth == null);
+  }
+
+  private UserEntity combineUserEntity(boolean addAuthentication, Boolean 
active, Integer consecutiveFailures) {
+    PrincipalEntity principalEntity = new PrincipalEntity();
+
+    UserEntity userEntity = new UserEntity();
+    userEntity.setUserId(1);
+    userEntity.setUserName(UserName.fromString(TEST_USER_NAME).toString());
+    userEntity.setLocalUsername(TEST_USER_NAME);
+    userEntity.setPrincipal(principalEntity);
+    userEntity.setActive(active);
+    userEntity.setConsecutiveFailures(consecutiveFailures);
+
+    if(addAuthentication) {
+      UserAuthenticationEntity userAuthenticationEntity = new 
UserAuthenticationEntity();
+      
userAuthenticationEntity.setAuthenticationType(UserAuthenticationType.PAM);
+      userAuthenticationEntity.setAuthenticationKey(TEST_USER_NAME);
+
+      
userEntity.setAuthenticationEntities(Collections.singletonList(userAuthenticationEntity));
+    }
+    return userEntity;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6b271e6/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProviderTest.java
deleted file mode 100644
index 38f9a9e..0000000
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariPamAuthenticationProviderTest.java
+++ /dev/null
@@ -1,177 +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;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-
-import java.util.Collections;
-
-import javax.persistence.EntityManager;
-
-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.DBAccessor;
-import org.apache.ambari.server.orm.dao.MemberDAO;
-import org.apache.ambari.server.orm.dao.PrivilegeDAO;
-import org.apache.ambari.server.orm.dao.UserDAO;
-import org.apache.ambari.server.orm.entities.PrincipalEntity;
-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.apache.ambari.server.security.authentication.AmbariUserAuthentication;
-import 
org.apache.ambari.server.security.authentication.pam.PamAuthenticationFactory;
-import org.apache.ambari.server.state.stack.OsFamily;
-import org.easymock.EasyMockSupport;
-import org.junit.Before;
-import org.junit.Test;
-import org.jvnet.libpam.PAM;
-import org.jvnet.libpam.PAMException;
-import org.jvnet.libpam.UnixUser;
-import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.crypto.password.StandardPasswordEncoder;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-
-import junit.framework.Assert;
-
-public class AmbariPamAuthenticationProviderTest extends EasyMockSupport {
-
-  private static final String TEST_USER_NAME = "userName";
-  private static final String TEST_USER_PASS = "userPass";
-  private static final String TEST_USER_INCORRECT_PASS = "userIncorrectPass";
-
-  private Injector injector;
-
-  @Before
-  public void setup() {
-    injector = Guice.createInjector(new AbstractModule() {
-
-      @Override
-      protected void configure() {
-        
bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
-        bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
-        
bind(HookContextFactory.class).toInstance(createNiceMock(HookContextFactory.class));
-        bind(HookService.class).toInstance(createNiceMock(HookService.class));
-        bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
-        bind(UserDAO.class).toInstance(createNiceMock(UserDAO.class));
-        bind(MemberDAO.class).toInstance(createNiceMock(MemberDAO.class));
-        
bind(PrivilegeDAO.class).toInstance(createNiceMock(PrivilegeDAO.class));
-        
bind(PamAuthenticationFactory.class).toInstance(createMock(PamAuthenticationFactory.class));
-        bind(PasswordEncoder.class).toInstance(new StandardPasswordEncoder());
-      }
-    });
-
-    Configuration configuration = injector.getInstance(Configuration.class);
-    configuration.setClientSecurityType(ClientSecurityType.PAM);
-    configuration.setProperty(Configuration.PAM_CONFIGURATION_FILE, 
"ambari-pam");
-  }
-
-  @Test(expected = AuthenticationException.class)
-  public void testBadCredential() throws Exception {
-
-    PAM pam = createMock(PAM.class);
-    expect(pam.authenticate(eq(TEST_USER_NAME), eq(TEST_USER_INCORRECT_PASS)))
-        .andThrow(new PAMException())
-        .once();
-    pam.dispose();
-    expectLastCall().once();
-
-    PamAuthenticationFactory pamAuthenticationFactory = 
injector.getInstance(PamAuthenticationFactory.class);
-    
expect(pamAuthenticationFactory.createInstance(anyObject(String.class))).andReturn(pam).once();
-
-    replayAll();
-
-    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_INCORRECT_PASS);
-
-    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
-    authenticationProvider.authenticate(authentication);
-
-    verifyAll();
-  }
-
-  @Test
-  public void testAuthenticate() throws Exception {
-
-    UnixUser unixUser = createNiceMock(UnixUser.class);
-    expect(unixUser.getUserName()).andReturn(TEST_USER_NAME).atLeastOnce();
-
-    PAM pam = createMock(PAM.class);
-    expect(pam.authenticate(eq(TEST_USER_NAME), 
eq(TEST_USER_PASS))).andReturn(unixUser).once();
-
-    UserEntity userEntity = combineUserEntity();
-
-    UserDAO userDAO = injector.getInstance(UserDAO.class);
-    
expect(userDAO.findUserByName(TEST_USER_NAME)).andReturn(userEntity).once();
-
-    MemberDAO memberDAO = injector.getInstance(MemberDAO.class);
-    
expect(memberDAO.findAllMembersByUser(userEntity)).andReturn(Collections.emptyList()).once();
-
-    PrivilegeDAO privilegeDAO = injector.getInstance(PrivilegeDAO.class);
-    
expect(privilegeDAO.findAllByPrincipal(anyObject())).andReturn(Collections.emptyList()).once();
-
-    replayAll();
-
-    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
-    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
-
-    Authentication result = authenticationProvider.authenticateViaPam(pam, 
authentication);
-    Assert.assertNotNull(result);
-    Assert.assertEquals(true, result.isAuthenticated());
-    Assert.assertTrue(result instanceof AmbariUserAuthentication);
-
-    verifyAll();
-  }
-
-  @Test
-  public void testDisabled() throws Exception {
-
-    Configuration configuration = injector.getInstance(Configuration.class);
-    configuration.setClientSecurityType(ClientSecurityType.LOCAL);
-
-    Authentication authentication = new 
UsernamePasswordAuthenticationToken(TEST_USER_NAME, TEST_USER_PASS);
-
-    AmbariPamAuthenticationProvider authenticationProvider = 
injector.getInstance(AmbariPamAuthenticationProvider.class);
-    Authentication auth = authenticationProvider.authenticate(authentication);
-    Assert.assertTrue(auth == null);
-  }
-
-  private UserEntity combineUserEntity() {
-    PrincipalEntity principalEntity = new PrincipalEntity();
-
-    UserAuthenticationEntity userAuthenticationEntity = new 
UserAuthenticationEntity();
-    userAuthenticationEntity.setAuthenticationType(UserAuthenticationType.PAM);
-    userAuthenticationEntity.setAuthenticationKey(TEST_USER_NAME);
-
-    UserEntity userEntity = new UserEntity();
-    userEntity.setUserId(1);
-    userEntity.setUserName(UserName.fromString(TEST_USER_NAME).toString());
-    userEntity.setPrincipal(principalEntity);
-    
userEntity.setAuthenticationEntities(Collections.singletonList(userAuthenticationEntity));
-    return userEntity;
-  }
-
-}

Reply via email to