http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java index 0997f65..bbcd6e8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java @@ -18,21 +18,17 @@ package org.apache.ambari.server.serveraction.kerberos; -import java.text.NumberFormat; -import java.text.ParseException; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Queue; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.Set; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.security.credential.PrincipalKeyCredential; import org.apache.ambari.server.utils.ShellCommandUtil; -import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; +import org.apache.directory.shared.kerberos.codec.types.EncryptionType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,37 +41,24 @@ import com.google.inject.Inject; * It is assumed that a MIT Kerberos client is installed and that the kdamin shell command is * available */ -public class MITKerberosOperationHandler extends KerberosOperationHandler { +public class MITKerberosOperationHandler extends KDCKerberosOperationHandler { + + private final static Logger LOG = LoggerFactory.getLogger(MITKerberosOperationHandler.class); @Inject private Configuration configuration; /** - * A regular expression pattern to use to parse the key number from the text captured from the - * get_principal kadmin command - */ - private final static Pattern PATTERN_GET_KEY_NUMBER = Pattern.compile("^.*?Key: vno (\\d+).*$", Pattern.DOTALL); - - private final static Logger LOG = LoggerFactory.getLogger(MITKerberosOperationHandler.class); - - /** * A String containing user-specified attributes used when creating principals */ private String createAttributes = null; - private String adminServerHost = null; - /** * A String containing the resolved path to the kdamin executable */ private String executableKadmin = null; /** - * A String containing the resolved path to the kdamin.local executable - */ - private String executableKadminLocal = null; - - /** * Prepares and creates resources to be used by this KerberosOperationHandler * <p/> * It is expected that this KerberosOperationHandler will not be used before this call. @@ -92,39 +75,25 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @throws KerberosOperationException if an unexpected error occurred */ @Override - public void open(PrincipalKeyCredential administratorCredentials, String realm, - Map<String, String> kerberosConfiguration) + public void open(PrincipalKeyCredential administratorCredentials, String realm, Map<String, String> kerberosConfiguration) throws KerberosOperationException { - setAdministratorCredential(administratorCredentials); - setDefaultRealm(realm); - if (kerberosConfiguration != null) { - setKeyEncryptionTypes(translateEncryptionTypes(kerberosConfiguration.get(KERBEROS_ENV_ENCRYPTION_TYPES), "\\s+")); - setAdminServerHost(kerberosConfiguration.get(KERBEROS_ENV_ADMIN_SERVER_HOST)); - setExecutableSearchPaths(kerberosConfiguration.get(KERBEROS_ENV_EXECUTABLE_SEARCH_PATHS)); - setCreateAttributes(kerberosConfiguration.get(KERBEROS_ENV_KDC_CREATE_ATTRIBUTES)); - } else { - setKeyEncryptionTypes(null); - setAdminServerHost(null); - setExecutableSearchPaths((String) null); - setCreateAttributes(null); + createAttributes = kerberosConfiguration.get(KERBEROS_ENV_KDC_CREATE_ATTRIBUTES); } // Pre-determine the paths to relevant Kerberos executables executableKadmin = getExecutable("kadmin"); - executableKadminLocal = getExecutable("kadmin.local"); - setOpen(true); + super.open(administratorCredentials, realm, kerberosConfiguration); } @Override public void close() throws KerberosOperationException { - // There is nothing to do here. - setOpen(false); - + createAttributes = null; executableKadmin = null; - executableKadminLocal = null; + + super.close(); } /** @@ -134,6 +103,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * the result from STDOUT to determine if the presence of the specified principal. * * @param principal a String containing the principal to test + * @param service a boolean value indicating whether the principal is for a service or not * @return true if the principal exists; false otherwise * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate @@ -141,26 +111,25 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @throws KerberosOperationException if an unexpected error occurred */ @Override - public boolean principalExists(String principal) + public boolean principalExists(String principal, boolean service) throws KerberosOperationException { if (!isOpen()) { throw new KerberosOperationException("This operation handler has not been opened"); } - if (principal == null) { - return false; - } else { + if (!StringUtils.isEmpty(principal)) { // Create the KAdmin query to execute: - ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal), null); + ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal)); // If there is data from STDOUT, see if the following string exists: // Principal: <principal> String stdOut = result.getStdout(); return (stdOut != null) && stdOut.contains(String.format("Principal: %s", principal)); } - } + return false; + } /** * Creates a new principal in a previously configured MIT KDC @@ -188,72 +157,25 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { if (StringUtils.isEmpty(principal)) { throw new KerberosOperationException("Failed to create new principal - no principal specified"); - } else if (StringUtils.isEmpty(password)) { - throw new KerberosOperationException("Failed to create new principal - no password specified"); - } else { - String createAttributes = getCreateAttributes(); - // Create the kdamin query: add_principal <-randkey|-pw <password>> [<options>] <principal> - ShellCommandUtil.Result result = invokeKAdmin(String.format("add_principal %s %s", - (createAttributes == null) ? "" : createAttributes, principal), password); - - // If there is data from STDOUT, see if the following string exists: - // Principal "<principal>" created - String stdOut = result.getStdout(); - String stdErr = result.getStderr(); - if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) { - return getKeyNumber(principal); - } else if ((stdErr != null) && stdErr.contains(String.format("Principal or policy already exists while creating \"%s\"", principal))) { - throw new KerberosPrincipalAlreadyExistsException(principal); - } else { - LOG.error("Failed to execute kadmin query: add_principal -pw \"********\" {} {}\nSTDOUT: {}\nSTDERR: {}", - (createAttributes == null) ? "" : createAttributes, principal, stdOut, result.getStderr()); - throw new KerberosOperationException(String.format("Failed to create service principal for %s\nSTDOUT: %s\nSTDERR: %s", - principal, stdOut, result.getStderr())); - } - } - } - - /** - * Updates the password for an existing principal in a previously configured MIT KDC - * <p/> - * This implementation creates a query to send to the kadmin shell command and then interrogates - * the exit code to determine if the operation executed successfully. - * - * @param principal a String containing the principal to update - * @param password a String containing the password to set - * @return an Integer declaring the new key number - * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made - * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate - * @throws KerberosRealmException if the realm does not map to a KDC - * @throws KerberosPrincipalDoesNotExistException if the principal does not exist - * @throws KerberosOperationException if an unexpected error occurred - */ - @Override - public Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException { - if (!isOpen()) { - throw new KerberosOperationException("This operation handler has not been opened"); } - if (StringUtils.isEmpty(principal)) { - throw new KerberosOperationException("Failed to set password - no principal specified"); - } else if (StringUtils.isEmpty(password)) { - throw new KerberosOperationException("Failed to set password - no password specified"); + // Create the kdamin query: add_principal <-randkey|-pw <password>> [<options>] <principal> + ShellCommandUtil.Result result = invokeKAdmin(String.format("add_principal -randkey %s %s", + (createAttributes == null) ? "" : createAttributes, principal)); + + // If there is data from STDOUT, see if the following string exists: + // Principal "<principal>" created + String stdOut = result.getStdout(); + String stdErr = result.getStderr(); + if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) { + return 0; + } else if ((stdErr != null) && stdErr.contains(String.format("Principal or policy already exists while creating \"%s\"", principal))) { + throw new KerberosPrincipalAlreadyExistsException(principal); } else { - // Create the kdamin query: change_password <-randkey|-pw <password>> <principal> - ShellCommandUtil.Result result = invokeKAdmin(String.format("change_password %s", principal), password); - - String stdOut = result.getStdout(); - String stdErr = result.getStderr(); - if ((stdOut != null) && stdOut.contains(String.format("Password for \"%s\" changed", principal))) { - return getKeyNumber(principal); - } else if ((stdErr != null) && stdErr.contains("Principal does not exist")) { - throw new KerberosPrincipalDoesNotExistException(principal); - } else { - LOG.error("Failed to execute kadmin query: change_password -pw \"********\" {} \nSTDOUT: {}\nSTDERR: {}", - principal, stdOut, result.getStderr()); - throw new KerberosOperationException(String.format("Failed to update password for %s\nSTDOUT: %s\nSTDERR: %s", - principal, stdOut, result.getStderr())); - } + LOG.error("Failed to execute kadmin query: add_principal -pw \"********\" {} {}\nSTDOUT: {}\nSTDERR: {}", + (createAttributes == null) ? "" : createAttributes, principal, stdOut, result.getStderr()); + throw new KerberosOperationException(String.format("Failed to create service principal for %s\nSTDOUT: %s\nSTDERR: %s", + principal, stdOut, result.getStderr())); } } @@ -263,6 +185,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * The implementation is specific to a particular type of KDC. * * @param principal a String containing the principal to remove + * @param service a boolean value indicating whether the principal is for a service or not * @return true if the principal was successfully removed; otherwise false * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate @@ -270,181 +193,63 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @throws KerberosOperationException if an unexpected error occurred */ @Override - public boolean removePrincipal(String principal) throws KerberosOperationException { + public boolean removePrincipal(String principal, boolean service) throws KerberosOperationException { if (!isOpen()) { throw new KerberosOperationException("This operation handler has not been opened"); } if (StringUtils.isEmpty(principal)) { - throw new KerberosOperationException("Failed to remove new principal - no principal specified"); - } else { - ShellCommandUtil.Result result = invokeKAdmin(String.format("delete_principal -force %s", principal), null); - - // If there is data from STDOUT, see if the following string exists: - // Principal "<principal>" created - String stdOut = result.getStdout(); - return (stdOut != null) && !stdOut.contains("Principal does not exist"); + throw new KerberosOperationException("Failed to remove principal - no principal specified"); } - } - /** - * Sets the KDC administrator server host address - * - * @param adminServerHost the ip address or FQDN of the KDC administrator server - */ - public void setAdminServerHost(String adminServerHost) { - this.adminServerHost = adminServerHost; - } + ShellCommandUtil.Result result = invokeKAdmin(String.format("delete_principal -force %s", principal)); - /** - * Gets the IP address or FQDN of the KDC administrator server - * - * @return the IP address or FQDN of the KDC administrator server - */ - public String getAdminServerHost() { - return this.adminServerHost; - } - - /** - * Sets the (additional) principal creation attributes - * - * @param createAttributes the additional principal creations attributes - */ - public void setCreateAttributes(String createAttributes) { - this.createAttributes = createAttributes; - } - - /** - * Gets the (additional) principal creation attributes - * - * @return the additional principal creations attributes or null - */ - public String getCreateAttributes() { - return createAttributes; - } - - /** - * Retrieves the current key number assigned to the identity identified by the specified principal - * - * @param principal a String declaring the principal to look up - * @return an Integer declaring the current key number - * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made - * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate - * @throws KerberosRealmException if the realm does not map to a KDC - * @throws KerberosOperationException if an unexpected error occurred - */ - private Integer getKeyNumber(String principal) throws KerberosOperationException { - if (!isOpen()) { - throw new KerberosOperationException("This operation handler has not been opened"); - } - - if (StringUtils.isEmpty(principal)) { - throw new KerberosOperationException("Failed to get key number for principal - no principal specified"); - } else { - // Create the kdamin query: get_principal <principal> - ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal), null); - - String stdOut = result.getStdout(); - if (stdOut == null) { - String message = String.format("Failed to get key number for %s:\n\tExitCode: %s\n\tSTDOUT: NULL\n\tSTDERR: %s", - principal, result.getExitCode(), result.getStderr()); - LOG.warn(message); - throw new KerberosOperationException(message); - } - - Matcher matcher = PATTERN_GET_KEY_NUMBER.matcher(stdOut); - if (matcher.matches()) { - NumberFormat numberFormat = NumberFormat.getIntegerInstance(); - String keyNumber = matcher.group(1); - - numberFormat.setGroupingUsed(false); - try { - Number number = numberFormat.parse(keyNumber); - return (number == null) ? 0 : number.intValue(); - } catch (ParseException e) { - String message = String.format("Failed to get key number for %s - invalid key number value (%s):\n\tExitCode: %s\n\tSTDOUT: NULL\n\tSTDERR: %s", - principal, keyNumber, result.getExitCode(), result.getStderr()); - LOG.warn(message); - throw new KerberosOperationException(message); - } - } else { - String message = String.format("Failed to get key number for %s - unexpected STDOUT data:\n\tExitCode: %s\n\tSTDOUT: NULL\n\tSTDERR: %s", - principal, result.getExitCode(), result.getStderr()); - LOG.warn(message); - throw new KerberosOperationException(message); - } - } + // If there is data from STDOUT, see if the following string exists: + // Principal "<principal>" created + String stdOut = result.getStdout(); + return (stdOut != null) && !stdOut.contains("Principal does not exist"); } /** * Invokes the kadmin shell command to issue queries * - * @param query a String containing the query to send to the kdamin command - * @param userPassword a String containing the user's password to set or update if necessary, - * null if not needed + * @param query a String containing the query to send to the kdamin command * @return a ShellCommandUtil.Result containing the result of the operation * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate * @throws KerberosRealmException if the realm does not map to a KDC * @throws KerberosOperationException if an unexpected error occurred */ - protected ShellCommandUtil.Result invokeKAdmin(String query, String userPassword) + protected ShellCommandUtil.Result invokeKAdmin(String query) throws KerberosOperationException { if (StringUtils.isEmpty(query)) { throw new KerberosOperationException("Missing kadmin query"); } - ShellCommandUtil.Result result = null; - PrincipalKeyCredential administratorCredential = getAdministratorCredential(); - String defaultRealm = getDefaultRealm(); + if (StringUtils.isEmpty(executableKadmin)) { + throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened."); + } List<String> command = new ArrayList<>(); + command.add(executableKadmin); - String adminPrincipal = (administratorCredential == null) - ? null - : administratorCredential.getPrincipal(); - - ShellCommandUtil.InteractiveHandler interactiveHandler = null; - - if (StringUtils.isEmpty(adminPrincipal)) { - // Set the kdamin interface to be kadmin.local - if (StringUtils.isEmpty(executableKadminLocal)) { - throw new KerberosOperationException("No path for kadmin.local is available - this KerberosOperationHandler may not have been opened."); - } - - command.add(executableKadminLocal); - - if (userPassword != null) { - interactiveHandler = new InteractivePasswordHandler(null, userPassword); - } - } else { - if (StringUtils.isEmpty(executableKadmin)) { - throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened."); - } - char[] adminPassword = administratorCredential.getKey(); - - // Set the kdamin interface to be kadmin - command.add(executableKadmin); - - // Add explicit KDC admin host, if available - if (!StringUtils.isEmpty(getAdminServerHost())) { - command.add("-s"); - command.add(getAdminServerHost()); - } - - // Add the administrative principal - command.add("-p"); - command.add(adminPrincipal); + // Add the credential cache, if available + String credentialCacheFilePath = getCredentialCacheFilePath(); + if (!StringUtils.isEmpty(credentialCacheFilePath)) { + command.add("-c"); + command.add(credentialCacheFilePath); + } - if (!ArrayUtils.isEmpty(adminPassword)) { - interactiveHandler = new InteractivePasswordHandler(String.valueOf(adminPassword), userPassword); - } else if (userPassword != null) { - interactiveHandler = new InteractivePasswordHandler(null, userPassword); - } + // Add explicit KDC admin host, if available + String adminSeverHost = getAdminServerHost(); + if (!StringUtils.isEmpty(adminSeverHost)) { + command.add("-s"); + command.add(adminSeverHost); } + // Add default realm clause, if available + String defaultRealm = getDefaultRealm(); if (!StringUtils.isEmpty(defaultRealm)) { - // Add default realm clause command.add("-r"); command.add(defaultRealm); } @@ -457,12 +262,13 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { LOG.debug("Executing: {}", command); } + ShellCommandUtil.Result result = null; int retryCount = configuration.getKerberosOperationRetries(); int tries = 0; while (tries <= retryCount) { try { - result = executeCommand(command.toArray(new String[command.size()]), null, interactiveHandler); + result = executeCommand(command.toArray(new String[command.size()])); } catch (KerberosOperationException exception) { if (tries == retryCount) { throw exception; @@ -486,13 +292,16 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { } - if (!result.isSuccessful()) { + if ((result == null) || !result.isSuccessful()) { + int exitCode = (result == null) ? -999 : result.getExitCode(); + String stdOut = (result == null) ? "" : result.getStdout(); + String stdErr = (result == null) ? "" : result.getStderr(); + String message = String.format("Failed to execute kadmin:\n\tCommand: %s\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s", - command, result.getExitCode(), result.getStdout(), result.getStderr()); + command, exitCode, stdOut, stdErr); LOG.warn(message); // Test STDERR to see of any "expected" error conditions were encountered... - String stdErr = result.getStderr(); // Did admin credentials fail? if (stdErr.contains("Client not found in Kerberos database")) { throw new KerberosAdminAuthenticationException(stdErr); @@ -513,57 +322,56 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { } else { throw new KerberosOperationException(String.format("Unexpected error condition executing the kadmin command. STDERR: %s", stdErr)); } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Executed the following command:\n{}\nSTDOUT: {}\nSTDERR: {}", + StringUtils.join(command, " "), result.getStdout(), result.getStderr()); + } } return result; } - /** - * InteractivePasswordHandler is a {@link org.apache.ambari.server.utils.ShellCommandUtil.InteractiveHandler} - * implementation that answers queries from kadmin or kdamin.local command for the admin and/or user - * passwords. - */ - protected static class InteractivePasswordHandler implements ShellCommandUtil.InteractiveHandler { - /** - * The queue of responses to return - */ - private LinkedList<String> responses; - private Queue<String> currentResponses; - - /** - * Constructor. - * - * @param adminPassword the KDC administrator's password (optional) - * @param userPassword the user's password (optional) - */ - public InteractivePasswordHandler(String adminPassword, String userPassword) { - responses = new LinkedList<>(); - - if (adminPassword != null) { - responses.offer(adminPassword); - } + @Override + protected String[] getKinitCommand(String executableKinit, PrincipalKeyCredential credentials, String credentialsCache) { + // kinit -c <path> -S kadmin/`hostname -f` <principal> + return new String[]{ + executableKinit, + "-c", + credentialsCache, + "-S", + String.format("kadmin/%s", getAdminServerHost()), + credentials.getPrincipal() + }; + } - if (userPassword != null) { - responses.offer(userPassword); - responses.offer(userPassword); // Add a 2nd time for the password "confirmation" request + @Override + protected void exportKeytabFile(String principal, String keytabFileDestinationPath, Set<EncryptionType> keyEncryptionTypes) throws KerberosOperationException { + String encryptionTypeSpec = null; + if (!CollectionUtils.isEmpty(keyEncryptionTypes)) { + StringBuilder encryptionTypeSpecBuilder = new StringBuilder(); + for (EncryptionType encryptionType : keyEncryptionTypes) { + if (encryptionTypeSpecBuilder.length() > 0) { + encryptionTypeSpecBuilder.append(','); + } + encryptionTypeSpecBuilder.append(encryptionType.getName()); + encryptionTypeSpecBuilder.append(":normal"); } - currentResponses = new LinkedList<>(responses); + encryptionTypeSpec = encryptionTypeSpecBuilder.toString(); } - @Override - public boolean done() { - return currentResponses.size() == 0; - } + String query = (StringUtils.isEmpty(encryptionTypeSpec)) + ? String.format("xst -k \"%s\" %s", keytabFileDestinationPath, principal) + : String.format("xst -k \"%s\" -e %s %s", keytabFileDestinationPath, encryptionTypeSpec, principal); - @Override - public String getResponse(String query) { - return currentResponses.poll(); - } + ShellCommandUtil.Result result = invokeKAdmin(query); - @Override - public void start() { - currentResponses = new LinkedList<>(responses); + if (!result.isSuccessful()) { + String message = String.format("Failed to export the keytab file for %s:\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s", + principal, result.getExitCode(), result.getStdout(), result.getStderr()); + LOG.warn(message); + throw new KerberosOperationException(message); } } }
http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java index bfe2a13..d3e924e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java @@ -45,6 +45,7 @@ import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.Config; import org.apache.ambari.server.state.ConfigHelper; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -149,6 +150,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog { showHcatDeletedUserMessage(); setStatusOfStagesAndRequests(); updateLogSearchConfigs(); + updateKerberosConfigurations(); } protected void showHcatDeletedUserMessage() { @@ -265,7 +267,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog { "logsearch-common-properties", Collections.emptyMap(), "ambari-upgrade", String.format("Updated logsearch-common-properties during Ambari Upgrade from %s to %s", getSourceVersion(), getTargetVersion())); - + String defaultLogLevels = logSearchProperties.getProperties().get("logsearch.logfeeder.include.default.level"); Set<String> removeProperties = Sets.newHashSet("logsearch.logfeeder.include.default.level"); @@ -324,7 +326,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog { updateConfigurationPropertiesForCluster(cluster, "logsearch-audit_logs-solrconfig", Collections.singletonMap("content", content), true, true); } } - + Config logFeederOutputConfig = cluster.getDesiredConfigByType("logfeeder-output-config"); if (logFeederOutputConfig != null) { String content = logFeederOutputConfig.getProperties().get("content"); @@ -346,4 +348,28 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog { } } } + + protected void updateKerberosConfigurations() throws AmbariException { + AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class); + Clusters clusters = ambariManagementController.getClusters(); + if (clusters != null) { + Map<String, Cluster> clusterMap = clusters.getClusters(); + + if (!MapUtils.isEmpty(clusterMap)) { + for (Cluster cluster : clusterMap.values()) { + Config config = cluster.getDesiredConfigByType("kerberos-env"); + + if (config != null) { + Map<String, String> properties = config.getProperties(); + if (properties.containsKey("group")) { + // Covert kerberos-env/group to kerberos-env/ipa_user_group + updateConfigurationPropertiesForCluster(cluster, "kerberos-env", + Collections.singletonMap("ipa_user_group", properties.get("group")), Collections.singleton("group"), + true, false); + } + } + } + } + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/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 0a08121..293bcf8 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 @@ -349,8 +349,8 @@ <on-ambari-upgrade add="true"/> </property> <property> - <name>group</name> - <display-name>IPA Group</display-name> + <name>ipa_user_group</name> + <display-name>IPA User Group</display-name> <description> The group in IPA user principals should be member of </description> @@ -362,38 +362,6 @@ <on-ambari-upgrade add="true"/> </property> <property> - <name>set_password_expiry</name> - <display-name>Set IPA principal password expiry</display-name> - <description> - Indicates whether Ambari should set the password expiry for the principals it creates. By default - IPA does not allow this. It requires write permission of the admin principal to the krbPasswordExpiry - attribute. If set IPA principal password expiry is not true it is assumed that a suitable password - policy is in place for the IPA Group principals are added to. - </description> - <value>false</value> - <value-attributes> - <type>boolean</type> - <overridable>false</overridable> - <visible>false</visible> - </value-attributes> - <on-ambari-upgrade add="true"/> - </property> - <property> - <name>password_chat_timeout</name> - <display-name>Set IPA kinit password chat timeout</display-name> - <description> - Indicates the timeout in seconds that Ambari should wait for a response during a password chat. This is - because it can take some time due to lookups before a response is there. - </description> - <value>5</value> - <value-attributes> - <visible>false</visible> - <type>int</type> - <overridable>false</overridable> - </value-attributes> - <on-ambari-upgrade add="true"/> - </property> - <property> <name>preconfigure_services</name> <display-name>Pre-configure services</display-name> <description> http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/configuration/kerberos-env.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/configuration/kerberos-env.xml b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/configuration/kerberos-env.xml index 0a08121..293bcf8 100644 --- a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/configuration/kerberos-env.xml +++ b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/configuration/kerberos-env.xml @@ -349,8 +349,8 @@ <on-ambari-upgrade add="true"/> </property> <property> - <name>group</name> - <display-name>IPA Group</display-name> + <name>ipa_user_group</name> + <display-name>IPA User Group</display-name> <description> The group in IPA user principals should be member of </description> @@ -362,38 +362,6 @@ <on-ambari-upgrade add="true"/> </property> <property> - <name>set_password_expiry</name> - <display-name>Set IPA principal password expiry</display-name> - <description> - Indicates whether Ambari should set the password expiry for the principals it creates. By default - IPA does not allow this. It requires write permission of the admin principal to the krbPasswordExpiry - attribute. If set IPA principal password expiry is not true it is assumed that a suitable password - policy is in place for the IPA Group principals are added to. - </description> - <value>false</value> - <value-attributes> - <type>boolean</type> - <overridable>false</overridable> - <visible>false</visible> - </value-attributes> - <on-ambari-upgrade add="true"/> - </property> - <property> - <name>password_chat_timeout</name> - <display-name>Set IPA kinit password chat timeout</display-name> - <description> - Indicates the timeout in seconds that Ambari should wait for a response during a password chat. This is - because it can take some time due to lookups before a response is there. - </description> - <value>5</value> - <value-attributes> - <visible>false</visible> - <type>int</type> - <overridable>false</overridable> - </value-attributes> - <on-ambari-upgrade add="true"/> - </property> - <property> <name>preconfigure_services</name> <display-name>Pre-configure services</display-name> <description> http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/main/resources/stacks/PERF/1.0/services/KERBEROS/configuration/kerberos-env.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/PERF/1.0/services/KERBEROS/configuration/kerberos-env.xml b/ambari-server/src/main/resources/stacks/PERF/1.0/services/KERBEROS/configuration/kerberos-env.xml index 66e81db..a66a7a6 100644 --- a/ambari-server/src/main/resources/stacks/PERF/1.0/services/KERBEROS/configuration/kerberos-env.xml +++ b/ambari-server/src/main/resources/stacks/PERF/1.0/services/KERBEROS/configuration/kerberos-env.xml @@ -348,8 +348,8 @@ <on-ambari-upgrade add="true"/> </property> <property> - <name>group</name> - <display-name>IPA Group</display-name> + <name>ipa_user_group</name> + <display-name>IPA User Group</display-name> <description> The group in IPA user principals should be member of </description> @@ -360,36 +360,4 @@ </value-attributes> <on-ambari-upgrade add="true"/> </property> - <property> - <name>set_password_expiry</name> - <display-name>Set IPA principal password expiry</display-name> - <description> - Indicates whether Ambari should set the password expiry for the principals it creates. By default - IPA does not allow this. It requires write permission of the admin principal to the krbPasswordExpiry - attribute. If set IPA principal password expiry is not true it is assumed that a suitable password - policy is in place for the IPA Group principals are added to. - </description> - <value>false</value> - <value-attributes> - <type>boolean</type> - <overridable>false</overridable> - <visible>false</visible> - </value-attributes> - <on-ambari-upgrade add="true"/> - </property> - <property> - <name>password_chat_timeout</name> - <display-name>Set IPA kinit password chat timeout</display-name> - <description> - Indicates the timeout in seconds that Ambari should wait for a response during a password chat. This is - because it can take some time due to lookups before a response is there. - </description> - <value>5</value> - <value-attributes> - <visible>false</visible> - <type>int</type> - <overridable>false</overridable> - </value-attributes> - <on-ambari-upgrade add="true"/> - </property> </configuration> http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java index a3074ae..ee87d24 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java @@ -188,7 +188,7 @@ public class KerberosHelperTest extends EasyMockSupport { } @Override - public boolean principalExists(String principal) throws KerberosOperationException { + public boolean principalExists(String principal, boolean service) throws KerberosOperationException { return "principal".equals(principal); } @@ -198,12 +198,12 @@ public class KerberosHelperTest extends EasyMockSupport { } @Override - public Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException { + public Integer setPrincipalPassword(String principal, String password, boolean service) throws KerberosOperationException { return null; } @Override - public boolean removePrincipal(String principal) throws KerberosOperationException { + public boolean removePrincipal(String principal, boolean service) throws KerberosOperationException { return false; } http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/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 483cc0a..8b3c19a 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 @@ -19,11 +19,15 @@ package org.apache.ambari.server.serveraction.kerberos; import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.anyString; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isNull; import static org.easymock.EasyMock.newCapture; import static org.easymock.EasyMock.replay; +import java.lang.reflect.Method; import java.nio.charset.Charset; import java.util.HashMap; import java.util.List; @@ -50,6 +54,8 @@ import org.apache.ambari.server.state.stack.OsFamily; import org.easymock.Capture; import org.easymock.CaptureType; import org.easymock.IAnswer; +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -65,6 +71,36 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest private static final String DEFAULT_LDAP_URL = "ldaps://10.0.100.4"; private static final String DEFAULT_PRINCIPAL_CONTAINER_DN = "ou=HDP,DC=HDP01,DC=LOCAL"; private static final String DEFAULT_REALM = "HDP01.LOCAL"; + private static final Map<String, String> KERBEROS_ENV_MAP = new HashMap<String, String>() { + { + put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); + put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); + } + }; + + private static Method methodCreateInitialLdapContext; + + private Injector injector; + private LdapContext ldapContext; + + @BeforeClass + public static void beforeMITKerberosOperationHandlerTest() throws Exception { + methodCreateInitialLdapContext = ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class); + } + + @Before + public void setup() { + injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(Clusters.class).toInstance(createNiceMock(Clusters.class)); + bind(Configuration.class).toInstance(createNiceMock(Configuration.class)); + bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class)); + } + }); + + ldapContext = createMock(LdapContext.class); + } @Test(expected = KerberosKDCConnectionException.class) public void testOpenExceptionLdapUrlNotProvided() throws Exception { @@ -95,13 +131,8 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest @Test(expected = KerberosAdminAuthenticationException.class) public void testOpenExceptionAdminCredentialsNotProvided() throws Exception { KerberosOperationHandler handler = new ADKerberosOperationHandler(); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - } - }; - handler.open(null, DEFAULT_REALM, kerberosEnvMap); + + handler.open(null, DEFAULT_REALM, getKerberosEnv()); handler.close(); } @@ -124,13 +155,6 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest Injector injector = getInjector(); PrincipalKeyCredential kc = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, "wrong"); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - } - }; - ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) .createNiceMock(); @@ -145,7 +169,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest replayAll(); - handler.open(kc, DEFAULT_REALM, kerberosEnvMap); + handler.open(kc, DEFAULT_REALM, getKerberosEnv()); handler.testAdministratorCredentials(); handler.close(); } @@ -155,12 +179,6 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest Injector injector = getInjector(); PrincipalKeyCredential kc = new PrincipalKeyCredential("wrong", DEFAULT_ADMIN_PASSWORD); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - } - }; ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) @@ -176,7 +194,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest replayAll(); - handler.open(kc, DEFAULT_REALM, kerberosEnvMap); + handler.open(kc, DEFAULT_REALM, getKerberosEnv()); handler.testAdministratorCredentials(); handler.close(); } @@ -184,17 +202,8 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest @Test(expected = KerberosKDCConnectionException.class) public void testTestAdministratorCredentialsKDCConnectionException() throws Exception { PrincipalKeyCredential kc = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, "invalid"); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - } - }; - - ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) - .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) - .createNiceMock(); + ADKerberosOperationHandler handler = createMockedHandler(methodCreateInitialLdapContext); expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class))).andAnswer(new IAnswer<LdapContext>() { @Override public LdapContext answer() throws Throwable { @@ -204,7 +213,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest replayAll(); - handler.open(kc, DEFAULT_REALM, kerberosEnvMap); + handler.open(kc, DEFAULT_REALM, getKerberosEnv()); handler.testAdministratorCredentials(); handler.close(); } @@ -212,21 +221,8 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest @Test public void testTestAdministratorCredentialsSuccess() throws Exception { - Injector injector = getInjector(); - PrincipalKeyCredential kc = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - } - }; - - ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) - .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) - .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createSearchControls")) - .createNiceMock(); - injector.injectMembers(handler); + ADKerberosOperationHandler handler = createMockedHandler(methodCreateInitialLdapContext); expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class))) .andAnswer(new IAnswer<LdapContext>() { @@ -245,23 +241,14 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest } }) .once(); - replay(ldapContext); return ldapContext; } }) .once(); - expect(handler.createSearchControls()).andAnswer(new IAnswer<SearchControls>() { - @Override - public SearchControls answer() throws Throwable { - SearchControls searchControls = createNiceMock(SearchControls.class); - replay(searchControls); - return searchControls; - } - }).once(); replayAll(); - handler.open(kc, DEFAULT_REALM, kerberosEnvMap); + handler.open(kc, DEFAULT_REALM, getKerberosEnv()); handler.testAdministratorCredentials(); handler.close(); } @@ -271,12 +258,6 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest Injector injector = getInjector(); PrincipalKeyCredential kc = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - } - }; Capture<Name> capturedName = newCapture(CaptureType.ALL); Capture<Attributes> capturedAttributes = newCapture(CaptureType.ALL); @@ -315,7 +296,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest replayAll(); - handler.open(kc, DEFAULT_REALM, kerberosEnvMap); + handler.open(kc, DEFAULT_REALM, getKerberosEnv()); handler.createPrincipal("nn/c6501.ambari.apache.org", "secret", true); handler.createPrincipal("hdfs@" + DEFAULT_REALM, "secret", false); handler.close(); @@ -384,31 +365,26 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest Injector injector = getInjector(); PrincipalKeyCredential kc = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD); - Map<String, String> kerberosEnvMap = new HashMap<String, String>() { - { - put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - put(ADKerberosOperationHandler.KERBEROS_ENV_AD_CREATE_ATTRIBUTES_TEMPLATE, "" + - "#set( $user = \"${principal_primary}-${principal_digest}\" )" + - "{" + - " \"objectClass\": [" + - " \"top\"," + - " \"person\"," + - " \"organizationalPerson\"," + - " \"user\"" + - " ]," + - " \"cn\": \"$user\"," + - " \"sAMAccountName\": \"$user.substring(0,20)\"," + - " #if( $is_service )" + - " \"servicePrincipalName\": \"$principal_name\"," + - " #end" + - " \"userPrincipalName\": \"$normalized_principal\"," + - " \"unicodePwd\": \"$password\"," + - " \"accountExpires\": \"0\"," + - " \"userAccountControl\": \"66048\"" + - "}"); - } - }; + Map<String, String> kerberosEnvMap = new HashMap<>(getKerberosEnv()); + kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_AD_CREATE_ATTRIBUTES_TEMPLATE, "" + + "#set( $user = \"${principal_primary}-${principal_digest}\" )" + + "{" + + " \"objectClass\": [" + + " \"top\"," + + " \"person\"," + + " \"organizationalPerson\"," + + " \"user\"" + + " ]," + + " \"cn\": \"$user\"," + + " \"sAMAccountName\": \"$user.substring(0,20)\"," + + " #if( $is_service )" + + " \"servicePrincipalName\": \"$principal_name\"," + + " #end" + + " \"userPrincipalName\": \"$normalized_principal\"," + + " \"unicodePwd\": \"$password\"," + + " \"accountExpires\": \"0\"," + + " \"userAccountControl\": \"66048\"" + + "}"); Capture<Name> capturedName = newCapture(); Capture<Attributes> capturedAttributes = newCapture(); @@ -491,9 +467,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest Injector injector = getInjector(); PrincipalKeyCredential kc = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD); - Map<String, String> kerberosEnvMap = new HashMap<>(); - kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); + Map<String, String> kerberosEnvMap = new HashMap<>(getKerberosEnv()); kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_AD_CREATE_ATTRIBUTES_TEMPLATE, "" + "{" + "\"principal_digest\": \"$principal_digest\"," + @@ -596,7 +570,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest System.out.println("Test Admin Credentials: " + handler.testAdministratorCredentials()); // does the principal already exist? - System.out.println("Principal exists: " + handler.principalExists("nn/c1508.ambari.apache.org")); + System.out.println("Principal exists: " + handler.principalExists("nn/c1508.ambari.apache.org", true)); handler.close(); @@ -605,15 +579,15 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest String evaluatedPrincipal; evaluatedPrincipal = "nn/c6501.ambari.apache.org@" + DEFAULT_REALM; - if (handler.principalExists(evaluatedPrincipal)) { - handler.setPrincipalPassword(evaluatedPrincipal, "some password"); + if (handler.principalExists(evaluatedPrincipal, true)) { + handler.setPrincipalPassword(evaluatedPrincipal, "some password", true); } else { handler.createPrincipal(evaluatedPrincipal, "some password", true); } evaluatedPrincipal = "hdfs@" + DEFAULT_REALM; - if (handler.principalExists(evaluatedPrincipal)) { - handler.setPrincipalPassword(evaluatedPrincipal, "some password"); + if (handler.principalExists(evaluatedPrincipal, false)) { + handler.setPrincipalPassword(evaluatedPrincipal, "some password", false); } else { handler.createPrincipal(evaluatedPrincipal, "some password", true); } @@ -644,14 +618,14 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest handler.open(credentials, realm, kerberosEnvMap); // remove the principal - handler.removePrincipal("abcdefg"); - handler.removePrincipal("abcdefg/c1509.ambari.apache.org@" + DEFAULT_REALM); + handler.removePrincipal("abcdefg", false); + handler.removePrincipal("abcdefg/c1509.ambari.apache.org@" + DEFAULT_REALM, true); 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, "some password"); + handler.setPrincipalPassword("abcdefg/c1509.ambari.apache.org@" + DEFAULT_REALM, "some password", true); handler.close(); } @@ -687,11 +661,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest replayAll(); - Map<String, String> kerberosConfiguration = new HashMap<>(); - kerberosConfiguration.put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL); - kerberosConfiguration.put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN); - - handler.open(new PrincipalKeyCredential("principal", "key"), "EXAMPLE.COM", kerberosConfiguration); + handler.open(new PrincipalKeyCredential("principal", "key"), "EXAMPLE.COM", getKerberosEnv()); Properties properties = capturedProperties.getValue(); Assert.assertNotNull(properties); @@ -705,13 +675,78 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest } private Injector getInjector() { - return Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Clusters.class).toInstance(createNiceMock(Clusters.class)); - bind(Configuration.class).toInstance(createNiceMock(Configuration.class)); - bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class)); - } - }); + return injector; + } + + @Override + protected KerberosOperationHandler createMockedHandler() throws KerberosOperationException { + return createMockedHandler(methodCreateInitialLdapContext); + } + + + private ADKerberosOperationHandler createMockedHandler(Method... mockedMethods) { + ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) + .addMockedMethods(mockedMethods) + .createMock(); + injector.injectMembers(handler); + return handler; + } + + + @Override + protected void setupOpenSuccess(KerberosOperationHandler handler) throws Exception { + + ADKerberosOperationHandler adHandler = (ADKerberosOperationHandler) handler; + + expect(adHandler.createInitialLdapContext(anyObject(Properties.class), isNull())).andReturn(ldapContext).anyTimes(); + } + + @Override + protected void setupOpenFailure(KerberosOperationHandler handler) throws Exception { + ADKerberosOperationHandler adHandler = (ADKerberosOperationHandler) handler; + expect(adHandler.createInitialLdapContext(anyObject(Properties.class), isNull())).andThrow(new AuthenticationException("Bogus error!")).anyTimes(); + } + + @Override + protected void setupPrincipalAlreadyExists(KerberosOperationHandler handler, boolean service) throws Exception { + setupPrincipalExists(handler, service); + } + + @Override + protected void setupPrincipalDoesNotExist(KerberosOperationHandler handler, boolean service) throws Exception { + NamingEnumeration<SearchResult> results = createMock(NamingEnumeration.class); + results.close(); + expectLastCall().once(); + expect(results.hasMore()).andReturn(false).anyTimes(); + + expect(ldapContext.search(anyObject(Name.class), anyString(), anyObject(SearchControls.class))) + .andReturn(results) + .anyTimes(); + ldapContext.close(); + expectLastCall().once(); + } + + @Override + protected void setupPrincipalExists(KerberosOperationHandler handler, boolean service) throws Exception { + SearchResult result = createMock(SearchResult.class); + expect(result.getNameInNamespace()).andReturn("user/service dn").anyTimes(); + + NamingEnumeration<SearchResult> results = createMock(NamingEnumeration.class); + results.close(); + expectLastCall().anyTimes(); + expect(results.hasMore()).andReturn(true).once(); + expect(results.next()).andReturn(result).once(); + expect(results.hasMore()).andReturn(false).anyTimes(); + + expect(ldapContext.search(anyObject(Name.class), anyString(), anyObject(SearchControls.class))) + .andReturn(results) + .anyTimes(); + ldapContext.close(); + expectLastCall().once(); + } + + @Override + protected Map<String, String> getKerberosEnv() { + return KERBEROS_ENV_MAP; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/IPAKerberosOperationHandlerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/IPAKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/IPAKerberosOperationHandlerTest.java index f2a09ba..558ca79 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/IPAKerberosOperationHandlerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/IPAKerberosOperationHandlerTest.java @@ -18,36 +18,26 @@ package org.apache.ambari.server.serveraction.kerberos; +import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.configuration.Configuration; -import org.apache.ambari.server.security.credential.PrincipalKeyCredential; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.stack.OsFamily; +import org.apache.ambari.server.utils.ShellCommandUtil; import org.easymock.EasyMock; import org.junit.BeforeClass; -import org.junit.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; -import junit.framework.Assert; - -public class IPAKerberosOperationHandlerTest extends KerberosOperationHandlerTest { - private static final String DEFAULT_ADMIN_PRINCIPAL = "admin"; - private static final String DEFAULT_ADMIN_PASSWORD = "Hadoop12345"; - - private static final String DEFAULT_REALM = "IPA01.LOCAL"; - - private static Injector injector; - - private static boolean hasIpa = false; +public class IPAKerberosOperationHandlerTest extends KDCKerberosOperationHandlerTest { private static final Map<String, String> KERBEROS_ENV_MAP = new HashMap<String, String>() { { @@ -58,8 +48,10 @@ public class IPAKerberosOperationHandlerTest extends KerberosOperationHandlerTes } }; + private static Injector injector; + @BeforeClass - public static void beforeClass() throws AmbariException { + public static void beforeIPAKerberosOperationHandlerTest() throws Exception { injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { @@ -72,85 +64,74 @@ public class IPAKerberosOperationHandlerTest extends KerberosOperationHandlerTes bind(OsFamily.class).toInstance(EasyMock.createNiceMock(OsFamily.class)); } }); - if (System.getenv("HAS_IPA") != null) { - hasIpa = true; - } } - @Test - public void testSetPrincipalPasswordExceptions() throws Exception { - if (!hasIpa) { - return; - } + @Override + protected IPAKerberosOperationHandler createMockedHandler(Method... mockedMethods) { + IPAKerberosOperationHandler handler = createMockBuilder(IPAKerberosOperationHandler.class) + .addMockedMethods(mockedMethods) + .createMock(); + injector.injectMembers(handler); + return handler; + } - IPAKerberosOperationHandler handler = injector.getInstance(IPAKerberosOperationHandler.class); - handler.open(new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD), DEFAULT_REALM, KERBEROS_ENV_MAP); - try { - handler.setPrincipalPassword(DEFAULT_ADMIN_PRINCIPAL, null); - Assert.fail("KerberosOperationException not thrown for null password"); - } catch (Throwable t) { - Assert.assertEquals(KerberosOperationException.class, t.getClass()); - } + @Override + protected Map<String, String> getKerberosEnv() { + return KERBEROS_ENV_MAP; + } - try { - handler.setPrincipalPassword(DEFAULT_ADMIN_PRINCIPAL, ""); - Assert.fail("KerberosOperationException not thrown for empty password"); - handler.createPrincipal("", "1234", false); - Assert.fail("AmbariException not thrown for empty principal"); - } catch (Throwable t) { - Assert.assertEquals(KerberosOperationException.class, t.getClass()); + @Override + protected void setupPrincipalAlreadyExists(KerberosOperationHandler handler, boolean service) throws Exception { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + expect(result.getExitCode()).andReturn(1).anyTimes(); + expect(result.isSuccessful()).andReturn(false).anyTimes(); + if(service) { + expect(result.getStderr()).andReturn("ipa: ERROR: service with name \"service/[email protected]\" already exists").anyTimes(); } - - try { - handler.setPrincipalPassword(null, DEFAULT_ADMIN_PASSWORD); - Assert.fail("KerberosOperationException not thrown for null principal"); - } catch (Throwable t) { - Assert.assertEquals(KerberosOperationException.class, t.getClass()); + else { + expect(result.getStderr()).andReturn("ipa: ERROR: user with name \"user\" already exists").anyTimes(); } + expect(result.getStdout()).andReturn("").anyTimes(); - try { - handler.setPrincipalPassword("", DEFAULT_ADMIN_PASSWORD); - Assert.fail("KerberosOperationException not thrown for empty principal"); - } catch (Throwable t) { - Assert.assertEquals(KerberosOperationException.class, t.getClass()); - } + expect(handler.executeCommand(arrayContains(new String[]{"ipa", (service) ? "service-add" : "user-add"}), anyObject(Map.class), anyObject(KDCKerberosOperationHandler.InteractivePasswordHandler.class))) + .andReturn(result) + .anyTimes(); } - @Test - public void testCreateServicePrincipal_Exceptions() throws Exception { - if (!hasIpa) { - return; - } - - IPAKerberosOperationHandler handler = new IPAKerberosOperationHandler(); - handler.open(new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD), DEFAULT_REALM, KERBEROS_ENV_MAP); + @Override + protected void setupPrincipalDoesNotExist(KerberosOperationHandler handler, boolean service) throws Exception { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + expect(result.getExitCode()).andReturn(2).anyTimes(); + expect(result.isSuccessful()).andReturn(false).anyTimes(); + expect(result.getStderr()).andReturn(String.format("ipa: ERROR: %s: user not found", (service) ? "service/host" : "user")).anyTimes(); + expect(result.getStdout()).andReturn("").anyTimes(); - try { - handler.createPrincipal(DEFAULT_ADMIN_PRINCIPAL, null, false); - Assert.fail("KerberosOperationException not thrown for null password"); - } catch (Throwable t) { - Assert.fail("KerberosOperationException thrown on null password with IPA"); - } - try { - handler.createPrincipal(DEFAULT_ADMIN_PRINCIPAL, "", false); - } catch (Throwable t) { - Assert.fail("KerberosOperationException thrown for empty password"); - } - - try { - handler.createPrincipal(null, DEFAULT_ADMIN_PASSWORD, false); - Assert.fail("KerberosOperationException not thrown for null principal"); - } catch (Throwable t) { - Assert.assertEquals(KerberosOperationException.class, t.getClass()); - } - - try { - handler.createPrincipal("", DEFAULT_ADMIN_PASSWORD, false); - Assert.fail("KerberosOperationException not thrown for empty principal"); - } catch (Throwable t) { - Assert.assertEquals(KerberosOperationException.class, t.getClass()); - } + expect(handler.executeCommand(arrayContains(new String[]{"ipa", (service) ? "service-show" : "user-show"}), anyObject(Map.class), anyObject(KDCKerberosOperationHandler.InteractivePasswordHandler.class))) + .andReturn(result) + .anyTimes(); } + @Override + protected void setupPrincipalExists(KerberosOperationHandler handler, boolean service) throws Exception { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + expect(result.getExitCode()).andReturn(0).anyTimes(); + expect(result.isSuccessful()).andReturn(true).anyTimes(); + expect(result.getStderr()).andReturn("").anyTimes(); + expect(result.getStdout()).andReturn(String.format(" User login: %s\n" + + " Last name: User\n" + + " Home directory: /home/user\n" + + " Login shell: /bin/bash\n" + + " Principal alias: [email protected]\n" + + " UID: 324200000\n" + + " GID: 324200000\n" + + " Account disabled: False\n" + + " Password: True\n" + + " Member of groups: users\n" + + " Kerberos keys available: True", (service) ? "service/host" : "user")).anyTimes(); + + expect(handler.executeCommand(arrayContains(new String[]{"ipa", (service) ? "service-show" : "user-show"}), anyObject(Map.class), anyObject(KDCKerberosOperationHandler.InteractivePasswordHandler.class))) + .andReturn(result) + .anyTimes(); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KDCKerberosOperationHandlerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KDCKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KDCKerberosOperationHandlerTest.java new file mode 100644 index 0000000..271c787 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KDCKerberosOperationHandlerTest.java @@ -0,0 +1,152 @@ +/* + * 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.serveraction.kerberos; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.expect; + +import java.lang.reflect.Method; +import java.util.Map; + +import org.apache.ambari.server.utils.ShellCommandUtil; +import org.apache.commons.lang.StringUtils; +import org.easymock.EasyMock; +import org.easymock.IArgumentMatcher; +import org.junit.BeforeClass; +import org.junit.Test; + +import junit.framework.Assert; + +abstract public class KDCKerberosOperationHandlerTest extends KerberosOperationHandlerTest { + + static Method methodExecuteCommand; + + @BeforeClass + public static void beforeKDCKerberosOperationHandlerTest() throws Exception { + methodExecuteCommand = KDCKerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class, Map.class, ShellCommandUtil.InteractiveHandler.class); + } + + @Test + public void testInteractivePasswordHandler() { + KDCKerberosOperationHandler.InteractivePasswordHandler handler = new KDCKerberosOperationHandler.InteractivePasswordHandler("admin_password", "user_password"); + + handler.start(); + Assert.assertEquals("admin_password", handler.getResponse("password")); + Assert.assertFalse(handler.done()); + Assert.assertEquals("user_password", handler.getResponse("password")); + Assert.assertFalse(handler.done()); + Assert.assertEquals("user_password", handler.getResponse("password")); + Assert.assertTrue(handler.done()); + + // Test restarting + handler.start(); + Assert.assertEquals("admin_password", handler.getResponse("password")); + Assert.assertFalse(handler.done()); + Assert.assertEquals("user_password", handler.getResponse("password")); + Assert.assertFalse(handler.done()); + Assert.assertEquals("user_password", handler.getResponse("password")); + Assert.assertTrue(handler.done()); + } + + @Override + protected KerberosOperationHandler createMockedHandler() throws KerberosOperationException { + return createMockedHandler(methodExecuteCommand); + } + + @Override + protected void setupOpenSuccess(KerberosOperationHandler handler) throws Exception { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + expect(result.isSuccessful()).andReturn(true); + + expect(handler.executeCommand(arrayContains("/usr/bin/kinit"), anyObject(Map.class), anyObject(KDCKerberosOperationHandler.InteractivePasswordHandler.class))) + .andReturn(result) + .anyTimes(); + } + + @Override + protected void setupOpenFailure(KerberosOperationHandler handler) throws Exception { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + expect(result.isSuccessful()).andReturn(false).once(); + expect(result.getExitCode()).andReturn(-1).once(); + expect(result.getStdout()).andReturn("STDOUT data").once(); + expect(result.getStderr()).andReturn("STDERR data").once(); + + expect(handler.executeCommand(arrayContains("/usr/bin/kinit"), anyObject(Map.class), anyObject(KDCKerberosOperationHandler.InteractivePasswordHandler.class))) + .andReturn(result) + .anyTimes(); + } + + protected abstract KDCKerberosOperationHandler createMockedHandler(Method... mockedMethods); + + public static class ArrayContains implements IArgumentMatcher { + + private String[] startItems; + + ArrayContains(String startItem) { + this.startItems = new String[]{startItem}; + } + + ArrayContains(String[] startItems) { + this.startItems = startItems; + } + + @Override + public boolean matches(Object o) { + if (o instanceof String[]) { + String[] array = (String[]) o; + + for (String item : startItems) { + boolean valueContains = false; + for (String value : array) { + if (value.contains(item)) { + valueContains = true; + break; + } + } + + if (!valueContains) { + return false; + } + } + + return true; + } + + return false; + } + + @Override + public void appendTo(StringBuffer stringBuffer) { + stringBuffer.append("arrayContains("); + stringBuffer.append(StringUtils.join(startItems, ", ")); + stringBuffer.append("\")"); + } + } + + static String[] arrayContains(String in) { + EasyMock.reportMatcher(new ArrayContains(in)); + return null; + } + + static String[] arrayContains(String[] in) { + EasyMock.reportMatcher(new ArrayContains(in)); + return null; + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/f844e5f3/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 88c841c..9d1e8e0 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 @@ -40,10 +40,128 @@ import junit.framework.Assert; public abstract class KerberosOperationHandlerTest extends EasyMockSupport { + static final String DEFAULT_ADMIN_PRINCIPAL = "admin"; + static final String DEFAULT_ADMIN_PASSWORD = "hadoop"; + static final String DEFAULT_REALM = "EXAMPLE.COM"; + static final PrincipalKeyCredential DEFAULT_ADMIN_CREDENTIALS = new PrincipalKeyCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD); + @Rule public TemporaryFolder folder = new TemporaryFolder(); @Test + public void testOpenSucceeded() throws Exception { + KerberosOperationHandler handler = createMockedHandler(); + + setupOpenSuccess(handler); + + replayAll(); + + handler.open(getAdminCredentials(), DEFAULT_REALM, getKerberosEnv()); + + verifyAll(); + + Assert.assertTrue(handler.isOpen()); + } + + @Test + public void testOpenFailed() throws Exception { + KerberosOperationHandler handler = createMockedHandler(); + + setupOpenFailure(handler); + + replayAll(); + + try { + handler.open(getAdminCredentials(), DEFAULT_REALM, getKerberosEnv()); + Assert.fail("KerberosAdminAuthenticationException expected"); + } catch (KerberosAdminAuthenticationException e) { + // This is expected + } + + verifyAll(); + + Assert.assertFalse(handler.isOpen()); + } + + @Test(expected = KerberosPrincipalAlreadyExistsException.class) + public void testCreateUserPrincipalPrincipalAlreadyExists() throws Exception { + testCreatePrincipalPrincipalAlreadyExists(false); + } + + @Test(expected = KerberosPrincipalAlreadyExistsException.class) + public void testCreateServicePrincipalPrincipalAlreadyExists() throws Exception { + testCreatePrincipalPrincipalAlreadyExists(true); + } + + private void testCreatePrincipalPrincipalAlreadyExists(boolean service) throws Exception { + KerberosOperationHandler handler = createMockedHandler(); + + setupOpenSuccess(handler); + setupPrincipalAlreadyExists(handler, service); + + replayAll(); + + handler.open(getAdminCredentials(), DEFAULT_REALM, getKerberosEnv()); + handler.createPrincipal(createPrincipal(service), "password", service); + handler.close(); + + verifyAll(); + + } + + + @Test + public void testUserPrincipalExistsNotFound() throws Exception { + testPrincipalExistsNotFound(false); + } + + @Test + public void testServicePrincipalExistsNotFound() throws Exception { + testPrincipalExistsNotFound(true); + } + + private void testPrincipalExistsNotFound(boolean service) throws Exception { + KerberosOperationHandler handler = createMockedHandler(); + + setupOpenSuccess(handler); + setupPrincipalDoesNotExist(handler, service); + + replayAll(); + + handler.open(getAdminCredentials(), DEFAULT_REALM, getKerberosEnv()); + Assert.assertFalse(handler.principalExists(createPrincipal(service), service)); + handler.close(); + + verifyAll(); + } + + @Test + public void testUserPrincipalExistsFound() throws Exception { + testPrincipalExistsFound(false); + } + + @Test + public void testServicePrincipalExistsFound() throws Exception { + testPrincipalExistsFound(true); + } + + private void testPrincipalExistsFound(boolean service) throws Exception { + KerberosOperationHandler handler = createMockedHandler(); + + setupOpenSuccess(handler); + setupPrincipalExists(handler, service); + + replayAll(); + + handler.open(getAdminCredentials(), DEFAULT_REALM, getKerberosEnv()); + Assert.assertTrue(handler.principalExists(createPrincipal(service), service)); + handler.close(); + + verifyAll(); + + } + + @Test public void testCreateKeytabFileOneAtATime() throws Exception { KerberosOperationHandler handler = createHandler(); File file = folder.newFile(); @@ -285,7 +403,7 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport { public void testAdminCredentialsNullCredential() throws KerberosOperationException { KerberosOperationHandler handler = createHandler(); - PrincipalKeyCredential credentials = new PrincipalKeyCredential("principal", (char[])null); + PrincipalKeyCredential credentials = new PrincipalKeyCredential("principal", (char[]) null); handler.setAdministratorCredential(credentials); } @@ -301,10 +419,10 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport { public void testSetExecutableSearchPaths() throws KerberosOperationException { KerberosOperationHandler handler = createHandler(); - handler.setExecutableSearchPaths((String)null); + handler.setExecutableSearchPaths((String) null); Assert.assertNull(handler.getExecutableSearchPaths()); - handler.setExecutableSearchPaths((String[])null); + handler.setExecutableSearchPaths((String[]) null); Assert.assertNull(handler.getExecutableSearchPaths()); handler.setExecutableSearchPaths(""); @@ -341,6 +459,24 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport { Assert.assertEquals("path3/", handler.getExecutableSearchPaths()[2]); } + protected abstract KerberosOperationHandler createMockedHandler() throws KerberosOperationException; + + protected abstract void setupOpenSuccess(KerberosOperationHandler handler) throws Exception; + + protected abstract void setupOpenFailure(KerberosOperationHandler handler) throws Exception; + + protected abstract void setupPrincipalAlreadyExists(KerberosOperationHandler handler, boolean service) throws Exception; + + protected abstract void setupPrincipalDoesNotExist(KerberosOperationHandler handler, boolean service) throws Exception; + + protected abstract void setupPrincipalExists(KerberosOperationHandler handler, boolean service) throws Exception; + + protected abstract Map<String, String> getKerberosEnv(); + + protected PrincipalKeyCredential getAdminCredentials() { + return DEFAULT_ADMIN_CREDENTIALS; + } + private KerberosOperationHandler createHandler() throws KerberosOperationException { KerberosOperationHandler handler = new KerberosOperationHandler() { @@ -357,7 +493,7 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport { } @Override - public boolean principalExists(String principal) throws KerberosOperationException { + public boolean principalExists(String principal, boolean service) throws KerberosOperationException { return false; } @@ -367,12 +503,12 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport { } @Override - public Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException { + public Integer setPrincipalPassword(String principal, String password, boolean service) throws KerberosOperationException { return 0; } @Override - public boolean removePrincipal(String principal) throws KerberosOperationException { + public boolean removePrincipal(String principal, boolean service) throws KerberosOperationException { return false; } }; @@ -380,4 +516,8 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport { handler.open(new PrincipalKeyCredential("admin/admin", "hadoop"), "EXAMPLE.COM", null); return handler; } + + private String createPrincipal(boolean service) { + return String.format("%s@%s", (service) ? "service/host" : "user", DEFAULT_REALM); + } }
