You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2015/08/05 17:24:19 UTC

ambari git commit: AMBARI-12604. When regenerating Kerberos principals, ensure Kerberos Descriptor changes are applied to services (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/trunk 77f2c23df -> eff899893


AMBARI-12604. When regenerating Kerberos principals, ensure Kerberos Descriptor changes are applied to services (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/eff89989
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/eff89989
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/eff89989

Branch: refs/heads/trunk
Commit: eff899893482c67ce6edd83f7a595e07fcbff834
Parents: 77f2c23
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Aug 5 11:24:09 2015 -0400
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Aug 5 11:24:09 2015 -0400

----------------------------------------------------------------------
 .../server/controller/KerberosHelperImpl.java   | 105 ++++++++----
 .../kerberos/KerberosServerAction.java          |  13 ++
 .../PrepareEnableKerberosServerAction.java      |  91 +----------
 .../PrepareKerberosIdentitiesServerAction.java  | 161 +++++++++++++++++--
 .../UpdateKerberosConfigsServerAction.java      |  10 +-
 .../server/controller/KerberosHelperTest.java   |   5 +
 6 files changed, 249 insertions(+), 136 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/eff89989/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 d9ae5d5..708d267 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
@@ -233,12 +233,17 @@ public class KerberosHelperImpl implements KerberosHelper {
                 throw new AmbariException(String.format("Custom operation %s can only be requested with the security type cluster property: %s", operation.name(), SecurityType.KERBEROS.name()));
               }
 
+              CreatePrincipalsAndKeytabsHandler handler = null;
+
               if ("true".equalsIgnoreCase(value) || "all".equalsIgnoreCase(value)) {
-                requestStageContainer = handle(cluster, getKerberosDetails(cluster, manageIdentities), null, null, null,
-                    requestStageContainer, new CreatePrincipalsAndKeytabsHandler(true));
+                handler = new CreatePrincipalsAndKeytabsHandler(true, true);
               } else if ("missing".equalsIgnoreCase(value)) {
-                requestStageContainer = handle(cluster, getKerberosDetails(cluster, manageIdentities), null, null, null,
-                    requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false));
+                handler = new CreatePrincipalsAndKeytabsHandler(false, true);
+              }
+
+              if (handler != null) {
+                requestStageContainer = handle(cluster, getKerberosDetails(cluster, manageIdentities),
+                    null, null, null, requestStageContainer, handler);
               } else {
                 throw new AmbariException(String.format("Unexpected directive value: %s", value));
               }
@@ -262,7 +267,7 @@ public class KerberosHelperImpl implements KerberosHelper {
                                                 RequestStageContainer requestStageContainer, Boolean manageIdentities)
       throws AmbariException, KerberosOperationException {
     return handle(cluster, getKerberosDetails(cluster, manageIdentities), serviceComponentFilter, identityFilter,
-        hostsToForceKerberosOperations, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false));
+        hostsToForceKerberosOperations, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false, false));
   }
 
   @Override
@@ -331,7 +336,7 @@ public class KerberosHelperImpl implements KerberosHelper {
   public RequestStageContainer createTestIdentity(Cluster cluster, Map<String, String> commandParamsStage,
                                                   RequestStageContainer requestStageContainer)
       throws KerberosOperationException, AmbariException {
-    return handleTestIdentity(cluster, getKerberosDetails(cluster, null), commandParamsStage, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false));
+    return handleTestIdentity(cluster, getKerberosDetails(cluster, null), commandParamsStage, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false, false));
   }
 
   @Override
@@ -2390,10 +2395,11 @@ public class KerberosHelperImpl implements KerberosHelper {
                              Map<String, ? extends Collection<String>> serviceComponentFilter, Collection<String> identityFilter, Set<String> hostsWithValidKerberosClient)
         throws AmbariException {
       // If there are principals, keytabs, and configurations to process, setup the following sages:
-      //  1) generate principals
-      //  2) generate keytab files
-      //  3) distribute keytab files
-      //  4) update configurations
+      //  1) prepare identities
+      //  2) generate principals
+      //  3) generate keytab files
+      //  4) distribute keytab files
+      //  5) update configurations
 
       // If a RequestStageContainer does not already exist, create a new one...
       if (requestStageContainer == null) {
@@ -2406,6 +2412,8 @@ public class KerberosHelperImpl implements KerberosHelper {
 
       Map<String, String> commandParameters = new HashMap<String, String>();
       commandParameters.put(KerberosServerAction.AUTHENTICATED_USER_NAME, ambariManagementController.getAuthName());
+      commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_NOTE, "Enabling Kerberos");
+      commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATIONS, "true");
       commandParameters.put(KerberosServerAction.DEFAULT_REALM, kerberosDetails.getDefaultRealm());
       if (dataDirectory != null) {
         commandParameters.put(KerberosServerAction.DATA_DIRECTORY, dataDirectory.getAbsolutePath());
@@ -2511,6 +2519,8 @@ public class KerberosHelperImpl implements KerberosHelper {
 
       Map<String, String> commandParameters = new HashMap<String, String>();
       commandParameters.put(KerberosServerAction.AUTHENTICATED_USER_NAME, ambariManagementController.getAuthName());
+      commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_NOTE, "Disabling Kerberos");
+      commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATIONS, "true");
       commandParameters.put(KerberosServerAction.DEFAULT_REALM, kerberosDetails.getDefaultRealm());
       if (dataDirectory != null) {
         commandParameters.put(KerberosServerAction.DATA_DIRECTORY, dataDirectory.getAbsolutePath());
@@ -2577,15 +2587,25 @@ public class KerberosHelperImpl implements KerberosHelper {
     private boolean regenerateAllKeytabs;
 
     /**
+     * A boolean value indicating whether to update service configurations (<code>true</code>)
+     * or ignore any potential configuration changes (<code>false</code>).
+     */
+    private boolean updateConfigurations;
+
+    /**
      * CreatePrincipalsAndKeytabsHandler constructor to set whether this instance should be used to
      * regenerate all keytabs or just the ones that have not been distributed
      *
      * @param regenerateAllKeytabs A boolean value indicating whether to create keytabs for all
      *                             principals (<code>true</code> or only the ones that are missing
      *                             (<code>false</code>)
+     * @param updateConfigurations A boolean value indicating whether to update service configurations
+     *                             (<code>true</code>) or ignore any potential configuration changes
+     *                             (<code>false</code>)
      */
-    public CreatePrincipalsAndKeytabsHandler(boolean regenerateAllKeytabs) {
+    public CreatePrincipalsAndKeytabsHandler(boolean regenerateAllKeytabs, boolean updateConfigurations) {
       this.regenerateAllKeytabs = regenerateAllKeytabs;
+      this.updateConfigurations = updateConfigurations;
     }
 
     @Override
@@ -2617,6 +2637,12 @@ public class KerberosHelperImpl implements KerberosHelper {
                              List<ServiceComponentHost> serviceComponentHosts,
                              Map<String, ? extends Collection<String>> serviceComponentFilter, Collection<String> identityFilter, Set<String> hostsWithValidKerberosClient)
         throws AmbariException {
+      // If there are principals and keytabs to process, setup the following sages:
+      //  1) prepare identities
+      //  2) generate principals
+      //  3) generate keytab files
+      //  4) distribute keytab files
+      //  5) update configurations (optional)
 
       // If a RequestStageContainer does not already exist, create a new one...
       if (requestStageContainer == null) {
@@ -2627,34 +2653,35 @@ public class KerberosHelperImpl implements KerberosHelper {
             actionManager);
       }
 
-      if (kerberosDetails.manageIdentities()) {
-        // If there are principals and keytabs to process, setup the following sages:
-        //  1) prepare identities
-        //  2) generate principals
-        //  3) generate keytab files
-        //  4) distribute keytab files
 
-        Map<String, String> commandParameters = new HashMap<String, String>();
-        commandParameters.put(KerberosServerAction.AUTHENTICATED_USER_NAME, ambariManagementController.getAuthName());
-        commandParameters.put(KerberosServerAction.DEFAULT_REALM, kerberosDetails.getDefaultRealm());
-        if (dataDirectory != null) {
-          commandParameters.put(KerberosServerAction.DATA_DIRECTORY, dataDirectory.getAbsolutePath());
-        }
-        if (serviceComponentFilter != null) {
-          commandParameters.put(KerberosServerAction.SERVICE_COMPONENT_FILTER, StageUtils.getGson().toJson(serviceComponentFilter));
-        }
-        if (identityFilter != null) {
-          commandParameters.put(KerberosServerAction.IDENTITY_FILTER, StageUtils.getGson().toJson(identityFilter));
-        }
+      Map<String, String> commandParameters = new HashMap<String, String>();
+      commandParameters.put(KerberosServerAction.AUTHENTICATED_USER_NAME, ambariManagementController.getAuthName());
+      commandParameters.put(KerberosServerAction.DEFAULT_REALM, kerberosDetails.getDefaultRealm());
+      if (dataDirectory != null) {
+        commandParameters.put(KerberosServerAction.DATA_DIRECTORY, dataDirectory.getAbsolutePath());
+      }
+      if (serviceComponentFilter != null) {
+        commandParameters.put(KerberosServerAction.SERVICE_COMPONENT_FILTER, StageUtils.getGson().toJson(serviceComponentFilter));
+      }
+      if (identityFilter != null) {
+        commandParameters.put(KerberosServerAction.IDENTITY_FILTER, StageUtils.getGson().toJson(identityFilter));
+      }
+
+      commandParameters.put(KerberosServerAction.REGENERATE_ALL, (regenerateAllKeytabs) ? "true" : "false");
+
+      if(updateConfigurations) {
+        commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_NOTE, "Updated Kerberos-related configurations");
+        commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATIONS, "true");
+      }
+
+      // *****************************************************************
+      // Create stage to create principals
+      addPrepareKerberosIdentitiesStage(cluster, clusterHostInfoJson, hostParamsJson, event,
+          commandParameters, roleCommandOrder, requestStageContainer);
 
+      if (kerberosDetails.manageIdentities()) {
         commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
         commandParameters.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL, getEncryptedAdministratorCredentials(cluster));
-        commandParameters.put(KerberosServerAction.REGENERATE_ALL, (regenerateAllKeytabs) ? "true" : "false");
-
-        // *****************************************************************
-        // Create stage to create principals
-        addPrepareKerberosIdentitiesStage(cluster, clusterHostInfoJson, hostParamsJson, event,
-            commandParameters, roleCommandOrder, requestStageContainer);
 
         // *****************************************************************
         // Create stage to create principals
@@ -2666,11 +2693,19 @@ public class KerberosHelperImpl implements KerberosHelper {
         addCreateKeytabFilesStage(cluster, clusterHostInfoJson, hostParamsJson, event,
             commandParameters, roleCommandOrder, requestStageContainer);
 
+        // *****************************************************************
         // Create stage to distribute keytabs
         addDistributeKeytabFilesStage(cluster, serviceComponentHosts, clusterHostInfoJson,
             hostParamsJson, commandParameters, roleCommandOrder, requestStageContainer, hostsWithValidKerberosClient);
       }
 
+      if(updateConfigurations) {
+        // *****************************************************************
+        // Create stage to update configurations of services
+        addUpdateConfigurationsStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters,
+            roleCommandOrder, requestStageContainer);
+      }
+
       return requestStageContainer.getLastStageId();
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/eff89989/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
index 57e5527..389f1b8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
@@ -78,6 +78,7 @@ public abstract class KerberosServerAction extends AbstractServerAction {
    * A (command parameter) property name used to hold the (serialized) identity filter list.
    */
   public static final String IDENTITY_FILTER = "identity_filter";
+
   /**
    * A (command parameter) property name used to hold the relevant KDC type value.  See
    * {@link org.apache.ambari.server.serveraction.kerberos.KDCType} for valid values
@@ -85,6 +86,18 @@ public abstract class KerberosServerAction extends AbstractServerAction {
   public static final String KDC_TYPE = "kdc_type";
 
   /**
+   * A (command parameter) property name used to hold a boolean value indicating whether configurations
+   * should be process to see if they need to be updated
+   */
+  public static final String UPDATE_CONFIGURATIONS = "update_configurations";
+
+  /**
+   * A (command parameter) property name used to hold the note to set when applying any
+   * configuration changes
+   */
+  public static final String UPDATE_CONFIGURATION_NOTE = "update_configuration_note";
+
+  /**
    * The prefix to use for the data directory name.
    */
   public static final String DATA_DIRECTORY_PREFIX = ".ambari_";

http://git-wip-us.apache.org/repos/asf/ambari/blob/eff89989/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
index 9caf7df..84248dc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
@@ -18,20 +18,14 @@
 
 package org.apache.ambari.server.serveraction.kerberos;
 
-import com.google.inject.Inject;
 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.SecurityState;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -42,18 +36,7 @@ import java.util.concurrent.ConcurrentMap;
  * PrepareEnableKerberosServerAction is a ServerAction implementation that prepares metadata needed
  * to enable Kerberos on the cluster.
  */
-public class PrepareEnableKerberosServerAction extends AbstractPrepareKerberosServerAction {
-  private final static Logger LOG = LoggerFactory.getLogger(PrepareEnableKerberosServerAction.class);
-
-  /**
-   * KerberosHelper
-   */
-  @Inject
-  private KerberosHelper kerberosHelper;
-
-  @Inject
-  private KerberosConfigDataFileWriterFactory kerberosConfigDataFileWriterFactory;
-
+public class PrepareEnableKerberosServerAction extends PrepareKerberosIdentitiesServerAction {
 
   /**
    * Called to execute this action.  Upon invocation, calls
@@ -78,18 +61,9 @@ public class PrepareEnableKerberosServerAction extends AbstractPrepareKerberosSe
       throw new AmbariException("Missing cluster object");
     }
 
-    KerberosDescriptor kerberosDescriptor = kerberosHelper.getKerberosDescriptor(cluster);
+    KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster);
     Collection<String> identityFilter = getIdentityFilter();
-    List<ServiceComponentHost> schToProcess = kerberosHelper.getServiceComponentHostsToProcess(cluster,
-        kerberosDescriptor,
-        getServiceComponentFilter(),
-        identityFilter,
-        new KerberosHelper.Command<Boolean, ServiceComponentHost>() {
-          @Override
-          public Boolean invoke(ServiceComponentHost sch) throws AmbariException {
-            return (sch.getDesiredSecurityState() == SecurityState.SECURED_KERBEROS) && (sch.getSecurityState() != SecurityState.SECURED_KERBEROS);
-          }
-        });
+    List<ServiceComponentHost> schToProcess = getServiceComponentHostsToProcess(cluster, kerberosDescriptor, identityFilter);
 
     Map<String, String> commandParameters = getCommandParameters();
     String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY);
@@ -105,16 +79,8 @@ public class PrepareEnableKerberosServerAction extends AbstractPrepareKerberosSe
     }
 
     processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory, kerberosConfigurations);
+    processAuthToLocalRules(cluster, kerberosDescriptor, schToProcess, kerberosConfigurations, getDefaultRealm(commandParameters));
 
-    if (!schToProcess.isEmpty()) {
-      actionLog.writeStdOut("Creating auth-to-local rules");
-      kerberosHelper.setAuthToLocalRules(kerberosDescriptor, cluster, getDefaultRealm(commandParameters),
-          kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor.getProperties()),
-          kerberosConfigurations);
-    }
-
-
-    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) {
@@ -123,54 +89,7 @@ public class PrepareEnableKerberosServerAction extends AbstractPrepareKerberosSe
     }
     clusterEnvProperties.put(KerberosHelper.SECURITY_ENABLED_PROPERTY_NAME, "true");
 
-    // 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);
-      }
-
-      File configFile = new File(dataDirectory, KerberosConfigDataFileWriter.DATA_FILE_NAME);
-      KerberosConfigDataFileWriter kerberosConfDataFileWriter = null;
-
-      actionLog.writeStdOut(String.format("Writing configuration changes metadata file to %s", configFile.getAbsolutePath()));
-      try {
-        kerberosConfDataFileWriter = kerberosConfigDataFileWriterFactory.createKerberosConfigDataFileWriter(configFile);
-
-        for (Map.Entry<String, Map<String, String>> entry : kerberosConfigurations.entrySet()) {
-          String type = entry.getKey();
-          Map<String, String> properties = entry.getValue();
-
-          if (properties != null) {
-            for (Map.Entry<String, String> configTypeEntry : properties.entrySet()) {
-              kerberosConfDataFileWriter.addRecord(type,
-                  configTypeEntry.getKey(),
-                  configTypeEntry.getValue(),
-                  KerberosConfigDataFileWriter.OPERATION_TYPE_SET);
-            }
-          }
-        }
-      } catch (IOException e) {
-        String message = String.format("Failed to write kerberos configurations file - %s", configFile.getAbsolutePath());
-        LOG.error(message, e);
-        actionLog.writeStdOut(message);
-        actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
-        throw new AmbariException(message, e);
-      } finally {
-        if (kerberosConfDataFileWriter != null) {
-          try {
-            kerberosConfDataFileWriter.close();
-          } catch (IOException e) {
-            String message = "Failed to close the kerberos configurations file writer";
-            LOG.warn(message, e);
-            actionLog.writeStdOut(message);
-            actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
-          }
-        }
-      }
-    }
+    processConfigurationChanges(dataDirectory, kerberosConfigurations);
 
     return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/eff89989/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
index 55f75ad..5f067ec 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
@@ -29,6 +29,8 @@ import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -48,6 +50,9 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
   @Inject
   private KerberosHelper kerberosHelper;
 
+  @Inject
+  private KerberosConfigDataFileWriterFactory kerberosConfigDataFileWriterFactory;
+
   /**
    * Called to execute this action.  Upon invocation, calls
    * {@link KerberosServerAction#processIdentities(Map)}
@@ -71,18 +76,9 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
       throw new AmbariException("Missing cluster object");
     }
 
-    KerberosDescriptor kerberosDescriptor = kerberosHelper.getKerberosDescriptor(cluster);
+    KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster);
     Collection<String> identityFilter = getIdentityFilter();
-    List<ServiceComponentHost> schToProcess = kerberosHelper.getServiceComponentHostsToProcess(cluster,
-        kerberosDescriptor,
-        getServiceComponentFilter(),
-        identityFilter,
-        new KerberosHelper.Command<Boolean, ServiceComponentHost>() {
-          @Override
-          public Boolean invoke(ServiceComponentHost sch) throws AmbariException {
-            return true;
-          }
-        });
+    List<ServiceComponentHost> schToProcess = getServiceComponentHostsToProcess(cluster, kerberosDescriptor, identityFilter);
 
     Map<String, String> commandParameters = getCommandParameters();
     String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY);
@@ -99,13 +95,154 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
 
     processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory, kerberosConfigurations);
 
+    if("true".equalsIgnoreCase(getCommandParameterValue(commandParameters, UPDATE_CONFIGURATIONS))) {
+      processAuthToLocalRules(cluster, kerberosDescriptor, schToProcess, kerberosConfigurations, getDefaultRealm(commandParameters));
+      processConfigurationChanges(dataDirectory, kerberosConfigurations);
+    }
 
     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 {
+  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, 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, KerberosHelper.Command)
+   */
+  protected List<ServiceComponentHost> getServiceComponentHostsToProcess(Cluster cluster,
+                                                                         KerberosDescriptor kerberosDescriptor,
+                                                                         Collection<String> identityFilter)
+      throws AmbariException {
+    return kerberosHelper.getServiceComponentHostsToProcess(cluster,
+        kerberosDescriptor,
+        getServiceComponentFilter(),
+        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 kerberosHelper.getKerberosDescriptor(cluster);
+  }
+
+  /**
+   * Conditionally calls {@link KerberosHelper#setAuthToLocalRules(KerberosDescriptor, Cluster, String, 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, Cluster, String, 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");
+      kerberosHelper.setAuthToLocalRules(kerberosDescriptor, cluster, defaultRealm,
+          kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor.getProperties()),
+          kerberosConfigurations);
+    }
+  }
+
+  /**
+   * Processes configuration changes to determine if any work needs to be done.
+   * <p/>
+   * If work is to be done, a data file containing the details is created so it they changes may be
+   * processed in the appropriate stage.
+   *
+   * @param dataDirectory          the directory in which to write the configuration changes data file
+   * @param kerberosConfigurations the Kerberos-specific configuration map
+   * @throws AmbariException
+   */
+  protected void processConfigurationChanges(String dataDirectory,
+                                             Map<String, Map<String, String>> kerberosConfigurations)
+      throws AmbariException {
+    actionLog.writeStdOut("Determining configuration changes");
+
+    // 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);
+      }
+
+      File configFile = new File(dataDirectory, KerberosConfigDataFileWriter.DATA_FILE_NAME);
+      KerberosConfigDataFileWriter kerberosConfDataFileWriter = null;
+
+      actionLog.writeStdOut(String.format("Writing configuration changes metadata file to %s", configFile.getAbsolutePath()));
+      try {
+        kerberosConfDataFileWriter = kerberosConfigDataFileWriterFactory.createKerberosConfigDataFileWriter(configFile);
+
+        for (Map.Entry<String, Map<String, String>> entry : kerberosConfigurations.entrySet()) {
+          String type = entry.getKey();
+          Map<String, String> properties = entry.getValue();
+
+          if (properties != null) {
+            for (Map.Entry<String, String> configTypeEntry : properties.entrySet()) {
+              kerberosConfDataFileWriter.addRecord(type,
+                  configTypeEntry.getKey(),
+                  configTypeEntry.getValue(),
+                  KerberosConfigDataFileWriter.OPERATION_TYPE_SET);
+            }
+          }
+        }
+      } catch (IOException e) {
+        String message = String.format("Failed to write kerberos configurations file - %s", configFile.getAbsolutePath());
+        LOG.error(message, e);
+        actionLog.writeStdOut(message);
+        actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+        throw new AmbariException(message, e);
+      } finally {
+        if (kerberosConfDataFileWriter != null) {
+          try {
+            kerberosConfDataFileWriter.close();
+          } catch (IOException e) {
+            String message = "Failed to close the kerberos configurations file writer";
+            LOG.warn(message, e);
+            actionLog.writeStdOut(message);
+            actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+          }
+        }
+      }
+    }
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/eff89989/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
index f2484e6..931806d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
@@ -120,9 +120,13 @@ public class UpdateKerberosConfigsServerAction extends AbstractServerAction {
           }
 
           if (!configTypes.isEmpty()) {
-            String configNote = cluster.getSecurityType() == SecurityType.KERBEROS
-                ? "Enabling Kerberos"
-                : "Disabling Kerberos";
+            String configNote = getCommandParameterValue(getCommandParameters(), KerberosServerAction.UPDATE_CONFIGURATION_NOTE);
+
+            if((configNote == null) || configNote.isEmpty()) {
+              configNote = cluster.getSecurityType() == SecurityType.KERBEROS
+                  ? "Enabling Kerberos"
+                  : "Disabling Kerberos";
+            }
 
             for (String configType : configTypes) {
               configHelper.updateConfigType(cluster, controller, configType,

http://git-wip-us.apache.org/repos/asf/ambari/blob/eff89989/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 467c3ac..5d84fbc 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
@@ -1483,6 +1483,11 @@ public class KerberosHelperTest extends EasyMockSupport {
       expect(requestStageContainer.getId()).andReturn(1L).once();
       requestStageContainer.addStages(anyObject(List.class));
       expectLastCall().once();
+      // Update Configurations Stage
+      expect(requestStageContainer.getLastStageId()).andReturn(1L).anyTimes();
+      expect(requestStageContainer.getId()).andReturn(1L).once();
+      requestStageContainer.addStages(anyObject(List.class));
+      expectLastCall().once();
       // Clean-up/Finalize Stage
       expect(requestStageContainer.getLastStageId()).andReturn(3L).anyTimes();
       expect(requestStageContainer.getId()).andReturn(1L).once();