Repository: ambari Updated Branches: refs/heads/trunk 4a46fe4d8 -> 7c6a40901
AMBARI-15961. Kerberos wizard stuck trying to schedule service check operation (rlevas) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7c6a4090 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7c6a4090 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7c6a4090 Branch: refs/heads/trunk Commit: 7c6a40901f16313b057874dda00e727bb99a936a Parents: 4a46fe4 Author: Robert Levas <[email protected]> Authored: Tue Apr 19 15:52:20 2016 -0400 Committer: Robert Levas <[email protected]> Committed: Tue Apr 19 15:52:26 2016 -0400 ---------------------------------------------------------------------- .../server/controller/KerberosHelperImpl.java | 469 ++++++++----------- .../kerberos/ADKerberosOperationHandler.java | 9 +- .../kerberos/CreatePrincipalsServerAction.java | 165 ++++--- .../kerberos/DestroyPrincipalsServerAction.java | 96 ++-- ...erberosMissingAdminCredentialsException.java | 34 +- .../kerberos/KerberosOperationHandler.java | 2 + ...KerberosPrincipalAlreadyExistsException.java | 45 ++ .../KerberosPrincipalDoesNotExistException.java | 45 ++ .../kerberos/MITKerberosOperationHandler.java | 34 +- .../AMBARI_METRICS/0.1.0/kerberos.json | 3 + .../server/controller/KerberosHelperTest.java | 67 +-- 11 files changed, 526 insertions(+), 443 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java index 350ad6d..dca81c5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java @@ -286,7 +286,7 @@ public class KerberosHelperImpl implements KerberosHelper { throws AmbariException, KerberosOperationException { return handle(cluster, getKerberosDetails(cluster, manageIdentities), serviceComponentFilter, hostFilter, identityFilter, hostsToForceKerberosOperations, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false, false, - false)); + false)); } @Override @@ -433,8 +433,8 @@ public class KerberosHelperImpl implements KerberosHelper { return (applyStackAdvisorUpdates) ? applyStackAdvisorUpdates(cluster, services, configurations, kerberosConfigurations, propertiesToIgnore, - null, null, - kerberosEnabled) + null, null, + kerberosEnabled) : kerberosConfigurations; } @@ -510,12 +510,12 @@ public class KerberosHelperImpl implements KerberosHelper { } StackAdvisorRequest request = StackAdvisorRequest.StackAdvisorRequestBuilder - .forStack(stackVersion.getStackName(), stackVersion.getStackVersion()) - .forServices(new ArrayList<String>(services)) - .forHosts(hostNames) - .withConfigurations(requestConfigurations) - .ofType(StackAdvisorRequest.StackAdvisorRequestType.CONFIGURATIONS) - .build(); + .forStack(stackVersion.getStackName(), stackVersion.getStackVersion()) + .forServices(new ArrayList<String>(services)) + .forHosts(hostNames) + .withConfigurations(requestConfigurations) + .ofType(StackAdvisorRequest.StackAdvisorRequestType.CONFIGURATIONS) + .build(); try { RecommendationResponse response = stackAdvisorHelper.recommend(request); @@ -534,13 +534,13 @@ public class KerberosHelperImpl implements KerberosHelper { Set<String> ignoreProperties = (propertiesToIgnore == null) ? null : propertiesToIgnore.get(configType); addRecommendedPropertiesForConfigType(kerberosEnabled, kerberosConfigurations, configType, - recommendedConfigProperties, - existingConfigProperties, kerberosConfigProperties, ignoreProperties, propertiesToInsert); + recommendedConfigProperties, + existingConfigProperties, kerberosConfigProperties, ignoreProperties, propertiesToInsert); if (recommendedConfigPropertyAttributes != null) { removeRecommendedPropertiesForConfigType(kerberosEnabled, configType, - recommendedConfigPropertyAttributes, - existingConfigProperties, - kerberosConfigurations, ignoreProperties, propertiesToRemove); + recommendedConfigPropertyAttributes, + existingConfigProperties, + kerberosConfigurations, ignoreProperties, propertiesToRemove); } } } @@ -561,8 +561,8 @@ public class KerberosHelperImpl implements KerberosHelper { String configType, Map<String, String> recommendedConfigProperties, Map<String, String> existingConfigProperties, Map<String, String> kerberosConfigProperties, - Set<String> ignoreProperties, Map<String, Map<String, String>> - propertiesToInsert) { + Set<String> ignoreProperties, + Map<String, Map<String, String>> propertiesToInsert) { for (Map.Entry<String, String> property : recommendedConfigProperties.entrySet()) { String propertyName = property.getKey(); @@ -575,8 +575,8 @@ public class KerberosHelperImpl implements KerberosHelper { // add the config and property if it also does not exist in the existing configurations if ((existingConfigProperties == null) || !existingConfigProperties.containsKey(propertyName)) { LOG.debug("Adding Kerberos configuration based on StackAdvisor recommendation:" + - "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}", - configType, propertyName, recommendedValue); + "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}", + configType, propertyName, recommendedValue); HashMap<String, String> properties = new HashMap<String, String>(); properties.put(propertyName, recommendedValue); @@ -589,22 +589,22 @@ public class KerberosHelperImpl implements KerberosHelper { // add the property if it also does not exist in the existing configurations if ((existingConfigProperties == null) || !existingConfigProperties.containsKey(propertyName)) { LOG.debug("Adding Kerberos configuration based on StackAdvisor recommendation:" + - "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}", - configType, propertyName, recommendedValue); + "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}", + configType, propertyName, recommendedValue); kerberosConfigProperties.put(propertyName, recommendedValue); } } else if (!value.equals(recommendedValue)) { // If the recommended value is a change, automatically change it. LOG.debug("Updating Kerberos configuration based on StackAdvisor recommendation:" + - "\n\tConfigType: {}\n\tProperty: {}\n\tOld Value: {}\n\tNew Value: {}", - configType, propertyName, value, recommendedValue); + "\n\tConfigType: {}\n\tProperty: {}\n\tOld Value: {}\n\tNew Value: {}", + configType, propertyName, value, recommendedValue); kerberosConfigProperties.put(propertyName, recommendedValue); } } } else if (propertiesToInsert != null && ((existingConfigProperties == null) || !existingConfigProperties - .containsKey(propertyName))) { + .containsKey(propertyName))) { Map<String, String> properties = propertiesToInsert.get(configType); if (properties == null) { properties = new HashMap<>(); @@ -612,8 +612,8 @@ public class KerberosHelperImpl implements KerberosHelper { } LOG.debug("Property to add to configuration based on StackAdvisor recommendation:" + - "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}", - configType, propertyName, recommendedValue); + "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}", + configType, propertyName, recommendedValue); properties.put(propertyName, recommendedValue); } @@ -633,7 +633,7 @@ public class KerberosHelperImpl implements KerberosHelper { Map<String, String> existingConfigProperties, Map<String, Map<String, String>> kerberosConfigurations, Set<String> ignoreProperties, Map<String, Set<String>> - propertiesToRemove) { + propertiesToRemove) { for (Map.Entry<String, ValueAttributesInfo> property : recommendedConfigPropertyAttributes.entrySet()) { String propertyName = property.getKey(); @@ -642,12 +642,12 @@ public class KerberosHelperImpl implements KerberosHelper { // add to propertiesToBeRemoved map Map<String, String> kerberosConfigProperties = kerberosConfigurations.get(configType); if (((ignoreProperties == null) || !ignoreProperties.contains(propertyName)) && - ((kerberosConfigProperties == null) || kerberosConfigProperties.get(propertyName) == null) && - (existingConfigProperties != null && existingConfigProperties.containsKey(propertyName))) { + ((kerberosConfigProperties == null) || kerberosConfigProperties.get(propertyName) == null) && + (existingConfigProperties != null && existingConfigProperties.containsKey(propertyName))) { LOG.debug("Property to remove from configuration based on StackAdvisor recommendation:" + - "\n\tConfigType: {}\n\tProperty: {}", - configType, propertyName); + "\n\tConfigType: {}\n\tProperty: {}", + configType, propertyName); // kerberosEnabled add property to propertiesToRemove, otherwise to kerberosConfigurations map if (kerberosEnabled && propertiesToRemove != null) { @@ -681,7 +681,7 @@ public class KerberosHelperImpl implements KerberosHelper { Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); Map<String, Map<String, String>> configurations = addAdditionalConfigurations(cluster, - deepCopy(existingConfigurations), null, kerberosDescriptorProperties); + deepCopy(existingConfigurations), null, kerberosDescriptorProperties); Map<String, String> kerberosConfiguration = kerberosDetails.getKerberosEnvProperties(); KerberosOperationHandler kerberosOperationHandler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kerberosDetails.getKdcType()); @@ -691,7 +691,7 @@ public class KerberosHelperImpl implements KerberosHelper { kerberosOperationHandler.open(administratorCredential, kerberosDetails.getDefaultRealm(), kerberosConfiguration); } catch (KerberosOperationException e) { String message = String.format("Failed to process the identities, could not properly open the KDC operation handler: %s", - e.getMessage()); + e.getMessage()); LOG.error(message); throw new AmbariException(message, e); } @@ -734,7 +734,7 @@ public class KerberosHelperImpl implements KerberosHelper { configureAmbariIdentity(ambariServerIdentity, kerberosOperationHandler, configurations); try { KerberosChecker.checkJaasConfiguration(); - } catch(AmbariException e) { + } catch (AmbariException e) { LOG.error("Error in Ambari JAAS configuration: ", e); } } @@ -754,8 +754,8 @@ public class KerberosHelperImpl implements KerberosHelper { } private boolean configureAmbariIdentity(KerberosIdentityDescriptor ambariServerIdentity, - KerberosOperationHandler kerberosOperationHandler, Map<String, Map<String, String>> - configurations) throws AmbariException { + KerberosOperationHandler kerberosOperationHandler, + Map<String, Map<String, String>> configurations) throws AmbariException { boolean created = false; @@ -772,8 +772,8 @@ public class KerberosHelperImpl implements KerberosHelper { if (keytabDescriptor != null) { injector.getInstance(ConfigureAmbariIndetityServerAction.class) - .createAndConfigureAmbariKeytab(principal, kerberosOperationHandler, keytabFilePath, - keytabDescriptor.getOwnerName(), keytabDescriptor.getOwnerAccess(), null); + .createAndConfigureAmbariKeytab(principal, kerberosOperationHandler, keytabFilePath, + keytabDescriptor.getOwnerName(), keytabDescriptor.getOwnerAccess(), null); // throw new AmbariException("Failed to create the keytab for " + principal); } @@ -788,7 +788,7 @@ public class KerberosHelperImpl implements KerberosHelper { RequestStageContainer requestStageContainer) throws KerberosOperationException, AmbariException { return handleTestIdentity(cluster, getKerberosDetails(cluster, null), commandParamsStage, requestStageContainer, - new CreatePrincipalsAndKeytabsHandler(false, false, false)); + new CreatePrincipalsAndKeytabsHandler(false, false, false)); } @Override @@ -815,7 +815,7 @@ public class KerberosHelperImpl implements KerberosHelper { boolean processAuthToLocalRules = true; Map<String, String> kerberosEnvProperties = existingConfigurations.get("kerberos-env"); - if(kerberosEnvProperties.containsKey("manage_auth_to_local")) { + if (kerberosEnvProperties.containsKey("manage_auth_to_local")) { processAuthToLocalRules = Boolean.valueOf(kerberosEnvProperties.get("manage_auth_to_local")); } @@ -856,37 +856,37 @@ public class KerberosHelperImpl implements KerberosHelper { Map<String, KerberosComponentDescriptor> components = service.getComponents(); if (components != null) { - Map<String,ServiceComponent> serviceComponents = svc.getServiceComponents(); + Map<String, ServiceComponent> serviceComponents = svc.getServiceComponents(); for (KerberosComponentDescriptor component : components.values()) { // When the cluster is provisioned by a Blueprint service components with // cardinality 0+ might be left out from the Blueprint thus we have to check // if they exist ServiceComponent svcComp = null; - if (!serviceComponents.containsKey(component.getName())) + if (!serviceComponents.containsKey(component.getName())) { continue; + } svcComp = serviceComponents.get(component.getName()); boolean addSvcCompIdentities = false; - if (cluster.isBluePrintDeployed()) - { - if (svcComp.getDesiredState() == State.INSTALLED || svcComp.getDesiredState() == State.STARTED) + if (cluster.isBluePrintDeployed()) { + if (svcComp.getDesiredState() == State.INSTALLED || svcComp.getDesiredState() == State.STARTED) { addSvcCompIdentities = true; - } - else { + } + } else { // Since when the cluster is deployed through the UI ALL service components of the selected services are created // with desired state INSTALLED regardless whether the service components were associated with hosts or not thus // we can not determine if the component is installed or not. // We rather look at service compoent hosts - for (ServiceComponentHost svcCompHost: svcComp.getServiceComponentHosts().values()) { + for (ServiceComponentHost svcCompHost : svcComp.getServiceComponentHosts().values()) { if (svcCompHost.getDesiredState() != State.UNKNOWN - && svcCompHost.getDesiredState() != State.UNINSTALLING - && svcCompHost.getDesiredState() != State.UNINSTALLED - && svcCompHost.getDesiredState() != State.INSTALL_FAILED - && svcCompHost.getDesiredState() != State.WIPING_OUT) { + && svcCompHost.getDesiredState() != State.UNINSTALLING + && svcCompHost.getDesiredState() != State.UNINSTALLED + && svcCompHost.getDesiredState() != State.INSTALL_FAILED + && svcCompHost.getDesiredState() != State.WIPING_OUT) { // If there is at least a host that contains the component add the identities addSvcCompIdentities = true; @@ -1300,7 +1300,7 @@ public class KerberosHelperImpl implements KerberosHelper { KerberosPrincipalType principalType = principalDescriptor.getType(); // Assume the principal is a service principal if not specified - if(principalType == null) { + if (principalType == null) { principalType = KerberosPrincipalType.SERVICE; } @@ -1402,6 +1402,7 @@ public class KerberosHelperImpl implements KerberosHelper { false, kerberosEnvProperties, kerberosOperationHandler, + false, null); if (result == null) { @@ -1455,16 +1456,7 @@ public class KerberosHelperImpl implements KerberosHelper { if (kerberosDetails.manageIdentities()) { PrincipalKeyCredential credentials = getKDCAdministratorCredentials(cluster.getClusterName()); if (credentials == null) { - throw new KerberosMissingAdminCredentialsException( - "Missing KDC administrator credentials.\n" + - "The KDC administrator credentials must be set as a persisted or temporary credential resource." + - "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" + - "{\n" + - " \"Credential\" : {\n" + - " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" + - " }\n" + - "}" - ); + throw new KerberosMissingAdminCredentialsException(); } else { KerberosOperationHandler operationHandler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kerberosDetails.getKdcType()); @@ -1513,16 +1505,7 @@ public class KerberosHelperImpl implements KerberosHelper { // need to throw this outside of the try/catch so it isn't caught if (missingCredentials) { - throw new KerberosMissingAdminCredentialsException( - "Invalid KDC administrator credentials.\n" + - "The KDC administrator credentials must be set as a persisted or temporary credential resource." + - "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" + - "{\n" + - " \"Credential\" : {\n" + - " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" + - " }\n" + - "}" - ); + throw new KerberosMissingAdminCredentialsException(); } } } @@ -1715,192 +1698,145 @@ public class KerberosHelperImpl implements KerberosHelper { throw new AmbariException("The properties map must not be null. It is needed to store data related to the service check identity"); } - Map<String, Service> services = cluster.getServices(); + List<ServiceComponentHost> serviceComponentHostsToProcess = new ArrayList<ServiceComponentHost>(); + KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster); + KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = null; - if ((services != null) && !services.isEmpty()) { - String clusterName = cluster.getClusterName(); - Map<String, Host> hosts = clusters.getHostsForCluster(clusterName); - - if ((hosts != null) && !hosts.isEmpty()) { - List<ServiceComponentHost> serviceComponentHostsToProcess = new ArrayList<ServiceComponentHost>(); - KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster); - KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = null; - Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); - - // This is needed to help determine which hosts to perform actions for and create tasks for. - Set<String> hostsWithValidKerberosClient = getHostsWithValidKerberosClient(cluster); - - // Create a temporary directory to store metadata needed to complete this task. Information - // such as which principals and keytabs files to create as well as what configurations need - // to be update are stored in data files in this directory. Any keytab files are stored in - // this directory until they are distributed to their appropriate hosts. - File dataDirectory = createTemporaryDirectory(); - - // Create the file used to store details about principals and keytabs to create - File identityDataFile = new File(dataDirectory, KerberosIdentityDataFileWriter.DATA_FILE_NAME); - - // Create a special identity for the test user - KerberosIdentityDescriptor identity = new KerberosIdentityDescriptor(new HashMap<String, Object>() { - { - put("principal", - new HashMap<String, Object>() { - { - put("value", "${kerberos-env/service_check_principal_name}@${realm}"); - put("type", "user"); - } - }); - put("keytab", - new HashMap<String, Object>() { - { - put("file", "${keytab_dir}/kerberos.service_check.${short_date}.keytab"); - - put("owner", new HashMap<String, Object>() {{ - put("name", "${cluster-env/smokeuser}"); - put("access", "rw"); - }}); - - put("group", new HashMap<String, Object>() {{ - put("name", "${cluster-env/user_group}"); - put("access", "r"); - }}); - - put("cachable", "false"); - } - }); - } - }); + Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); - try { - // Iterate over the hosts in the cluster to find the components installed in each. For each - // component (aka service component host - sch) determine the configuration updates and - // and the principals an keytabs to create. - for (Host host : hosts.values()) { - String hostname = host.getHostName(); - - // Get a list of components on the current host - List<ServiceComponentHost> serviceComponentHosts = cluster.getServiceComponentHosts(hostname); - - if ((serviceComponentHosts != null) && !serviceComponentHosts.isEmpty()) { - // Calculate the current host-specific configurations. These will be used to replace - // variables within the Kerberos descriptor data - Map<String, Map<String, String>> configurations = calculateConfigurations(cluster, hostname, kerberosDescriptorProperties); - - // Add a short date value - configurations.get("").put("short_date", new SimpleDateFormat("MMddyy").format(new Date())); - - // Iterate over the components installed on the current host to get the service and - // component-level Kerberos descriptors in order to determine which principals, - // keytab files, and configurations need to be created or updated. - for (ServiceComponentHost sch : serviceComponentHosts) { - String serviceName = sch.getServiceName(); - String componentName = sch.getServiceComponentName(); - - // If the current ServiceComponentHost represents the KERBEROS/KERBEROS_CLIENT and - // indicates that the KERBEROS_CLIENT component is in the INSTALLED state, add the - // current host to the set of hosts that should be handled... - if (Service.Type.KERBEROS.name().equals(serviceName) && - Role.KERBEROS_CLIENT.name().equals(componentName) && - (sch.getState() == State.INSTALLED)) { - hostsWithValidKerberosClient.add(hostname); - int identitiesAdded = 0; - - // Lazily create the KerberosIdentityDataFileWriter instance... - if (kerberosIdentityDataFileWriter == null) { - kerberosIdentityDataFileWriter = kerberosIdentityDataFileWriterFactory.createKerberosIdentityDataFileWriter(identityDataFile); - } + // This is needed to help determine which hosts to perform actions for and create tasks for. + Set<String> hostsWithValidKerberosClient = getHostsWithValidKerberosClient(cluster); - // Add service-level principals (and keytabs) - identitiesAdded += addIdentities(kerberosIdentityDataFileWriter, Collections.singleton(identity), - null, hostname, serviceName, componentName, null, configurations); + // Create a temporary directory to store metadata needed to complete this task. Information + // such as which principals and keytabs files to create as well as what configurations need + // to be update are stored in data files in this directory. Any keytab files are stored in + // this directory until they are distributed to their appropriate hosts. + File dataDirectory = createTemporaryDirectory(); - if (identitiesAdded > 0) { - // Add the relevant principal name and keytab file data to the command params state - if (!commandParameters.containsKey("principal_name") || !commandParameters.containsKey("keytab_file")) { - commandParameters.put("principal_name", - variableReplacementHelper.replaceVariables(identity.getPrincipalDescriptor().getValue(), configurations)); - commandParameters.put("keytab_file", - variableReplacementHelper.replaceVariables(identity.getKeytabDescriptor().getFile(), configurations)); - } + // Create the file used to store details about principals and keytabs to create + File identityDataFile = new File(dataDirectory, KerberosIdentityDataFileWriter.DATA_FILE_NAME); - serviceComponentHostsToProcess.add(sch); - } - } - } - } - } - } catch (IOException e) { - String message = String.format("Failed to write index file - %s", identityDataFile.getAbsolutePath()); - LOG.error(message); - throw new AmbariException(message, e); - } catch (Exception e) { - // make sure to log what is going wrong - LOG.error("Failed " + e); - throw e; - } finally { - if (kerberosIdentityDataFileWriter != null) { - // Make sure the data file is closed - try { - kerberosIdentityDataFileWriter.close(); - } catch (IOException e) { - LOG.warn("Failed to close the index file writer", e); - } - } - } + // Calculate the current non-host-specific configurations. These will be used to replace + // variables within the Kerberos descriptor data + Map<String, Map<String, String>> configurations = calculateConfigurations(cluster, null, kerberosDescriptorProperties); - // If there are ServiceComponentHosts to process, make sure the administrator credential - // are available - if (!serviceComponentHostsToProcess.isEmpty()) { - try { - validateKDCCredentials(kerberosDetails, cluster); - } catch (Exception e) { - LOG.error("Cannot validate credentials: " + e); - try { - FileUtils.deleteDirectory(dataDirectory); - } catch (Throwable t) { - LOG.warn(String.format("The data directory (%s) was not deleted due to an error condition - {%s}", - dataDirectory.getAbsolutePath(), t.getMessage()), t); - } + String principal = variableReplacementHelper.replaceVariables("${kerberos-env/service_check_principal_name}@${realm}", configurations); + String principalType = "user"; + + String keytabFilePath = variableReplacementHelper.replaceVariables("${keytab_dir}/kerberos.service_check.${short_date}.keytab", configurations); + String keytabFileOwnerName = variableReplacementHelper.replaceVariables("${cluster-env/smokeuser}", configurations); + String keytabFileOwnerAccess = "rw"; + String keytabFileGroupName = variableReplacementHelper.replaceVariables("${cluster-env/user_group}", configurations); + String keytabFileGroupAccess = "r"; + + // Add the relevant principal name and keytab file data to the command params state + commandParameters.put("principal_name", principal); + commandParameters.put("keytab_file", keytabFilePath); - throw e; + try { + // Get a list KERBEROS/KERBEROS_CLIENT ServiceComponentHost objects + List<ServiceComponentHost> serviceComponentHosts = cluster.getServiceComponentHosts(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name()); + + if ((serviceComponentHosts != null) && !serviceComponentHosts.isEmpty()) { + kerberosIdentityDataFileWriter = kerberosIdentityDataFileWriterFactory.createKerberosIdentityDataFileWriter(identityDataFile); + + // Iterate over the KERBEROS_CLIENT service component hosts to get the service and + // component-level Kerberos descriptors in order to determine which principals, + // keytab files needed to be created or updated. + for (ServiceComponentHost sch : serviceComponentHosts) { + if (sch.getState() == State.INSTALLED) { + String hostname = sch.getHostName(); + + kerberosIdentityDataFileWriter.writeRecord( + hostname, + Service.Type.KERBEROS.name(), + Role.KERBEROS_CLIENT.name(), + principal, + principalType, + keytabFilePath, + keytabFileOwnerName, + keytabFileOwnerAccess, + keytabFileGroupName, + keytabFileGroupAccess, + "false"); + + hostsWithValidKerberosClient.add(hostname); + serviceComponentHostsToProcess.add(sch); } } + } + + } catch (IOException e) { + String message = String.format("Failed to write index file - %s", identityDataFile.getAbsolutePath()); + LOG.error(message); + throw new AmbariException(message, e); + } catch (Exception e) { + // make sure to log what is going wrong + LOG.error("Failed " + e); + throw e; + } finally { + if (kerberosIdentityDataFileWriter != null) { + // Make sure the data file is closed + try { + kerberosIdentityDataFileWriter.close(); + } catch (IOException e) { + LOG.warn("Failed to close the index file writer", e); + } + } + } - // Always set up the necessary stages to perform the tasks needed to complete the operation. - // Some stages may be no-ops, this is expected. - // Gather data needed to create stages and tasks... - Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster); - String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo); - Map<String, String> hostParams = customCommandExecutionHelper.createDefaultHostParams(cluster); - String hostParamsJson = StageUtils.getGson().toJson(hostParams); - String ambariServerHostname = StageUtils.getHostName(); - ServiceComponentHostServerActionEvent event = new ServiceComponentHostServerActionEvent( - "AMBARI_SERVER", - ambariServerHostname, // TODO: Choose a random hostname from the cluster. All tasks for the AMBARI_SERVER service will be executed on this Ambari server - System.currentTimeMillis()); - RoleCommandOrder roleCommandOrder = ambariManagementController.getRoleCommandOrder(cluster); - - // If a RequestStageContainer does not already exist, create a new one... - if (requestStageContainer == null) { - requestStageContainer = new RequestStageContainer( - actionManager.getNextRequestId(), - null, - requestFactory, - actionManager); + // If there are ServiceComponentHosts to process, make sure the administrator credential + // are available + if (!serviceComponentHostsToProcess.isEmpty()) { + try { + validateKDCCredentials(kerberosDetails, cluster); + } catch (Exception e) { + LOG.error("Cannot validate credentials: " + e); + try { + FileUtils.deleteDirectory(dataDirectory); + } catch (Throwable t) { + LOG.warn(String.format("The data directory (%s) was not deleted due to an error condition - {%s}", + dataDirectory.getAbsolutePath(), t.getMessage()), t); } - // Use the handler implementation to setup the relevant stages. - // Set the service/component filter to an empty map since the service/component processing - // was done above. - handler.createStages(cluster, - clusterHostInfoJson, hostParamsJson, event, roleCommandOrder, kerberosDetails, - dataDirectory, requestStageContainer, serviceComponentHostsToProcess, - Collections.<String, Collection<String>>emptyMap(), null, null, hostsWithValidKerberosClient); + throw e; + } + } + // Always set up the necessary stages to perform the tasks needed to complete the operation. + // Some stages may be no-ops, this is expected. + // Gather data needed to create stages and tasks... + Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster); + String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo); + Map<String, String> hostParams = customCommandExecutionHelper.createDefaultHostParams(cluster); + String hostParamsJson = StageUtils.getGson().toJson(hostParams); + String ambariServerHostname = StageUtils.getHostName(); + ServiceComponentHostServerActionEvent event = new ServiceComponentHostServerActionEvent( + "AMBARI_SERVER", + ambariServerHostname, // TODO: Choose a random hostname from the cluster. All tasks for the AMBARI_SERVER service will be executed on this Ambari server + System.currentTimeMillis()); + RoleCommandOrder roleCommandOrder = ambariManagementController.getRoleCommandOrder(cluster); - handler.addFinalizeOperationStage(cluster, clusterHostInfoJson, hostParamsJson, event, - dataDirectory, roleCommandOrder, requestStageContainer); - } + // If a RequestStageContainer does not already exist, create a new one... + if (requestStageContainer == null) { + requestStageContainer = new RequestStageContainer( + actionManager.getNextRequestId(), + null, + requestFactory, + actionManager); } + + // Use the handler implementation to setup the relevant stages. + // Set the service/component filter to an empty map since the service/component processing + // was done above. + handler.createStages(cluster, + clusterHostInfoJson, hostParamsJson, event, roleCommandOrder, kerberosDetails, + dataDirectory, requestStageContainer, serviceComponentHostsToProcess, + Collections.<String, Collection<String>>emptyMap(), null, null, hostsWithValidKerberosClient); + + + handler.addFinalizeOperationStage(cluster, clusterHostInfoJson, hostParamsJson, event, + dataDirectory, roleCommandOrder, requestStageContainer); } return requestStageContainer; @@ -2449,6 +2385,9 @@ public class KerberosHelperImpl implements KerberosHelper { // Add the current cluster's name generalProperties.put("cluster_name", cluster.getClusterName()); + // Add the current date in short format (MMddyy) + generalProperties.put("short_date", new SimpleDateFormat("MMddyy").format(new Date())); + // add clusterHostInfo config if (configurations.get("clusterHostInfo") == null) { Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster); @@ -2702,22 +2641,22 @@ public class KerberosHelperImpl implements KerberosHelper { } public void addConfigureAmbariIdentityStage(Cluster cluster, String clusterHostInfoJson, - String hostParamsJson, ServiceComponentHostServerActionEvent event, - Map<String, String> commandParameters, - RoleCommandOrder roleCommandOrder, RequestStageContainer requestStageContainer) - throws AmbariException { + String hostParamsJson, ServiceComponentHostServerActionEvent event, + Map<String, String> commandParameters, + RoleCommandOrder roleCommandOrder, RequestStageContainer requestStageContainer) + throws AmbariException { Stage stage = createServerActionStage(requestStageContainer.getLastStageId(), - cluster, - requestStageContainer.getId(), - "Configure Ambari Identity", - clusterHostInfoJson, - "{}", - hostParamsJson, - ConfigureAmbariIndetityServerAction.class, - event, - commandParameters, - "Configure Ambari Identity", - configuration.getDefaultServerTaskTimeout()); + cluster, + requestStageContainer.getId(), + "Configure Ambari Identity", + clusterHostInfoJson, + "{}", + hostParamsJson, + ConfigureAmbariIndetityServerAction.class, + event, + commandParameters, + "Configure Ambari Identity", + configuration.getDefaultServerTaskTimeout()); RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder); roleGraph.build(stage); @@ -3025,18 +2964,18 @@ public class KerberosHelperImpl implements KerberosHelper { // ***************************************************************** // Create stage to create principals addCreatePrincipalsStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters, - roleCommandOrder, requestStageContainer); + roleCommandOrder, requestStageContainer); // ***************************************************************** // Create stage to generate keytabs addCreateKeytabFilesStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters, - roleCommandOrder, requestStageContainer); + roleCommandOrder, requestStageContainer); // ***************************************************************** // Create stage to distribute and configure keytab for Ambari server and configure JAAS if (kerberosDetails.createAmbariPrincipal()) { addConfigureAmbariIdentityStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters, - roleCommandOrder, requestStageContainer); + roleCommandOrder, requestStageContainer); } // ***************************************************************** @@ -3206,8 +3145,8 @@ public class KerberosHelperImpl implements KerberosHelper { * (<code>true</code>) or ignore any potential configuration changes * (<code>false</code>) */ - public CreatePrincipalsAndKeytabsHandler(boolean regenerateAllKeytabs, boolean updateConfigurations, boolean - includeAmbariIdentity) { + public CreatePrincipalsAndKeytabsHandler(boolean regenerateAllKeytabs, boolean updateConfigurations, + boolean includeAmbariIdentity) { this.regenerateAllKeytabs = regenerateAllKeytabs; this.updateConfigurations = updateConfigurations; this.includeAmbariIdentity = includeAmbariIdentity; @@ -3306,7 +3245,7 @@ public class KerberosHelperImpl implements KerberosHelper { // Create stage to distribute and configure keytab for Ambari server and configure JAAS if (includeAmbariIdentity && kerberosDetails.createAmbariPrincipal()) { addConfigureAmbariIdentityStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters, - roleCommandOrder, requestStageContainer); + roleCommandOrder, requestStageContainer); } // ***************************************************************** @@ -3477,7 +3416,7 @@ public class KerberosHelperImpl implements KerberosHelper { public boolean createAmbariPrincipal() { if (createAmbariPrincipal == null) { return (kerberosEnvProperties == null) || - !"false".equalsIgnoreCase(kerberosEnvProperties.get(CREATE_AMBARI_PRINCIPAL)); + !"false".equalsIgnoreCase(kerberosEnvProperties.get(CREATE_AMBARI_PRINCIPAL)); } else { return createAmbariPrincipal; } http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java index deea158..48e04f4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java @@ -235,6 +235,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { * @param password a String containing the password to use when creating the principal * @param service a boolean value indicating whether the principal is to be created as a service principal or not * @return an Integer declaring the generated key number + * @throws KerberosPrincipalAlreadyExistsException if the principal already exists * @throws KerberosOperationException */ @Override @@ -243,13 +244,15 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { if (!isOpen()) { throw new KerberosOperationException("This operation handler has not been opened"); } - if (principal == null) { throw new KerberosOperationException("principal is null"); } if (password == null) { throw new KerberosOperationException("principal password is null"); } + if (principalExists(principal)) { + throw new KerberosPrincipalAlreadyExistsException(principal); + } DeconstructedPrincipal deconstructedPrincipal = createDeconstructPrincipal(principal); @@ -335,6 +338,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { * @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 KerberosPrincipalDoesNotExistException if the principal does not exist * @throws KerberosOperationException */ @Override @@ -348,6 +352,9 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { if (password == null) { throw new KerberosOperationException("principal password is null"); } + if(!principalExists(principal)) { + throw new KerberosPrincipalDoesNotExistException(principal); + } DeconstructedPrincipal deconstructPrincipal = createDeconstructPrincipal(principal); http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/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 e6fe51f..e31e6ff 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 @@ -33,7 +33,9 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentMap; /** @@ -66,6 +68,12 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { private SecurePasswordHelper securePasswordHelper; /** + * A set of visited principal names used to prevent unnecessary processing on already processed + * principal names + */ + private Set<String> seenPrincipals = new HashSet<String>(); + + /** * 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 @@ -115,44 +123,50 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { throws AmbariException { CommandReport commandReport = null; - boolean processPrincipal; - boolean regenerateKeytabs = "true".equalsIgnoreCase(getCommandParameterValue(getCommandParameters(), REGENERATE_ALL)); + // Only process this principal name if we haven't already processed it + if (!seenPrincipals.contains(evaluatedPrincipal)) { + seenPrincipals.add(evaluatedPrincipal); - if (regenerateKeytabs) { - processPrincipal = true; - } else { - KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); + boolean processPrincipal; + boolean regenerateKeytabs = "true".equalsIgnoreCase(getCommandParameterValue(getCommandParameters(), REGENERATE_ALL)); - if (kerberosPrincipalEntity == null) { - // This principal has not been processed before, process it. + if (regenerateKeytabs) { processPrincipal = true; - } else if (!StringUtils.isEmpty(kerberosPrincipalEntity.getCachedKeytabPath())) { - // This principal has been processed and a keytab file has been cached for it... do not process it. - processPrincipal = false; - } else if (kerberosPrincipalHostDAO.exists(evaluatedPrincipal)) { - // This principal has been processed and a keytab file has been distributed... do not process it. - processPrincipal = false; } else { - // This principal has been processed but a keytab file for it has been distributed... process it. - processPrincipal = true; + KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); + + if (kerberosPrincipalEntity == null) { + // This principal has not been processed before, process it. + processPrincipal = true; + } else if (!StringUtils.isEmpty(kerberosPrincipalEntity.getCachedKeytabPath())) { + // This principal has been processed and a keytab file has been cached for it... do not process it. + processPrincipal = false; + } else if (kerberosPrincipalHostDAO.exists(evaluatedPrincipal)) { + // This principal has been processed and a keytab file has been distributed... do not process it. + processPrincipal = false; + } else { + // This principal has been processed but a keytab file for it has been distributed... process it. + processPrincipal = true; + } } - } - if (processPrincipal) { - Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext); - Map<String, Integer> principalKeyNumberMap = getPrincipalKeyNumberMap(requestSharedDataContext); + if (processPrincipal) { + Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext); - String password = principalPasswordMap.get(evaluatedPrincipal); + String password = principalPasswordMap.get(evaluatedPrincipal); - if (password == null) { - boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE)); - CreatePrincipalResult result = createPrincipal(evaluatedPrincipal, servicePrincipal, kerberosConfiguration, operationHandler, actionLog); + if (password == null) { + boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE)); + CreatePrincipalResult result = createPrincipal(evaluatedPrincipal, servicePrincipal, kerberosConfiguration, operationHandler, regenerateKeytabs, actionLog); - if (result == null) { - commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr()); - } else { - principalPasswordMap.put(evaluatedPrincipal, result.getPassword()); - principalKeyNumberMap.put(evaluatedPrincipal, result.getKeyNumber()); + if (result == null) { + commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr()); + } else { + Map<String, Integer> principalKeyNumberMap = getPrincipalKeyNumberMap(requestSharedDataContext); + + principalPasswordMap.put(evaluatedPrincipal, result.getPassword()); + principalKeyNumberMap.put(evaluatedPrincipal, result.getKeyNumber()); + } } } } @@ -168,25 +182,25 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { * principal is a user principal * @param kerberosConfiguration the kerberos-env configuration properties * @param kerberosOperationHandler the KerberosOperationHandler for the relevant KDC - * @param actionLog the logger (may be null if no logging is desired) - * @return a CreatePrincipalResult containing the generated password and key number value + * @param regenerateKeytabs true if this was triggered in response to regenerating keytab files; false otherwise + * @param actionLog the logger (may be null if no logging is desired) @return a CreatePrincipalResult containing the generated password and key number value */ public CreatePrincipalResult createPrincipal(String principal, boolean isServicePrincipal, Map<String, String> kerberosConfiguration, KerberosOperationHandler kerberosOperationHandler, - ActionLog actionLog) { + boolean regenerateKeytabs, ActionLog actionLog) { // in case this is called directly from TopologyManager there's no HostRoleCommand CreatePrincipalKerberosAuditEvent.CreatePrincipalKerberosAuditEventBuilder auditEventBuilder = CreatePrincipalKerberosAuditEvent.builder() - .withTimestamp(System.currentTimeMillis()) - .withRequestId(getHostRoleCommand() != null ? getHostRoleCommand().getRequestId() : -1) - .withTaskId(getHostRoleCommand() != null ? getHostRoleCommand().getTaskId() : -1) - .withPrincipal(principal); + .withTimestamp(System.currentTimeMillis()) + .withRequestId(getHostRoleCommand() != null ? getHostRoleCommand().getRequestId() : -1) + .withTaskId(getHostRoleCommand() != null ? getHostRoleCommand().getTaskId() : -1) + .withPrincipal(principal); CreatePrincipalResult result = null; String message = null; - try { - message = String.format("Creating principal, %s", principal); + try { + message = String.format("Processing principal, %s", principal); LOG.info(message); if (actionLog != null) { actionLog.writeStdOut(message); @@ -218,45 +232,60 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { String password = securePasswordHelper.createSecurePassword(length, minLowercaseLetters, minUppercaseLetters, minDigits, minPunctuation, minWhitespace); try { + /** + * true indicates a new principal was created, false indicates an existing principal was updated + */ + boolean created; + Integer keyNumber; + + if (regenerateKeytabs) { + try { + keyNumber = kerberosOperationHandler.setPrincipalPassword(principal, password); + created = false; + } catch (KerberosPrincipalDoesNotExistException e) { + message = String.format("Principal, %s, does not exist, creating new principal", principal); + LOG.warn(message); + if (actionLog != null) { + actionLog.writeStdOut(message); + } - if (kerberosOperationHandler.principalExists(principal)) { - // Create a new password since we need to know what it is. - // A new password/key would have been generated after exporting the keytab anyways. - message = String.format("Principal, %s, already exists, setting new password", principal); - LOG.warn(message); - if (actionLog != null) { - actionLog.writeStdOut(message); + keyNumber = kerberosOperationHandler.createPrincipal(principal, password, isServicePrincipal); + created = true; } - - Integer keyNumber = kerberosOperationHandler.setPrincipalPassword(principal, password); - - if (keyNumber != null) { - result = new CreatePrincipalResult(principal, password, keyNumber); - message = String.format("Successfully set password for %s", principal); - LOG.debug(message); - } else { - message = String.format("Failed to set password for %s - unknown reason", principal); - LOG.error(message); + } else { + try { + keyNumber = kerberosOperationHandler.createPrincipal(principal, password, isServicePrincipal); + created = true; + } catch (KerberosPrincipalAlreadyExistsException e) { + message = String.format("Principal, %s, already exists, setting new password", principal); + LOG.warn(message); if (actionLog != null) { - actionLog.writeStdErr(message); + actionLog.writeStdOut(message); } + + keyNumber = kerberosOperationHandler.setPrincipalPassword(principal, password); + created = false; } - } else { - message = String.format("Creating new principal, %s", principal); - LOG.debug(message); + } - Integer keyNumber = kerberosOperationHandler.createPrincipal(principal, password, isServicePrincipal); + if (keyNumber != null) { + result = new CreatePrincipalResult(principal, password, keyNumber); - if (keyNumber != null) { - result = new CreatePrincipalResult(principal, password, keyNumber); + if (created) { message = String.format("Successfully created new principal, %s", principal); - LOG.debug(message); } else { + message = String.format("Successfully set password for %s", principal); + } + LOG.debug(message); + } else { + if (created) { message = String.format("Failed to create principal, %s - unknown reason", principal); - LOG.error(message); - if (actionLog != null) { - actionLog.writeStdErr(message); - } + } else { + message = String.format("Failed to set password for %s - unknown reason", principal); + } + LOG.error(message); + if (actionLog != null) { + actionLog.writeStdErr(message); } } @@ -272,7 +301,7 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { } } } finally { - if(result == null) { + if (result == null) { auditEventBuilder.withReasonOfFailure(message == null ? "Unknown error" : message); } auditLog(auditEventBuilder.build()); http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/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 2bdcd81..c28b725 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 @@ -29,7 +29,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentMap; /** @@ -48,6 +50,12 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction { private KerberosPrincipalDAO kerberosPrincipalDAO; /** + * A set of visited principal names used to prevent unnecessary processing on already processed + * principal names + */ + private Set<String> seenPrincipals = new HashSet<String>(); + + /** * Called to execute this action. Upon invocation, calls * {@link KerberosServerAction#processIdentities(java.util.Map)} * to iterate through the Kerberos identity metadata and call @@ -88,60 +96,64 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction { Map<String, Object> requestSharedDataContext) throws AmbariException { - String message = String.format("Destroying identity, %s", evaluatedPrincipal); - LOG.info(message); - actionLog.writeStdOut(message); - DestroyPrincipalKerberosAuditEvent.DestroyPrincipalKerberosAuditEventBuilder auditEventBuilder = DestroyPrincipalKerberosAuditEvent.builder() - .withTimestamp(System.currentTimeMillis()) - .withRequestId(getHostRoleCommand().getRequestId()) - .withTaskId(getHostRoleCommand().getTaskId()) - .withPrincipal(evaluatedPrincipal); + // Only process this principal if we haven't already processed it + if (!seenPrincipals.contains(evaluatedPrincipal)) { + seenPrincipals.add(evaluatedPrincipal); - try { + String message = String.format("Destroying identity, %s", evaluatedPrincipal); + LOG.info(message); + actionLog.writeStdOut(message); + DestroyPrincipalKerberosAuditEvent.DestroyPrincipalKerberosAuditEventBuilder auditEventBuilder = DestroyPrincipalKerberosAuditEvent.builder() + .withTimestamp(System.currentTimeMillis()) + .withRequestId(getHostRoleCommand().getRequestId()) + .withTaskId(getHostRoleCommand().getTaskId()) + .withPrincipal(evaluatedPrincipal); try { - operationHandler.removePrincipal(evaluatedPrincipal); - } catch (KerberosOperationException e) { - message = String.format("Failed to remove identity for %s from the KDC - %s", evaluatedPrincipal, e.getMessage()); - LOG.warn(message); - actionLog.writeStdErr(message); - auditEventBuilder.withReasonOfFailure(message); - } + try { + operationHandler.removePrincipal(evaluatedPrincipal); + } catch (KerberosOperationException e) { + message = String.format("Failed to remove identity for %s from the KDC - %s", evaluatedPrincipal, e.getMessage()); + LOG.warn(message); + actionLog.writeStdErr(message); + auditEventBuilder.withReasonOfFailure(message); + } - try { - KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); + try { + KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); - if (principalEntity != null) { - String cachedKeytabPath = principalEntity.getCachedKeytabPath(); + if (principalEntity != null) { + String cachedKeytabPath = principalEntity.getCachedKeytabPath(); - kerberosPrincipalDAO.remove(principalEntity); + kerberosPrincipalDAO.remove(principalEntity); - // If a cached keytabs file exists for this principal, delete it. - if (cachedKeytabPath != null) { - if (!new File(cachedKeytabPath).delete()) { - LOG.debug(String.format("Failed to remove cached keytab for %s", evaluatedPrincipal)); + // If a cached keytabs file exists for this principal, delete it. + if (cachedKeytabPath != null) { + if (!new File(cachedKeytabPath).delete()) { + LOG.debug(String.format("Failed to remove cached keytab for %s", evaluatedPrincipal)); + } + } } - } - } - // delete Ambari server keytab - String hostName = identityRecord.get(KerberosIdentityDataFileReader.HOSTNAME); - if (hostName != null && hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME)) { - String keytabFilePath = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_PATH); - if (keytabFilePath != null) { - if (!new File(keytabFilePath).delete()) { - LOG.debug(String.format("Failed to remove ambari keytab for %s", evaluatedPrincipal)); + // delete Ambari server keytab + String hostName = identityRecord.get(KerberosIdentityDataFileReader.HOSTNAME); + if (hostName != null && hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME)) { + String keytabFilePath = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_PATH); + if (keytabFilePath != null) { + if (!new File(keytabFilePath).delete()) { + LOG.debug(String.format("Failed to remove ambari keytab for %s", evaluatedPrincipal)); + } + } } + } catch (Throwable t) { + message = String.format("Failed to remove identity for %s from the Ambari database - %s", evaluatedPrincipal, t.getMessage()); + LOG.warn(message); + actionLog.writeStdErr(message); + auditEventBuilder.withReasonOfFailure(message); } + } finally { + auditLog(auditEventBuilder.build()); } - } catch (Throwable t) { - message = String.format("Failed to remove identity for %s from the Ambari database - %s", evaluatedPrincipal, t.getMessage()); - LOG.warn(message); - actionLog.writeStdErr(message); - auditEventBuilder.withReasonOfFailure(message); - } - } finally { - auditLog(auditEventBuilder.build()); } // There is no reason to fail this task if an identity was not removed. The cluster will work http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java index ddb2769..228b2a37 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java @@ -23,6 +23,25 @@ package org.apache.ambari.server.serveraction.kerberos; */ public class KerberosMissingAdminCredentialsException extends KerberosOperationException { /** + * The default error message to use when handling this exception + */ + private static final String DEFAULT_MESSAGE = "Missing KDC administrator credentials.\n" + + "The KDC administrator credentials must be set as a persisted or temporary credential resource." + + "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" + + "{\n" + + " \"Credential\" : {\n" + + " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" + + " }\n" + + "}"; + + /** + * Constructor using the default missing credentials message. + */ + public KerberosMissingAdminCredentialsException() { + this(DEFAULT_MESSAGE); + } + + /** * Constructor. * * @param message error message @@ -32,12 +51,21 @@ public class KerberosMissingAdminCredentialsException extends KerberosOperationE } /** + * Constructor using the default message. + * + * @param cause root cause + */ + public KerberosMissingAdminCredentialsException(Throwable cause) { + this(DEFAULT_MESSAGE, cause); + } + + /** * Constructor. * - * @param message error message - * @param cause root cause + * @param message error message + * @param cause root cause */ public KerberosMissingAdminCredentialsException(String message, Throwable cause) { super(message, cause); } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/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 f800072..7eb88bf 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 @@ -266,6 +266,7 @@ public abstract class KerberosOperationHandler { * @param service a boolean value indicating whether the principal is to be created as a service principal or not * @return an Integer declaring the generated key number * @throws KerberosOperationException + * @throws KerberosPrincipalAlreadyExistsException if the principal already exists */ public abstract Integer createPrincipal(String principal, String password, boolean service) throws KerberosOperationException; @@ -279,6 +280,7 @@ public abstract class KerberosOperationHandler { * @param password a String containing the password to set * @return an Integer declaring the new key number * @throws KerberosOperationException + * @throws KerberosPrincipalDoesNotExistException if the principal does not exist */ public abstract Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException; http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java new file mode 100644 index 0000000..2291c83 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java @@ -0,0 +1,45 @@ +/* + * 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; + +/** + * KerberosPrincipalAlreadyExistsException is a KerberosOperationException thrown in the event a + * request to create a new princip7als was made but the princial already exists in the KDC. + */ +public class KerberosPrincipalAlreadyExistsException extends KerberosOperationException { + + /** + * Creates a new KerberosPrincipalAlreadyExistsException with a message + * + * @param message a String containing the message indicating the reason for this exception + */ + public KerberosPrincipalAlreadyExistsException(String message) { + super(message); + } + + /** + * Creates a new KerberosPrincipalAlreadyExistsException with a message and a cause + * + * @param message a String containing the message indicating the reason for this exception + * @param cause a Throwable declaring the previously thrown Throwable that led to this exception + */ + public KerberosPrincipalAlreadyExistsException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java new file mode 100644 index 0000000..cb8b56a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java @@ -0,0 +1,45 @@ +/* + * 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; + +/** + * KerberosPrincipalDoesNotExistException is a KerberosOperationException thrown in the event a + * request to modify an existing principal was made but the princial does not exist in the KDC. + */ +public class KerberosPrincipalDoesNotExistException extends KerberosOperationException { + + /** + * Creates a new KerberosPrincipalDoesNotExistException with a message + * + * @param message a String containing the message indicating the reason for this exception + */ + public KerberosPrincipalDoesNotExistException(String message) { + super(message); + } + + /** + * Creates a new KerberosPrincipalDoesNotExistException with a message and a cause + * + * @param message a String containing the message indicating the reason for this exception + * @param cause a Throwable declaring the previously thrown Throwable that led to this exception + */ + public KerberosPrincipalDoesNotExistException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/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 90858fb..f48052f 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 @@ -165,10 +165,11 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @param password a String containing the password to use when creating the principal * @param service a boolean value indicating whether the principal is to be created as a service principal or not * @return an Integer declaring the generated 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 + * @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 KerberosPrincipalAlreadyExistsException if the principal already exists + * @throws KerberosOperationException if an unexpected error occurred */ @Override public Integer createPrincipal(String principal, String password, boolean service) @@ -193,6 +194,8 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { String stdOut = result.getStdout(); if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) { return getKeyNumber(principal); + } else if ((stdOut != null) && stdOut.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()); @@ -211,10 +214,11 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @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 KerberosOperationException if an unexpected error occurred + * @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 { @@ -228,9 +232,19 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { throw new KerberosOperationException("Failed to set password - no password specified"); } else { // Create the kdamin query: change_password <-randkey|-pw <password>> <principal> - invokeKAdmin(String.format("change_password -pw \"%s\" %s", password, principal)); + ShellCommandUtil.Result result = invokeKAdmin(String.format("change_password -pw \"%s\" %s", password, principal)); - return getKeyNumber(principal); + String stdOut = result.getStdout(); + if ((stdOut != null) && stdOut.contains(String.format("Password for \"%s\" changed", principal))) { + return getKeyNumber(principal); + } else if ((stdOut != null) && stdOut.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())); + } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json index 34de6a8..d84ed02 100644 --- a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json +++ b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json @@ -12,6 +12,9 @@ "name": "METRICS_COLLECTOR", "identities": [ { + "name": "/HDFS/NAMENODE/hdfs" + }, + { "name": "ams_hbase_master_hbase", "principal": { "value": "amshbase/_HOST@${realm}", http://git-wip-us.apache.org/repos/asf/ambari/blob/7c6a4090/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 7c70e5e..84f0bac 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 @@ -2603,7 +2603,7 @@ public class KerberosHelperTest extends EasyMockSupport { Capture<? extends String> capturePrincipalForKeytab = newCapture(CaptureType.ALL); CreatePrincipalsServerAction createPrincipalsServerAction = injector.getInstance(CreatePrincipalsServerAction.class); - expect(createPrincipalsServerAction.createPrincipal(capture(capturePrincipal), eq(false), anyObject(Map.class), anyObject(KerberosOperationHandler.class), isNull(ActionLog.class))) + expect(createPrincipalsServerAction.createPrincipal(capture(capturePrincipal), eq(false), anyObject(Map.class), anyObject(KerberosOperationHandler.class), eq(false), isNull(ActionLog.class))) .andReturn(new CreatePrincipalsServerAction.CreatePrincipalResult("anything", "password", 1)) .times(3); @@ -3214,20 +3214,19 @@ public class KerberosHelperTest extends EasyMockSupport { KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class); boolean managingIdentities = !Boolean.FALSE.equals(manageIdentities); - final Map<String, String> kerberosEnvProperties = createMock(Map.class); - expect(kerberosEnvProperties.get("kdc_type")).andReturn("mit-kdc").anyTimes(); - expect(kerberosEnvProperties.get("realm")).andReturn("FOOBAR.COM").anyTimes(); - - expect(kerberosEnvProperties.get("manage_identities")) - .andReturn((manageIdentities == null) + final Map<String, String> kerberosEnvProperties = new HashMap<String,String>(); + kerberosEnvProperties.put("kdc_type","mit-kdc"); + kerberosEnvProperties.put("realm","FOOBAR.COM"); + kerberosEnvProperties.put("manage_identities","FOOBAR.COM"); + kerberosEnvProperties.put("manage_identities", + (manageIdentities == null) ? null - : ((manageIdentities) ? "true" : "false")) - .anyTimes(); + : ((manageIdentities) ? "true" : "false")); final Config kerberosEnvConfig = createMock(Config.class); expect(kerberosEnvConfig.getProperties()).andReturn(kerberosEnvProperties).anyTimes(); - final Map<String, String> krb5ConfProperties = createMock(Map.class); + final Map<String, String> krb5ConfProperties = new HashMap<String, String>(); final Config krb5ConfConfig = createMock(Config.class); expect(krb5ConfConfig.getProperties()).andReturn(krb5ConfProperties).anyTimes(); @@ -3252,20 +3251,6 @@ public class KerberosHelperTest extends EasyMockSupport { expect(schKerberosClient.getHostName()).andReturn("host1").anyTimes(); expect(schKerberosClient.getState()).andReturn(State.INSTALLED).anyTimes(); - final ServiceComponentHost sch1 = createMock(ServiceComponentHost.class); - expect(sch1.getServiceName()).andReturn("SERVICE1").anyTimes(); - expect(sch1.getServiceComponentName()).andReturn("COMPONENT1").anyTimes(); - expect(sch1.getHostName()).andReturn("host1").anyTimes(); - - final ServiceComponentHost sch2 = createStrictMock(ServiceComponentHost.class); - expect(sch2.getServiceName()).andReturn("SERVICE2").anyTimes(); - expect(sch2.getServiceComponentName()).andReturn("COMPONENT3").anyTimes(); - - final ServiceComponentHost sch3 = createStrictMock(ServiceComponentHost.class); - expect(sch3.getServiceName()).andReturn("SERVICE3").anyTimes(); - expect(sch3.getServiceComponentName()).andReturn("COMPONENT3").anyTimes(); - expect(sch3.getHostName()).andReturn("host1").anyTimes(); - final ServiceComponent serviceComponentKerberosClient = createNiceMock(ServiceComponent.class); expect(serviceComponentKerberosClient.getName()).andReturn(Role.KERBEROS_CLIENT.name()).anyTimes(); expect(serviceComponentKerberosClient.getServiceComponentHosts()).andReturn(Collections.singletonMap("host1", schKerberosClient)).anyTimes(); @@ -3299,16 +3284,13 @@ public class KerberosHelperTest extends EasyMockSupport { } }) .anyTimes(); - expect(cluster.getServiceComponentHosts("host1")) + expect(cluster.getServiceComponentHosts(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name())) .andReturn(new ArrayList<ServiceComponentHost>() { { - add(sch1); - add(sch2); - add(sch3); add(schKerberosClient); } }) - .once(); + .anyTimes(); expect(cluster.getCurrentStackVersion()) .andReturn(new StackId("HDP", "2.2")) .anyTimes(); @@ -3325,21 +3307,11 @@ public class KerberosHelperTest extends EasyMockSupport { }).anyTimes(); final Clusters clusters = injector.getInstance(Clusters.class); - expect(clusters.getHostsForCluster("c1")) - .andReturn(new HashMap<String, Host>() { - { - put("host1", host); - } - }) - .once(); expect(clusters.getHost("host1")) .andReturn(host) .once(); final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class); - expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, "host1")) - .andReturn(Collections.<String, Map<String, String>>emptyMap()) - .once(); expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null)) .andReturn(Collections.<String, Map<String, String>>emptyMap()) .once(); @@ -3505,37 +3477,24 @@ public class KerberosHelperTest extends EasyMockSupport { } }) .anyTimes(); - expect(cluster.getServiceComponentHosts("host1")) + expect(cluster.getServiceComponentHosts(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name())) .andReturn(new ArrayList<ServiceComponentHost>() { { - add(sch1); - add(sch2); - add(sch3); add(schKerberosClient); } }) - .once(); + .anyTimes(); expect(cluster.getCurrentStackVersion()) .andReturn(new StackId("HDP", "2.2")) .anyTimes(); expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>()).anyTimes(); final Clusters clusters = injector.getInstance(Clusters.class); - expect(clusters.getHostsForCluster("c1")) - .andReturn(new HashMap<String, Host>() { - { - put("host1", host); - } - }) - .once(); expect(clusters.getHost("host1")) .andReturn(host) .once(); final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class); - expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, "host1")) - .andReturn(Collections.<String, Map<String, String>>emptyMap()) - .once(); expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null)) .andReturn(Collections.<String, Map<String, String>>emptyMap()) .once();
