/* * 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 java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.regex.Matcher; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.actionmanager.HostRoleStatus; import org.apache.ambari.server.agent.CommandReport; import org.apache.ambari.server.controller.KerberosHelper; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.ConfigHelper; import org.apache.ambari.server.state.PropertyInfo; import org.apache.ambari.server.state.SecurityState; import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.kerberos.KerberosDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; /** * PrepareEnableKerberosServerAction is a ServerAction implementation that prepares metadata needed * to enable Kerberos on the cluster. */ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosServerAction { private final static Logger LOG = LoggerFactory.getLogger(PrepareDisableKerberosServerAction.class); @Inject private ConfigHelper configHelper; /** * Called to execute this action. Upon invocation, calls * {@link KerberosServerAction#processIdentities(Map)} * to iterate through the Kerberos identity metadata and call * {@link PrepareDisableKerberosServerAction#processIdentities(Map)} * for each identity to process. * * @param requestSharedDataContext a Map to be used a shared data among all ServerActions related * to a given request * @return a CommandReport indicating the result of this action * @throws AmbariException * @throws InterruptedException */ @Override public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException { Cluster cluster = getCluster(); if (cluster == null) { throw new AmbariException("Missing cluster object"); } KerberosHelper kerberosHelper = getKerberosHelper(); KerberosDescriptor kerberosDescriptor = kerberosHelper.getKerberosDescriptor(cluster); Collection<String> identityFilter = getIdentityFilter(); List<ServiceComponentHost> schToProcess = kerberosHelper.getServiceComponentHostsToProcess(cluster, kerberosDescriptor, getServiceComponentFilter(), null, identityFilter, new KerberosHelper.Command<Boolean, ServiceComponentHost>() { @Override public Boolean invoke(ServiceComponentHost sch) throws AmbariException { return (sch.getDesiredSecurityState() == SecurityState.UNSECURED) && (sch.getSecurityState() != SecurityState.UNSECURED); } }); Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>(); Map<String, String> commandParameters = getCommandParameters(); String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY); int schCount = schToProcess.size(); if (schCount == 0) { actionLog.writeStdOut("There are no components to process"); } else if (schCount == 1) { actionLog.writeStdOut(String.format("Processing %d component", schCount)); } else { actionLog.writeStdOut(String.format("Processing %d components", schCount)); } Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); Set<String> services = cluster.getServices().keySet(); boolean includeAmbariIdentity = "true".equalsIgnoreCase(getCommandParameterValue(commandParameters, KerberosServerAction.INCLUDE_AMBARI_IDENTITY)); Map<String, Set<String>> propertiesToIgnore = new HashMap<>(); // Calculate the current host-specific configurations. These will be used to replace // variables within the Kerberos descriptor data Map<String, Map<String, String>> configurations = kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptorProperties); processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory, configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore); // Add auth-to-local configurations to the set of changes Set<String> authToLocalProperties = kerberosDescriptor.getAllAuthToLocalProperties(); if (authToLocalProperties != null) { for (String authToLocalProperty : authToLocalProperties) { Matcher m = KerberosDescriptor.AUTH_TO_LOCAL_PROPERTY_SPECIFICATION_PATTERN.matcher(authToLocalProperty); if (m.matches()) { String configType = m.group(1); String propertyName = m.group(2); if (configType == null) { configType = ""; } // Add existing auth_to_local configuration, if set Map<String, String> configuration = kerberosConfigurations.get(configType); if (configuration != null) { configuration.put(propertyName, "DEFAULT"); } } } } actionLog.writeStdOut("Determining configuration changes"); // Ensure the cluster-env/security_enabled flag is set properly Map<String, String> clusterEnvProperties = kerberosConfigurations.get(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE); if (clusterEnvProperties == null) { clusterEnvProperties = new HashMap<>(); kerberosConfigurations.put(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE, clusterEnvProperties); } clusterEnvProperties.put(KerberosHelper.SECURITY_ENABLED_PROPERTY_NAME, "false"); // If there are configurations to set, create a (temporary) data file to store the configuration // updates and fill it will the relevant configurations. if (!kerberosConfigurations.isEmpty()) { if (dataDirectory == null) { String message = "The data directory has not been set. Generated data can not be stored."; LOG.error(message); throw new AmbariException(message); } Map<String, Set<String>> configurationsToRemove = new HashMap<>(); // Fill the configurationsToRemove map with all Kerberos-related configurations. Values // needed to be kept will have new values from the stack definition and thus pruned from // this map. for (Map.Entry<String, Map<String, String>> entry : kerberosConfigurations.entrySet()) { configurationsToRemove.put(entry.getKey(), new HashSet<>(entry.getValue().keySet())); } // Remove cluster-env from the set of configurations to remove since it has no default set // or properties and the logic below will remove all from this set - which is not desirable. configurationsToRemove.remove("cluster-env"); if (!schToProcess.isEmpty()) { Set<String> visitedServices = new HashSet<>(); for (ServiceComponentHost sch : schToProcess) { String serviceName = sch.getServiceName(); if (!visitedServices.contains(serviceName)) { StackId stackVersion = sch.getStackVersion(); visitedServices.add(serviceName); if (stackVersion != null) { Set<PropertyInfo> serviceProperties = configHelper.getServiceProperties(stackVersion, serviceName, true); if (serviceProperties != null) { for (PropertyInfo propertyInfo : serviceProperties) { String filename = propertyInfo.getFilename(); if (filename != null) { String type = ConfigHelper.fileNameToConfigType(filename); String propertyName = propertyInfo.getName(); Map<String, String> kerberosConfiguration = kerberosConfigurations.get(type); if ((kerberosConfiguration != null) && (kerberosConfiguration.containsKey(propertyName))) { kerberosConfiguration.put(propertyName, propertyInfo.getValue()); } // Remove the relevant from the set of properties (for the given type) to remove Collection<String> propertiesToRemove = configurationsToRemove.get(type); if (propertiesToRemove != null) { propertiesToRemove.remove(propertyName); } } } } } } } } kerberosHelper.applyStackAdvisorUpdates(cluster, services, configurations, kerberosConfigurations, propertiesToIgnore, configurationsToRemove, false); processConfigurationChanges(dataDirectory, kerberosConfigurations, configurationsToRemove); } return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr()); } }