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",
