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/01/19 21:01:45 UTC

ambari git commit: AMBARI-9170. Principal creation for Active Directory accounts should be configurable (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/trunk 7c5fb7b53 -> 01fa8eb03


AMBARI-9170. Principal creation for Active Directory accounts should be configurable (rlevas)


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

Branch: refs/heads/trunk
Commit: 01fa8eb03bc1a7de7bb914a8d8bc468cd87c4bd5
Parents: 7c5fb7b
Author: Robert Levas <rl...@hortonworks.com>
Authored: Mon Jan 19 15:00:36 2015 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Mon Jan 19 15:00:42 2015 -0500

----------------------------------------------------------------------
 .../ambari/server/actionmanager/Stage.java      |  23 +-
 .../server/controller/KerberosHelper.java       |  67 +----
 .../internal/UpgradeResourceProvider.java       |   1 +
 .../serveraction/AbstractServerAction.java      |  35 +++
 .../kerberos/ADKerberosOperationHandler.java    | 288 +++++++++++++-----
 .../kerberos/KerberosOperationHandler.java      |  24 +-
 .../kerberos/KerberosServerAction.java          |  27 +-
 .../kerberos/MITKerberosOperationHandler.java   |  23 +-
 .../ambari/server/state/ConfigHelper.java       |   6 +-
 .../1.10.3-10/configuration/kerberos-env.xml    |  21 ++
 .../actionmanager/TestActionDBAccessorImpl.java |   2 +-
 .../actionmanager/TestActionScheduler.java      |   2 +-
 .../server/controller/KerberosHelperTest.java   |   2 +-
 .../serveraction/ServerActionExecutorTest.java  |   4 +-
 .../ADKerberosOperationHandlerTest.java         | 298 +++++++++++++++++--
 .../kerberos/KerberosOperationHandlerTest.java  |   7 +-
 .../kerberos/KerberosServerActionTest.java      |  11 +-
 .../MITKerberosOperationHandlerTest.java        |  18 +-
 18 files changed, 630 insertions(+), 229 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
index f0e4e9c..097145d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
@@ -328,6 +328,8 @@ public class Stage {
    *                      empty or null if no data is relevant
    * @param commandDetail a String declaring a descriptive name to pass to the action - null or an
    *                      empty string indicates no value is to be set
+   * @param configTags    a Map of configuration tags to set for this command - if null, no
+   *                      configurations will be available for the command
    * @param timeout       an Integer declaring the timeout for this action - if null, a default
    * @param retryAllowed   indicates whether retry after failure is allowed
    */
@@ -335,11 +337,12 @@ public class Stage {
                                                   String clusterName, ServiceComponentHostServerActionEvent event,
                                                   @Nullable Map<String, String> commandParams,
                                                   @Nullable String commandDetail,
+                                                  @Nullable Map<String, Map<String,String>> configTags,
                                                   @Nullable Integer timeout,
                                                   boolean retryAllowed) {
 
-    addServerActionCommand(actionName, role, command,
-        clusterName, StageUtils.getHostName(), event, commandParams, commandDetail, timeout, retryAllowed);
+    addServerActionCommand(actionName, role, command, clusterName, StageUtils.getHostName(), event,
+        commandParams, commandDetail, configTags, timeout, retryAllowed);
   }
 
   /**
@@ -363,14 +366,17 @@ public class Stage {
    *                      empty or null if no data is relevant
    * @param commandDetail a String declaring a descriptive name to pass to the action - null or an
    *                      empty string indicates no value is to be set
+   * @param configTags    a Map of configuration tags to set for this command - if null, no
+   *                      configurations will be available for the command
    * @param timeout       an Integer declaring the timeout for this action - if null, a default
-   * @param retryAllowed   indicates whether retry after failure is allowed
+   * @param retryAllowed  indicates whether retry after failure is allowed
    */
   public synchronized void addServerActionCommand(String actionName, Role role, RoleCommand command,
                                                   String clusterName, String hostName,
                                                   ServiceComponentHostServerActionEvent event,
                                                   @Nullable Map<String, String> commandParams,
                                                   @Nullable String commandDetail,
+                                                  @Nullable Map<String, Map<String,String>> configTags,
                                                   @Nullable Integer timeout, boolean retryAllowed) {
     ExecutionCommandWrapper commandWrapper =
         addGenericExecutionCommand(clusterName, hostName, role, command, event, retryAllowed);
@@ -386,6 +392,17 @@ public class Stage {
     }
     cmd.setCommandParams(cmdParams);
 
+    Map<String, Map<String, String>> configurations = new TreeMap<String, Map<String, String>>();
+    cmd.setConfigurations(configurations);
+
+    Map<String, Map<String, Map<String, String>>> configurationAttributes = new TreeMap<String, Map<String, Map<String, String>>>();
+    cmd.setConfigurationAttributes(configurationAttributes);
+
+    if (configTags == null) {
+      configTags = new TreeMap<String, Map<String, String>>();
+    }
+    cmd.setConfigurationTags(configTags);
+
     Map<String, String> roleParams = new HashMap<String, String>();
     roleParams.put(ServerAction.ACTION_NAME, actionName);
     cmd.setRoleParams(roleParams);

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
index 6d0e159..a425e95 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
@@ -219,18 +219,12 @@ public class KerberosHelper {
         kdcType = KDCType.MIT_KDC;
       }
 
-      KDCDetails kdcDetails = new KDCDetails(
-          kdcType,
-          (kerberosEnvProperties == null) ? null : kerberosEnvProperties.get("ldap_url"),
-          (kerberosEnvProperties == null) ? null : kerberosEnvProperties.get("container_dn")
-      );
-
       if ("true".equalsIgnoreCase(securityEnabled)) {
         LOG.info("Configuring Kerberos for realm {} on cluster, {}", defaultRealm, cluster.getClusterName());
-        requestStageContainer = handle(cluster, kerberosDescriptor, defaultRealm, kdcDetails, requestStageContainer, enableKerberosHandler);
+        requestStageContainer = handle(cluster, kerberosDescriptor, defaultRealm, kdcType, kerberosEnvProperties, requestStageContainer, enableKerberosHandler);
       } else if ("false".equalsIgnoreCase(securityEnabled)) {
         LOG.info("Disabling Kerberos from cluster, {}", cluster.getClusterName());
-        requestStageContainer = handle(cluster, kerberosDescriptor, defaultRealm, kdcDetails, requestStageContainer, disableKerberosHandler);
+        requestStageContainer = handle(cluster, kerberosDescriptor, defaultRealm, kdcType, kerberosEnvProperties, requestStageContainer, disableKerberosHandler);
       } else {
         String message = String.format("Invalid value for `security_enabled` property of cluster-env: %s", securityEnabled);
         LOG.error(message);
@@ -253,7 +247,8 @@ public class KerberosHelper {
    * @param cluster               the relevant Cluster
    * @param kerberosDescriptor    the (derived) KerberosDescriptor
    * @param realm                 the default Kerberos realm for the Cluster
-   * @param kdcDetails            a KDCDetails containing information about relevant KDC
+   * @param kdcType               a KDCType declaring the type of the relevant KDC
+   * @param kerberosEnvProperties a MAp of key/value pairs from the kerberos-env configuration
    * @param requestStageContainer a RequestStageContainer to place generated stages, if needed -
    *                              if null a new RequestStageContainer will be created.
    * @return the updated or a new RequestStageContainer containing the stages that need to be
@@ -263,8 +258,8 @@ public class KerberosHelper {
   @Transactional
   private RequestStageContainer handle(Cluster cluster,
                                        KerberosDescriptor kerberosDescriptor,
-                                       String realm, KDCDetails kdcDetails,
-                                       RequestStageContainer requestStageContainer,
+                                       String realm, KDCType kdcType,
+                                       Map<String, String> kerberosEnvProperties, RequestStageContainer requestStageContainer,
                                        Handler handler) throws AmbariException {
 
     Map<String, Service> services = cluster.getServices();
@@ -425,7 +420,7 @@ public class KerberosHelper {
                       "}"
               );
             } else {
-              KerberosOperationHandler operationHandler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kdcDetails.getKdcType());
+              KerberosOperationHandler operationHandler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kdcType);
 
               if (operationHandler == null) {
                 throw new AmbariException("Failed to get an appropriate Kerberos operation handler.");
@@ -434,7 +429,7 @@ public class KerberosHelper {
                 KerberosCredential kerberosCredentials = KerberosCredential.decrypt(credentials, key);
 
                 try {
-                  operationHandler.open(kerberosCredentials, realm, kdcDetails.getLdapUrl(), kdcDetails.getPrincipalContainerDn());
+                  operationHandler.open(kerberosCredentials, realm, kerberosEnvProperties);
                   if (!operationHandler.testAdministratorCredentials()) {
                     throw new IllegalArgumentException(
                         "Invalid KDC administrator credentials.\n" +
@@ -526,7 +521,7 @@ public class KerberosHelper {
 
         // Use the handler implementation to setup the relevant stages.
         int lastStageId = handler.createStages(cluster, hosts, kerberosConfigurations,
-            clusterHostInfoJson, hostParamsJson, event, roleCommandOrder, realm, kdcDetails,
+            clusterHostInfoJson, hostParamsJson, event, roleCommandOrder, realm, kdcType,
             dataDirectory, requestStageContainer, serviceComponentHostsToProcess);
 
         // Add the cleanup stage...
@@ -892,7 +887,7 @@ public class KerberosHelper {
                                         Class<? extends ServerAction> actionClass,
                                         ServiceComponentHostServerActionEvent event,
                                         Map<String, String> commandParameters, String commandDetail,
-                                        Integer timeout) {
+                                        Integer timeout) throws AmbariException {
 
     Stage stage = createNewStage(id, cluster, requestId, requestContext, clusterHostInfo, commandParams, hostParams);
     stage.addServerActionCommand(actionClass.getName(),
@@ -902,6 +897,7 @@ public class KerberosHelper {
         event,
         commandParameters,
         commandDetail,
+        ambariManagementController.findConfigurationTagsWithOverrides(cluster, null),
         timeout, false);
 
     return stage;
@@ -1017,7 +1013,7 @@ public class KerberosHelper {
      * @param event                  a ServiceComponentHostServerActionEvent to pass to any created tasks
      * @param roleCommandOrder       the RoleCommandOrder to use to generate the RoleGraph for any newly created Stages
      * @param realm                  a String declaring the cluster's Kerberos realm
-     * @param kdcDetails             a KDCDetails containing the information about the relevant KDC
+     * @param kdcType                a KDCType declaring the type of the relevant KDC
      * @param dataDirectory          a File pointing to the (temporary) data directory
      * @param requestStageContainer  a RequestStageContainer to store the new stages in, if null a
      *                               new RequestStageContainer will be created
@@ -1030,7 +1026,7 @@ public class KerberosHelper {
                      String clusterHostInfo, String hostParams,
                      ServiceComponentHostServerActionEvent event,
                      RoleCommandOrder roleCommandOrder,
-                     String realm, KDCDetails kdcDetails, File dataDirectory,
+                     String realm, KDCType kdcType, File dataDirectory,
                      RequestStageContainer requestStageContainer,
                      List<ServiceComponentHost> serviceComponentHosts)
         throws AmbariException;
@@ -1083,7 +1079,7 @@ public class KerberosHelper {
                             Map<String, Map<String, String>> kerberosConfigurations,
                             String clusterHostInfoJson, String hostParamsJson,
                             ServiceComponentHostServerActionEvent event,
-                            RoleCommandOrder roleCommandOrder, String realm, KDCDetails kdcDetails,
+                            RoleCommandOrder roleCommandOrder, String realm, KDCType kdcType,
                             File dataDirectory, RequestStageContainer requestStageContainer,
                             List<ServiceComponentHost> serviceComponentHosts)
         throws AmbariException {
@@ -1145,9 +1141,7 @@ public class KerberosHelper {
       Map<String, String> commandParameters = new HashMap<String, String>();
       commandParameters.put(KerberosServerAction.DATA_DIRECTORY, dataDirectory.getAbsolutePath());
       commandParameters.put(KerberosServerAction.DEFAULT_REALM, realm);
-      commandParameters.put(KerberosServerAction.KDC_TYPE, kdcDetails.getKdcType().name());
-      commandParameters.put(KerberosServerAction.KDC_LDAP_URL, kdcDetails.getLdapUrl());
-      commandParameters.put(KerberosServerAction.KDC_PRINCIPAL_CONTAINER_DN, kdcDetails.getPrincipalContainerDn());
+      commandParameters.put(KerberosServerAction.KDC_TYPE, kdcType.name());
       commandParameters.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL, getEncryptedAdministratorCredentials(cluster));
 
       // *****************************************************************
@@ -1284,7 +1278,7 @@ public class KerberosHelper {
                             Map<String, Map<String, String>> kerberosConfigurations,
                             String clusterHostInfoJson, String hostParamsJson,
                             ServiceComponentHostServerActionEvent event,
-                            RoleCommandOrder roleCommandOrder, String realm, KDCDetails kdcDetails,
+                            RoleCommandOrder roleCommandOrder, String realm, KDCType kdcType,
                             File dataDirectory, RequestStageContainer requestStageContainer,
                             List<ServiceComponentHost> serviceComponentHosts) {
       // TODO (rlevas): If there are principals, keytabs, and configurations to process, setup the following sages:
@@ -1295,33 +1289,4 @@ public class KerberosHelper {
       return -1;
     }
   }
-
-
-  /**
-   * KDCDetails is a helper class to hold the details of the relevant KDC so they may be passed
-   * around more easily.
-   */
-  private static class KDCDetails {
-    private final KDCType kdcType;
-    private final String ldapUrl;
-    private final String principalContainerDn;
-
-    public KDCDetails(KDCType kdcType, String ldapUrl, String principalContainerDn) {
-      this.kdcType = kdcType;
-      this.ldapUrl = ldapUrl;
-      this.principalContainerDn = principalContainerDn;
-    }
-
-    public KDCType getKdcType() {
-      return kdcType;
-    }
-
-    public String getLdapUrl() {
-      return ldapUrl;
-    }
-
-    public String getPrincipalContainerDn() {
-      return principalContainerDn;
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index befd014..da034ce 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -768,6 +768,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         new ServiceComponentHostServerActionEvent(StageUtils.getHostName(), System.currentTimeMillis()),
         commandParams,
         itemDetail,
+        null,
         Integer.valueOf(1200),
         allowRtery);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/AbstractServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/AbstractServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/AbstractServerAction.java
index 9882e73..ff396e6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/AbstractServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/AbstractServerAction.java
@@ -135,4 +135,39 @@ public abstract class AbstractServerAction implements ServerAction {
     }
   }
 
+  /**
+   * Attempts to safely retrieve a property with the specified name from the this action's relevant
+   * command parameters Map.
+   *
+   * @param propertyName a String declaring the name of the item from commandParameters to retrieve
+   * @return the value of the requested property, or null if not found or set
+   */
+  protected String getCommandParameterValue(String propertyName) {
+    Map<String, String> commandParameters = getCommandParameters();
+    return (commandParameters == null) ? null : commandParameters.get(propertyName);
+  }
+
+  /**
+   * Returns the configurations value from the ExecutionCommand
+   * <p/>
+   * The returned map should be assumed to be read-only.
+   *
+   * @return the (assumed read-only) configurations value from the ExecutionCommand
+   */
+  protected Map<String, Map<String, String>> getConfigurations() {
+    return (executionCommand == null) ? Collections.<String, Map<String, String>>emptyMap() : executionCommand.getConfigurations();
+  }
+
+  /**
+   * Returns the requested configuration Map from the ExecutionCommand
+   * <p/>
+   * The returned map should be assumed to be read-only.
+   *
+   * @param configurationName a String indicating the name of the configuration data to retrieve
+   * @return the (assumed read-only) configuration Map from the ExecutionCommand, or null if not available
+   */
+  protected Map<String, String> getConfiguration(String configurationName) {
+    return getConfigurations().get(configurationName);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/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 dce980d..20f7e60 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
@@ -19,16 +19,31 @@
 package org.apache.ambari.server.serveraction.kerberos;
 
 
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
 
 import javax.naming.*;
 import javax.naming.directory.*;
 import javax.naming.ldap.Control;
 import javax.naming.ldap.InitialLdapContext;
 import javax.naming.ldap.LdapContext;
+import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Implementation of <code>KerberosOperationHandler</code> to created principal in Active Directory
@@ -37,46 +52,76 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
 
   private static Log LOG = LogFactory.getLog(ADKerberosOperationHandler.class);
 
+  /**
+   * Regular expression to parse the different principal formats:
+   * primary/instance@REALM
+   * primary@REALM
+   * primary/instance
+   * primary
+   */
+  private static Pattern PATTERN_PRINCIPAL = Pattern.compile("^(([^ /@]+)(?:/([^ /@]+))?)(?:@(.+)?)?$");
+
   private static final String LDAP_CONTEXT_FACTORY_CLASS = "com.sun.jndi.ldap.LdapCtxFactory";
 
-  private String ldapUrl;
-  private String principalContainerDn;
+  public final static String KERBEROS_ENV_LDAP_URL = "ldap_url";
+  public final static String KERBEROS_ENV_PRINCIPAL_CONTAINER_DN = "container_dn";
+  public final static String KERBEROS_ENV_CREATE_ATTRIBUTES_TEMPLATE = "create_attributes_template";
 
-  private static final int ONE_LEVEL_SCOPE = SearchControls.ONELEVEL_SCOPE;
-  private static final String LDAP_ATUH_MECH_SIMPLE = "simple";
+  /**
+   * A String containing the URL for the LDAP interface for the relevant Active Directory
+   */
+  private String ldapUrl = null;
 
-  private LdapContext ldapContext;
-  private SearchControls searchControls;
+  /**
+   * A String containing the DN of the container to create new account in
+   */
+  private String principalContainerDn = null;
 
   /**
-   * Prepares and creates resources to be used by this KerberosOperationHandler.
-   * This method in this class would always throw <code>KerberosOperationException</code> reporting
-   * ldapUrl is not provided.
-   * Use <code>open(KerberosCredential administratorCredentials, String defaultRealm,
-   * String ldapUrl, String principalContainerDn)</code> for successful operation.
+   * A String containing the Velocity template to use to generate the JSON structure declaring the
+   * attributes to use to create new Active Directory accounts.
    * <p/>
-   * It is expected that this KerberosOperationHandler will not be used before this call.
-   *
-   * @param administratorCredentials a KerberosCredential containing the administrative credentials
-   *                                 for the relevant KDC
-   * @param realm                    a String declaring the  Kerberos realm (or domain)
+   * If this value is null, a default template will be used.
    */
-  @Override
-  public void open(KerberosCredential administratorCredentials, String realm)
-      throws KerberosOperationException {
-    open(administratorCredentials, realm, null, null);
-  }
+  private String createTemplate = null;
+
+  /**
+   * The relevant LDAP context, created upon opening this KerberosOperationHandler
+   */
+  private LdapContext ldapContext = null;
+
+  /**
+   * The relevant SearchControls, created upon opening this KerberosOperationHandler
+   */
+  private SearchControls searchControls = null;
+
+  /**
+   * VelocityEngine used to process the "create principal template" that is expected to generate
+   * a JSON structure declaring the attributes of the Active Directory account
+   */
+  private VelocityEngine velocityEngine = null;
+
+  /**
+   * The Gson instance to use to convert the template-generated JSON structure to a Map of attribute
+   * names to values.
+   */
+  private Gson gson = new Gson();
 
   /**
    * Prepares and creates resources to be used by this KerberosOperationHandler
    * <p/>
    * It is expected that this KerberosOperationHandler will not be used before this call.
+   * <p/>
+   * It is expected that the kerberosConfiguration Map has the following properties:
+   * <ul>
+   * <li>ldap_url - ldapUrl of ldap back end where principals would be created</li>
+   * <li>container_dn - DN of the container in ldap back end where principals would be created</li>
+   * </il>
    *
    * @param administratorCredentials a KerberosCredential containing the administrative credentials
    *                                 for the relevant KDC
    * @param realm                    a String declaring the default Kerberos realm (or domain)
-   * @param ldapUrl                  ldapUrl of ldap back end where principals would be created
-   * @param principalContainerDn     DN of the container in ldap back end where principals would be created
+   * @param kerberosConfiguration    a Map of key/value pairs containing data from the kerberos-env configuration set
    * @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
@@ -84,34 +129,45 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
    */
   @Override
   public void open(KerberosCredential administratorCredentials, String realm,
-                   String ldapUrl, String principalContainerDn)
-      throws KerberosOperationException {
+                   Map<String, String> kerberosConfiguration) throws KerberosOperationException {
 
     if (isOpen()) {
       close();
     }
 
     if (administratorCredentials == null) {
-      throw new KerberosAdminAuthenticationException("administrator Credential not provided");
+      throw new KerberosAdminAuthenticationException("administrator credentials not provided");
     }
     if (realm == null) {
       throw new KerberosRealmException("realm not provided");
     }
-    if (ldapUrl == null) {
+    if (kerberosConfiguration == null) {
+      throw new KerberosRealmException("kerberos-env configuration may not be null");
+    }
+
+    this.ldapUrl = kerberosConfiguration.get(KERBEROS_ENV_LDAP_URL);
+    if (this.ldapUrl == null) {
       throw new KerberosKDCConnectionException("ldapUrl not provided");
     }
-    if (principalContainerDn == null) {
+
+    this.principalContainerDn = kerberosConfiguration.get(KERBEROS_ENV_PRINCIPAL_CONTAINER_DN);
+    if (this.principalContainerDn == null) {
       throw new KerberosLDAPContainerException("principalContainerDn not provided");
     }
 
     setAdministratorCredentials(administratorCredentials);
     setDefaultRealm(realm);
 
-    this.ldapUrl = ldapUrl;
-    this.principalContainerDn = principalContainerDn;
     this.ldapContext = createLdapContext();
     this.searchControls = createSearchControls();
 
+    this.createTemplate = kerberosConfiguration.get(KERBEROS_ENV_CREATE_ATTRIBUTES_TEMPLATE);
+
+    this.velocityEngine = new VelocityEngine();
+    this.velocityEngine.init();
+
+    this.gson = new Gson();
+
     setOpen(true);
   }
 
@@ -122,11 +178,18 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
    */
   @Override
   public void close() throws KerberosOperationException {
-    if (ldapContext != null) {
+    this.searchControls = null;
+    this.velocityEngine = null;
+
+    this.gson = null;
+
+    if (this.ldapContext != null) {
       try {
-        ldapContext.close();
+        this.ldapContext.close();
       } catch (NamingException e) {
         throw new KerberosOperationException("Unexpected error", e);
+      } finally {
+        this.ldapContext = null;
       }
     }
 
@@ -199,52 +262,75 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
     }
 
     // TODO: (rlevas) pass components and realm in separately (AMBARI-9122)
-    String realm = getDefaultRealm();
-    int atIndex = principal.indexOf("@");
-    if (atIndex >= 0) {
-      realm = principal.substring(atIndex + 1);
-      principal = principal.substring(0, atIndex);
+    String realm = null;
+    String principal_primary = null;
+    String principal_instance = null;
+
+    Matcher matcher = PATTERN_PRINCIPAL.matcher(principal);
+    if (matcher.matches()) {
+      principal = matcher.group(1);
+      principal_primary = matcher.group(2);
+      principal_instance = matcher.group(3);
+      realm = matcher.group(4);
     }
 
-    if (realm == null) {
-      realm = "";
+    if ((realm == null) || realm.isEmpty()) {
+      realm = getDefaultRealm();
     }
 
-    Attributes attributes = new BasicAttributes();
-
-    Attribute objectClass = new BasicAttribute("objectClass");
-    objectClass.add("user");
-    attributes.put(objectClass);
+    Map<String, Object> context = new HashMap<String, Object>();
+    context.put("principal", principal);
+    context.put("principal_primary", principal_primary);
+    context.put("principal_instance", principal_instance);
+    context.put("realm", realm);
+    context.put("realm_lowercase", (realm == null) ? null : realm.toLowerCase());
+    context.put("password", password);
+    context.put("is_service", service);
+    context.put("container_dn", this.principalContainerDn);
 
-    Attribute cn = new BasicAttribute("cn");
-    cn.add(principal);
-    attributes.put(cn);
+    Map<String, Object> data = processCreateTemplate(context);
 
-    Attribute upn = new BasicAttribute("userPrincipalName");
-    upn.add(String.format("%s@%s", principal, realm.toLowerCase()));
-    attributes.put(upn);
-
-    if (service) {
-      Attribute spn = new BasicAttribute("servicePrincipalName");
-      spn.add(principal);
-      attributes.put(spn);
+    Attributes attributes = new BasicAttributes();
+    String cn = null;
+
+    if (data != null) {
+      for (Map.Entry<String, Object> entry : data.entrySet()) {
+        String key = entry.getKey();
+        Object value = entry.getValue();
+
+        if ("unicodePwd".equals(key)) {
+          if (value instanceof String) {
+            Attribute passwordAttr = new BasicAttribute("unicodePwd");  // password
+            try {
+              passwordAttr.add(((String) value).getBytes("UTF-16LE"));
+            } catch (UnsupportedEncodingException ue) {
+              throw new KerberosOperationException("Can not encode password with UTF-16LE", ue);
+            }
+            attributes.put(passwordAttr);
+          }
+        } else {
+          Attribute attribute = new BasicAttribute(key);
+          if (value instanceof Collection) {
+            for (Object object : (Collection) value) {
+              attribute.add(object);
+            }
+          } else {
+            attribute.add(value);
+
+            if ("cn".equals(key) && (value != null)) {
+              cn = value.toString();
+            }
+          }
+          attributes.put(attribute);
+        }
+      }
     }
 
-    Attribute uac = new BasicAttribute("userAccountControl");  // userAccountControl
-    uac.add("512");
-    attributes.put(uac);
-
-    Attribute passwordAttr = new BasicAttribute("unicodePwd");  // password
-    String quotedPasswordVal = "\"" + password + "\"";
-    try {
-      passwordAttr.add(quotedPasswordVal.getBytes("UTF-16LE"));
-    } catch (UnsupportedEncodingException ue) {
-      throw new KerberosOperationException("Can not encode password with UTF-16LE", ue);
+    if (cn == null) {
+      cn = String.format("%s@%s", principal, realm);
     }
-    attributes.put(passwordAttr);
-
     try {
-      Name name = new CompositeName().add("cn=" + principal + "," + principalContainerDn);
+      Name name = new CompositeName().add(String.format("cn=%s,%s", cn, principalContainerDn));
       ldapContext.createSubcontext(name, attributes);
     } catch (NamingException ne) {
       throw new KerberosOperationException("Can not create principal : " + principal, ne);
@@ -357,7 +443,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
     properties.put(Context.PROVIDER_URL, ldapUrl);
     properties.put(Context.SECURITY_PRINCIPAL, administratorCredentials.getPrincipal());
     properties.put(Context.SECURITY_CREDENTIALS, administratorCredentials.getPassword());
-    properties.put(Context.SECURITY_AUTHENTICATION, LDAP_ATUH_MECH_SIMPLE);
+    properties.put(Context.SECURITY_AUTHENTICATION, "simple");
     properties.put(Context.REFERRAL, "follow");
     properties.put("java.naming.ldap.factory.socket", TrustingSSLSocketFactory.class.getName());
 
@@ -413,9 +499,71 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
    */
   protected SearchControls createSearchControls() {
     SearchControls searchControls = new SearchControls();
-    searchControls.setSearchScope(ONE_LEVEL_SCOPE);
+    searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
     searchControls.setReturningAttributes(new String[]{"cn"});
     return searchControls;
   }
 
+  /**
+   * Processes a Velocity template to generate a map of attributes and values to use to create
+   * Active Directory accounts.
+   * <p/>
+   * If a template was not set, a default template will be used.
+   *
+   * @param context a map of properties to pass to the Velocity engine
+   * @return a Map of attribute names and values to use for creating an Active Directory account
+   * @throws KerberosOperationException if an error occurs processing the template.
+   */
+  protected Map<String, Object> processCreateTemplate(Map<String, Object> context)
+      throws KerberosOperationException {
+
+    if (velocityEngine == null) {
+      throw new KerberosOperationException("The Velocity Engine must not be null");
+    }
+    if (gson == null) {
+      throw new KerberosOperationException("The JSON parser must not be null");
+    }
+
+    Map<String, Object> data = null;
+    String template;
+    StringWriter stringWriter = new StringWriter();
+
+    if ((createTemplate == null) || createTemplate.isEmpty()) {
+      template = "{" +
+          "\"objectClass\": [\"top\", \"person\", \"organizationalPerson\", \"user\"]," +
+          "\"cn\": \"$principal\"," +
+          "#if( $is_service )" +
+          "  \"servicePrincipalName\": \"$principal\"," +
+          "#end" +
+          "\"userPrincipalName\": \"$principal@$realm.toLowerCase()\"," +
+          "\"unicodePwd\": \"\\\"$password\\\"\"," +
+          "\"accountExpires\": \"0\"," +
+          "\"userAccountControl\": \"512\"" +
+          "}";
+    } else {
+      template = createTemplate;
+    }
+
+    try {
+      if (velocityEngine.evaluate(new VelocityContext(context), stringWriter, "Active Directory principal create template", template)) {
+        String json = stringWriter.toString();
+        Type type = new TypeToken<Map<String, Object>>() {
+        }.getType();
+
+        data = gson.fromJson(json, type);
+      }
+    } catch (ParseErrorException e) {
+      LOG.warn("Failed to parse Active Directory create principal template", e);
+      throw new KerberosOperationException("Failed to parse Active Directory create principal template", e);
+    } catch (MethodInvocationException e) {
+      LOG.warn("Failed to process Active Directory create principal template", e);
+      throw new KerberosOperationException("Failed to process Active Directory create principal template", e);
+    } catch (ResourceNotFoundException e) {
+      LOG.warn("Failed to process Active Directory create principal template", e);
+      throw new KerberosOperationException("Failed to process Active Directory create principal template", e);
+    }
+
+    return data;
+  }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/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 49f573e..7a9233b 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
@@ -120,18 +120,6 @@ public abstract class KerberosOperationHandler {
   }
 
   /**
-   * Prepares and creates resources to be used by this KerberosOperationHandler
-   * <p/>
-   * It is expected that this KerberosOperationHandler will not be used before this call.
-   *
-   * @param administratorCredentials a KerberosCredential containing the administrative credentials
-   *                                 for the relevant KDC
-   * @param defaultRealm             a String declaring the default Kerberos realm (or domain)
-   */
-  public abstract void open(KerberosCredential administratorCredentials, String defaultRealm)
-      throws KerberosOperationException;
-
-  /**
    * Prepares and creates resources to be used by this KerberosOperationHandler.
    * Implementation in this class is ignoring parameters ldapUrl and principalContainerDn and delegate to
    * <code>open(KerberosCredential administratorCredentials, String defaultRealm)</code>
@@ -142,14 +130,10 @@ public abstract class KerberosOperationHandler {
    * @param administratorCredentials a KerberosCredential containing the administrative credentials
    *                                 for the relevant KDC
    * @param defaultRealm             a String declaring the default Kerberos realm (or domain)
-   * @param ldapUrl                  ldapUrl of ldap back end where principals would be created
-   * @param principalContainerDn     DN of the container in ldap back end where principals would be created
+   * @param kerberosConfiguration    a Map of key/value pairs containing data from the kerberos-env configuration set
    */
-  public void open(KerberosCredential administratorCredentials, String defaultRealm,
-                   String ldapUrl, String principalContainerDn)
-      throws KerberosOperationException {
-    open(administratorCredentials, defaultRealm);
-  }
+  public abstract void open(KerberosCredential administratorCredentials, String defaultRealm, Map<String, String> kerberosConfiguration)
+      throws KerberosOperationException;
 
   /**
    * Closes and cleans up any resources used by this KerberosOperationHandler
@@ -178,7 +162,7 @@ public abstract class KerberosOperationHandler {
    *
    * @param principal a String containing the principal to add
    * @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
+   * @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
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/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 b3592e6..e965bd5 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
@@ -70,18 +70,6 @@ public abstract class KerberosServerAction extends AbstractServerAction {
   public static final String KDC_TYPE = "kdc_type";
 
   /**
-   * A (command parameter) property name used to hold the URL for the LDAP interface to the KDC.
-   * This value may be null.
-   */
-  public static final String KDC_LDAP_URL = "kdc_ldap_url";
-
-  /**
-   * A (command parameter) property name used to hold the distinguished name (DN) of the container
-   * in which to store principals within the KDC.  This value may be null.
-   */
-  public static final String KDC_PRINCIPAL_CONTAINER_DN = "kdc_principal_container_dn";
-
-  /**
    * The prefix to use for the data directory name.
    */
   public static final String DATA_DIRECTORY_PREFIX = ".ambari_";
@@ -294,17 +282,6 @@ public abstract class KerberosServerAction extends AbstractServerAction {
   }
 
   /**
-   * Attempts to safely retrieve a property with the specified name from the this action's relevant
-   * command parameters Map.
-   *
-   * @param propertyName a String declaring the name of the item from commandParameters to retrieve
-   * @return the value of the requested property, or null if not found or set
-   */
-  protected String getCommandParameterValue(String propertyName) {
-    return getCommandParameterValue(getCommandParameters(), propertyName);
-  }
-
-  /**
    * Attempts to safely retrieve the "data_directory" property from the this action's relevant
    * command parameters Map.
    *
@@ -372,10 +349,8 @@ public abstract class KerberosServerAction extends AbstractServerAction {
               throw new AmbariException(message);
             }
 
-            String ldapUrl = getCommandParameterValue(KDC_LDAP_URL);
-            String principalContainerDn = getCommandParameterValue(KDC_PRINCIPAL_CONTAINER_DN);
             try {
-              handler.open(administratorCredential, defaultRealm, ldapUrl, principalContainerDn);
+              handler.open(administratorCredential, defaultRealm, getConfiguration("kerberos-env"));
             } catch (KerberosOperationException e) {
               String message = String.format("Failed to process the identities, could not properly open the KDC operation handler: %s",
                   e.getMessage());

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/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 23eed35..c79b846 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
@@ -28,6 +28,7 @@ import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -49,10 +50,28 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
   private final static Logger LOG = LoggerFactory.getLogger(MITKerberosOperationHandler.class);
 
 
+  /**
+   * Prepares and creates resources to be used by this KerberosOperationHandler
+   * <p/>
+   * It is expected that this KerberosOperationHandler will not be used before this call.
+   * <p/>
+   * The kerberosConfiguration Map is not being used.
+   *
+   * @param administratorCredentials a KerberosCredential containing the administrative credentials
+   *                                 for the relevant KDC
+   * @param realm                    a String declaring the default Kerberos realm (or domain)
+   * @param kerberosConfiguration    a Map of key/value pairs containing data from the kerberos-env configuration set
+   * @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
+   */
   @Override
-  public void open(KerberosCredential administratorCredentials, String defaultRealm) throws KerberosOperationException {
+  public void open(KerberosCredential administratorCredentials, String realm,
+                   Map<String, String> kerberosConfiguration)
+      throws KerberosOperationException {
     setAdministratorCredentials(administratorCredentials);
-    setDefaultRealm(defaultRealm);
+    setDefaultRealm(realm);
     setOpen(true);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index e2e8c09..122e0a3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -88,9 +88,9 @@ public class ConfigHelper {
   public Map<String, Map<String, String>> getEffectiveDesiredTags(
       Cluster cluster, String hostName) throws AmbariException {
 
-    Host host = clusters.getHost(hostName);
-
-    return getEffectiveDesiredTags(cluster, host.getDesiredHostConfigs(cluster));
+    Host host = (hostName == null) ? null : clusters.getHost(hostName);
+    Map<String, HostConfig> desiredHostConfigs = (host == null) ? null : host.getDesiredHostConfigs(cluster);
+    return getEffectiveDesiredTags(cluster, desiredHostConfigs);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
index 0ecf6c0..f44677f 100644
--- a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
+++ b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/configuration/kerberos-env.xml
@@ -36,4 +36,25 @@
     </description>
     <value></value>
   </property>
+
+  <property require-input="true">
+    <name>create_attributes_template</name>
+    <description>
+      A Velocity template to use to generate a JSON-formatted document containing the set of
+      attribute names and values needed to create a new Kerberos identity in the relevant KDC.
+    </description>
+    <value>
+{
+  "objectClass": ["top", "person", "organizationalPerson", "user"],
+  "cn": "$principal",
+  #if( $is_service )
+  "servicePrincipalName": "$principal",
+  #end
+  "userPrincipalName": "$principal@$realm.toLowerCase()",
+  "unicodePwd": "\"$password\"",
+  "accountExpires": "0",
+  "userAccountControl": "512"
+}
+    </value>
+  </property>
 </configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
index 2e79741..3c80b4e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
@@ -581,7 +581,7 @@ public class TestActionDBAccessorImpl {
     Stage s = new Stage(requestId, "/a/b", "cluster1", 1L, "action db accessor test",
         "", "commandParamsStage", "hostParamsStage");
     s.setStageId(stageId);
-    s.addServerActionCommand(serverActionName, Role.AMBARI_SERVER_ACTION, RoleCommand.ACTIONEXECUTE, clusterName, null, null, "command details", 300, false);
+    s.addServerActionCommand(serverActionName, Role.AMBARI_SERVER_ACTION, RoleCommand.ACTIONEXECUTE, clusterName, null, null, "command details", null, 300, false);
     List<Stage> stages = new ArrayList<Stage>();
     stages.add(s);
     final RequestResourceFilter resourceFilter = new RequestResourceFilter("AMBARI", "SERVER", Arrays.asList(hostname));

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
index c3418dc..139dff6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
@@ -769,7 +769,7 @@ public class TestActionScheduler {
         RoleCommand.EXECUTE, "cluster1",
         new ServiceComponentHostServerActionEvent(serverHostname, System.currentTimeMillis()),
         payload,
-        null, timeout, false);
+        null, null, timeout, false);
 
     return stage;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/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 8900a26..0b58fc0 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
@@ -88,7 +88,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(kerberosOperationHandlerFactory.getKerberosOperationHandler(KDCType.MIT_KDC))
         .andReturn(new KerberosOperationHandler() {
           @Override
-          public void open(KerberosCredential administratorCredentials, String defaultRealm) throws KerberosOperationException {
+          public void open(KerberosCredential administratorCredentials, String defaultRealm, Map<String, String> kerberosConfiguration) throws KerberosOperationException {
             setAdministratorCredentials(administratorCredentials);
             setDefaultRealm(defaultRealm);
             setOpen(true);

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/serveraction/ServerActionExecutorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/ServerActionExecutorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/ServerActionExecutorTest.java
index 73f7be7..3a1dea6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/ServerActionExecutorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/ServerActionExecutorTest.java
@@ -99,7 +99,7 @@ public class ServerActionExecutorTest {
         RoleCommand.EXECUTE,
         "cluster1", SERVER_HOST_NAME,
         new ServiceComponentHostServerActionEvent(StageUtils.getHostName(), System.currentTimeMillis()),
-        Collections.<String, String>emptyMap(), null, 1200, false);
+        Collections.<String, String>emptyMap(), null, null, 1200, false);
 
     final List<Stage> stages = new ArrayList<Stage>() {
       {
@@ -289,7 +289,7 @@ public class ServerActionExecutorTest {
     stage.addServerActionCommand(MockServerAction.class.getName(), Role.AMBARI_SERVER_ACTION,
         RoleCommand.EXECUTE, "cluster1",
         new ServiceComponentHostServerActionEvent(SERVER_HOST_NAME, System.currentTimeMillis()),
-        payload, "command detail", timeout, false);
+        payload, "command detail", null, timeout, false);
 
     return stage;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
index aad325a..6a89dbb 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.serveraction.kerberos;
 
+import junit.framework.Assert;
 import org.easymock.EasyMockSupport;
 import org.easymock.IAnswer;
 import org.junit.Ignore;
@@ -31,6 +32,10 @@ import javax.naming.directory.SearchResult;
 import javax.naming.ldap.Control;
 import javax.naming.ldap.LdapContext;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
 
 import static org.easymock.EasyMock.anyObject;
@@ -48,7 +53,12 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
   public void testOpenExceptionLdapUrlNotProvided() throws Exception {
     KerberosOperationHandler handler = new ADKerberosOperationHandler();
     KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
-    handler.open(kc, DEFAULT_REALM, null, DEFAULT_PRINCIPAL_CONTAINER_DN);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
     handler.close();
   }
 
@@ -56,19 +66,38 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
   public void testOpenExceptionPrincipalContainerDnNotProvided() throws Exception {
     KerberosOperationHandler handler = new ADKerberosOperationHandler();
     KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
-    handler.open(kc, DEFAULT_REALM, DEFAULT_LDAP_URL, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+      }
+    };
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
     handler.close();
   }
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testOpenExceptionAdminCredentialsNotProvided() throws Exception {
     KerberosOperationHandler handler = new ADKerberosOperationHandler();
-    handler.open(null, DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+    handler.open(null, DEFAULT_REALM, kerberosEnvMap);
     handler.close();
   }
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testTestAdministratorCredentialsIncorrectAdminPassword() throws Exception {
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, "wrong", null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+
     ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class)
         .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class))
         .createNiceMock();
@@ -82,14 +111,21 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, "wrong", null),
-        DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN);
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
     handler.testAdministratorCredentials();
     handler.close();
   }
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testTestAdministratorCredentialsIncorrectAdminPrincipal() throws Exception {
+    KerberosCredential kc = new KerberosCredential("wrong", DEFAULT_ADMIN_PASSWORD, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+
     ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class)
         .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class))
         .createNiceMock();
@@ -103,14 +139,21 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential("wrong", DEFAULT_ADMIN_PASSWORD, null),
-        DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN);
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
     handler.testAdministratorCredentials();
     handler.close();
   }
 
   @Test(expected = KerberosKDCConnectionException.class)
   public void testTestAdministratorCredentialsKDCConnectionException() throws Exception {
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, "invalid");
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+
     ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class)
         .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class))
         .createNiceMock();
@@ -124,8 +167,7 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null),
-        DEFAULT_REALM, "invalid", DEFAULT_PRINCIPAL_CONTAINER_DN);
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -133,6 +175,14 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
 
   @Test
   public void testTestAdministratorCredentialsSuccess() throws Exception {
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+
     ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class)
         .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class))
         .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createSearchControls"))
@@ -170,12 +220,197 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null),
-        DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN);
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
     handler.testAdministratorCredentials();
     handler.close();
   }
 
+  @Test
+  public void testProcessCreateTemplateDefault() throws Exception {
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+      }
+    };
+
+    ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class)
+        .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class))
+        .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createSearchControls"))
+        .createNiceMock();
+
+    expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class)))
+        .andAnswer(new IAnswer<LdapContext>() {
+          @Override
+          public LdapContext answer() throws Throwable {
+            LdapContext ldapContext = createNiceMock(LdapContext.class);
+            expect(ldapContext.search(anyObject(String.class), anyObject(String.class), anyObject(SearchControls.class)))
+                .andAnswer(new IAnswer<NamingEnumeration<SearchResult>>() {
+                  @Override
+                  public NamingEnumeration<SearchResult> answer() throws Throwable {
+                    NamingEnumeration<SearchResult> result = createNiceMock(NamingEnumeration.class);
+                    expect(result.hasMore()).andReturn(false).once();
+                    replay(result);
+                    return result;
+                  }
+                })
+                .once();
+            replay(ldapContext);
+            return ldapContext;
+          }
+        })
+        .once();
+    expect(handler.createSearchControls()).andAnswer(new IAnswer<SearchControls>() {
+      @Override
+      public SearchControls answer() throws Throwable {
+        SearchControls searchControls = createNiceMock(SearchControls.class);
+        replay(searchControls);
+        return searchControls;
+      }
+    }).once();
+
+    replayAll();
+
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
+
+    Map<String, Object> context = new HashMap<String, Object>();
+    context.put("principal", "nn/c6501.ambari.apache.org");
+    context.put("principal_primary", "nn");
+    context.put("principal_instance", "c6501.ambari.apache.org");
+    context.put("realm", "EXAMPLE.COM");
+    context.put("realm_lowercase", "example.com");
+    context.put("password", "secret");
+    context.put("is_service", true);
+    context.put("container_dn", "ou=cluster,DC=EXAMPLE,DC=COM");
+
+    Map<String, Object> data;
+
+    data = handler.processCreateTemplate(context);
+
+    Assert.assertNotNull(data);
+    Assert.assertEquals(7, data.size());
+    Assert.assertEquals(new ArrayList<String>(Arrays.asList("top", "person", "organizationalPerson", "user")), data.get("objectClass"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org", data.get("cn"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org", data.get("servicePrincipalName"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org@example.com", data.get("userPrincipalName"));
+    Assert.assertEquals("\"secret\"", data.get("unicodePwd"));
+    Assert.assertEquals("0", data.get("accountExpires"));
+    Assert.assertEquals("512", data.get("userAccountControl"));
+
+
+    context.put("is_service", false);
+    data = handler.processCreateTemplate(context);
+
+    Assert.assertNotNull(data);
+    Assert.assertEquals(6, data.size());
+    Assert.assertEquals(new ArrayList<String>(Arrays.asList("top", "person", "organizationalPerson", "user")), data.get("objectClass"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org", data.get("cn"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org@example.com", data.get("userPrincipalName"));
+    Assert.assertEquals("\"secret\"", data.get("unicodePwd"));
+    Assert.assertEquals("0", data.get("accountExpires"));
+    Assert.assertEquals("512", data.get("userAccountControl"));
+
+    handler.close();
+  }
+
+  @Test
+  public void testProcessCreateTemplateCustom() throws Exception {
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
+      {
+        put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
+        put(ADKerberosOperationHandler.KERBEROS_ENV_CREATE_ATTRIBUTES_TEMPLATE, "{" +
+            "  \"objectClass\": [" +
+            "    \"top\"," +
+            "    \"person\"," +
+            "    \"organizationalPerson\"," +
+            "    \"user\"" +
+            "  ]," +
+            "  \"cn\": \"$principal@$realm\"," +
+            "  \"dn\": \"$principal@$realm,$container_dn\"," +
+            "  \"distinguishedName\": \"$principal@$realm,$container_dn\"," +
+            "  \"sAMAccountName\": \"$principal\"," +
+            "  #if( $is_service )" +
+            "  \"servicePrincipalName\": \"$principal\"," +
+            "  #end" +
+            "  \"userPrincipalName\": \"$principal@$realm.toLowerCase()\"," +
+            "  \"unicodePwd\": \"`$password`\"," +
+            "  \"accountExpires\": \"0\"," +
+            "  \"userAccountControl\": \"66048\"" +
+            "}");
+      }
+    };
+
+    ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class)
+        .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class))
+        .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createSearchControls"))
+        .createNiceMock();
+
+    expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class)))
+        .andAnswer(new IAnswer<LdapContext>() {
+          @Override
+          public LdapContext answer() throws Throwable {
+            LdapContext ldapContext = createNiceMock(LdapContext.class);
+            expect(ldapContext.search(anyObject(String.class), anyObject(String.class), anyObject(SearchControls.class)))
+                .andAnswer(new IAnswer<NamingEnumeration<SearchResult>>() {
+                  @Override
+                  public NamingEnumeration<SearchResult> answer() throws Throwable {
+                    NamingEnumeration<SearchResult> result = createNiceMock(NamingEnumeration.class);
+                    expect(result.hasMore()).andReturn(false).once();
+                    replay(result);
+                    return result;
+                  }
+                })
+                .once();
+            replay(ldapContext);
+            return ldapContext;
+          }
+        })
+        .once();
+    expect(handler.createSearchControls()).andAnswer(new IAnswer<SearchControls>() {
+      @Override
+      public SearchControls answer() throws Throwable {
+        SearchControls searchControls = createNiceMock(SearchControls.class);
+        replay(searchControls);
+        return searchControls;
+      }
+    }).once();
+
+    replayAll();
+
+    handler.open(kc, DEFAULT_REALM, kerberosEnvMap);
+
+
+    Map<String, Object> context = new HashMap<String, Object>();
+    context.put("principal", "nn/c6501.ambari.apache.org");
+    context.put("principal_primary", "nn");
+    context.put("principal_instance", "c6501.ambari.apache.org");
+    context.put("realm", "EXAMPLE.COM");
+    context.put("realm_lowercase", "example.com");
+    context.put("password", "secret");
+    context.put("is_service", true);
+    context.put("container_dn", "ou=cluster,DC=EXAMPLE,DC=COM");
+
+    Map<String, Object> data = handler.processCreateTemplate(context);
+
+    Assert.assertNotNull(data);
+    Assert.assertEquals(10, data.size());
+    Assert.assertEquals(new ArrayList<String>(Arrays.asList("top", "person", "organizationalPerson", "user")), data.get("objectClass"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org@EXAMPLE.COM", data.get("cn"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org", data.get("servicePrincipalName"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org@example.com", data.get("userPrincipalName"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org", data.get("sAMAccountName"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org@EXAMPLE.COM,ou=cluster,DC=EXAMPLE,DC=COM", data.get("distinguishedName"));
+    Assert.assertEquals("nn/c6501.ambari.apache.org@EXAMPLE.COM,ou=cluster,DC=EXAMPLE,DC=COM", data.get("dn"));
+    Assert.assertEquals("`secret`", data.get("unicodePwd"));
+    Assert.assertEquals("0", data.get("accountExpires"));
+    Assert.assertEquals("66048", data.get("userAccountControl"));
+
+    handler.close();
+  }
+
   /**
    * Implementation to illustrate the use of operations on this class
    *
@@ -184,18 +419,6 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
   @Test
   @Ignore
   public void testLive() throws Throwable {
-
-    /* ******************************************************************************************
-     * SSL Certificate of AD should have been imported into truststore when that certificate
-     * is not issued by trusted authority. This is typical with self signed certificated in
-     * development environment.  To use specific trust store, set path to it in
-     * javax.net.ssl.trustStore System property.  Example:
-     *      System.setProperty(
-     *        "javax.net.ssl.trustStore",
-     *        "/tmp/workspace/ambari/apache-ambari-rd/cacerts"
-     *       );
-     * ****************************************************************************************** */
-
     ADKerberosOperationHandler handler = new ADKerberosOperationHandler();
     String principal = System.getProperty("principal");
     String password = System.getProperty("password");
@@ -224,16 +447,36 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
     }
 
     KerberosCredential credentials = new KerberosCredential(principal, password, null);
+    Map<String, String> kerberosEnvMap = new HashMap<String, String>();
+
+    kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, ldapUrl);
+    kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, containerDN);
 
-    handler.open(credentials, realm, ldapUrl, containerDN);
+    handler.open(credentials, realm, kerberosEnvMap);
 
     System.out.println("Test Admin Credentials: " + handler.testAdministratorCredentials());
     // does the principal already exist?
     System.out.println("Principal exists: " + handler.principalExists("nn/c1508.ambari.apache.org"));
 
     //create principal
-    handler.createPrincipal("nn/c1508.ambari.apache.org@" + DEFAULT_REALM.toLowerCase(), handler.createSecurePassword(), true);
-    handler.createPrincipal("nn/c1508.ambari.apache.org", handler.createSecurePassword(), true);
+//    handler.createPrincipal("nn/c1508.ambari.apache.org@" + DEFAULT_REALM, handler.createSecurePassword(), true);
+
+    handler.close();
+
+    kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_CREATE_ATTRIBUTES_TEMPLATE, "{" +
+        "\"objectClass\": [\"top\", \"person\", \"organizationalPerson\", \"user\"]," +
+        "\"distinguishedName\": \"CN=$principal@$realm,$container_dn\"," +
+        "#if( $is_service )" +
+        "\"servicePrincipalName\": \"$principal\"," +
+        "#end" +
+        "\"userPrincipalName\": \"$principal@$realm.toLowerCase()\"," +
+        "\"unicodePwd\": \"\\\"$password\\\"\"," +
+        "\"accountExpires\": \"0\"," +
+        "\"userAccountControl\": \"66048\"" +
+        "}");
+
+    handler.open(credentials, realm, kerberosEnvMap);
+    handler.createPrincipal("abcdefg/c1509.ambari.apache.org@" + DEFAULT_REALM, handler.createSecurePassword(), true);
 
     //update the password
     handler.setPrincipalPassword("nn/c1508.ambari.apache.org", handler.createSecurePassword());
@@ -243,5 +486,4 @@ public class ADKerberosOperationHandlerTest extends EasyMockSupport {
 
     handler.close();
   }
-
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
index 40686d6..2f205b2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java
@@ -30,6 +30,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public abstract class KerberosOperationHandlerTest {
@@ -204,7 +205,7 @@ public abstract class KerberosOperationHandlerTest {
     KerberosOperationHandler handler = new KerberosOperationHandler() {
 
       @Override
-      public void open(KerberosCredential administratorCredentials, String defaultRealm) throws KerberosOperationException {
+      public void open(KerberosCredential administratorCredentials, String defaultRealm, Map<String, String> kerberosConfiguration) throws KerberosOperationException {
         setAdministratorCredentials(administratorCredentials);
         setDefaultRealm(defaultRealm);
       }
@@ -220,7 +221,7 @@ public abstract class KerberosOperationHandlerTest {
       }
 
       @Override
-      public Integer createPrincipal(String principal, String password, boolean serivce) throws KerberosOperationException{
+      public Integer createPrincipal(String principal, String password, boolean service) throws KerberosOperationException {
         return 0;
       }
 
@@ -235,7 +236,7 @@ public abstract class KerberosOperationHandlerTest {
       }
     };
 
-    handler.open(new KerberosCredential("admin/admin", "hadoop", null), "EXAMPLE.COM");
+    handler.open(new KerberosCredential("admin/admin", "hadoop", null), "EXAMPLE.COM", null);
     return handler;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
index 5d72585..0b34a77 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
@@ -135,8 +135,8 @@ public class KerberosServerActionTest {
 
   @Test
   public void testGetCommandParameterValueStatic() throws Exception {
-    Assert.assertNull(action.getCommandParameterValue("nonexistingvalue"));
-    Assert.assertEquals("REALM.COM", action.getCommandParameterValue(KerberosServerAction.DEFAULT_REALM));
+    Assert.assertNull(KerberosServerAction.getCommandParameterValue(commandParams, "nonexistingvalue"));
+    Assert.assertEquals("REALM.COM", KerberosServerAction.getCommandParameterValue(commandParams, KerberosServerAction.DEFAULT_REALM));
   }
 
   @Test
@@ -171,13 +171,6 @@ public class KerberosServerActionTest {
   }
 
   @Test
-  public void testGetCommandParameterValue() throws Exception {
-    Assert.assertNull(action.getCommandParameterValue("invalid_parameter"));
-    Assert.assertEquals(commandParams.get(KerberosServerAction.DEFAULT_REALM),
-        action.getCommandParameterValue(KerberosServerAction.DEFAULT_REALM));
-  }
-
-  @Test
   public void testGetDataDirectoryPath() throws Exception {
     Assert.assertEquals(temporaryDirectory.getAbsolutePath(), action.getDataDirectoryPath());
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01fa8eb0/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
index bd0e938..d997159 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
@@ -39,7 +39,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
   @Test
   public void testSetPrincipalPasswordExceptions() throws Exception {
     MITKerberosOperationHandler handler = new MITKerberosOperationHandler();
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
 
     try {
       handler.setPrincipalPassword(DEFAULT_ADMIN_PRINCIPAL, null);
@@ -75,7 +75,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
   @Test
   public void testCreateServicePrincipalExceptions() throws Exception {
     MITKerberosOperationHandler handler = new MITKerberosOperationHandler();
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
 
     try {
       handler.createPrincipal(DEFAULT_ADMIN_PRINCIPAL, null, false);
@@ -134,7 +134,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -167,7 +167,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -200,7 +200,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -233,7 +233,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -266,7 +266,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
     Assert.assertFalse(handler.testAdministratorCredentials());
     handler.close();
   }
@@ -319,7 +319,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, null);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -346,7 +346,7 @@ public class MITKerberosOperationHandlerTest extends EasyMockSupport {
 
     KerberosCredential credentials = new KerberosCredential(principal, password, null);
 
-    handler.open(credentials, realm);
+    handler.open(credentials, realm, null);
     handler.testAdministratorCredentials();
     handler.close();
   }