AMBARI-10018. Kerberos: Password generator needs to generate passwords based on 
rules to satisfy password policy (rlevas)


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

Branch: refs/heads/trunk
Commit: 6691a1742fe9927d68008d8f54d7a38bff97f524
Parents: c775434
Author: Robert Levas <[email protected]>
Authored: Thu May 7 14:44:50 2015 -0400
Committer: Robert Levas <[email protected]>
Committed: Thu May 7 14:44:50 2015 -0400

----------------------------------------------------------------------
 .../server/security/SecurePasswordHelper.java   | 190 +++++++++++++++++++
 .../kerberos/CleanupServerAction.java           |  10 +-
 .../kerberos/CreateKeytabFilesServerAction.java |   8 +-
 .../kerberos/CreatePrincipalsServerAction.java  |  64 ++++++-
 .../kerberos/DestroyPrincipalsServerAction.java |   8 +-
 .../kerberos/FinalizeKerberosServerAction.java  |   5 +-
 .../kerberos/KerberosOperationHandler.java      |  54 +-----
 .../kerberos/KerberosServerAction.java          |  25 ++-
 .../1.10.3-10/configuration/kerberos-env.xml    |  48 +++++
 .../security/SecurePasswordHelperTest.java      | 153 +++++++++++++++
 .../ADKerberosOperationHandlerTest.java         |  14 +-
 .../kerberos/KerberosOperationHandlerTest.java  |  54 +-----
 .../kerberos/KerberosServerActionTest.java      |   1 +
 ambari-web/app/data/HDP2/site_properties.js     | 112 ++++++++++-
 14 files changed, 607 insertions(+), 139 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/security/SecurePasswordHelper.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/SecurePasswordHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/SecurePasswordHelper.java
new file mode 100644
index 0000000..e995eec
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/SecurePasswordHelper.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+import com.google.inject.Singleton;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+
+@Singleton
+public class SecurePasswordHelper {
+
+  /**
+   * The default number of characters to generate for a secure password
+   */
+  public final static int DEFAULT_SECURE_PASSWORD_LENGTH = 18;
+  /**
+   * The default minimum number of lowercase letters to include when 
generating a secure password
+   */
+  public final static int DEFAULT_SECURE_PASSWORD_MIN_LOWERCASE_LETTERS = 1;
+  /**
+   * The default minimum number of uppercase letters to include when 
generating a secure password
+   */
+  public final static int DEFAULT_SECURE_PASSWORD_MIN_UPPERCASE_LETTERS = 1;
+  /**
+   * The default minimum number of digits to include when generating a secure 
password
+   */
+  public final static int DEFAULT_SECURE_PASSWORD_MIN_DIGITS = 1;
+  /**
+   * The default minimum number of punctuation characters to include when 
generating a secure password
+   */
+  public final static int DEFAULT_SECURE_PASSWORD_MIN_PUNCTUATION = 1;
+  /**
+   * The default minimum number of whitespace characters to include when 
generating a secure password
+   */
+  public final static int DEFAULT_SECURE_PASSWORD_MIN_WHITESPACE = 1;
+
+  /**
+   * The set of available lowercase letters to use when generating a secure 
password
+   */
+  protected final static char[] 
SECURE_PASSWORD_CHARACTER_CLASS_LOWERCASE_LETTERS = 
"abcdefghijklmnopqrstuvwxyz".toCharArray();
+  /**
+   * The set of available uppercase letters to use when generating a secure 
password
+   */
+  protected final static char[] 
SECURE_PASSWORD_CHARACTER_CLASS_UPPERCASE_LETTERS = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+  /**
+   * The set of available digits to use when generating a secure password
+   */
+  protected final static char[] SECURE_PASSWORD_CHARACTER_CLASS_DIGITS = 
"0123456789".toCharArray();
+  /**
+   * The set of available punctuation characters to use when generating a 
secure password
+   */
+  protected final static char[] SECURE_PASSWORD_CHARACTER_CLASS_PUNCTUATION = 
"?.!$%^*()-_+=~".toCharArray();
+  /**
+   * The set of available whitespace characters to use when generating a 
secure password
+   */
+  protected final static char[] SECURE_PASSWORD_CHARACTER_CLASS_WHITESPACE = " 
".toCharArray();
+  /**
+   * The collection of available character classes
+   */
+  private final static char[][] SECURE_PASSWORD_CHARACTER_CLASSES = {
+      SECURE_PASSWORD_CHARACTER_CLASS_LOWERCASE_LETTERS,
+      SECURE_PASSWORD_CHARACTER_CLASS_UPPERCASE_LETTERS,
+      SECURE_PASSWORD_CHARACTER_CLASS_DIGITS,
+      SECURE_PASSWORD_CHARACTER_CLASS_PUNCTUATION,
+      SECURE_PASSWORD_CHARACTER_CLASS_WHITESPACE
+  };
+  
+  private final SecureRandom secureRandom = new SecureRandom();
+
+  /**
+   * Create a secure (random) password using a secure random number generator 
and a set of (reasonable)
+   * characters.
+   * <p/>
+   * The default rules are used to generate the password. See {@link 
#createSecurePassword(Integer, Integer, Integer, Integer, Integer, Integer)}
+   *
+   * @return a String containing the new password
+   * @see #createSecurePassword(Integer, Integer, Integer, Integer, Integer, 
Integer)
+   */
+  public String createSecurePassword() {
+    return createSecurePassword(null, null, null, null, null, null);
+  }
+
+  /**
+   * Create a secure (random) password using a secure random number generator, 
a set of (reasonable)
+   * characters, and meeting the specified rules.
+   * <p/>
+   * If any rule is <code>null</code>, it's default value will be used:
+   * <ul>
+   * <li>length: 18</li>
+   * <li>minimum lowercase letters (a-z): 1</li>
+   * <li>minimum uppercase letters (A-Z): 1</li>
+   * <li>minimum digits (0-9): 1</li>
+   * <li>minimum punctuation (?.!$%^*()-_+=~): 1</li>
+   * <li>minimum whitespace ( ): 0</li>
+   * </ul>
+   *
+   * @param length              the required length of the generated password
+   * @param minLowercaseLetters the required minimum number of lowercase 
letters
+   * @param minUppercaseLetters the required minimum number of uppercase 
letters
+   * @param minDigits           the required minimum number of digits
+   * @param minPunctuation      the required minimum number of punctuation 
characters
+   * @param minWhitespace       the required minimum number of space characters
+   * @return a String containing the new password
+   */
+  public String createSecurePassword(Integer length, Integer 
minLowercaseLetters, Integer minUppercaseLetters, Integer minDigits, Integer 
minPunctuation, Integer minWhitespace) {
+    if ((length == null) || (length < 1)) {
+      length = SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_LENGTH;
+    }
+
+    if (minLowercaseLetters == null) {
+      minLowercaseLetters = 
SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_LOWERCASE_LETTERS;
+    }
+
+    if (minUppercaseLetters == null) {
+      minUppercaseLetters = 
SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_UPPERCASE_LETTERS;
+    }
+
+    if (minDigits == null) {
+      minDigits = SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_DIGITS;
+    }
+
+    if (minPunctuation == null) {
+      minPunctuation = 
SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_PUNCTUATION;
+    }
+
+    if (minWhitespace == null) {
+      minWhitespace = 
SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_WHITESPACE;
+    }
+
+    // Gather the set of characters that meet the specified requirements
+    List<Character> characters = new ArrayList<Character>(length);
+
+    for (int i = 0; i < minLowercaseLetters; i++) {
+      
characters.add(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_LOWERCASE_LETTERS[secureRandom.nextInt(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_LOWERCASE_LETTERS.length)]);
+    }
+
+    for (int i = 0; i < minUppercaseLetters; i++) {
+      
characters.add(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_UPPERCASE_LETTERS[secureRandom.nextInt(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_UPPERCASE_LETTERS.length)]);
+    }
+
+    for (int i = 0; i < minDigits; i++) {
+      
characters.add(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_DIGITS[secureRandom.nextInt(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_DIGITS.length)]);
+    }
+
+    for (int i = 0; i < minPunctuation; i++) {
+      
characters.add(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_PUNCTUATION[secureRandom.nextInt(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_PUNCTUATION.length)]);
+    }
+
+    for (int i = 0; i < minWhitespace; i++) {
+      
characters.add(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_WHITESPACE[secureRandom.nextInt(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_WHITESPACE.length)]);
+    }
+
+    // If we need to gather more characters, select randomly from the set of 
character classes
+    if (characters.size() < length) {
+      int difference = length - characters.size();
+      for (int i = 0; i < difference; i++) {
+        char[] characterClass = 
SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASSES[secureRandom.nextInt(SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASSES.length
 - 1)];
+        
characters.add(characterClass[secureRandom.nextInt(characterClass.length)]);
+      }
+    }
+
+    // Generate the password string by randomly selecting from the list of 
available characters
+    StringBuilder passwordBuilder = new StringBuilder(characters.size());
+
+    while (!characters.isEmpty()) {
+      
passwordBuilder.append(characters.remove(secureRandom.nextInt(characters.size())));
+    }
+
+    return passwordBuilder.toString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
index 52ac8ac..64ebe0f 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
@@ -49,13 +49,18 @@ public class CleanupServerAction extends 
KerberosServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
    *                                 to a given request
    * @return null, always
-   * @throws AmbariException
+   * @throws AmbariException if an error occurs while processing the identity 
record
    */
   @Override
-  protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal, KerberosOperationHandler operationHandler, 
Map<String, Object> requestSharedDataContext) throws AmbariException {
+  protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal,
+                                          KerberosOperationHandler 
operationHandler,
+                                          Map<String, String> 
kerberosConfiguration,
+                                          Map<String, Object> 
requestSharedDataContext)
+      throws AmbariException {
     return null;
   }
 
@@ -105,4 +110,5 @@ public class CleanupServerAction extends 
KerberosServerAction {
       throw new AmbariException("An unknown error occurred while trying to 
delete the cluster Kerberos descriptor", e);
     }
   }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
index f48c4cf..34780d6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
@@ -48,7 +48,7 @@ import java.util.concurrent.ConcurrentMap;
  * This class mainly relies on the KerberosServerAction to iterate through 
metadata identifying
  * the Kerberos keytab files that need to be created. For each identity in the 
metadata, this
  * implementation's
- * {@link KerberosServerAction#processIdentity(java.util.Map, String, 
KerberosOperationHandler, java.util.Map)}
+ * {@link KerberosServerAction#processIdentity(Map, String, 
KerberosOperationHandler, Map, Map)}
  * is invoked attempting the creation of the relevant keytab file.
  */
 public class CreateKeytabFilesServerAction extends KerberosServerAction {
@@ -134,14 +134,16 @@ public class CreateKeytabFilesServerAction extends 
KerberosServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
-   *                                 to a given request
-   * @return a CommandReport, indicating an error condition; or null, 
indicating a success condition
+   *                                 to a given request  @return a 
CommandReport, indicating an error
+   *                                 condition; or null, indicating a success 
condition
    * @throws AmbariException if an error occurs while processing the identity 
record
    */
   @Override
   protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal,
                                           KerberosOperationHandler 
operationHandler,
+                                          Map<String, String> 
kerberosConfiguration,
                                           Map<String, Object> 
requestSharedDataContext)
       throws AmbariException {
     CommandReport commandReport = null;

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
index 13fb49b..f5282af 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
 import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
+import org.apache.ambari.server.security.SecurePasswordHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,7 +36,7 @@ import java.util.concurrent.ConcurrentMap;
  * <p/>
  * This class mainly relies on the KerberosServerAction to iterate through 
metadata identifying
  * the Kerberos principals that need to be created. For each identity in the 
metadata, this implementation's
- * {@link KerberosServerAction#processIdentity(java.util.Map, String, 
KerberosOperationHandler, java.util.Map)}
+ * {@link KerberosServerAction#processIdentity(Map, String, 
KerberosOperationHandler, Map, Map)}
  * is invoked attempting the creation of the relevant principal.
  */
 public class CreatePrincipalsServerAction extends KerberosServerAction {
@@ -54,6 +55,12 @@ public class CreatePrincipalsServerAction extends 
KerberosServerAction {
   private KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
 
   /**
+   * SecurePasswordHelper used to generate secure passwords for newly created 
principals
+   */
+  @Inject
+  private SecurePasswordHelper securePasswordHelper;
+
+  /**
    * Called to execute this action.  Upon invocation, calls
    * {@link 
org.apache.ambari.server.serveraction.kerberos.KerberosServerAction#processIdentities(java.util.Map)}
    * to iterate through the Kerberos identity metadata and call
@@ -78,7 +85,7 @@ public class CreatePrincipalsServerAction extends 
KerberosServerAction {
    * an assume to be configured KDC.
    * <p/>
    * If a password has not been previously created the current 
evaluatedPrincipal, create a "secure"
-   * password using {@link KerberosOperationHandler#createSecurePassword()}.  
Then if the principal
+   * password using {@link SecurePasswordHelper#createSecurePassword()}.  Then 
if the principal
    * does not exist in the KDC, create it using the generated password; else 
if it does exist update
    * its password.  Finally store the generated password in the shared 
principal-to-password map and
    * store the new key numbers in the shared principal-to-key_number map so 
that subsequent process
@@ -89,14 +96,16 @@ public class CreatePrincipalsServerAction extends 
KerberosServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
-   *                                 to a given request
-   * @return a CommandReport, indicating an error condition; or null, 
indicating a success condition
+   *                                 to a given request  @return a 
CommandReport, indicating an error
+   *                                 condition; or null, indicating a success 
condition
    * @throws AmbariException if an error occurs while processing the identity 
record
    */
   @Override
   protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal,
                                           KerberosOperationHandler 
operationHandler,
+                                          Map<String, String> 
kerberosConfiguration,
                                           Map<String, Object> 
requestSharedDataContext)
       throws AmbariException {
     CommandReport commandReport = null;
@@ -114,7 +123,31 @@ public class CreatePrincipalsServerAction extends 
KerberosServerAction {
         LOG.info(message);
         actionLog.writeStdOut(message);
 
-        password = operationHandler.createSecurePassword();
+        Integer length;
+        Integer minLowercaseLetters;
+        Integer minUppercaseLetters;
+        Integer minDigits;
+        Integer minPunctuation;
+        Integer minWhitespace;
+
+        if(kerberosConfiguration == null) {
+          length = null;
+          minLowercaseLetters= null;
+          minUppercaseLetters= null;
+          minDigits= null;
+          minPunctuation= null;
+          minWhitespace= null;
+        }
+        else {
+          length = toInt(kerberosConfiguration.get("password_length"));
+          minLowercaseLetters = 
toInt(kerberosConfiguration.get("password_min_lowercase_letters"));
+          minUppercaseLetters = 
toInt(kerberosConfiguration.get("password_min_uppercase_letters"));
+          minDigits = toInt(kerberosConfiguration.get("password_min_digits"));
+          minPunctuation = 
toInt(kerberosConfiguration.get("password_min_punctuation"));
+          minWhitespace = 
toInt(kerberosConfiguration.get("password_min_whitespace"));
+        }
+
+        password = securePasswordHelper.createSecurePassword(length, 
minLowercaseLetters, minUppercaseLetters, minDigits, minPunctuation, 
minWhitespace);
 
         try {
           boolean servicePrincipal = 
"service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE));
@@ -172,4 +205,25 @@ public class CreatePrincipalsServerAction extends 
KerberosServerAction {
 
     return commandReport;
   }
+
+  /**
+   * Translates a String containing an integer value to an Integer.
+   * <p/>
+   * If the string is null, empty or not a number, returns null; otherwise 
returns an Integer value
+   * representing the integer value of the string.
+   *
+   * @param string the string to parse
+   * @return an Integer or null
+   */
+  private Integer toInt(String string) {
+    if ((string == null) || string.isEmpty()) {
+      return null;
+    } else {
+      try {
+        return Integer.parseInt(string);
+      } catch (NumberFormatException e) {
+        return null;
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
index a215a56..93daae8 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
@@ -36,7 +36,7 @@ import java.util.concurrent.ConcurrentMap;
  * This class mainly relies on the KerberosServerAction to iterate through 
metadata identifying
  * the Kerberos principals that need to be removed from the relevant KDC. For 
each identity in the
  * metadata, this implementation's
- * {@link 
org.apache.ambari.server.serveraction.kerberos.KerberosServerAction#processIdentity(java.util.Map,
 String, 
org.apache.ambari.server.serveraction.kerberos.KerberosOperationHandler, 
java.util.Map)}
+ * {@link KerberosServerAction#processIdentity(Map, String, 
KerberosOperationHandler, Map, Map)}
  * is invoked attempting the removal of the relevant principal.
  */
 public class DestroyPrincipalsServerAction extends KerberosServerAction {
@@ -73,14 +73,16 @@ public class DestroyPrincipalsServerAction extends 
KerberosServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
-   *                                 to a given request
-   * @return a CommandReport, indicating an error condition; or null, 
indicating a success condition
+   *                                 to a given request  @return a 
CommandReport, indicating an error
+   *                                 condition; or null, indicating a success 
condition
    * @throws org.apache.ambari.server.AmbariException if an error occurs while 
processing the identity record
    */
   @Override
   protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal,
                                           KerberosOperationHandler 
operationHandler,
+                                          Map<String, String> 
kerberosConfiguration,
                                           Map<String, Object> 
requestSharedDataContext)
       throws AmbariException {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
index 4925582..c710b8e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
@@ -48,14 +48,15 @@ public class FinalizeKerberosServerAction extends 
KerberosServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
-   *                                 to a given request
-   * @return null, always
+   *                                 to a given request  @return null, always
    * @throws AmbariException
    */
   @Override
   protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal,
                                           KerberosOperationHandler 
operationHandler,
+                                          Map<String, String> 
kerberosConfiguration,
                                           Map<String, Object> 
requestSharedDataContext)
       throws AmbariException {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
index ed31ccf..20426f0 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.serveraction.kerberos;
 
+import org.apache.ambari.server.security.SecurePasswordHelper;
 import org.apache.ambari.server.utils.ShellCommandUtil;
 import org.apache.commons.codec.binary.Base64;
 import 
org.apache.directory.server.kerberos.shared.crypto.encryption.KerberosKeyFactory;
@@ -34,7 +35,6 @@ import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -53,13 +53,6 @@ import java.util.Set;
 public abstract class KerberosOperationHandler {
   private final static Logger LOG = 
LoggerFactory.getLogger(KerberosOperationHandler.class);
 
-  private final static SecureRandom SECURE_RANDOM = new SecureRandom();
-
-  /**
-   * The number of characters to generate for a secure password
-   */
-  protected final static int SECURE_PASSWORD_LENGTH = 18;
-
   /**
    * Kerberos-env configuration property name: ldap_url
    */
@@ -96,12 +89,6 @@ public abstract class KerberosOperationHandler {
   public final static String KERBEROS_ENV_EXECUTABLE_SEARCH_PATHS = 
"executable_search_paths";
 
   /**
-   * The set of available characters to use when generating a secure password
-   */
-  private final static char[] SECURE_PASSWORD_CHARS =
-      
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890?.!$%^*()-_+=~".toCharArray();
-
-  /**
    * An array of String values declaring the default (ordered) list of path to 
search for executables
    */
   private static final String[] DEFAULT_EXECUTABLE_SEARCH_PATHS = {"/usr/bin", 
"/usr/kerberos/bin", "/usr/sbin", "/usr/lib/mit/bin", "/usr/lib/mit/sbin"};
@@ -210,45 +197,6 @@ public abstract class KerberosOperationHandler {
 
 
   /**
-   * Create a secure (random) password using a secure random number generator 
and a set of (reasonable)
-   * characters.
-   *
-   * @return a String containing the new password
-   */
-  public String createSecurePassword() {
-    return createSecurePassword(SECURE_PASSWORD_LENGTH);
-  }
-
-  /**
-   * Create a secure (random) password using a secure random number generator 
and a set of (reasonable)
-   * characters.
-   *
-   * @param length an integer value declaring the length of the password to 
create,
-   *               if <1, a default will be used.
-   * @return a String containing the new password
-   */
-  public String createSecurePassword(int length) {
-    StringBuilder passwordBuilder;
-
-    // If the supplied length is less than 1 use the default value.
-    if (length < 1) {
-      length = SECURE_PASSWORD_LENGTH;
-    }
-
-    // Create a new StringBuilder and ensure its capacity is set for the 
length of the password to
-    // be generated
-    passwordBuilder = new StringBuilder(length);
-
-    // For each character to be added to the password, (securely) generate a 
random number to pull
-    // a random character from the character array
-    for (int i = 0; i < length; i++) {
-      
passwordBuilder.append(SECURE_PASSWORD_CHARS[SECURE_RANDOM.nextInt(SECURE_PASSWORD_CHARS.length)]);
-    }
-
-    return passwordBuilder.toString();
-  }
-
-  /**
    * Prepares and creates resources to be used by this 
KerberosOperationHandler.
    * Implementation in this class is ignoring parameters ldapUrl and 
principalContainerDn and delegate to
    * <code>open(KerberosCredential administratorCredentials, String 
defaultRealm)</code>

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
index a92fb12..55018de 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
@@ -316,7 +316,7 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
    * Using the "data_directory" value from this action's command parameters 
map, creates a
    * {@link KerberosIdentityDataFileReader} to parse
    * the relative identity.dat file and iterate through its "records".  Each 
"record" is process using
-   * {@link #processRecord(java.util.Map, String, KerberosOperationHandler, 
java.util.Map)}.
+   * {@link #processRecord(Map, String, KerberosOperationHandler, Map, Map)}.
    *
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
    *                                 to a given request
@@ -372,8 +372,10 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
               throw new AmbariException(message);
             }
 
+            Map<String, String> kerberosConfiguration = 
getConfiguration("kerberos-env");
+
             try {
-              handler.open(administratorCredential, defaultRealm, 
getConfiguration("kerberos-env"));
+              handler.open(administratorCredential, defaultRealm, 
kerberosConfiguration);
             } catch (KerberosOperationException e) {
               String message = String.format("Failed to process the 
identities, could not properly open the KDC operation handler: %s",
                   e.getMessage());
@@ -388,7 +390,7 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
               reader = 
kerberosIdentityDataFileReaderFactory.createKerberosIdentityDataFileReader(identityDataFile);
               for (Map<String, String> record : reader) {
                 // Process the current record
-                commandReport = processRecord(record, defaultRealm, handler, 
requestSharedDataContext);
+                commandReport = processRecord(record, defaultRealm, handler, 
kerberosConfiguration, requestSharedDataContext);
 
                 // If the principal processor returns a CommandReport, than it 
is time to stop since
                 // an error condition has probably occurred, else all is 
assumed to be well.
@@ -452,14 +454,16 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
-   *                                 to a given request
-   * @return a CommandReport, indicating an error condition; or null, 
indicating a success condition
+   *                                 to a given request  @return a 
CommandReport, indicating an error
+   *                                 condition; or null, indicating a success 
condition
    * @throws AmbariException if an error occurs while processing the identity 
record
    */
   protected abstract CommandReport processIdentity(Map<String, String> 
identityRecord,
                                                    String evaluatedPrincipal,
                                                    KerberosOperationHandler 
operationHandler,
+                                                   Map<String, String> 
kerberosConfiguration,
                                                    Map<String, Object> 
requestSharedDataContext)
       throws AmbariException;
 
@@ -468,7 +472,7 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
    * <p/>
    * Given the data from the record Map, attempts to replace variables in the 
principal pattern to
    * generate a concrete principal value to further process. This "evaluated 
principal" is then passed to
-   * {@link #processIdentity(java.util.Map, String, KerberosOperationHandler, 
java.util.Map)}
+   * {@link #processIdentity(Map, String, KerberosOperationHandler, Map, Map)}
    * to be handled as needed.
    *
    * @param record                   a Map containing the data for the current 
identity record
@@ -476,14 +480,15 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
    * @param operationHandler         a KerberosOperationHandler used to 
perform Kerberos-related
    *                                 tasks for specific Kerberos 
implementations
    *                                 (MIT, Active Directory, etc...)
+   * @param kerberosConfiguration    a Map of configuration properties from 
kerberos-env
    * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
-   *                                 to a given request
-   * @return a CommandReport, indicating an error condition; or null, 
indicating a success condition
+   *                                 to a given request  @return a 
CommandReport, indicating an error
+   *                                 condition; or null, indicating a success 
condition
    * @throws AmbariException if an error occurs while processing the identity 
record
    */
   private CommandReport processRecord(Map<String, String> record, String 
defaultRealm,
                                       KerberosOperationHandler 
operationHandler,
-                                      Map<String, Object> 
requestSharedDataContext)
+                                      Map<String, String> 
kerberosConfiguration, Map<String, Object> requestSharedDataContext)
       throws AmbariException {
     CommandReport commandReport = null;
 
@@ -496,7 +501,7 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
         // by replacing the _HOST and _REALM variables.
         String evaluatedPrincipal = principal.replace("_HOST", 
host).replace("_REALM", defaultRealm);
 
-        commandReport = processIdentity(record, evaluatedPrincipal, 
operationHandler, requestSharedDataContext);
+        commandReport = processIdentity(record, evaluatedPrincipal, 
operationHandler, kerberosConfiguration, requestSharedDataContext);
       }
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
 
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
index 682d675..ec50f69 100644
--- 
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
+++ 
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
@@ -104,6 +104,54 @@
     <value>/usr/bin, /usr/kerberos/bin, /usr/sbin, /usr/lib/mit/bin, 
/usr/lib/mit/sbin</value>
   </property>
 
+  <property>
+    <name>password_length</name>
+    <description>
+      The length required length for generated passwords.
+    </description>
+    <value>20</value>
+  </property>
+
+  <property>
+    <name>password_min_lowercase_letters</name>
+    <description>
+      The minimum number of lowercase letters (a-z) required in generated 
passwords
+    </description>
+    <value>1</value>
+  </property>
+
+  <property>
+    <name>password_min_uppercase_letters</name>
+    <description>
+      The minimum number of uppercase letters (A-Z) required in generated 
passwords
+    </description>
+    <value>1</value>
+  </property>
+
+  <property>
+    <name>password_min_digits</name>
+    <description>
+      The minimum number of digits (0-9) required in generated passwords
+    </description>
+    <value>1</value>
+  </property>
+
+  <property>
+    <name>password_min_punctuation</name>
+    <description>
+      The minimum number of punctuation characters (?.!$%^*()-_+=~) required 
in generated passwords
+    </description>
+    <value>1</value>
+  </property>
+
+  <property>
+    <name>password_min_whitespace</name>
+    <description>
+      The minimum number of whitespace characters required in generated 
passwords
+    </description>
+    <value>0</value>
+  </property>
+
   <property require-input="true">
     <name>create_attributes_template</name>
     <description>

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/test/java/org/apache/ambari/server/security/SecurePasswordHelperTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/security/SecurePasswordHelperTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/security/SecurePasswordHelperTest.java
new file mode 100644
index 0000000..1c61109
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/security/SecurePasswordHelperTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class SecurePasswordHelperTest {
+
+  private SecurePasswordHelper securePasswordHelper;
+
+  @Before
+  public void setUp() throws Exception {
+    securePasswordHelper = new SecurePasswordHelper();
+  }
+
+  @Test
+  public void testCreateSecurePassword() throws Exception {
+
+    String password1 = securePasswordHelper.createSecurePassword();
+    Assert.assertNotNull(password1);
+    Assert.assertEquals(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_LENGTH, 
password1.length());
+
+    String password2 = securePasswordHelper.createSecurePassword();
+    Assert.assertNotNull(password2);
+    Assert.assertEquals(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_LENGTH, 
password2.length());
+
+    // Make sure the passwords are different... if they are the same, that 
indicated the random
+    // number generators are generating using the same pattern and that is not 
secure.
+    Assert.assertFalse((password1.equals(password2)));
+  }
+
+  @Test
+  public void testCreateSecurePasswordWithRules() throws Exception {
+    String password;
+
+    //Default rules....
+    password = securePasswordHelper.createSecurePassword(null, null, null, 
null, null, null);
+    Assert.assertNotNull(password);
+    Assert.assertEquals(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_LENGTH, 
password.length());
+    
assertMinLowercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_LOWERCASE_LETTERS,
 password);
+    
assertMinUppercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_UPPERCASE_LETTERS,
 password);
+    assertMinDigits(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_DIGITS, 
password);
+    
assertMinPunctuation(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_PUNCTUATION,
 password);
+    
assertMinWhitespace(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_WHITESPACE,
 password);
+
+    password = securePasswordHelper.createSecurePassword(10, null, null, null, 
null, null);
+    Assert.assertNotNull(password);
+    Assert.assertEquals(10, password.length());
+    
assertMinLowercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_LOWERCASE_LETTERS,
 password);
+    
assertMinUppercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_UPPERCASE_LETTERS,
 password);
+    assertMinDigits(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_DIGITS, 
password);
+    
assertMinPunctuation(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_PUNCTUATION,
 password);
+    
assertMinWhitespace(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_WHITESPACE,
 password);
+
+    password = securePasswordHelper.createSecurePassword(0, null, null, null, 
null, null);
+    Assert.assertNotNull(password);
+    Assert.assertEquals(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_LENGTH, 
password.length());
+    
assertMinLowercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_LOWERCASE_LETTERS,
 password);
+    
assertMinUppercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_UPPERCASE_LETTERS,
 password);
+    assertMinDigits(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_DIGITS, 
password);
+    
assertMinPunctuation(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_PUNCTUATION,
 password);
+    
assertMinWhitespace(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_WHITESPACE,
 password);
+
+    password = securePasswordHelper.createSecurePassword(-20, null, null, 
null, null, null);
+    Assert.assertNotNull(password);
+    Assert.assertEquals(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_LENGTH, 
password.length());
+    
assertMinLowercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_LOWERCASE_LETTERS,
 password);
+    
assertMinUppercaseLetters(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_UPPERCASE_LETTERS,
 password);
+    assertMinDigits(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_DIGITS, 
password);
+    
assertMinPunctuation(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_PUNCTUATION,
 password);
+    
assertMinWhitespace(SecurePasswordHelper.DEFAULT_SECURE_PASSWORD_MIN_WHITESPACE,
 password);
+
+    password = securePasswordHelper.createSecurePassword(100, 30, 20, 10, 5, 
2);
+    Assert.assertNotNull(password);
+    Assert.assertEquals(100, password.length());
+    assertMinLowercaseLetters(30, password);
+    assertMinUppercaseLetters(20, password);
+    assertMinDigits(10, password);
+    assertMinPunctuation(5, password);
+    assertMinWhitespace(2, password);
+
+    password = securePasswordHelper.createSecurePassword(100, 20, 20, 20, 20, 
0);
+    Assert.assertNotNull(password);
+    Assert.assertEquals(100, password.length());
+    assertMinLowercaseLetters(20, password);
+    assertMinUppercaseLetters(20, password);
+    assertMinDigits(20, password);
+    assertMinPunctuation(20, password);
+    assertMinWhitespace(0, password);
+  }
+
+  private void assertMinLowercaseLetters(int minCount, String password) {
+    assertMinCharacterCount(minCount, password, 
SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_LOWERCASE_LETTERS);
+  }
+
+  private void assertMinUppercaseLetters(int minCount, String password) {
+    assertMinCharacterCount(minCount, password, 
SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_UPPERCASE_LETTERS);
+  }
+
+  private void assertMinDigits(int minCount, String password) {
+    assertMinCharacterCount(minCount, password, 
SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_DIGITS);
+  }
+
+  private void assertMinPunctuation(int minCount, String password) {
+    assertMinCharacterCount(minCount, password, 
SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_PUNCTUATION);
+  }
+
+  private void assertMinWhitespace(int minCount, String password) {
+    assertMinCharacterCount(minCount, password, 
SecurePasswordHelper.SECURE_PASSWORD_CHARACTER_CLASS_WHITESPACE);
+  }
+
+  private void assertMinCharacterCount(int minCount, String string, char[] 
characters) {
+
+    int count = 0;
+    Set<Character> set = new HashSet<Character>();
+    for(char c:characters) {
+      set.add(c);
+    }
+
+    for (char c : string.toCharArray()) {
+      if (set.contains(c)) {
+        count++;
+
+        if (count == minCount) {
+          break;
+        }
+      }
+    }
+
+    Assert.assertEquals(string, minCount, count);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
index d833c35..48bf473 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
@@ -511,16 +511,16 @@ public class ADKerberosOperationHandlerTest extends 
KerberosOperationHandlerTest
 
     evaluatedPrincipal = "nn/c6501.ambari.apache.org@" + DEFAULT_REALM;
     if (handler.principalExists(evaluatedPrincipal)) {
-      handler.setPrincipalPassword(evaluatedPrincipal, 
handler.createSecurePassword());
+      handler.setPrincipalPassword(evaluatedPrincipal, "some password");
     } else {
-      handler.createPrincipal(evaluatedPrincipal, 
handler.createSecurePassword(), true);
+      handler.createPrincipal(evaluatedPrincipal, "some password", true);
     }
 
     evaluatedPrincipal = "hdfs@" + DEFAULT_REALM;
     if (handler.principalExists(evaluatedPrincipal)) {
-      handler.setPrincipalPassword(evaluatedPrincipal, 
handler.createSecurePassword());
+      handler.setPrincipalPassword(evaluatedPrincipal, "some password");
     } else {
-      handler.createPrincipal(evaluatedPrincipal, 
handler.createSecurePassword(), true);
+      handler.createPrincipal(evaluatedPrincipal, "some password", true);
     }
 
     
kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_CREATE_ATTRIBUTES_TEMPLATE,
@@ -552,11 +552,11 @@ public class ADKerberosOperationHandlerTest extends 
KerberosOperationHandlerTest
     handler.removePrincipal("abcdefg");
     handler.removePrincipal("abcdefg/c1509.ambari.apache.org@" + 
DEFAULT_REALM);
 
-    handler.createPrincipal("abcdefg/c1509.ambari.apache.org@" + 
DEFAULT_REALM, handler.createSecurePassword(), true);
-    handler.createPrincipal("abcdefg@" + DEFAULT_REALM, 
handler.createSecurePassword(), false);
+    handler.createPrincipal("abcdefg/c1509.ambari.apache.org@" + 
DEFAULT_REALM, "some password", true);
+    handler.createPrincipal("abcdefg@" + DEFAULT_REALM, "some password", 
false);
 
     //update the password
-    handler.setPrincipalPassword("abcdefg/c1509.ambari.apache.org@" + 
DEFAULT_REALM, handler.createSecurePassword());
+    handler.setPrincipalPassword("abcdefg/c1509.ambari.apache.org@" + 
DEFAULT_REALM, "some password");
 
     handler.close();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
index 07094a7..410eced 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
@@ -42,44 +42,6 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
   public TemporaryFolder folder = new TemporaryFolder();
 
   @Test
-  public void testCreateSecurePassword() throws Exception {
-
-    KerberosOperationHandler handler1 = createHandler();
-    KerberosOperationHandler handler2 = createHandler();
-
-    String password1 = handler1.createSecurePassword();
-    Assert.assertNotNull(password1);
-    Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, 
password1.length());
-
-    String password2 = handler2.createSecurePassword();
-    Assert.assertNotNull(password2);
-    Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, 
password2.length());
-
-    // Make sure the passwords are different... if they are the same, that 
indicated the random
-    // number generators are generating using the same pattern and that is not 
secure.
-    Assert.assertFalse((password1.equals(password2)));
-  }
-
-  @Test
-  public void testCreateSecurePasswordWithSize() throws Exception {
-    KerberosOperationHandler handler = createHandler();
-
-    String password;
-
-    password = handler.createSecurePassword(10);
-    Assert.assertNotNull(password);
-    Assert.assertEquals(10, password.length());
-
-    password = handler.createSecurePassword(0);
-    Assert.assertNotNull(password);
-    Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, 
password.length());
-
-    password = handler.createSecurePassword(-20);
-    Assert.assertNotNull(password);
-    Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, 
password.length());
-  }
-
-  @Test
   public void testCreateKeytabFileOneAtATime() throws Exception {
     KerberosOperationHandler handler = createHandler();
     File file = folder.newFile();
@@ -87,7 +49,7 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
     final String principal2 = "[email protected]";
     int count;
 
-    Assert.assertTrue(handler.createKeytabFile(principal1, 
handler.createSecurePassword(), 0, file));
+    Assert.assertTrue(handler.createKeytabFile(principal1, "some password", 0, 
file));
 
     Keytab keytab = Keytab.read(file);
     Assert.assertNotNull(keytab);
@@ -102,7 +64,7 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
       Assert.assertEquals(principal1, entry.getPrincipalName());
     }
 
-    Assert.assertTrue(handler.createKeytabFile(principal2, 
handler.createSecurePassword(), 0, file));
+    Assert.assertTrue(handler.createKeytabFile(principal2, "some password", 0, 
file));
 
     keytab = Keytab.read(file);
     Assert.assertNotNull(keytab);
@@ -122,11 +84,11 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
     final String principal2 = "[email protected]";
     Set<String> seenEntries = new HashSet<String>();
 
-    Assert.assertTrue(handler.createKeytabFile(principal1, 
handler.createSecurePassword(), 0, file));
-    Assert.assertTrue(handler.createKeytabFile(principal2, 
handler.createSecurePassword(), 0, file));
+    Assert.assertTrue(handler.createKeytabFile(principal1, "some password", 0, 
file));
+    Assert.assertTrue(handler.createKeytabFile(principal2, "some password", 0, 
file));
 
     // Attempt to add duplicate entries
-    Assert.assertTrue(handler.createKeytabFile(principal2, 
handler.createSecurePassword(), 0, file));
+    Assert.assertTrue(handler.createKeytabFile(principal2, "some password", 0, 
file));
 
     Keytab keytab = Keytab.read(file);
     Assert.assertNotNull(keytab);
@@ -149,7 +111,7 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
     final String principal1 = "[email protected]";
 
     try {
-      handler.createKeytabFile(null, handler.createSecurePassword(), 0, file);
+      handler.createKeytabFile(null, "some password", 0, file);
       Assert.fail("KerberosOperationException not thrown with null principal");
     } catch (Throwable t) {
       Assert.assertEquals(KerberosOperationException.class, t.getClass());
@@ -163,7 +125,7 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
     }
 
     try {
-      handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, 
null);
+      handler.createKeytabFile(principal1, "some password", 0, null);
       Assert.fail("KerberosOperationException not thrown with null file");
     } catch (Throwable t) {
       Assert.assertEquals(KerberosOperationException.class, t.getClass());
@@ -176,7 +138,7 @@ public abstract class KerberosOperationHandlerTest extends 
EasyMockSupport {
     File file = folder.newFile();
     final String principal = "[email protected]";
 
-    Assert.assertTrue(handler.createKeytabFile(principal, 
handler.createSecurePassword(), 0, file));
+    Assert.assertTrue(handler.createKeytabFile(principal, "some password", 0, 
file));
 
     FileInputStream fis = new FileInputStream(file);
     byte[] data = new byte[(int) file.length()];

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
index 336090b..8fc5325 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
@@ -73,6 +73,7 @@ public class KerberosServerActionTest {
           @Override
           protected CommandReport processIdentity(Map<String, String> 
identityRecord, String evaluatedPrincipal,
                                                   KerberosOperationHandler 
operationHandler,
+                                                  Map<String, String> 
kerberosConfiguration,
                                                   Map<String, Object> 
requestSharedDataContext)
               throws AmbariException {
             Assert.assertNotNull(requestSharedDataContext);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6691a174/ambari-web/app/data/HDP2/site_properties.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/HDP2/site_properties.js 
b/ambari-web/app/data/HDP2/site_properties.js
index ae6051f..661e49e 100644
--- a/ambari-web/app/data/HDP2/site_properties.js
+++ b/ambari-web/app/data/HDP2/site_properties.js
@@ -1171,7 +1171,7 @@ var hdp2properties = [
   },
   {
     "id": "site property",
-    "isOverrideable": false,
+    "isOverridable": false,
     "serviceName": "STORM",
     "category": "SUPERVISOR",
     "displayName": "supervisor.childopts",
@@ -1983,36 +1983,132 @@ var hdp2properties = [
     "name": "manage_identities",
     "displayName": "Manage Kerberos Identities",
     "displayType": "checkbox",
+    "isOverridable": false,
+    "isVisible": true,
     "serviceName": "KERBEROS",
     "filename": "kerberos-env.xml",
-    "category": "Advanced kerberos-env"
+    "category": "Advanced kerberos-env",
+    "index" : 0
   },
   {
     "id": "puppet var",
     "name": "install_packages",
     "displayName": "Install OS-specific Kerberos client package(s)",
     "displayType": "checkbox",
+    "isOverridable": false,
+    "isVisible": true,
     "serviceName": "KERBEROS",
     "filename": "kerberos-env.xml",
-    "category": "Advanced kerberos-env"
+    "category": "Advanced kerberos-env",
+    "index" : 1
   },
   {
     "id": "puppet var",
-    "name": "create_attributes_template",
-    "displayName": "Attribute template",
+    "name": "executable_search_paths",
+    "displayName": "Executable Search Paths",
+    "displayType": "multiline",
+    "isOverridable": false,
+    "isVisible": true,
     "serviceName": "KERBEROS",
     "filename": "kerberos-env.xml",
-    "displayType": "content",
-    "category": "Advanced kerberos-env"
+    "category": "Advanced kerberos-env",
+    "index" : 2
   },
   {
     "id": "puppet var",
     "name": "encryption_types",
     "displayName": "Encryption Types",
+    "isOverridable": false,
+    "isVisible": true,
     "serviceName": "KERBEROS",
     "filename": "kerberos-env.xml",
     "displayType": "multiLine",
-    "category": "Advanced kerberos-env"
+    "category": "Advanced kerberos-env",
+    "index" : 3
+  },
+  {
+    "id": "puppet var",
+    "name": "password_length",
+    "displayName": "Password Length",
+    "displayType": "int",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 4
+  },
+  {
+    "id": "puppet var",
+    "name": "password_min_lowercase_letters",
+    "displayName": "Password Minimum # Lowercase Letters",
+    "displayType": "int",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 5
+  },
+  {
+    "id": "puppet var",
+    "name": "password_min_uppercase_letters",
+    "displayName": "Password Minimum # Uppercase Letters",
+    "displayType": "int",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 6
+  },
+  {
+    "id": "puppet var",
+    "name": "password_min_digits",
+    "displayName": "Password Minimum # Digits",
+    "displayType": "int",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 7
+  },
+  {
+    "id": "puppet var",
+    "name": "password_min_punctuation",
+    "displayName": "Password Minimum # Punctuation Characters",
+    "displayType": "int",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 8
+  },
+  {
+    "id": "puppet var",
+    "name": "password_min_whitespace",
+    "displayName": "Password Minimum # Whitespace Characters",
+    "displayType": "int",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 9
+  },
+  {
+    "id": "puppet var",
+    "name": "create_attributes_template",
+    "displayName": "Attribute template",
+    "displayType": "content",
+    "isOverridable": false,
+    "isVisible": true,
+    "serviceName": "KERBEROS",
+    "filename": "kerberos-env.xml",
+    "category": "Advanced kerberos-env",
+    "index" : 10
   },
   {
     "id": "puppet var",

Reply via email to