This is an automated email from the ASF dual-hosted git repository.
dmitriusan pushed a commit to branch branch-2.6
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/branch-2.6 by this push:
new 12275a4 AMBARI-25268. implement configurable password policy for
Ambari users (dlysnichenko) (#2956)
12275a4 is described below
commit 12275a46d69f559350a757de7f0825e8c78a0ea8
Author: Lisnichenko Dmitro <[email protected]>
AuthorDate: Tue Apr 30 20:44:29 2019 +0300
AMBARI-25268. implement configurable password policy for Ambari users
(dlysnichenko) (#2956)
---
.../ambari/server/configuration/Configuration.java | 15 ++++++++++
.../server/security/authorization/Users.java | 21 ++++++++++++++
.../server/security/authorization/TestUsers.java | 32 ++++++++++++++++++++++
3 files changed, 68 insertions(+)
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 352b9ae..f553905 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
@@ -515,6 +515,14 @@ public class Configuration {
"agent.ssl", "true");
/**
+ * Configurable password policy for Ambari users
+ */
+ @Markdown(
+ description = "Determines Ambari user password policy. Passwords should
match the regex")
+ public static final ConfigurationProperty<String> PASSWORD_POLICY_REGEXP =
new ConfigurationProperty<>(
+ "security.password.policy.regexp", ".*");
+
+ /**
* Determines whether the Ambari Agent host names should be validated against
* a regular expression to ensure that they are well-formed.
*/
@@ -4133,6 +4141,13 @@ public class Configuration {
return getProperty(MYSQL_JAR_NAME);
}
+ /**
+ * @return Configurable password policy for Ambari users
+ */
+ public String getPasswordPolicyRegexp() {
+ return getProperty(PASSWORD_POLICY_REGEXP);
+ }
+
public JPATableGenerationStrategy getJPATableGenerationStrategy() {
return JPATableGenerationStrategy.fromString(
System.getProperty(SERVER_JDBC_GENERATE_TABLES.getKey()));
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 0b869a5..5013987 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
@@ -26,6 +26,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.persistence.EntityManager;
@@ -187,6 +188,7 @@ public class Users {
if (currentUserName == null) {
throw new AmbariException("Authentication required. Please sign in.");
}
+ validatePassword(newPassword);
UserEntity currentUserEntity =
userDAO.findLocalUserByName(currentUserName);
@@ -318,6 +320,9 @@ public class Users {
throw new AmbariException("User " + existingUser.getUserName() + "
already exists with type "
+ existingUser.getUserType());
}
+ if (!StringUtils.isEmpty(password)) {
+ validatePassword(password);
+ }
PrincipalTypeEntity principalTypeEntity =
principalTypeDAO.findById(PrincipalTypeEntity.USER_PRINCIPAL_TYPE);
if (principalTypeEntity == null) {
@@ -1041,4 +1046,20 @@ public class Users {
return implicitPrivileges;
}
+
+ /**
+ * Validates that password meets configured requirements according to
ambari.properties.
+ * @param password the password
+ * @throws IllegalArgumentException if password does not meet the password
policy requirements
+ */
+ public void validatePassword(String password) {
+ if (StringUtils.isEmpty(password)) {
+ throw new IllegalArgumentException("The password does not meet the
password policy requirements");
+ }
+ String regexp = configuration.getPasswordPolicyRegexp();
+ if (!StringUtils.isEmpty(regexp) && (!Pattern.matches(regexp,password))) {
+ final String msg = "The password does not meet the Ambari user password
policy regexp:" + regexp;
+ throw new IllegalArgumentException(msg);
+ }
+ }
}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
index 364664d..fb60f80 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
@@ -23,12 +23,14 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.sql.SQLException;
import java.util.List;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.H2DatabaseCleaner;
+import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
import org.apache.ambari.server.orm.dao.GroupDAO;
@@ -79,6 +81,8 @@ public class TestUsers {
protected PrincipalDAO principalDAO;
@Inject
protected PasswordEncoder passwordEncoder;
+ @Inject
+ protected Configuration configuration;
@Before
public void setup() throws AmbariException {
@@ -156,6 +160,34 @@ public class TestUsers {
}
@Test
+ public void testValidatePassword() throws Exception {
+ try {
+ users.validatePassword(null);
+ fail("Null password should not be allowed");
+ } catch (IllegalArgumentException e) {
+ assertEquals("The password does not meet the password policy
requirements", e.getLocalizedMessage());
+ }
+
+ try {
+ users.validatePassword("");
+ fail("Empty password should not be allowed");
+ } catch (IllegalArgumentException e) {
+ assertEquals("The password does not meet the password policy
requirements", e.getLocalizedMessage());
+ }
+
+ //Minimum eight characters, at least one letter and one number:
+ configuration.setProperty(Configuration.PASSWORD_POLICY_REGEXP,
"^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$");
+ try {
+ users.validatePassword("abc123");
+ fail("Should not pass validation");
+ } catch (IllegalArgumentException e) {
+ assertEquals("The password does not meet the Ambari user password policy
regexp:^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$", e.getLocalizedMessage());
+ }
+
+ users.validatePassword("abcd1234");
+ }
+
+ @Test
public void testRevokeAdminPrivilege() throws Exception {
users.createUser("old_admin", "old_admin", UserType.LOCAL, true, true);