/* * 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 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.ServiceComponentHost; import org.apache.ambari.server.state.kerberos.KerberosDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * PrepareKerberosIdentitiesServerAction is a ServerAction implementation that prepares metadata needed * to process Kerberos identities (principals and keytabs files). */ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerberosServerAction { private final static Logger LOG = LoggerFactory.getLogger(PrepareKerberosIdentitiesServerAction.class); /** * Called to execute this action. Upon invocation, calls * {@link KerberosServerAction#processIdentities(Map)} * to iterate through the Kerberos identity metadata and call * {@link PrepareKerberosIdentitiesServerAction#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"); } KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster); Collection<String> identityFilter = getIdentityFilter(); List<ServiceComponentHost> schToProcess = getServiceComponentHostsToProcess(cluster, kerberosDescriptor, identityFilter); Map<String, String> commandParameters = getCommandParameters(); String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY); Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>(); 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)); } KerberosHelper kerberosHelper = getKerberosHelper(); Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); Set<String> services = cluster.getServices().keySet(); Map<String, Set<String>> propertiesToRemove = new HashMap<>(); Map<String, Set<String>> propertiesToIgnore = new HashMap<>(); boolean includeAmbariIdentity = "true".equalsIgnoreCase(getCommandParameterValue(commandParameters, KerberosServerAction.INCLUDE_AMBARI_IDENTITY)); // 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); kerberosHelper.applyStackAdvisorUpdates(cluster, services, configurations, kerberosConfigurations, propertiesToIgnore, propertiesToRemove, true); if ("true".equalsIgnoreCase(getCommandParameterValue(commandParameters, UPDATE_CONFIGURATIONS))) { processAuthToLocalRules(cluster, kerberosDescriptor, schToProcess, kerberosConfigurations, getDefaultRealm(commandParameters)); processConfigurationChanges(dataDirectory, kerberosConfigurations, propertiesToRemove); } return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr()); } @Override protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal, KerberosOperationHandler operationHandler, Map<String, String> kerberosConfiguration, Map<String, Object> requestSharedDataContext) throws AmbariException { throw new UnsupportedOperationException(); } /** * Calls {@link KerberosHelper#getServiceComponentHostsToProcess(Cluster, KerberosDescriptor, Map, Collection, Collection, KerberosHelper.Command)} * with no filter on ServiceComponentHosts * <p/> * The <code>shouldProcessCommand</code> implementation passed to KerberosHelper#getServiceComponentHostsToProcess * always returns true, indicating to process all ServiceComponentHosts. * * @param cluster the cluster * @param kerberosDescriptor the current Kerberos descriptor * @param identityFilter a list of identities to include, or all if null @return the list of ServiceComponentHosts to process * @throws AmbariException * @see KerberosHelper#getServiceComponentHostsToProcess(Cluster, KerberosDescriptor, Map, Collection, Collection, KerberosHelper.Command) */ protected List<ServiceComponentHost> getServiceComponentHostsToProcess(Cluster cluster, KerberosDescriptor kerberosDescriptor, Collection<String> identityFilter) throws AmbariException { return getKerberosHelper().getServiceComponentHostsToProcess(cluster, kerberosDescriptor, getServiceComponentFilter(), getHostFilter(), identityFilter, new KerberosHelper.Command<Boolean, ServiceComponentHost>() { @Override public Boolean invoke(ServiceComponentHost sch) throws AmbariException { return true; } }); } /** * Calls {@link KerberosHelper#getKerberosDescriptor(Cluster)} * * @param cluster cluster instance * @return the kerberos descriptor associated with the specified cluster * @throws AmbariException if unable to obtain the descriptor * @see KerberosHelper#getKerberosDescriptor(Cluster) */ protected KerberosDescriptor getKerberosDescriptor(Cluster cluster) throws AmbariException { return getKerberosHelper().getKerberosDescriptor(cluster); } /** * Conditionally calls {@link KerberosHelper#setAuthToLocalRules(KerberosDescriptor, String, Map, Map, Map)} * if there are ServiceComponentHosts to process * * @param cluster cluster instance * @param kerberosDescriptor the current Kerberos descriptor * @param schToProcess a list of ServiceComponentHosts to process * @param kerberosConfigurations the Kerberos-specific configuration map * @param defaultRealm the default realm * @throws AmbariException * @see KerberosHelper#setAuthToLocalRules(KerberosDescriptor, String, Map, Map, Map) */ protected void processAuthToLocalRules(Cluster cluster, KerberosDescriptor kerberosDescriptor, List<ServiceComponentHost> schToProcess, Map<String, Map<String, String>> kerberosConfigurations, String defaultRealm) throws AmbariException { if (!schToProcess.isEmpty()) { actionLog.writeStdOut("Creating auth-to-local rules"); Map<String, Set<String>> services = new HashMap<>(); for (ServiceComponentHost sch : schToProcess) { Set<String> components = services.get(sch.getServiceName()); if (components == null) { components = new HashSet<>(); services.put(sch.getServiceName(), components); } components.add(sch.getServiceComponentName()); } KerberosHelper kerberosHelper = getKerberosHelper(); kerberosHelper.setAuthToLocalRules(kerberosDescriptor, defaultRealm, services, kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor.getProperties()), kerberosConfigurations); } } }