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/09/04 16:56:26 UTC

[1/2] ambari git commit: AMBARI-12772. Adding host via blueprint fails on secure cluster (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/trunk 6c98f47a5 -> e681f2bf4


http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 d3e3fa4..6f36bf5 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
@@ -390,7 +390,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
         if((executableKadmin == null) || executableKadmin.isEmpty()) {
           throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened.");
         }
-        String adminPassword = administratorCredentials.getPassword();
+        char[] adminPassword = administratorCredentials.getPassword();
         String adminKeyTab = administratorCredentials.getKeytab();
 
         // Set the kdamin interface to be kadmin
@@ -418,7 +418,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
         } else if (adminPassword != null) {
           // Add password for administrative principal
           command.add("-w");
-          command.add(adminPassword);
+          command.add(String.valueOf(adminPassword));
         }
       }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
index 2a1ac3c..074fbb4 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
@@ -60,7 +60,7 @@ import com.google.inject.Injector;
 
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({ Configuration.class })
-@PowerMockIgnore( {"javax.management.*"})
+@PowerMockIgnore( {"javax.management.*", "javax.crypto.*"})
 public class ConfigurationTest {
   public TemporaryFolder temp = new TemporaryFolder();
   private Injector injector;

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 5d84fbc..f28a19b 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
@@ -258,22 +258,22 @@ public class KerberosHelperTest extends EasyMockSupport {
 
   @Test
   public void testEnableKerberos() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", "keytab"), "mit-kdc", "true", true, false);
+    testEnableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), "mit-kdc", "true", true, false);
   }
 
   @Test
   public void testEnableKerberos_ManageIdentitiesFalseKdcNone() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", "keytab"), "none", "false", true, false);
+    testEnableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), "none", "false", true, false);
   }
 
   @Test(expected = AmbariException.class)
   public void testEnableKerberos_ManageIdentitiesTrueKdcNone() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", "keytab"), "none", "true", true, false);
+    testEnableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), "none", "true", true, false);
   }
 
   @Test(expected = KerberosInvalidConfigurationException.class)
   public void testEnableKerberos_ManageIdentitiesTrueKdcNull() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", "keytab"), null, "true", true, false);
+    testEnableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), null, "true", true, false);
   }
 
   @Test(expected = KerberosMissingAdminCredentialsException.class)
@@ -289,7 +289,7 @@ public class KerberosHelperTest extends EasyMockSupport {
   @Test(expected = KerberosMissingAdminCredentialsException.class)
   public void testEnableKerberosInvalidCredentials() throws Exception {
     try {
-      testEnableKerberos(new KerberosCredential("invalid_principal", "password", "keytab"), "mit-kdc", "true", true, false);
+      testEnableKerberos(new KerberosCredential("invalid_principal", "password".toCharArray(), "keytab"), "mit-kdc", "true", true, false);
     } catch (IllegalArgumentException e) {
       Assert.assertTrue(e.getMessage().startsWith("Invalid KDC administrator credentials"));
       throw e;
@@ -298,17 +298,17 @@ public class KerberosHelperTest extends EasyMockSupport {
 
   @Test
   public void testEnableKerberos_GetKerberosDescriptorFromCluster() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", "keytab"), "mit-kdc", "true", true, false);
+    testEnableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), "mit-kdc", "true", true, false);
   }
 
   @Test
   public void testEnableKerberos_GetKerberosDescriptorFromStack() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", "keytab"), "mit-kdc", "true", false, true);
+    testEnableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), "mit-kdc", "true", false, true);
   }
 
   @Test
   public void testEnsureIdentities() throws Exception {
-    testEnsureIdentities(new KerberosCredential("principal", "password", "keytab"));
+    testEnsureIdentities(new KerberosCredential("principal", "password".toCharArray(), "keytab"));
   }
 
   @Test(expected = KerberosMissingAdminCredentialsException.class)
@@ -324,7 +324,7 @@ public class KerberosHelperTest extends EasyMockSupport {
   @Test(expected = KerberosMissingAdminCredentialsException.class)
   public void testEnsureIdentitiesInvalidCredentials() throws Exception {
     try {
-      testEnsureIdentities(new KerberosCredential("invalid_principal", "password", "keytab"));
+      testEnsureIdentities(new KerberosCredential("invalid_principal", "password".toCharArray(), "keytab"));
     } catch (IllegalArgumentException e) {
       Assert.assertTrue(e.getMessage().startsWith("Invalid KDC administrator credentials"));
       throw e;
@@ -332,7 +332,7 @@ public class KerberosHelperTest extends EasyMockSupport {
   }
   @Test
   public void testDeleteIdentities() throws Exception {
-    testDeleteIdentities(new KerberosCredential("principal", "password", "keytab"));
+    testDeleteIdentities(new KerberosCredential("principal", "password".toCharArray(), "keytab"));
   }
 
   @Test(expected = KerberosMissingAdminCredentialsException.class)
@@ -348,7 +348,7 @@ public class KerberosHelperTest extends EasyMockSupport {
   @Test(expected = KerberosMissingAdminCredentialsException.class)
   public void testDeleteIdentitiesInvalidCredentials() throws Exception {
     try {
-      testDeleteIdentities(new KerberosCredential("invalid_principal", "password", "keytab"));
+      testDeleteIdentities(new KerberosCredential("invalid_principal", "password".toCharArray(), "keytab"));
     } catch (IllegalArgumentException e) {
       Assert.assertTrue(e.getMessage().startsWith("Invalid KDC administrator credentials"));
       throw e;
@@ -382,37 +382,37 @@ public class KerberosHelperTest extends EasyMockSupport {
 
   @Test
   public void testRegenerateKeytabsValidateRequestStageContainer() throws Exception {
-    testRegenerateKeytabs(new KerberosCredential("principal", "password", "keytab"), true, false);
+    testRegenerateKeytabs(new KerberosCredential("principal", "password".toCharArray(), "keytab"), true, false);
   }
 
   @Test
   public void testRegenerateKeytabsValidateSkipInvalidHost() throws Exception {
-    testRegenerateKeytabs(new KerberosCredential("principal", "password", "keytab"), true, true);
+    testRegenerateKeytabs(new KerberosCredential("principal", "password".toCharArray(), "keytab"), true, true);
   }
 
   @Test
   public void testRegenerateKeytabs() throws Exception {
-    testRegenerateKeytabs(new KerberosCredential("principal", "password", "keytab"), false, false);
+    testRegenerateKeytabs(new KerberosCredential("principal", "password".toCharArray(), "keytab"), false, false);
   }
 
   @Test
   public void testDisableKerberos() throws Exception {
-    testDisableKerberos(new KerberosCredential("principal", "password", "keytab"), false, true);
+    testDisableKerberos(new KerberosCredential("principal", "password".toCharArray(), "keytab"), false, true);
   }
 
   @Test
   public void testCreateTestIdentity_ManageIdentitiesDefault() throws Exception {
-    testCreateTestIdentity(new KerberosCredential("principal", "password", "keytab"), null);
+    testCreateTestIdentity(new KerberosCredential("principal", "password".toCharArray(), "keytab"), null);
   }
 
   @Test
   public void testCreateTestIdentity_ManageIdentitiesTrue() throws Exception {
-    testCreateTestIdentity(new KerberosCredential("principal", "password", "keytab"), Boolean.TRUE);
+    testCreateTestIdentity(new KerberosCredential("principal", "password".toCharArray(), "keytab"), Boolean.TRUE);
   }
 
   @Test
   public void testCreateTestIdentity_ManageIdentitiesFalse() throws Exception {
-    testCreateTestIdentity(new KerberosCredential("principal", "password", "keytab"), Boolean.FALSE);
+    testCreateTestIdentity(new KerberosCredential("principal", "password".toCharArray(), "keytab"), Boolean.FALSE);
   }
 
   @Test(expected = KerberosMissingAdminCredentialsException.class)
@@ -432,7 +432,7 @@ public class KerberosHelperTest extends EasyMockSupport {
 
   @Test
   public void testDeleteTestIdentity() throws Exception {
-    testDeleteTestIdentity(new KerberosCredential("principal", "password", "keytab"));
+    testDeleteTestIdentity(new KerberosCredential("principal", "password".toCharArray(), "keytab"));
   }
 
   @Test(expected = IllegalArgumentException.class)
@@ -967,13 +967,6 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(cluster.getCurrentStackVersion())
         .andReturn(new StackId("HDP", "2.2"))
         .anyTimes();
-    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>() {{
-      if (kerberosCredential != null) {
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-      }
-    }}).anyTimes();
     expect(cluster.getServiceComponentHosts("KERBEROS", "KERBEROS_CLIENT")).andReturn(
         Arrays.asList(schKerberosClient)
     ).once();
@@ -1068,6 +1061,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     // Needed by infrastructure
     metaInfo.init();
 
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     kerberosHelper.toggleKerberos(cluster, SecurityType.KERBEROS, requestStageContainer, null);
 
     verifyAll();
@@ -1188,13 +1182,6 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(cluster.getCurrentStackVersion())
         .andReturn(new StackId("HDP", "2.2"))
         .anyTimes();
-    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>() {{
-      if (kerberosCredential != null) {
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-      }
-    }}).anyTimes();
 
     final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
     expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null))
@@ -1277,6 +1264,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     // Needed by infrastructure
     metaInfo.init();
 
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     kerberosHelper.toggleKerberos(cluster, SecurityType.NONE, requestStageContainer, true);
 
     verifyAll();
@@ -1413,13 +1401,6 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(cluster.getCurrentStackVersion())
         .andReturn(new StackId("HDP", "2.2"))
         .anyTimes();
-    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>() {{
-      if (kerberosCredential != null) {
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-      }
-    }}).anyTimes();
 
     final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
     expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null))
@@ -1502,6 +1483,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     // Needed by infrastructure
     metaInfo.init();
 
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     Assert.assertNotNull(kerberosHelper.executeCustomOperations(cluster, Collections.singletonMap("regenerate_keytabs", "true"), requestStageContainer, true));
 
     verifyAll();
@@ -1910,13 +1892,6 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(cluster.getCurrentStackVersion())
         .andReturn(new StackId("HDP", "2.2"))
         .anyTimes();
-    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>() {{
-      if (kerberosCredential != null) {
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-      }
-    }}).anyTimes();
 
     final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
     expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null))
@@ -2031,6 +2006,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     serviceComponentFilter.put("SERVICE3", Collections.singleton("COMPONENT3"));
     serviceComponentFilter.put("SERVICE1", null);
 
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     kerberosHelper.ensureIdentities(cluster, serviceComponentFilter, identityFilter, null, requestStageContainer, true);
 
     verifyAll();
@@ -2124,13 +2100,6 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(cluster.getCurrentStackVersion())
         .andReturn(new StackId("HDP", "2.2"))
         .anyTimes();
-    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>() {{
-      if (kerberosCredential != null) {
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-      }
-    }}).anyTimes();
 
     final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
     expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null))
@@ -2238,6 +2207,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     serviceComponentFilter.put("SERVICE3", Collections.singleton("COMPONENT3"));
     serviceComponentFilter.put("SERVICE1", null);
 
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     kerberosHelper.deleteIdentities(cluster, serviceComponentFilter, identityFilter, requestStageContainer, true);
 
     verifyAll();
@@ -2266,11 +2236,6 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(krb5ConfConfig.getProperties()).andReturn(krb5ConfProperties).anyTimes();
 
     final Map<String,Object> attributeMap = new HashMap<String, Object>();
-    if (kerberosCredential != null) {
-      attributeMap.put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-      attributeMap.put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-      attributeMap.put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-    }
 
     final Cluster cluster = createNiceMock(Cluster.class);
     expect(cluster.getDesiredConfigByType("krb5-conf")).andReturn(krb5ConfConfig).anyTimes();
@@ -2454,14 +2419,12 @@ public class KerberosHelperTest extends EasyMockSupport {
     injector.getInstance(AmbariMetaInfo.class).init();
 
     Map<String, String> commandParamsStage = new HashMap<String, String>();
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     kerberosHelper.createTestIdentity(cluster, commandParamsStage, requestStageContainer);
 
     verifyAll();
 
     if (managingIdentities) {
-      String serviceCheckID = (String) cluster.getSessionAttributes().get("_kerberos_internal_service_check_identifier");
-      Assert.assertNotNull(serviceCheckID);
-
       Assert.assertTrue(commandParamsStage.containsKey("principal_name"));
       Assert.assertEquals("${kerberos-env/service_check_principal_name}@${realm}", commandParamsStage.get("principal_name"));
 
@@ -2560,13 +2523,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(cluster.getCurrentStackVersion())
         .andReturn(new StackId("HDP", "2.2"))
         .anyTimes();
-    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>() {{
-      if (kerberosCredential != null) {
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PRINCIPAL, kerberosCredential.getPrincipal());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_PASSWORD, kerberosCredential.getPassword());
-        put("kerberos_admin/" + KerberosCredential.KEY_NAME_KEYTAB, kerberosCredential.getKeytab());
-      }
-    }}).anyTimes();
+    expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>()).anyTimes();
 
     final Clusters clusters = injector.getInstance(Clusters.class);
     expect(clusters.getHostsForCluster("c1"))
@@ -2653,14 +2610,11 @@ public class KerberosHelperTest extends EasyMockSupport {
     // Needed by infrastructure
     injector.getInstance(AmbariMetaInfo.class).init();
 
-    String serviceCheckID = "some_random_value";
-
-    cluster.getSessionAttributes().put("_kerberos_internal_service_check_identifier", serviceCheckID);
-
     Map<String, String> commandParamsStage = new HashMap<String, String>();
-    commandParamsStage.put("principal_name", "${cluster-env/smokeuser}_" + serviceCheckID + "@${realm}");
-    commandParamsStage.put("keytab_file", "${keytab_dir}/kerberos.service_check." + serviceCheckID + ".keytab");
+    commandParamsStage.put("principal_name", "${cluster-env/smokeuser}@${realm}");
+    commandParamsStage.put("keytab_file", "${keytab_dir}/kerberos.service_check.keytab");
 
+    kerberosHelper.setKDCCredentials(kerberosCredential);
     kerberosHelper.deleteTestIdentity(cluster, commandParamsStage, requestStageContainer);
 
     verifyAll();

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
index 51f2220..ef1a9c8 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialProviderTest.java
@@ -18,43 +18,29 @@
 package org.apache.ambari.server.security.encryption;
 
 import junit.framework.Assert;
-import junit.framework.TestCase;
-import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+
 import java.io.File;
 import java.io.IOException;
 
-public class CredentialProviderTest extends TestCase {
-  private String keystore_dir;
-  private static final Log LOG = LogFactory.getLog
-    (CredentialProviderTest.class);
-
+public class CredentialProviderTest {
   @Rule
   public TemporaryFolder tmpFolder = new TemporaryFolder();
 
-  @Override
-  protected void setUp() throws Exception {
+  @Before
+  public void setUp() throws Exception {
     tmpFolder.create();
-    keystore_dir = tmpFolder.getRoot().getAbsolutePath();
   }
 
-  private void createMasterKey(String dir) {
-    File f = new File(dir + System.getProperty("file" +
-      ".separator") + Configuration.MASTER_KEY_FILENAME_DEFAULT);
-    if (!f.exists()) {
-      try {
-        f.createNewFile();
-      } catch (IOException e) {
-        e.printStackTrace();
-      }
-    }
-    MasterKeyService ms = new MasterKeyServiceImpl("blahblah!",
-      f.getAbsolutePath(), true);
+  private void createMasterKey() throws IOException {
+    File f = tmpFolder.newFile(Configuration.MASTER_KEY_FILENAME_DEFAULT);
+    Assert.assertTrue(MasterKeyServiceImpl.initializeMasterKeyFile(f, "blahblah!"));
+    MasterKeyService ms = new MasterKeyServiceImpl(f);
     if (!ms.isMasterKeyInitialized()) {
       throw new ExceptionInInitializerError("Cannot create master key.");
     }
@@ -62,35 +48,29 @@ public class CredentialProviderTest extends TestCase {
 
   @Test
   public void testInitialization() throws Exception {
-    CredentialProvider cr = null;
-    String msFile = keystore_dir + System.getProperty("file" +
-      ".separator") + Configuration.MASTER_KEY_FILENAME_DEFAULT;
+    CredentialProvider cr;
+    File msFile = tmpFolder.newFile(Configuration.MASTER_KEY_FILENAME_DEFAULT);
     try {
       new CredentialProvider(null, null, true);
-      fail("Expected an exception");
+      Assert.fail("Expected an exception");
     } catch (Throwable t) {
       Assert.assertTrue(t instanceof IllegalArgumentException);
     }
-    try {
-      new CredentialProvider(null, msFile, true);
-      fail("Expected an exception");
-    } catch (Throwable t) {
-      Assert.assertTrue(t instanceof AmbariException);
-    }
     // Without master key persisted
-    cr = new CredentialProvider("blahblah!", msFile, false);
+    cr = new CredentialProvider("blahblah!", msFile.getAbsolutePath(), false);
     Assert.assertNotNull(cr);
     Assert.assertNotNull(cr.getKeystoreService());
     // With master key persisted
-    createMasterKey(keystore_dir);
-    cr = new CredentialProvider(null, msFile, true);
+    msFile.delete();
+    createMasterKey();
+    cr = new CredentialProvider(null, msFile.getAbsolutePath(), true);
     Assert.assertNotNull(cr);
     Assert.assertNotNull(cr.getKeystoreService());
   }
 
   @Test
   public void testIsAliasString() {
-    String test  = "cassablanca";
+    String test = "cassablanca";
     Assert.assertFalse(CredentialProvider.isAliasString(test));
     test = "${}";
     Assert.assertFalse(CredentialProvider.isAliasString(test));
@@ -106,35 +86,35 @@ public class CredentialProviderTest extends TestCase {
 
   @Test
   public void testCredentialStore() throws Exception {
-    String msFile = keystore_dir + System.getProperty("file" +
-      ".separator") + Configuration.MASTER_KEY_FILENAME_DEFAULT;
+    File msFile = tmpFolder.newFile(Configuration.MASTER_KEY_FILENAME_DEFAULT);
+
     // With master key persisted
-    createMasterKey(keystore_dir);
-    CredentialProvider cr = new CredentialProvider(null, msFile, true);
+    createMasterKey();
+    CredentialProvider cr = new CredentialProvider(null, msFile.getAbsolutePath(), true);
     Assert.assertNotNull(cr);
     Assert.assertNotNull(cr.getKeystoreService());
 
     try {
       cr.addAliasToCredentialStore("", "xyz");
-      fail("Expected an exception");
+      Assert.fail("Expected an exception");
     } catch (Throwable t) {
       Assert.assertTrue(t instanceof IllegalArgumentException);
     }
 
     try {
       cr.addAliasToCredentialStore("xyz", null);
-      fail("Expected an exception");
+      Assert.fail("Expected an exception");
     } catch (Throwable t) {
       Assert.assertTrue(t instanceof IllegalArgumentException);
     }
 
     cr.addAliasToCredentialStore("myalias", "mypassword");
     Assert.assertEquals("mypassword", new String(cr.getPasswordForAlias
-      ("myalias")));
+        ("myalias")));
   }
 
-  @Override
-  protected void tearDown() throws Exception {
+  @After
+  public void tearDown() throws Exception {
     tmpFolder.delete();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceTest.java
index 0652a52..9725746 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceTest.java
@@ -18,92 +18,222 @@
 package org.apache.ambari.server.security.encryption;
 
 import junit.framework.Assert;
-import junit.framework.TestCase;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.concurrent.TimeUnit;
 
-public class CredentialStoreServiceTest extends TestCase {
-  private File keystore_dir;
-  private CredentialStoreService credentialStoreService;
-  private static final Log LOG = LogFactory.getLog
-    (CredentialStoreServiceTest.class);
+public class CredentialStoreServiceTest {
 
   @Rule
   public TemporaryFolder tmpFolder = new TemporaryFolder();
 
-  @Override
-  protected void setUp() throws Exception {
+  @Before
+  public void setUp() throws Exception {
     tmpFolder.create();
-    keystore_dir = tmpFolder.newFolder("jcekeystore");
-    LOG.debug("Setting default keystore_dir to " + keystore_dir);
-    credentialStoreService = new
-      CredentialStoreServiceImpl(keystore_dir.getAbsolutePath());
+  }
+
+  @After
+  public void cleanUp() throws Exception {
+    tmpFolder.delete();
   }
 
   @Test
-  public void testAddCredentialToStoreWithPersistMaster() throws Exception {
-    String masterKey = "ThisissomeSecretPassPhrasse";
-    String masterKeyLocation = keystore_dir.getAbsolutePath() + "/master";
-    MasterKeyService masterKeyService = new MasterKeyServiceImpl(masterKey,
-      masterKeyLocation, true);
-    credentialStoreService.setMasterKeyService(masterKeyService);
+  public void testFileBasedCredentialStoreService_AddCredentialToStoreWithPersistMaster() throws Exception {
+    addCredentialToStoreWithPersistMasterTest(new FileBasedCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testFileBasedCredentialStoreService_AddCredentialToStore() throws Exception {
+    addCredentialToStoreTest(new FileBasedCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testFileBasedCredentialStoreService_GetCredential() throws Exception {
+    getCredentialTest(new FileBasedCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testFileBasedCredentialStoreService_RemoveCredential() throws Exception {
+    removeCredentialTest(new FileBasedCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testInMemoryCredentialStoreService_AddCredentialToStoreWithPersistMaster() throws Exception {
+    addCredentialToStoreWithPersistMasterTest(new InMemoryCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testInMemoryCredentialStoreService_AddCredentialToStore() throws Exception {
+    addCredentialToStoreTest(new InMemoryCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testInMemoryCredentialStoreService_GetCredential() throws Exception {
+    getCredentialTest(new InMemoryCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testInMemoryCredentialStoreService_RemoveCredential() throws Exception {
+    removeCredentialTest(new InMemoryCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  @Test
+  public void testInMemoryCredentialStoreService_CredentialExpired() throws Exception {
+    getExpiredCredentialTest(new InMemoryCredentialStoreServiceFactory(), new DefaultMasterKeyServiceFactory());
+  }
+
+  private void addCredentialToStoreWithPersistMasterTest(CredentialStoreServiceFactory credentialStoreServiceFactory,
+                                                         MasterKeyServiceFactory masterKeyServiceFactory) throws Exception {
+    File directory = tmpFolder.getRoot();
+
+    String masterKey = "ThisIsSomeSecretPassPhrase1234";
+    File masterKeyFile = new File(directory, "master");
+
+    MasterKeyService masterKeyService = masterKeyServiceFactory.createPersisted(masterKeyFile, masterKey);
+    CredentialStoreService credentialStoreService = credentialStoreServiceFactory.create(directory, masterKeyService);
+
     String password = "mypassword";
-    credentialStoreService.addCredential("myalias", password);
+    credentialStoreService.addCredential("myalias", password.toCharArray());
     char[] credential = credentialStoreService.getCredential("myalias");
     Assert.assertEquals(password, new String(credential));
+
+    Assert.assertTrue(masterKeyFile.exists());
   }
 
-  @Test
-  public void testAddCredentialToStore() throws Exception {
-    String masterKey = "ThisissomeSecretPassPhrasse";
-    String masterKeyLocation = keystore_dir.getAbsolutePath() + "/master";
-    MasterKeyService masterKeyService = new MasterKeyServiceImpl(masterKey,
-      masterKeyLocation, false);
-    credentialStoreService.setMasterKeyService(masterKeyService);
+  private void addCredentialToStoreTest(CredentialStoreServiceFactory credentialStoreServiceFactory,
+                                        MasterKeyServiceFactory masterKeyServiceFactory) throws Exception {
+    File directory = tmpFolder.getRoot();
+
+    String masterKey = "ThisIsSomeSecretPassPhrase1234";
+    File masterKeyFile = new File(directory, "master");
+
+    MasterKeyService masterKeyService = masterKeyServiceFactory.create(masterKey);
+    CredentialStoreService credentialStoreService = credentialStoreServiceFactory.create(directory, masterKeyService);
+
     String password = "mypassword";
-    credentialStoreService.addCredential("myalias", password);
-    char[] credential = credentialStoreService.getCredential("myalias");
+    credentialStoreService.addCredential("password", password.toCharArray());
+    char[] credential = credentialStoreService.getCredential("password");
     Assert.assertEquals(password, new String(credential));
-    File f = new File(masterKeyLocation);
-    Assert.assertFalse(f.exists());
+
+    credentialStoreService.addCredential("null_password", null);
+    Assert.assertNull(credentialStoreService.getCredential("null_password"));
+
+    credentialStoreService.addCredential("empty_password", new char[0]);
+    Assert.assertNull(credentialStoreService.getCredential("empty_password"));
+
+    Assert.assertFalse(masterKeyFile.exists());
   }
 
-  @Test
-  public void testGetCredential() throws Exception {
-    String masterKey = "ThisissomeSecretPassPhrasse";
-    String masterKeyLocation = keystore_dir.getAbsolutePath() + "/master";
-    MasterKeyService masterKeyService = new MasterKeyServiceImpl(masterKey,
-      masterKeyLocation, false);
-    credentialStoreService.setMasterKeyService(masterKeyService);
+  private void getCredentialTest(CredentialStoreServiceFactory credentialStoreServiceFactory,
+                                 MasterKeyServiceFactory masterKeyServiceFactory) throws Exception {
+    File directory = tmpFolder.getRoot();
+
+    String masterKey = "ThisIsSomeSecretPassPhrase1234";
+
+    MasterKeyService masterKeyService = masterKeyServiceFactory.create(masterKey);
+    CredentialStoreService credentialStoreService = credentialStoreServiceFactory.create(directory, masterKeyService);
+
     Assert.assertNull(credentialStoreService.getCredential(""));
     Assert.assertNull(credentialStoreService.getCredential(null));
+
     String password = "mypassword";
-    credentialStoreService.addCredential("myalias", password);
+    credentialStoreService.addCredential("myalias", password.toCharArray());
     char[] credential = credentialStoreService.getCredential("myalias");
     Assert.assertEquals(password, new String(credential));
+
+    Assert.assertNull(credentialStoreService.getCredential("does_not_exist"));
   }
 
-  @Test
-  public void testAliasParsing() throws Exception {
-    String strPasswd = "${alias=ambari.password}";
-    Pattern PASSWORD_ALIAS_PATTERN = Pattern.compile
-      ("\\$\\{alias=[\\w\\.]+\\}");
-    Matcher matcher = PASSWORD_ALIAS_PATTERN.matcher(strPasswd);
-    Assert.assertTrue(matcher.matches());
-    Assert.assertEquals("ambari.password", strPasswd.substring(strPasswd
-      .indexOf("=")
-      + 1, strPasswd.length() - 1));
-  }
-
-  @Override
-  protected void tearDown() throws Exception {
-    tmpFolder.delete();
+  private void getExpiredCredentialTest(CredentialStoreServiceFactory credentialStoreServiceFactory,
+                                 MasterKeyServiceFactory masterKeyServiceFactory) throws Exception {
+    File directory = tmpFolder.getRoot();
+
+    String masterKey = "ThisIsSomeSecretPassPhrase1234";
+
+    MasterKeyService masterKeyService = masterKeyServiceFactory.create(masterKey);
+    CredentialStoreService credentialStoreService = credentialStoreServiceFactory.create(directory, masterKeyService);
+
+    String password = "mypassword";
+    credentialStoreService.addCredential("myalias", password.toCharArray());
+    Assert.assertEquals(password, new String(credentialStoreService.getCredential("myalias")));
+
+    Thread.sleep(250);
+    Assert.assertEquals(password, new String(credentialStoreService.getCredential("myalias")));
+
+    Thread.sleep(550);
+    Assert.assertNull(password, credentialStoreService.getCredential("myalias"));
+
   }
+
+  private void removeCredentialTest(CredentialStoreServiceFactory credentialStoreServiceFactory,
+                                    MasterKeyServiceFactory masterKeyServiceFactory) throws Exception {
+    File directory = tmpFolder.getRoot();
+
+    String masterKey = "ThisIsSomeSecretPassPhrase1234";
+
+    MasterKeyService masterKeyService = masterKeyServiceFactory.create(masterKey);
+    CredentialStoreService credentialStoreService = credentialStoreServiceFactory.create(directory, masterKeyService);
+
+    String password = "mypassword";
+    credentialStoreService.addCredential("myalias", password.toCharArray());
+
+    char[] credential = credentialStoreService.getCredential("myalias");
+    Assert.assertEquals(password, new String(credential));
+
+    credentialStoreService = credentialStoreServiceFactory.create(directory, masterKeyService);
+    credentialStoreService.setMasterKeyService(masterKeyService);
+
+    credentialStoreService.removeCredential("myalias");
+    Assert.assertNull(credentialStoreService.getCredential("myalias"));
+
+    credentialStoreService.removeCredential("does_not_exist");
+  }
+
+  private interface CredentialStoreServiceFactory {
+    CredentialStoreService create(File directory, MasterKeyService masterKeyService);
+  }
+
+  private class FileBasedCredentialStoreServiceFactory implements CredentialStoreServiceFactory {
+    @Override
+    public CredentialStoreService create(File directory, MasterKeyService masterKeyService) {
+      CredentialStoreService credentialStoreService = new FileBasedCredentialStoreService(directory.getAbsolutePath());
+      credentialStoreService.setMasterKeyService(masterKeyService);
+      return credentialStoreService;
+    }
+  }
+
+  private class InMemoryCredentialStoreServiceFactory implements CredentialStoreServiceFactory {
+    @Override
+    public CredentialStoreService create(File directory, MasterKeyService masterKeyService) {
+      CredentialStoreService credentialStoreService = new InMemoryCredentialStoreService(500, TimeUnit.MILLISECONDS, true);
+      credentialStoreService.setMasterKeyService(masterKeyService);
+      return credentialStoreService;
+    }
+  }
+
+  private interface MasterKeyServiceFactory {
+    MasterKeyService create(String masterKey);
+
+    MasterKeyService createPersisted(File masterKeyFile, String masterKey);
+  }
+
+  private class DefaultMasterKeyServiceFactory implements MasterKeyServiceFactory {
+
+    @Override
+    public MasterKeyService create(String masterKey) {
+      return new MasterKeyServiceImpl(masterKey);
+    }
+
+    @Override
+    public MasterKeyService createPersisted(File masterKeyFile, String masterKey) {
+      MasterKeyServiceImpl.initializeMasterKeyFile(masterKeyFile, masterKey);
+      return new MasterKeyServiceImpl(masterKeyFile);
+    }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
index 993601b..b597e0a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/encryption/MasterKeyServiceTest.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -29,9 +29,15 @@ import org.junit.runner.RunWith;
 import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
+
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
+
 import static org.easymock.EasyMock.expect;
 import static org.powermock.api.easymock.PowerMock.mockStatic;
 import static org.powermock.api.easymock.PowerMock.replayAll;
@@ -39,13 +45,13 @@ import static org.powermock.api.easymock.PowerMock.verifyAll;
 
 @RunWith(PowerMockRunner.class)
 @PowerMockIgnore({"javax.crypto.*", "org.apache.log4j.*"})
-@PrepareForTest({ MasterKeyServiceImpl.class })
+@PrepareForTest({MasterKeyServiceImpl.class})
 public class MasterKeyServiceTest extends TestCase {
   @Rule
   public TemporaryFolder tmpFolder = new TemporaryFolder();
   private String fileDir;
   private static final Log LOG = LogFactory.getLog
-    (MasterKeyServiceTest.class);
+      (MasterKeyServiceTest.class);
 
   @Override
   protected void setUp() throws Exception {
@@ -55,18 +61,35 @@ public class MasterKeyServiceTest extends TestCase {
   }
 
   @Test
-  public void testInitiliazeMasterKey() throws Exception {
-    MasterKeyService ms = new MasterKeyServiceImpl("ThisisSomePassPhrase",
-      fileDir + File.separator + "master", true);
+  public void testInitializeMasterKey() throws Exception {
+    File masterKeyFile = new File(fileDir, "master");
+    Assert.assertTrue(MasterKeyServiceImpl.initializeMasterKeyFile(masterKeyFile, "ThisisSomePassPhrase"));
+
+    MasterKeyService ms = new MasterKeyServiceImpl(masterKeyFile);
     Assert.assertTrue(ms.isMasterKeyInitialized());
-    File f = new File(fileDir + File.separator + "master");
-    Assert.assertTrue(f.exists());
+
+    Assert.assertTrue(masterKeyFile.exists());
+
+    // Make sure the created file is readable and writable only by the process owner.
+    Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(Paths.get(masterKeyFile.getAbsolutePath()));
+    Assert.assertNotNull(permissions);
+    Assert.assertEquals(2, permissions.size());
+    Assert.assertTrue(permissions.contains(PosixFilePermission.OWNER_READ));
+    Assert.assertTrue(permissions.contains(PosixFilePermission.OWNER_WRITE));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.OWNER_EXECUTE));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.GROUP_READ));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.GROUP_WRITE));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.GROUP_EXECUTE));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.OTHERS_READ));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.OTHERS_WRITE));
+    Assert.assertFalse(permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
+
     // Re-initialize master from file
-    MasterKeyService ms1 = new MasterKeyServiceImpl(fileDir + File.separator
-      + "master", true);
+    MasterKeyService ms1 = new MasterKeyServiceImpl(masterKeyFile);
     Assert.assertTrue(ms1.isMasterKeyInitialized());
-    Assert.assertEquals("ThisisSomePassPhrase", new String(ms1.getMasterSecret
-      ()));
+
+    Assert.assertEquals("ThisisSomePassPhrase", new String(ms1.getMasterSecret()));
+    Assert.assertEquals(new String(ms.getMasterSecret()), new String(ms1.getMasterSecret()));
   }
 
   @Test
@@ -81,20 +104,21 @@ public class MasterKeyServiceTest extends TestCase {
     Assert.assertTrue(ms.isMasterKeyInitialized());
     Assert.assertNotNull(ms.getMasterSecret());
     Assert.assertEquals("ThisisSomePassPhrase",
-      new String(ms.getMasterSecret()));
+        new String(ms.getMasterSecret()));
   }
 
   @Test
   public void testReadFromEnvAsPath() throws Exception {
     // Create a master key
-    MasterKeyService ms = new MasterKeyServiceImpl("ThisisSomePassPhrase",
-      fileDir + File.separator + "master", true);
+    File masterKeyFile = new File(fileDir, "master");
+    Assert.assertTrue(MasterKeyServiceImpl.initializeMasterKeyFile(masterKeyFile, "ThisisSomePassPhrase"));
+
+    MasterKeyService ms = new MasterKeyServiceImpl(masterKeyFile);
     Assert.assertTrue(ms.isMasterKeyInitialized());
-    File f = new File(fileDir + File.separator + "master");
-    Assert.assertTrue(f.exists());
+    Assert.assertTrue(masterKeyFile.exists());
 
     Map<String, String> mapRet = new HashMap<String, String>();
-    mapRet.put(Configuration.MASTER_KEY_LOCATION, f.getAbsolutePath());
+    mapRet.put(Configuration.MASTER_KEY_LOCATION, masterKeyFile.getAbsolutePath());
     mockStatic(System.class);
     expect(System.getenv()).andReturn(mapRet);
     replayAll();
@@ -102,9 +126,8 @@ public class MasterKeyServiceTest extends TestCase {
     verifyAll();
     Assert.assertTrue(ms.isMasterKeyInitialized());
     Assert.assertNotNull(ms.getMasterSecret());
-    Assert.assertEquals("ThisisSomePassPhrase",
-      new String(ms.getMasterSecret()));
-    Assert.assertFalse(f.exists());
+    Assert.assertEquals("ThisisSomePassPhrase", new String(ms.getMasterSecret()));
+    Assert.assertFalse(masterKeyFile.exists());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 9ad3da6..7bad60a 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
@@ -54,7 +54,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
   @Test(expected = KerberosKDCConnectionException.class)
   public void testOpenExceptionLdapUrlNotProvided() throws Exception {
     KerberosOperationHandler handler = new ADKerberosOperationHandler();
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_PRINCIPAL_CONTAINER_DN, DEFAULT_PRINCIPAL_CONTAINER_DN);
@@ -67,7 +67,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
   @Test(expected = KerberosLDAPContainerException.class)
   public void testOpenExceptionPrincipalContainerDnNotProvided() throws Exception {
     KerberosOperationHandler handler = new ADKerberosOperationHandler();
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
@@ -92,7 +92,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testTestAdministratorCredentialsIncorrectAdminPassword() throws Exception {
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, "wrong", null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, "wrong".toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
@@ -120,7 +120,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testTestAdministratorCredentialsIncorrectAdminPrincipal() throws Exception {
-    KerberosCredential kc = new KerberosCredential("wrong", DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential("wrong", DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
@@ -148,7 +148,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
 
   @Test(expected = KerberosKDCConnectionException.class)
   public void testTestAdministratorCredentialsKDCConnectionException() throws Exception {
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, "invalid");
@@ -177,7 +177,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
 
   @Test
   public void testTestAdministratorCredentialsSuccess() throws Exception {
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
@@ -229,7 +229,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
 
   @Test
   public void testProcessCreateTemplateDefault() throws Exception {
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
@@ -338,7 +338,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
 
   @Test
   public void testProcessCreateTemplateCustom() throws Exception {
-    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null);
+    KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>() {
       {
         put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, DEFAULT_LDAP_URL);
@@ -475,7 +475,7 @@ public class ADKerberosOperationHandlerTest extends KerberosOperationHandlerTest
       containerDN = DEFAULT_PRINCIPAL_CONTAINER_DN;
     }
 
-    KerberosCredential credentials = new KerberosCredential(principal, password, null);
+    KerberosCredential credentials = new KerberosCredential(principal, password.toCharArray(), null);
     Map<String, String> kerberosEnvMap = new HashMap<String, String>();
 
     kerberosEnvMap.put(ADKerberosOperationHandler.KERBEROS_ENV_LDAP_URL, ldapUrl);

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredentialTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredentialTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredentialTest.java
index 305b122..dbcdf3e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredentialTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredentialTest.java
@@ -58,7 +58,7 @@ public class KerberosCredentialTest {
     kerberosCredential = KerberosCredential.fromMap(attributes, "kerberos_admin/");
     Assert.assertNotNull(kerberosCredential);
     Assert.assertEquals("admin/admin@FOOBAR.COM", kerberosCredential.getPrincipal());
-    Assert.assertEquals("t0p_s3cr3t", kerberosCredential.getPassword());
+    Assert.assertEquals("t0p_s3cr3t", String.valueOf(kerberosCredential.getPassword()));
     Assert.assertNull(kerberosCredential.getKeytab());
 
     // Test with a prefix that does not resolve to any existing keys
@@ -73,7 +73,7 @@ public class KerberosCredentialTest {
     String cipherText;
     KerberosCredential decryptedCredential;
 
-    credential = new KerberosCredential("admin/admin@FOOBAR.COM", "t0p_s3cr3t", null);
+    credential = new KerberosCredential("admin/admin@FOOBAR.COM", "t0p_s3cr3t".toCharArray(), null);
     cipherText = credential.encrypt(key);
     Assert.assertNotNull(cipherText);
 
@@ -81,7 +81,7 @@ public class KerberosCredentialTest {
     decryptedCredential = KerberosCredential.decrypt(cipherText, key);
     Assert.assertNotNull(decryptedCredential);
     Assert.assertEquals(credential.getPrincipal(), decryptedCredential.getPrincipal());
-    Assert.assertEquals(credential.getPassword(), decryptedCredential.getPassword());
+    Assert.assertEquals(String.valueOf(credential.getPassword()), String.valueOf(decryptedCredential.getPassword()));
     Assert.assertEquals(credential.getKeytab(), decryptedCredential.getKeytab());
 
     // Test an invalid key

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 44a68ae..b91bbbc 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
@@ -267,7 +267,7 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport {
   public void testAdminCredentialsNullPrincipal() throws KerberosOperationException {
     KerberosOperationHandler handler = createHandler();
 
-    KerberosCredential credentials = new KerberosCredential(null, "password", null);
+    KerberosCredential credentials = new KerberosCredential(null, "password".toCharArray(), null);
     handler.setAdministratorCredentials(credentials);
   }
 
@@ -275,7 +275,7 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport {
   public void testAdminCredentialsEmptyPrincipal() throws KerberosOperationException {
     KerberosOperationHandler handler = createHandler();
 
-    KerberosCredential credentials = new KerberosCredential("", "password", null);
+    KerberosCredential credentials = new KerberosCredential("", "password".toCharArray(), null);
     handler.setAdministratorCredentials(credentials);
   }
 
@@ -291,7 +291,7 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport {
   public void testAdminCredentialsEmptyCredential1() throws KerberosOperationException {
     KerberosOperationHandler handler = createHandler();
 
-    KerberosCredential credentials = new KerberosCredential("principal", "", null);
+    KerberosCredential credentials = new KerberosCredential("principal", "".toCharArray(), null);
     handler.setAdministratorCredentials(credentials);
   }
 
@@ -383,7 +383,7 @@ public abstract class KerberosOperationHandlerTest extends EasyMockSupport {
       }
     };
 
-    handler.open(new KerberosCredential("admin/admin", "hadoop", null), "EXAMPLE.COM", null);
+    handler.open(new KerberosCredential("admin/admin", "hadoop".toCharArray(), null), "EXAMPLE.COM", null);
     return handler;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 8fc5325..2c5c4e0 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
@@ -29,6 +29,7 @@ import org.apache.ambari.server.actionmanager.HostRoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.agent.ExecutionCommand;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.stack.OsFamily;
@@ -42,10 +43,10 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import static org.easymock.EasyMock.*;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.easymock.EasyMock.createNiceMock;
 
 public class KerberosServerActionTest {
 
@@ -68,6 +69,7 @@ public class KerberosServerActionTest {
 
       @Override
       protected void configure() {
+        bind(KerberosHelper.class).toInstance(createNiceMock(KerberosHelper.class));
         bind(KerberosServerAction.class).toInstance(new KerberosServerAction() {
 
           @Override
@@ -118,9 +120,6 @@ public class KerberosServerActionTest {
     commandParams.put(KerberosServerAction.DATA_DIRECTORY, temporaryDirectory.getAbsolutePath());
     commandParams.put(KerberosServerAction.DEFAULT_REALM, "REALM.COM");
     commandParams.put(KerberosServerAction.KDC_TYPE, KDCType.MIT_KDC.toString());
-    commandParams.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL,
-        new KerberosCredential("principal", "password", "keytab")
-            .encrypt(Integer.toHexString(cluster.hashCode()).getBytes()));
 
     when(mockExecutionCommand.getCommandParams()).thenReturn(commandParams);
     when(mockExecutionCommand.getClusterName()).thenReturn("c1");
@@ -183,6 +182,13 @@ public class KerberosServerActionTest {
 
   @Test
   public void testProcessIdentitiesSuccess() throws Exception {
+    KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
+    expect(kerberosHelper.getKDCCredentials())
+        .andReturn(new KerberosCredential("principal", "password".toCharArray(), null))
+        .anyTimes();
+
+    replay(kerberosHelper);
+
     ConcurrentMap<String, Object> sharedMap = new ConcurrentHashMap<String, Object>();
     CommandReport report = action.processIdentities(sharedMap);
     Assert.assertNotNull(report);
@@ -192,24 +198,26 @@ public class KerberosServerActionTest {
       Assert.assertEquals(entry.getValue(),
           entry.getKey().replace("_HOST", "hostName").replace("_REALM", "REALM.COM"));
     }
+
+    verify(kerberosHelper);
   }
 
   @Test
   public void testProcessIdentitiesFail() throws Exception {
+    KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
+    expect(kerberosHelper.getKDCCredentials())
+        .andReturn(new KerberosCredential("principal", "password".toCharArray(), null))
+        .anyTimes();
+
+    replay(kerberosHelper);
+
     ConcurrentMap<String, Object> sharedMap = new ConcurrentHashMap<String, Object>();
     sharedMap.put("FAIL", "true");
 
     CommandReport report = action.processIdentities(sharedMap);
     Assert.assertNotNull(report);
     Assert.assertEquals(HostRoleStatus.FAILED.toString(), report.getStatus());
-  }
 
-  @Test
-  public void testGetAdministrativeCredentials() throws AmbariException {
-    KerberosCredential credentials = action.getAdministratorCredential(commandParams);
-    Assert.assertNotNull(credentials);
-    Assert.assertEquals("principal", credentials.getPrincipal());
-    Assert.assertEquals("password", credentials.getPassword());
-    Assert.assertEquals("keytab", credentials.getKeytab());
+    verify(kerberosHelper);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 8c096b0..2c41b54 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
@@ -83,7 +83,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
   @Test
   public void testSetPrincipalPasswordExceptions() throws Exception {
     MITKerberosOperationHandler handler = injector.getInstance(MITKerberosOperationHandler.class);
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
 
     try {
       handler.setPrincipalPassword(DEFAULT_ADMIN_PRINCIPAL, null);
@@ -139,7 +139,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replay(handler, result1, result2);
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.createPrincipal(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, false);
 
     verify(handler, result1, result2);
@@ -150,7 +150,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
   @Test
   public void testCreateServicePrincipal_Exceptions() throws Exception {
     MITKerberosOperationHandler handler = new MITKerberosOperationHandler();
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
 
     try {
       handler.createPrincipal(DEFAULT_ADMIN_PRINCIPAL, null, false);
@@ -209,7 +209,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -242,7 +242,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -275,7 +275,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -308,7 +308,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -341,7 +341,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -374,7 +374,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -407,7 +407,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     Assert.assertFalse(handler.testAdministratorCredentials());
     handler.close();
   }
@@ -460,7 +460,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
 
     replayAll();
 
-    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM, KERBEROS_ENV_MAP);
+    handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD.toCharArray(), null), DEFAULT_REALM, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();
     handler.close();
   }
@@ -485,7 +485,7 @@ public class MITKerberosOperationHandlerTest extends KerberosOperationHandlerTes
       realm = DEFAULT_REALM;
     }
 
-    KerberosCredential credentials = new KerberosCredential(principal, password, null);
+    KerberosCredential credentials = new KerberosCredential(principal, password.toCharArray(), null);
 
     handler.open(credentials, realm, KERBEROS_ENV_MAP);
     handler.testAdministratorCredentials();


[2/2] ambari git commit: AMBARI-12772. Adding host via blueprint fails on secure cluster (rlevas)

Posted by rl...@apache.org.
AMBARI-12772. Adding host via blueprint fails on secure cluster (rlevas)


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

Branch: refs/heads/trunk
Commit: e681f2bf4d2f902d9d46c195baf5c405ab9ebc8e
Parents: 6c98f47
Author: Robert Levas <rl...@hortonworks.com>
Authored: Fri Sep 4 10:55:36 2015 -0400
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Fri Sep 4 10:55:49 2015 -0400

----------------------------------------------------------------------
 .../AmbariManagementControllerImpl.java         |  46 ++-
 .../server/controller/KerberosHelper.java       |  29 ++
 .../server/controller/KerberosHelperImpl.java   | 167 ++++----
 .../security/encryption/CredentialProvider.java |  66 ++--
 .../encryption/CredentialStoreService.java      |  39 +-
 .../encryption/CredentialStoreServiceImpl.java  | 326 ++++++++++------
 .../FileBasedCredentialStoreService.java        | 151 ++++++++
 .../InMemoryCredentialStoreService.java         | 142 +++++++
 .../encryption/MasterKeyServiceImpl.java        | 381 ++++++++++---------
 .../kerberos/KerberosCredential.java            |  54 ++-
 .../kerberos/KerberosOperationHandler.java      |  14 +-
 .../kerberos/KerberosServerAction.java          |  30 +-
 .../kerberos/MITKerberosOperationHandler.java   |   4 +-
 .../server/configuration/ConfigurationTest.java |   2 +-
 .../server/controller/KerberosHelperTest.java   | 104 ++---
 .../encryption/CredentialProviderTest.java      |  74 ++--
 .../encryption/CredentialStoreServiceTest.java  | 244 +++++++++---
 .../encryption/MasterKeyServiceTest.java        |  69 ++--
 .../ADKerberosOperationHandlerTest.java         |  18 +-
 .../kerberos/KerberosCredentialTest.java        |   6 +-
 .../kerberos/KerberosOperationHandlerTest.java  |   8 +-
 .../kerberos/KerberosServerActionTest.java      |  32 +-
 .../MITKerberosOperationHandlerTest.java        |  24 +-
 23 files changed, 1338 insertions(+), 692 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 859b361..a90cb31 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -118,6 +118,7 @@ import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.ldap.AmbariLdapDataPopulator;
 import org.apache.ambari.server.security.ldap.LdapBatchDto;
 import org.apache.ambari.server.security.ldap.LdapSyncDto;
+import org.apache.ambari.server.serveraction.kerberos.KerberosCredential;
 import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
 import org.apache.ambari.server.serveraction.kerberos.KerberosOperationException;
 import org.apache.ambari.server.stageplanner.RoleGraph;
@@ -1258,7 +1259,50 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         throw new AmbariException("The cluster may not be null");
       }
 
-      cluster.addSessionAttributes(request.getSessionAttributes());
+      Map<String, Object> sessionAttributes = request.getSessionAttributes();
+
+      // TODO: Create REST API entry point to securely set credentials in the CredentialProvider then
+      // TODO: remove this block to _clean_ the session attributes and store any KDC administrator
+      // TODO: credentials in the secure credential provider facility.
+      // For now, to keep things backwards compatible, get and remove the KDC administrator credentials
+      // from the session attributes and store them in the CredentialsProvider. The KDC administrator
+      // credentials are prefixed with kdc_admin/. The following attributes are expected, if setting
+      // the KDC administrator credentials:
+      //    kerberos_admin/principal
+      //    kerberos_admin/password
+      if((sessionAttributes != null) && !sessionAttributes.isEmpty()) {
+        Map<String, Object> cleanedSessionAttributes = new HashMap<String, Object>();
+        String principal = null;
+        char[] password = null;
+
+        for(Map.Entry<String,Object> entry: sessionAttributes.entrySet()) {
+          String name = entry.getKey();
+          Object value = entry.getValue();
+
+          if ("kerberos_admin/principal".equals(name)) {
+            if(value instanceof String) {
+              principal = (String)value;
+            }
+          }
+          else if ("kerberos_admin/password".equals(name)) {
+            if(value instanceof String) {
+              password = ((String) value).toCharArray();
+            }
+          } else {
+            cleanedSessionAttributes.put(name, value);
+          }
+        }
+
+        if(principal != null) {
+          // The KDC admin principal exists... set the credentials in the credentials store
+          kerberosHelper.setKDCCredentials(new KerberosCredential(principal, password, null));
+        }
+
+        sessionAttributes = cleanedSessionAttributes;
+      }
+      // TODO: END
+
+      cluster.addSessionAttributes(sessionAttributes);
       //
       // ***************************************************
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 cb9e6ca..c39485b 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
@@ -21,6 +21,7 @@ package org.apache.ambari.server.controller;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.internal.RequestStageContainer;
 import org.apache.ambari.server.serveraction.kerberos.KerberosAdminAuthenticationException;
+import org.apache.ambari.server.serveraction.kerberos.KerberosCredential;
 import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWriter;
 import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
 import org.apache.ambari.server.serveraction.kerberos.KerberosMissingAdminCredentialsException;
@@ -415,6 +416,34 @@ public interface KerberosHelper {
                                                                           boolean replaceHostNames)
       throws AmbariException;
 
+  /**
+   * Sets the KDC administrator credentials.
+   * <p/>
+   * It is up to the implementation to determine how to store
+   * these credentials and for how long.
+   *
+   * @param credentials the KDC administrator credentials
+   * @throws AmbariException if an error occurs while storing the credentials
+   */
+  void setKDCCredentials(KerberosCredential credentials) throws AmbariException;
+
+  /**
+   * Removes the previously set KDC administrator credentials.
+   *
+   * @throws AmbariException if an error occurs while removing the credentials
+   * @see KerberosHelper#setKDCCredentials(KerberosCredential)
+   */
+  void removeKDCCredentials() throws AmbariException;
+
+  /**
+   * Gets the previously stored KDC administrator credentials.
+   *
+   * @return a KerberosCredential or null, if the KDC administrator credentials have not be set or
+   * have been removed
+   * @throws AmbariException if an error occurs while retrieving the credentials
+   * @see KerberosHelper#setKDCCredentials(KerberosCredential)
+   */
+  KerberosCredential getKDCCredentials() throws AmbariException;
 
   /**
    * Command to invoke against the Ambari backend.

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 708d267..6f407c9 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
@@ -30,8 +30,8 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Random;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -60,6 +60,9 @@ import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
+import org.apache.ambari.server.security.SecurePasswordHelper;
+import org.apache.ambari.server.security.encryption.InMemoryCredentialStoreService;
+import org.apache.ambari.server.security.encryption.MasterKeyServiceImpl;
 import org.apache.ambari.server.serveraction.ServerAction;
 import org.apache.ambari.server.serveraction.kerberos.CleanupServerAction;
 import org.apache.ambari.server.serveraction.kerberos.CreateKeytabFilesServerAction;
@@ -126,10 +129,15 @@ public class KerberosHelperImpl implements KerberosHelper {
   private static final Logger LOG = LoggerFactory.getLogger(KerberosHelperImpl.class);
 
   /**
-   * name of the property used to hold the service check identifier value, used when creating and
-   * destroying the (unique) service check identity.
+   * The alias to assign to the KDC administrator credential Keystore item
    */
-  private static final String SERVICE_CHECK_IDENTIFIER = "_kerberos_internal_service_check_identifier";
+  public static final String KDC_ADMINISTRATOR_CREDENTIAL_ALIAS = "kdc_admin";
+
+  /**
+   * The default length of time (in minutes) to store the KDC administrator credentials before
+   * automatically removing them.
+   */
+  private static final long DEFAULT_KDC_ADMINISTRATOR_CREDENTIALS_RETENTION_MINUTES = 90;
 
   /**
    * Regular expression pattern used to parse auth_to_local property specifications into the following
@@ -184,12 +192,29 @@ public class KerberosHelperImpl implements KerberosHelper {
   @Inject
   private KerberosIdentityDataFileWriterFactory kerberosIdentityDataFileWriterFactory;
 
+  @Inject
+  private SecurePasswordHelper securePasswordHelper;
+
   /**
    * Used to get kerberos descriptors associated with the cluster or stack.
    * Currently not available via injection.
    */
   private static ClusterController clusterController = null;
 
+  /**
+   * The secure storage facility to use to store KDC administrator credentials. This implementation
+   * is uses an InMemoryCredentialStoreService to keep the credentials in memory rather than
+   * storing them on disk.
+   */
+  private final InMemoryCredentialStoreService kdcCredentialStoreService;
+
+  /**
+   * Default KerberosHelperImpl constructor
+   */
+  public KerberosHelperImpl() {
+    kdcCredentialStoreService = new InMemoryCredentialStoreService(DEFAULT_KDC_ADMINISTRATOR_CREDENTIALS_RETENTION_MINUTES, TimeUnit.MINUTES, true);
+  }
+
   @Override
   public RequestStageContainer toggleKerberos(Cluster cluster, SecurityType securityType,
                                               RequestStageContainer requestStageContainer,
@@ -344,10 +369,6 @@ public class KerberosHelperImpl implements KerberosHelper {
                                                   RequestStageContainer requestStageContainer)
       throws KerberosOperationException, AmbariException {
     requestStageContainer = handleTestIdentity(cluster, getKerberosDetails(cluster, null), commandParamsStage, requestStageContainer, new DeletePrincipalsAndKeytabsHandler());
-
-    // Clear the Kerberos service check identifier
-    setKerberosServiceCheckIdentifier(cluster, null);
-
     return requestStageContainer;
   }
 
@@ -764,7 +785,7 @@ public class KerberosHelperImpl implements KerberosHelper {
     // add clusterHostInfo config
     Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster);
 
-    if(clusterHostInfo != null) {
+    if (clusterHostInfo != null) {
       Map<String, String> componentHosts = new HashMap<String, String>();
 
       clusterHostInfo = StageUtils.substituteHostIndexes(clusterHostInfo);
@@ -890,6 +911,67 @@ public class KerberosHelperImpl implements KerberosHelper {
   }
 
   /**
+   * Sets the KDC administrator credentials.
+   * <p/>
+   * This implementation stores the credentials in a secure CredentialStoreService implementation and
+   * sets a timer to remove the stored credentials after the retention period expires.
+   * <p/>
+   * If existing credentials are stored when setting new credentials, the previously stored data will
+   * be cleared out. Each time credentials are set, a new master key is generated and used to encrypt
+   * the data.
+   *
+   * @param credentials the KDC administrator credentials
+   * @throws AmbariException if an error occurs while storing the credentials
+   */
+  @Override
+  public void setKDCCredentials(KerberosCredential credentials) throws AmbariException {
+    kdcCredentialStoreService.removeCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
+
+    if (credentials != null) {
+      String jsonValue = credentials.toJSON();
+
+      if (jsonValue != null) {
+        kdcCredentialStoreService.setMasterKeyService(new MasterKeyServiceImpl(securePasswordHelper.createSecurePassword()));
+        kdcCredentialStoreService.addCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS, jsonValue.toCharArray());
+      }
+    }
+  }
+
+  /**
+   * Removes the previously set KDC administrator credentials.
+   * <p/>
+   * This implementation clears the secure CredentialsStoreService instance, removing the previously
+   * generated master key and credentials data.  The configured timer to enforce retention time is
+   * cleared and set to null.
+   *
+   * @throws AmbariException if an error occurs while removing the credentials
+   * @see KerberosHelper#setKDCCredentials(KerberosCredential)
+   */
+  @Override
+  public void removeKDCCredentials() throws AmbariException {
+    kdcCredentialStoreService.removeCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
+  }
+
+  /**
+   * Gets the previously stored KDC administrator credentials.
+   * <p/>
+   * This implementation accesses the secure CredentialStoreService instance to get the data.
+   *
+   * @return a KerberosCredential or null, if the KDC administrator credentials have not be set or
+   * have been removed
+   * @throws AmbariException if an error occurs while retrieving the credentials
+   * @see KerberosHelper#setKDCCredentials(KerberosCredential)
+   */
+  @Override
+  public KerberosCredential getKDCCredentials() throws AmbariException {
+    char[] credentials = kdcCredentialStoreService.getCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
+
+    return (credentials == null)
+        ? null
+        : KerberosCredential.fromJSON(new String(credentials));
+  }
+
+  /**
    * Validate the KDC admin credentials.
    *
    * @param kerberosDetails the KerberosDetails containing information about the Kerberos configuration
@@ -908,8 +990,8 @@ public class KerberosHelperImpl implements KerberosHelper {
     }
 
     if (kerberosDetails.manageIdentities()) {
-      String credentials = getEncryptedAdministratorCredentials(cluster);
-      if (credentials == null) {
+      KerberosCredential kerberosCredentials = getKDCCredentials();
+      if (kerberosCredentials == null) {
         throw new KerberosMissingAdminCredentialsException(
             "Missing KDC administrator credentials.\n" +
                 "The KDC administrator credentials must be set in session by updating the relevant Cluster resource." +
@@ -926,9 +1008,6 @@ public class KerberosHelperImpl implements KerberosHelper {
         if (operationHandler == null) {
           throw new AmbariException("Failed to get an appropriate Kerberos operation handler.");
         } else {
-          byte[] key = Integer.toHexString(cluster.hashCode()).getBytes();
-          KerberosCredential kerberosCredentials = KerberosCredential.decrypt(credentials, key);
-
           boolean missingCredentials = false;
           try {
             operationHandler.open(kerberosCredentials, kerberosDetails.getDefaultRealm(), kerberosDetails.getKerberosEnvProperties());
@@ -1243,9 +1322,6 @@ public class KerberosHelperImpl implements KerberosHelper {
             }
           });
 
-          // Get or create the unique service check identifier
-          String serviceCheckId = getKerberosServiceCheckIdentifier(cluster, true);
-
           try {
             // Iterate over the hosts in the cluster to find the components installed in each.  For each
             // component (aka service component host - sch) determine the configuration updates and
@@ -1261,9 +1337,6 @@ public class KerberosHelperImpl implements KerberosHelper {
                 // variables within the Kerberos descriptor data
                 Map<String, Map<String, String>> configurations = calculateConfigurations(cluster, hostname, kerberosDescriptorProperties);
 
-                // Set the unique service check identifier
-                configurations.get("").put("service_check_id", serviceCheckId);
-
                 // Add a short date value
                 configurations.get("").put("short_date", new SimpleDateFormat("MMddyy").format(new Date()));
 
@@ -1706,56 +1779,6 @@ public class KerberosHelperImpl implements KerberosHelper {
   }
 
   /**
-   * Using the session data from the relevant Cluster object, gets the previously stored
-   * Kerberos service check identifier value or creates a new one if indicated to do so.
-   * <p/>
-   * This value is used intended to be used by the KerberosHelper to manage uniquely crated
-   * principals for use in service checks.
-   *
-   * @param cluster the relevant Cluster
-   * @return the previously stored Kerberos service check identifier value, or null if
-   * not previously stored
-   */
-  private String getKerberosServiceCheckIdentifier(Cluster cluster, boolean createIfNull) {
-    Map<String, Object> sessionAttributes = cluster.getSessionAttributes();
-    Object value = (sessionAttributes == null) ? null : sessionAttributes.get(SERVICE_CHECK_IDENTIFIER);
-    String serviceCheckIdentifier = (value instanceof String) ? (String) value : null;
-
-    if ((serviceCheckIdentifier == null) && createIfNull) {
-      // Create a new (ideally) unique(ish) identifier
-      Random random = new Random(System.currentTimeMillis());
-      char[] chars = new char[8];
-
-      for (int i = 0; i < 8; i++) {
-        chars[i] = (char) ((int) 'a' + random.nextInt(26));
-      }
-
-      serviceCheckIdentifier = String.valueOf(chars);
-      setKerberosServiceCheckIdentifier(cluster, serviceCheckIdentifier);
-    }
-
-    return serviceCheckIdentifier;
-  }
-
-  /**
-   * Stores the Kerberos service check identifier value into the session data from the
-   * relevant Cluster object.
-   * <p/>
-   * This value is used intended to be used by the KerberosHelper to manage uniquely crated
-   * principals for use in service checks.
-   *
-   * @param cluster the relevant Cluster
-   * @param value   the Kerberos service check identifier to store or null to clear any previously set value
-   */
-  private void setKerberosServiceCheckIdentifier(Cluster cluster, String value) {
-    if (value == null) {
-      cluster.removeSessionAttribute(SERVICE_CHECK_IDENTIFIER);
-    } else {
-      cluster.setSessionAttribute(SERVICE_CHECK_IDENTIFIER, value);
-    }
-  }
-
-  /**
    * Given a Collection of ServiceComponentHosts generates a unique list of hosts.
    *
    * @param serviceComponentHosts a Collection of ServiceComponentHosts from which to to retrieve host names
@@ -2432,7 +2455,6 @@ public class KerberosHelperImpl implements KerberosHelper {
 
       if (kerberosDetails.manageIdentities()) {
         commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
-        commandParameters.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL, getEncryptedAdministratorCredentials(cluster));
 
         // *****************************************************************
         // Create stage to create principals
@@ -2544,7 +2566,6 @@ public class KerberosHelperImpl implements KerberosHelper {
 
       if (kerberosDetails.manageIdentities()) {
         commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
-        commandParameters.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL, getEncryptedAdministratorCredentials(cluster));
 
         // *****************************************************************
         // Create stage to remove principals
@@ -2681,7 +2702,6 @@ public class KerberosHelperImpl implements KerberosHelper {
 
       if (kerberosDetails.manageIdentities()) {
         commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
-        commandParameters.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL, getEncryptedAdministratorCredentials(cluster));
 
         // *****************************************************************
         // Create stage to create principals
@@ -2781,7 +2801,6 @@ public class KerberosHelperImpl implements KerberosHelper {
         }
 
         commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
-        commandParameters.put(KerberosServerAction.ADMINISTRATOR_CREDENTIAL, getEncryptedAdministratorCredentials(cluster));
 
         // *****************************************************************
         // Create stage to create principals

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
index 8351a99..b812337 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialProvider.java
@@ -22,48 +22,54 @@ import org.apache.ambari.server.configuration.Configuration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Random;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class CredentialProvider {
-  public static final Pattern PASSWORD_ALIAS_PATTERN =
-    Pattern.compile("\\$\\{alias=[\\w\\.]+\\}");
+  public static final Pattern PASSWORD_ALIAS_PATTERN = Pattern.compile("\\$\\{alias=[\\w\\.]+\\}");
 
-  protected char[] chars = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-    'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-    'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
-    'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-    '2', '3', '4', '5', '6', '7', '8', '9'};
+  protected char[] chars = {'a', 'b', 'c', 'd', 'e', 'f', 'g',
+      'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+      'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+      'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+      '2', '3', '4', '5', '6', '7', '8', '9'};
 
   private CredentialStoreService keystoreService;
   static final Logger LOG = LoggerFactory.getLogger(CredentialProvider.class);
 
   public CredentialProvider(String masterKey, String masterKeyLocation,
-              boolean isMasterKeyPersisted) throws AmbariException {
+                            boolean isMasterKeyPersisted) throws AmbariException {
     MasterKeyService masterKeyService;
     if (masterKey != null) {
       masterKeyService = new MasterKeyServiceImpl(masterKey);
     } else {
-      masterKeyService = new MasterKeyServiceImpl(masterKeyLocation,
-        isMasterKeyPersisted);
+      if (isMasterKeyPersisted) {
+        if ((masterKeyLocation == null) || masterKeyLocation.isEmpty()) {
+          throw new IllegalArgumentException("The master key file location may not be null or empty if the master key is persisted");
+        }
+        masterKeyService = new MasterKeyServiceImpl(new File(masterKeyLocation));
+      } else {
+        masterKeyService = new MasterKeyServiceImpl();
+      }
     }
     if (!masterKeyService.isMasterKeyInitialized()) {
       throw new AmbariException("Master key initialization failed.");
     }
     String storeDir = masterKeyLocation.substring(0,
-      masterKeyLocation.indexOf(Configuration.MASTER_KEY_FILENAME_DEFAULT));
-    this.keystoreService = new CredentialStoreServiceImpl(storeDir);
+        masterKeyLocation.indexOf(Configuration.MASTER_KEY_FILENAME_DEFAULT));
+    this.keystoreService = new FileBasedCredentialStoreService(storeDir);
     this.keystoreService.setMasterKeyService(masterKeyService);
   }
 
   public char[] getPasswordForAlias(String alias) throws AmbariException {
-    if (isAliasString(alias))
+    if (isAliasString(alias)) {
       return keystoreService.getCredential(getAliasFromString(alias));
+    }
     return keystoreService.getCredential(alias);
   }
 
@@ -73,13 +79,14 @@ public class CredentialProvider {
   }
 
   public void addAliasToCredentialStore(String alias, String passwordString)
-    throws AmbariException {
-    if (alias == null || alias.isEmpty())
+      throws AmbariException {
+    if (alias == null || alias.isEmpty()) {
       throw new IllegalArgumentException("Alias cannot be null or empty.");
-    if (passwordString == null || passwordString.isEmpty())
-      throw new IllegalArgumentException("Empty or null password not allowed" +
-        ".");
-    keystoreService.addCredential(alias, passwordString);
+    }
+    if (passwordString == null || passwordString.isEmpty()) {
+      throw new IllegalArgumentException("Empty or null password not allowed.");
+    }
+    keystoreService.addCredential(alias, passwordString.toCharArray());
   }
 
   private String generatePassword(int length) {
@@ -92,15 +99,15 @@ public class CredentialProvider {
   }
 
   public static boolean isAliasString(String aliasStr) {
-    if (aliasStr == null || aliasStr.isEmpty())
+    if (aliasStr == null || aliasStr.isEmpty()) {
       return false;
+    }
     Matcher matcher = PASSWORD_ALIAS_PATTERN.matcher(aliasStr);
     return matcher.matches();
   }
 
   private String getAliasFromString(String strPasswd) {
-    return strPasswd.substring(strPasswd.indexOf("=") + 1,
-      strPasswd.length() - 1);
+    return strPasswd.substring(strPasswd.indexOf("=") + 1, strPasswd.length() - 1);
   }
 
   protected CredentialStoreService getKeystoreService() {
@@ -113,8 +120,8 @@ public class CredentialProvider {
    * args[1] => Alias
    * args[2] => Payload (FilePath for GET/Password for PUT)
    * args[3] => Master Key (Empty)
-   * @param args
    *
+   * @param args
    */
   public static void main(String args[]) {
     if (args != null && args.length > 0) {
@@ -130,15 +137,14 @@ public class CredentialProvider {
         System.exit(1);
       }
       // None - To avoid incorrectly assuming redirection as argument
-      if (args.length > 3 && !args[3].isEmpty() && !args[3].equalsIgnoreCase
-        ("None")) {
+      if (args.length > 3 && !args[3].isEmpty() && !args[3].equalsIgnoreCase("None")) {
         masterKey = args[3];
         LOG.debug("Master key provided as an argument.");
       }
       try {
         credentialProvider = new CredentialProvider(masterKey,
-          configuration.getMasterKeyLocation(),
-          configuration.isMasterKeyPersisted());
+            configuration.getMasterKeyLocation(),
+            configuration.isMasterKeyPersisted());
       } catch (Exception ex) {
         ex.printStackTrace();
         System.exit(1);
@@ -150,7 +156,7 @@ public class CredentialProvider {
           password = args[2];
         }
         if (alias != null && !alias.isEmpty()
-          && password != null && !password.isEmpty()) {
+            && password != null && !password.isEmpty()) {
           try {
             credentialProvider.addAliasToCredentialStore(alias, password);
           } catch (AmbariException e) {
@@ -166,7 +172,7 @@ public class CredentialProvider {
           writeFilePath = args[2];
         }
         if (alias != null && !alias.isEmpty() && writeFilePath != null &&
-          !writeFilePath.isEmpty()) {
+            !writeFilePath.isEmpty()) {
           String passwd = "";
           try {
             char[] retPasswd = credentialProvider.getPasswordForAlias(alias);

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreService.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreService.java
index 8ea7ca2..4aa3b0a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreService.java
@@ -20,10 +20,39 @@ package org.apache.ambari.server.security.encryption;
 
 import org.apache.ambari.server.AmbariException;
 
-import java.security.KeyStore;
-
 public interface CredentialStoreService {
-  public void addCredential(String alias, String key) throws AmbariException;
-  public char[] getCredential(String alias) throws AmbariException;
-  public void setMasterKeyService(MasterKeyService masterService);
+  /**
+   * Adds a new credential to this CredentialStoreService
+   * <p/>
+   * The supplied key will be converted into UTF-8 bytes before being stored.
+   *
+   * @param alias a string declaring the alias (or name) of the credential
+   * @param key   an array of chars containing the credential
+   * @throws AmbariException if an error occurs while storing the new credential
+   */
+  void addCredential(String alias, char[] key) throws AmbariException;
+
+  /**
+   * Retrieves the specified credential from this CredentialStoreService
+   *
+   * @param alias a string declaring the alias (or name) of the credential
+   * @return an array of chars containing the credential
+   * @throws AmbariException if an error occurs while retrieving the new credential
+   */
+  char[] getCredential(String alias) throws AmbariException;
+
+  /**
+   * Removes the specified credential from this CredentialStoreService
+   *
+   * @param alias a string declaring the alias (or name) of the credential
+   * @throws AmbariException if an error occurs while removing the new credential
+   */
+  void removeCredential(String alias) throws AmbariException;
+
+  /**
+   * Sets the MasterKeyService for this CredentialStoreService
+   *
+   * @param masterKeyService the MasterKeyService
+   */
+  void setMasterKeyService(MasterKeyService masterKeyService);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
index d93faec..968e96a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/CredentialStoreServiceImpl.java
@@ -18,183 +18,263 @@
 package org.apache.ambari.server.security.encryption;
 
 import org.apache.ambari.server.AmbariException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.crypto.spec.SecretKeySpec;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
 import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
+import java.util.Arrays;
 
-public class CredentialStoreServiceImpl implements CredentialStoreService {
-  private static final String CREDENTIALS_SUFFIX = "credentials.jceks";
-  private static final String DEFAULT_STORE_TYPE = "JCEKS";
-  private MasterKeyService masterService;
-  private String keyStoreDir;
-  private static volatile boolean isCredentialStoreCreated = false;
-  static final Logger LOG = LoggerFactory.getLogger
-    (CredentialStoreServiceImpl.class);
-
-  public CredentialStoreServiceImpl(String keyStoreDir) {
-    this.keyStoreDir = keyStoreDir;
-    final File keyStoreFile = new File(keyStoreDir + File.separator +
-      CREDENTIALS_SUFFIX);
-    if (keyStoreFile.exists()) {
-      isCredentialStoreCreated = true;
+/**
+ * CredentialStoreServiceImpl is an abstract implementation of CredentialStoreService that loads and
+ * stores @{link KeyStore} data. Implementations of this class, provide the input and output streams
+ * used to read and write the data.
+ */
+public abstract class CredentialStoreServiceImpl implements CredentialStoreService {
+  protected static final String DEFAULT_STORE_TYPE = "JCEKS";
+
+  /**
+   * The MasterKeyService containing the key used to encrypt the KeyStore data
+   */
+  private MasterKeyService masterKeyService;
+
+  @Override
+  public void addCredential(String alias, char[] value) throws AmbariException {
+    if ((alias == null) || alias.isEmpty()) {
+      throw new IllegalArgumentException("Alias cannot be null or empty.");
     }
+
+    KeyStore ks = loadCredentialStore();
+    addCredential(ks, alias, value);
+    persistCredentialStore(ks);
   }
 
-  protected KeyStore loadCredentialStore() throws AmbariException {
-    if (masterService == null)
-      throw new AmbariException("Master Key Service is not set for this " +
-        "Credential store.");
+  @Override
+  public char[] getCredential(String alias) throws AmbariException {
+    if (alias == null) {
+      return null;
+    } else {
+      return getCredential(loadCredentialStore(), alias);
+    }
+  }
 
-    final File keyStoreFile = new File(keyStoreDir + File.separator +
-      CREDENTIALS_SUFFIX);
-    LOG.debug("keystoreFile => " + keyStoreFile.getAbsolutePath());
-    if (!isCredentialStoreCreated) {
-      createCredentialStore();
+  @Override
+  public void removeCredential(String alias) throws AmbariException {
+    if ((alias != null) && !alias.isEmpty()) {
+      KeyStore ks = loadCredentialStore();
+      if (ks != null) {
+        try {
+          ks.deleteEntry(alias);
+          persistCredentialStore(ks);
+        } catch (KeyStoreException e) {
+          throw new AmbariException("Failed to delete the KeyStore entry - the key store may not have been initialized", e);
+        }
+      }
     }
-    return getKeystore(keyStoreFile, DEFAULT_STORE_TYPE);
   }
 
   @Override
-  public void addCredential(String alias, String value) throws
-    AmbariException {
-    KeyStore ks = loadCredentialStore();
-    if (ks != null) {
+  public void setMasterKeyService(MasterKeyService masterKeyService) {
+    this.masterKeyService = masterKeyService;
+  }
+
+  /**
+   * Adds a new credential to the supplied KeyStore
+   * <p/>
+   * The supplied key will be converted into UTF-8 bytes before being stored.
+   *
+   * @param keyStore the KeyStore
+   * @param alias    a string declaring the alias (or name) of the credential
+   * @param value    an array of chars containing the credential
+   * @throws AmbariException if an error occurs while storing the new credential
+   */
+  protected void addCredential(KeyStore keyStore, String alias, char[] value) throws AmbariException {
+    if (keyStore != null) {
       try {
-        final Key key = new SecretKeySpec(value.getBytes("UTF8"), "AES");
-        ks.setKeyEntry( alias, key, masterService.getMasterSecret(), null);
-        final File  keyStoreFile = new File(keyStoreDir + File.separator +
-          CREDENTIALS_SUFFIX);
-        writeKeystoreToFile(ks, keyStoreFile);
+        Key key;
+
+        if ((value == null) || (value.length == 0)) {
+          key = null;
+        } else {
+          key = new SecretKeySpec(toBytes(value), "AES");
+        }
+
+        keyStore.setKeyEntry(alias, key, masterKeyService.getMasterSecret(), null);
       } catch (KeyStoreException e) {
-        e.printStackTrace();
-      } catch (NoSuchAlgorithmException e) {
-        e.printStackTrace();
-      } catch (CertificateException e) {
-        e.printStackTrace();
-      } catch (IOException e) {
-        e.printStackTrace();
+        throw new AmbariException("The key store has not been initialized", e);
       }
     }
   }
 
-  @Override
-  public char[] getCredential(String alias) throws AmbariException {
+  /**
+   * Retrieves the specified credential from a KeyStore
+   *
+   * @param keyStore the KeyStore
+   * @param alias    a string declaring the alias (or name) of the credential
+   * @return an array of chars containing the credential
+   * @throws AmbariException if an error occurs while retrieving the new credential
+   */
+  protected char[] getCredential(KeyStore keyStore, String alias) throws AmbariException {
     char[] credential = null;
-    KeyStore ks = loadCredentialStore();
-    if (ks != null && alias != null && !alias.isEmpty()) {
+
+    if (keyStore != null) {
       try {
-        LOG.debug("keystore = " + ks.aliases());
-        Key key = ks.getKey(alias, masterService.getMasterSecret());
-        if (key == null) {
-          throw new AmbariException("Credential not found for alias: " +
-            alias);
+        Key key = keyStore.getKey(alias, masterKeyService.getMasterSecret());
+        if (key != null) {
+          credential = toChars(key.getEncoded());
         }
-        credential = new String(key.getEncoded()).toCharArray();
       } catch (UnrecoverableKeyException e) {
-        e.printStackTrace();
+        throw new AmbariException("The key cannot be recovered (e.g., the given password is wrong)", e);
       } catch (KeyStoreException e) {
-        e.printStackTrace();
+        throw new AmbariException("The key store has not been initialized", e);
       } catch (NoSuchAlgorithmException e) {
-        e.printStackTrace();
+        throw new AmbariException(" if the algorithm for recovering the key cannot be found", e);
       }
     }
+
     return credential;
   }
 
-  public void writeKeystoreToFile(final KeyStore keyStore, final File file)
-    throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
-    final FileOutputStream  out = new FileOutputStream(file);
-    try {
-      keyStore.store(out, masterService.getMasterSecret());
-    }
-    finally {
-      out.close();
-    }
-  }
+  /**
+   * Calls the implementation-specific facility to persist the KeyStore
+   *
+   * @param keyStore the KeyStore to persist
+   * @throws AmbariException if an error occurs while persisting the key store data
+   */
+  protected abstract void persistCredentialStore(KeyStore keyStore) throws AmbariException;
 
-  private synchronized void createCredentialStore() {
-    String filename = keyStoreDir + File.separator + CREDENTIALS_SUFFIX;
-    createKeystore(filename, DEFAULT_STORE_TYPE);
-    isCredentialStoreCreated = true;
-  }
+  /**
+   * Calls the implementation-specific facility to load the KeyStore
+   *
+   * @throws AmbariException if an error occurs while loading the key store data
+   */
+  protected abstract KeyStore loadCredentialStore() throws AmbariException;
+
+  /**
+   * Loads a KeyStore from an InputStream
+   * <p/>
+   * Implementations are expected to call this to load the relevant KeyStore data from the
+   * InputStream of some storage facility.
+   *
+   * @param inputStream  the InputStream to read the data from
+   * @param keyStoreType the type of key store data expected
+   * @return a new KeyStore instance with the loaded data
+   * @throws AmbariException if an error occurs while loading the key store data from the InputStream
+   */
+  protected KeyStore loadKeyStore(InputStream inputStream, String keyStoreType) throws AmbariException {
+    if (masterKeyService == null) {
+      throw new AmbariException("Master Key Service is not set for this Credential store.");
+    }
 
-  private void createKeystore(String filename, String keystoreType) {
-    FileOutputStream out = null;
+    KeyStore keyStore;
     try {
-      out = new FileOutputStream(filename);
-      KeyStore ks = KeyStore.getInstance(keystoreType);
-      ks.load(null, null);
-      ks.store(out, masterService.getMasterSecret());
+      keyStore = KeyStore.getInstance(keyStoreType);
     } catch (KeyStoreException e) {
-      e.printStackTrace();
-    } catch (NoSuchAlgorithmException e) {
-      e.printStackTrace();
+      throw new AmbariException(String.format("No provider supports a key store implementation for the specified type: %s", keyStoreType), e);
+    }
+
+    try {
+      keyStore.load(inputStream, masterKeyService.getMasterSecret());
     } catch (CertificateException e) {
-      e.printStackTrace();
-    } catch (FileNotFoundException e) {
-      e.printStackTrace();
+      throw new AmbariException(String.format("One or more credentials from the key store could not be loaded: %s", e.getLocalizedMessage()), e);
+    } catch (NoSuchAlgorithmException e) {
+      throw new AmbariException(String.format("The algorithm used to check the integrity of the key store cannot be found: %s", e.getLocalizedMessage()), e);
     } catch (IOException e) {
-      e.printStackTrace();
-    } finally {
-      try {
-        out.close();
-      } catch (IOException e) {
-        e.printStackTrace();
+      if (e.getCause() instanceof UnrecoverableKeyException) {
+        throw new AmbariException(String.format("The password used to decrypt the key store is incorrect: %s", e.getLocalizedMessage()), e);
+      } else {
+        throw new AmbariException(String.format("Failed to read the key store: %s", e.getLocalizedMessage()), e);
       }
     }
+
+    return keyStore;
   }
 
-  private KeyStore getKeystore(final File keyStoreFile, String storeType) {
-    KeyStore credStore = null;
+  /**
+   * Writes a KeyStore to an OutputStream
+   * <p/>
+   * Implementations are expected to call this to write the relevant KeyStore data to the
+   * OutputStream of some storage facility.
+   *
+   * @param keyStore     the KeyStore to write
+   * @param outputStream the OutputStream to write the data into
+   * @throws AmbariException if an error occurs while writing the key store data
+   */
+  protected void writeKeyStore(KeyStore keyStore, OutputStream outputStream) throws AmbariException {
+    if (masterKeyService == null) {
+      throw new AmbariException("Master Key Service is not set for this Credential store.");
+    }
+
     try {
-      credStore = loadKeyStore(keyStoreFile, masterService.getMasterSecret(), storeType);
+      keyStore.store(outputStream, masterKeyService.getMasterSecret());
     } catch (CertificateException e) {
-      e.printStackTrace();
-    } catch (KeyStoreException e) {
-      e.printStackTrace();
+      throw new AmbariException(String.format("A credential within in the key store data could not be stored: %s", e.getLocalizedMessage()), e);
     } catch (NoSuchAlgorithmException e) {
-      e.printStackTrace();
+      throw new AmbariException(String.format("The appropriate data integrity algorithm could not be found: %s", e.getLocalizedMessage()), e);
+    } catch (KeyStoreException e) {
+      throw new AmbariException(String.format("The key store has not been initialized: %s", e.getLocalizedMessage()), e);
     } catch (IOException e) {
-      e.printStackTrace();
+      throw new AmbariException(String.format("Failed to write the key store: %s", e.getLocalizedMessage()), e);
     }
-    return credStore;
   }
 
-  private static KeyStore loadKeyStore(final File keyStoreFile,
-          final char[] masterPassword, String storeType)
-    throws CertificateException, IOException,
-    KeyStoreException, NoSuchAlgorithmException {
-    final KeyStore  keyStore = KeyStore.getInstance(storeType);
-    if (keyStoreFile.exists()) {
-      final FileInputStream input   = new FileInputStream(keyStoreFile);
-      try {
-        keyStore.load(input, masterPassword);
-      }
-      finally {
-        input.close();
-      }
-    }
-    else {
-      keyStore.load(null, masterPassword);
-    }
+  /**
+   * Converts an array of characters to an array of bytes by encoding each character into UTF-8 bytes.
+   * <p/>
+   * An attempt is made to clear out sensitive data by filling any buffers with 0's
+   *
+   * @param chars the array of chars to convert
+   * @return an array of bytes, or null if the original array was null
+   */
+  protected byte[] toBytes(char[] chars) {
+    if (chars == null) {
+      return null;
+    } else {
+      CharBuffer charBuffer = CharBuffer.wrap(chars);
+      ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
 
-    return keyStore;
+      byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
+
+      // Clear sensitive data
+      Arrays.fill(charBuffer.array(), '\u0000');
+      Arrays.fill(byteBuffer.array(), (byte) 0);
+
+      return bytes;
+    }
   }
 
-  @Override
-  public void setMasterKeyService(MasterKeyService masterService) {
-    this.masterService = masterService;
+  /**
+   * Converts an array of bytes to an array of character by decoding the bytes using the UTF-8
+   * character set.
+   * <p/>
+   * An attempt is made to clear out sensitive data by filling any buffers with 0's
+   *
+   * @param bytes the array of bytes to convert
+   * @return an array of chars, or null if the original array was null
+   */
+  protected char[] toChars(byte[] bytes) {
+    if (bytes == null) {
+      return null;
+    } else {
+      ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+      CharBuffer charBuffer = Charset.forName("UTF-8").decode(byteBuffer);
+
+      char[] chars = Arrays.copyOfRange(charBuffer.array(), charBuffer.position(), charBuffer.limit());
+
+      // Clear sensitive data
+      Arrays.fill(charBuffer.array(), '\u0000');
+      Arrays.fill(byteBuffer.array(), (byte) 0);
+
+      return chars;
+    }
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/FileBasedCredentialStoreService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/FileBasedCredentialStoreService.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/FileBasedCredentialStoreService.java
new file mode 100644
index 0000000..41ff71b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/FileBasedCredentialStoreService.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.security.encryption;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+
+/**
+ * FileBasedCredentialStoreService is a CredentialStoreService implementation that creates and manages
+ * a JCEKS (Java Cryptography Extension KeyStore) file on disk.  The key store and its contents are
+ * encrypted using the key from the supplied {@link MasterKeyService}.
+ * <p/>
+ * Most of the work for this implementation is handled by the {@link CredentialStoreServiceImpl}.
+ * This class handles the details of the storage location and associated input and output streams.
+ */
+public class FileBasedCredentialStoreService extends CredentialStoreServiceImpl {
+  private static final String KEYSTORE_FILENAME = "credentials.jceks";
+  private static final Logger LOG = LoggerFactory.getLogger(FileBasedCredentialStoreService.class);
+
+  /**
+   * The directory to use for storing the key store file
+   */
+  private File keyStoreDir;
+
+  /**
+   * Constructs a new FileBasedCredentialStoreService using the specified key store directory
+   *
+   * @param keyStoreDir a String containing the absolute path to the directory in which to store the key store file
+   */
+  public FileBasedCredentialStoreService(String keyStoreDir) {
+    this(new File(keyStoreDir));
+  }
+
+  /**
+   * Constructs a new FileBasedCredentialStoreService using the specified key store directory
+   *
+   * @param keyStoreDir a File pointing to the directory in which to store the key store file
+   */
+  public FileBasedCredentialStoreService(File keyStoreDir) {
+    if (keyStoreDir == null) {
+      LOG.warn("Writing key store to the current working directory of the running process");
+    } else if (!keyStoreDir.exists()) {
+      LOG.warn("The destination directory does not exist. Failures may occur when writing the key store to disk: {}", keyStoreDir.getAbsolutePath());
+    } else if (!keyStoreDir.isDirectory()) {
+      LOG.warn("The destination does not point to directory. Failures may occur when writing the key store to disk: {}", keyStoreDir.getAbsolutePath());
+    }
+
+    this.keyStoreDir = keyStoreDir;
+  }
+
+  @Override
+  protected void persistCredentialStore(KeyStore keyStore) throws AmbariException {
+    putKeyStore(keyStore, getKeyStoreFile());
+  }
+
+
+  @Override
+  protected KeyStore loadCredentialStore() throws AmbariException {
+    return getKeyStore(getKeyStoreFile(), DEFAULT_STORE_TYPE);
+  }
+
+  /**
+   * Reads the key store data from the specified file. If the file does not exist, a new KeyStore
+   * will be created.
+   *
+   * @param keyStoreFile a File pointing to the key store file
+   * @param keyStoreType the type of key store data to read (or create)
+   * @return the loaded KeyStore
+   * @throws AmbariException           if the Master Key Service is not set
+   * @see CredentialStoreServiceImpl#loadCredentialStore()
+   */
+  private KeyStore getKeyStore(final File keyStoreFile, String keyStoreType) throws AmbariException{
+    KeyStore keyStore;
+    FileInputStream inputStream;
+
+    if (keyStoreFile.exists()) {
+      LOG.debug("Reading key store from {}", keyStoreFile.getAbsolutePath());
+      try {
+        inputStream = new FileInputStream(keyStoreFile);
+      } catch (FileNotFoundException e) {
+        throw new AmbariException(String.format("Failed to open the key store file: %s", e.getLocalizedMessage()), e);
+      }
+    } else {
+      LOG.debug("Key store file not found in {}. Returning new (non-persisted) KeyStore", keyStoreFile.getAbsolutePath());
+      inputStream = null;
+    }
+
+    try {
+      keyStore = loadKeyStore(inputStream, keyStoreType);
+    } finally {
+      IOUtils.closeQuietly(inputStream);
+    }
+
+    return keyStore;
+  }
+
+  /**
+   * Writes the specified KeyStore to a file.
+   *
+   * @param keyStore     the KeyStore to write to a file
+   * @param keyStoreFile the File in which to store the KeyStore data
+   * @throws AmbariException if an error occurs while writing the KeyStore data
+   */
+  private void putKeyStore(KeyStore keyStore, File keyStoreFile) throws AmbariException {
+    LOG.debug("Writing key store to {}", keyStoreFile.getAbsolutePath());
+
+    FileOutputStream outputStream = null;
+
+    try {
+      outputStream = new FileOutputStream(new File(keyStoreDir, KEYSTORE_FILENAME));
+      writeKeyStore(keyStore, outputStream);
+    } catch (FileNotFoundException e) {
+      throw new AmbariException(String.format("Failed to open the key store file: %s", e.getLocalizedMessage()), e);
+    } finally {
+      IOUtils.closeQuietly(outputStream);
+    }
+  }
+
+  /**
+   * Calculates the absolute path to the key store file
+   *
+   * @return a File pointing to the absolute path of the key store file
+   */
+  private File getKeyStoreFile() {
+    return new File(keyStoreDir, KEYSTORE_FILENAME);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/InMemoryCredentialStoreService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/InMemoryCredentialStoreService.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/InMemoryCredentialStoreService.java
new file mode 100644
index 0000000..3766cbb
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/InMemoryCredentialStoreService.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.security.encryption;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.apache.ambari.server.AmbariException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.security.KeyStore;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * InMemoryCredentialStoreService is a CredentialStoreService implementation that creates and manages
+ * a JCEKS (Java Cryptography Extension KeyStore) in memory.  The key store and its contents are
+ * encrypted using the key from the supplied {@link MasterKeyService}.
+ * <p/>
+ * This class handles the details of the in-memory storage buffer and associated input and output
+ * streams. Each credential is stored in its own KeyStore that may be be purged upon some
+ * retention timeout - if specified.
+ */
+public class InMemoryCredentialStoreService extends CredentialStoreServiceImpl {
+  private static final Logger LOG = LoggerFactory.getLogger(InMemoryCredentialStoreService.class);
+
+  /**
+   * A cache containing the KeyStore data
+   */
+  private final Cache<String, KeyStore> cache;
+
+  /**
+   * Constructs a new InMemoryCredentialStoreService where credentials have no retention timeout
+   */
+  public InMemoryCredentialStoreService() {
+    this(0, TimeUnit.MINUTES, false);
+  }
+
+  /**
+   * Constructs a new InMemoryCredentialStoreService with a specified credential timeout
+   *
+   * @param retentionDuration the time in some units to keep stored credentials, from the time they are added
+   * @param units             the units for the retention duration (minutes, seconds, etc...)
+   * @param activelyPurge     true to actively purge credentials after the retention time has expired;
+   *                          otherwise false, to passively purge credentials after the retention time has expired
+   */
+  public InMemoryCredentialStoreService(final long retentionDuration, final TimeUnit units, boolean activelyPurge) {
+    CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
+
+    // If the retentionDuration is less the 1, then no retention policy is to be enforced
+    if (retentionDuration > 0) {
+      // If actively purging expired credentials, set up a timer to periodically clean the cache
+      if (activelyPurge) {
+        ThreadFactory threadFactory = new ThreadFactory() {
+          @Override
+          public Thread newThread(Runnable runnable) {
+            Thread t = Executors.defaultThreadFactory().newThread(runnable);
+            if (t != null) {
+              t.setName(String.format("%s active cleanup timer", InMemoryCredentialStoreService.class.getSimpleName()));
+            }
+            return t;
+          }
+        };
+        Runnable runnable = new Runnable() {
+          @Override
+          public void run() {
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("Cleaning up cache due to retention timeout of {} milliseconds",
+                  units.toMillis(retentionDuration));
+            }
+            cache.cleanUp();
+          }
+        };
+
+        Executors.newSingleThreadScheduledExecutor(threadFactory).schedule(runnable, 1, TimeUnit.MINUTES);
+      }
+
+      builder.expireAfterWrite(retentionDuration, units);
+    }
+
+    cache = builder.build();
+  }
+
+  @Override
+  public void addCredential(String alias, char[] value) throws AmbariException {
+    if ((alias == null) || alias.isEmpty()) {
+      throw new IllegalArgumentException("Alias cannot be null or empty.");
+    }
+
+    KeyStore keyStore = loadKeyStore(null, DEFAULT_STORE_TYPE);
+    addCredential(keyStore, alias, value);
+    cache.put(alias, keyStore);
+  }
+
+  @Override
+  public char[] getCredential(String alias) throws AmbariException {
+    char[] credential = null;
+
+    if ((alias != null) && !alias.isEmpty()) {
+      KeyStore keyStore = cache.getIfPresent(alias);
+      if (keyStore != null) {
+        credential = getCredential(keyStore, alias);
+      }
+    }
+
+    return credential;
+  }
+
+  @Override
+  public void removeCredential(String alias) throws AmbariException {
+    if (alias != null) {
+      cache.invalidate(alias);
+    }
+  }
+
+  @Override
+  protected void persistCredentialStore(KeyStore keyStore) throws AmbariException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  protected KeyStore loadCredentialStore() throws AmbariException {
+    throw new UnsupportedOperationException();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
index 219c14b..759fd8e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/encryption/MasterKeyServiceImpl.java
@@ -18,103 +18,62 @@
 
 package org.apache.ambari.server.security.encryption;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.net.ntp.TimeStamp;
+
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
-import java.io.PrintWriter;
+import java.nio.channels.FileChannel;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-import java.util.Random;
 
 public class MasterKeyServiceImpl implements MasterKeyService {
-  private static Log LOG = LogFactory.getLog(MasterKeyServiceImpl.class);
-  private static final String MASTER_PERSISTENCE_TAG = "#1.0# " +
-    TimeStamp.getCurrentTime().toDateString();
-  private char[] master = null;
-  private String MASTER_PASSPHRASE = "masterpassphrase";
-  private AESEncryptor aes = new AESEncryptor(MASTER_PASSPHRASE);
+  private static final Log LOG = LogFactory.getLog(MasterKeyServiceImpl.class);
+  private static final String MASTER_PASSPHRASE = "masterpassphrase";
+  private static final String MASTER_PERSISTENCE_TAG_PREFIX = "#1.0# ";
+  private static final AESEncryptor aes = new AESEncryptor(MASTER_PASSPHRASE);
 
-  // TODO: Create static factory methods vs constructors
+  private char[] master = null;
 
   /**
-   * Test/console friendly construction
-   * @param masterKey
-   * @param masterFileLocation
-   * @param persistMaster
+   * Constructs a new MasterKeyServiceImpl using a master key read from a file.
+   *
+   * @param masterKeyFile the location of the master key file
    */
-  public MasterKeyServiceImpl(String masterKey, String masterFileLocation,
-                              boolean persistMaster) {
-    this.master = masterKey.toCharArray();
-    if (masterFileLocation != null) {
-      if (persistMaster) {
-        LOG.debug("Persisting master key file.");
-        File masterFile = new File(masterFileLocation);
-        if (masterFile.exists()) {
-          LOG.info("Resetting master key before persist.");
-          try {
-            PrintWriter pw = new PrintWriter(masterFile);
-            pw.print("");
-            pw.close();
-          } catch (FileNotFoundException e) {
-            LOG.error("Cannot reset master key file located at: " +
-              masterFileLocation);
-            e.printStackTrace();
-          }
-        }
-        persistMaster(masterFile);
-      }
-    } else {
-      if (persistMaster) {
-        LOG.error("Cannot persist master key without specifying master key " +
-          "location.");
-      }
+  public MasterKeyServiceImpl(File masterKeyFile) {
+    if (masterKeyFile == null) {
+      throw new IllegalArgumentException("Master Key location not provided.");
     }
-  }
 
-  /**
-   * Construction - post creation of the key
-   * @param masterFileLocation
-   * @param isPersisted
-   */
-  public MasterKeyServiceImpl(String masterFileLocation, boolean isPersisted) {
-    if (masterFileLocation == null || masterFileLocation.isEmpty())
-      throw new IllegalArgumentException("Master Key location not provided.");
-    if (isPersisted) {
-      File masterFile = new File(masterFileLocation);
-      if (masterFile.exists()) {
+    if (masterKeyFile.exists()) {
+      if (isMasterKeyFile(masterKeyFile)) {
         try {
-          initializeFromFile(masterFile);
-        } catch (Exception ex) {
-          LOG.error("Cannot intitialize master key from file: " +
-            masterFileLocation + "\n" + ex);
+          initializeFromFile(masterKeyFile);
+        } catch (Exception e) {
+          LOG.error(String.format("Cannot initialize master key from %s: %s", masterKeyFile.getAbsolutePath(), e.getLocalizedMessage()), e);
         }
       } else {
-        LOG.error("Cannot find master key at specified location " +
-          masterFileLocation);
+        LOG.error(String.format("The file at %s is not a master ket file", masterKeyFile.getAbsolutePath()));
       }
     } else {
-      // Master key is not persisted, read from environment.
-      String key = readMasterKey();
-      if (key != null) {
-        this.master = key.toCharArray();
-      } else {
-        LOG.debug("Master key is not provided as a System property or an " +
-          "environment varialble.");
-      }
+      LOG.error(String.format("Cannot open master key file, %s", masterKeyFile.getAbsolutePath()));
     }
   }
 
   /**
-   * Construction for Non-persisted master key
-   * @param masterKey
+   * Constructs a new MasterKeyServiceImpl using the specified master key.
+   *
+   * @param masterKey the master key
    */
   public MasterKeyServiceImpl(String masterKey) {
     if (masterKey != null) {
@@ -125,16 +84,190 @@ public class MasterKeyServiceImpl implements MasterKeyService {
   }
 
   /**
-   * Construction for Non-persisted master key from environment
-   *
+   * Constructs a new MasterKeyServiceImpl using the master key found in the environment.
    */
   public MasterKeyServiceImpl() {
     String key = readMasterKey();
     if (key == null) {
-      throw new IllegalStateException("Cannot read master key from " +
-        "environment.");
-    } else
+      throw new IllegalStateException("Cannot read master key from environment.");
+    } else {
       this.master = key.toCharArray();
+    }
+  }
+
+  public boolean isMasterKeyInitialized() {
+    return this.master != null;
+  }
+
+  @Override
+  public char[] getMasterSecret() {
+    return this.master;
+  }
+
+  public static void main(String args[]) {
+    String masterKey = "ThisissomeSecretPassPhrasse";
+    String masterKeyLocation = "/var/lib/ambari-server/keys/master";
+    boolean persistMasterKey = false;
+    if (args != null && args.length > 0) {
+      masterKey = args[0];
+      if (args.length > 1) {
+        masterKeyLocation = args[1];
+      }
+      if (args.length > 2 && !args[2].isEmpty()) {
+        persistMasterKey = args[2].toLowerCase().equals("true");
+      }
+    }
+
+    if (persistMasterKey && !MasterKeyServiceImpl.initializeMasterKeyFile(new File(masterKeyLocation), masterKey)) {
+      System.exit(1);
+    } else {
+      System.exit(0);
+    }
+  }
+
+  /**
+   * Initializes the master key file.
+   * <p/>
+   * If the specified file already exists, it it tested to see if it is a master key file. If so, it
+   * will be truncated and the new master key will be stored in the new file. If the file appears
+   * to not be a master key file,no changes will be made. The user must manually remove the file if
+   * deemed appropriate.
+   *
+   * @param masterKeyFile the file to write the master key to
+   * @param masterKey     the master key
+   * @return true if the master key was written to the specified file; otherwise false
+   */
+  public static boolean initializeMasterKeyFile(File masterKeyFile, String masterKey) {
+    LOG.debug(String.format("Persisting master key into %s", masterKeyFile.getAbsolutePath()));
+
+    EncryptionResult atom = null;
+
+    if (masterKey != null) {
+      try {
+        atom = aes.encrypt(masterKey);
+      } catch (Exception e) {
+        LOG.error(String.format("Failed to encrypt master key, no changes have been made: %s", e.getLocalizedMessage()), e);
+        return false;
+      }
+    }
+
+    if (masterKeyFile.exists()) {
+      if ((masterKeyFile.length() == 0) || isMasterKeyFile(masterKeyFile)) {
+        LOG.info(String.format("Master key file exists at %s, resetting.", masterKeyFile.getAbsolutePath()));
+        FileChannel fileChannel = null;
+        try {
+          fileChannel = new FileOutputStream(masterKeyFile).getChannel();
+          fileChannel.truncate(0);
+        } catch (FileNotFoundException e) {
+          LOG.error(String.format("Failed to open key file at %s: %s", masterKeyFile.getAbsolutePath(), e.getLocalizedMessage()), e);
+        } catch (IOException e) {
+          LOG.error(String.format("Failed to reset key file at %s: %s", masterKeyFile.getAbsolutePath(), e.getLocalizedMessage()), e);
+        } finally {
+          if (fileChannel != null) {
+            try {
+              fileChannel.close();
+            } catch (IOException e) {
+              // Ignore...
+            }
+          }
+        }
+      } else {
+        LOG.info(String.format("File exists at %s, but may not be a master key file. " +
+            "It must be manually removed before this file location can be used", masterKeyFile.getAbsolutePath()));
+        return false;
+      }
+    }
+
+    if (atom != null) {
+      try {
+        ArrayList<String> lines = new ArrayList<String>();
+        lines.add(MASTER_PERSISTENCE_TAG_PREFIX + TimeStamp.getCurrentTime().toDateString());
+
+        String line = Base64.encodeBase64String((
+            Base64.encodeBase64String(atom.salt) + "::" +
+                Base64.encodeBase64String(atom.iv) + "::" +
+                Base64.encodeBase64String(atom.cipher)).getBytes("UTF8"));
+        lines.add(line);
+        FileUtils.writeLines(masterKeyFile, "UTF8", lines);
+
+        // restrict os permissions to only the user running this process
+        protectAccess(masterKeyFile);
+      } catch (IOException e) {
+        LOG.error(String.format("Failed to persist master key to %s: %s ", masterKeyFile.getAbsolutePath(), e.getLocalizedMessage()), e);
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Determines if the specified file is a "master key" file by checking the file header to see if it
+   * matches an expected value.
+   * <p/>
+   * The "master key" file is expected to have a header (or first line) that starts with "#1.0#". If it,
+   * it is assumed to be a "master key" file, otherwise it is assumed to not be.
+   *
+   * @param file the file to test
+   * @return true if the file is identitified as "master key" file; otherwise false
+   */
+  private static boolean isMasterKeyFile(File file) {
+    FileReader reader = null;
+
+    try {
+      reader = new FileReader(file);
+      char[] buffer = new char[MASTER_PERSISTENCE_TAG_PREFIX.length()];
+      return (reader.read(buffer) == buffer.length) && Arrays.equals(buffer, MASTER_PERSISTENCE_TAG_PREFIX.toCharArray());
+    } catch (Exception e) {
+      // Ignore, assume the file is not a master key file...
+    } finally {
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) {
+          // Ignore...
+        }
+      }
+    }
+
+    return false;
+  }
+
+
+  /**
+   * Ensures that the owner of this process is the only local user account able to read and write to
+   * the specified file or read, write to, and execute the specified directory.
+   *
+   * @param file the file or directory for which to modify access
+   */
+  private static void protectAccess(File file) throws AmbariException {
+    if (file.exists()) {
+      if (!file.setReadable(false, false) || !file.setReadable(true, true)) {
+        String message = String.format("Failed to set %s readable only by current user", file.getAbsolutePath());
+        LOG.warn(message);
+        throw new AmbariException(message);
+      }
+
+      if (!file.setWritable(false, false) || !file.setWritable(true, true)) {
+        String message = String.format("Failed to set %s writable only by current user", file.getAbsolutePath());
+        LOG.warn(message);
+        throw new AmbariException(message);
+      }
+
+      if (file.isDirectory()) {
+        if (!file.setExecutable(false, false) || !file.setExecutable(true, true)) {
+          String message = String.format("Failed to set %s executable by current user", file.getAbsolutePath());
+          LOG.warn(message);
+          throw new AmbariException(message);
+        }
+      } else {
+        if (!file.setExecutable(false, false)) {
+          String message = String.format("Failed to set %s not executable", file.getAbsolutePath());
+          LOG.warn(message);
+          throw new AmbariException(message);
+        }
+      }
+    }
   }
 
   private String readMasterKey() {
@@ -149,8 +282,9 @@ public class MasterKeyServiceImpl implements MasterKeyService {
           if (keyFile.exists()) {
             try {
               initializeFromFile(keyFile);
-              if (this.master != null)
+              if (this.master != null) {
                 key = new String(this.master);
+              }
               FileUtils.deleteQuietly(keyFile);
             } catch (IOException e) {
               LOG.error("Cannot read master key from file: " + keyPath);
@@ -166,42 +300,6 @@ public class MasterKeyServiceImpl implements MasterKeyService {
     return key;
   }
 
-  public boolean isMasterKeyInitialized() {
-    return this.master != null;
-  }
-
-  private EncryptionResult encryptMaster(char[] master) {
-    try {
-      return aes.encrypt(new String(master));
-    } catch (Exception e) {
-      // TODO log failed encryption attempt
-      // need to ensure that we don't persist now
-      e.printStackTrace();
-    }
-    return null;
-  }
-
-  private void persistMaster(File masterFile) {
-    EncryptionResult atom = encryptMaster(master);
-    try {
-      ArrayList<String> lines = new ArrayList<String>();
-      lines.add(MASTER_PERSISTENCE_TAG);
-
-      String line = Base64.encodeBase64String((
-        Base64.encodeBase64String(atom.salt) + "::" +
-          Base64.encodeBase64String(atom.iv) + "::" +
-          Base64.encodeBase64String(atom.cipher)).getBytes("UTF8"));
-      lines.add(line);
-      FileUtils.writeLines(masterFile, "UTF8", lines);
-
-      // restrict os permissions to only the user running this process
-      chmod("600", masterFile);
-    } catch (IOException e) {
-      LOG.error("Failed to persist master. " + e.getLocalizedMessage());
-      e.printStackTrace();
-    }
-  }
-
   private void initializeFromFile(File masterFile) throws Exception {
     try {
       List<String> lines = FileUtils.readLines(masterFile, "UTF8");
@@ -210,8 +308,8 @@ public class MasterKeyServiceImpl implements MasterKeyService {
       String line = new String(Base64.decodeBase64(lines.get(1)));
       String[] parts = line.split("::");
       this.master = new String(aes.decrypt(Base64.decodeBase64(parts[0]),
-        Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])),
-        "UTF8").toCharArray();
+          Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])),
+          "UTF8").toCharArray();
     } catch (IOException e) {
       e.printStackTrace();
       throw e;
@@ -220,65 +318,4 @@ public class MasterKeyServiceImpl implements MasterKeyService {
       throw e;
     }
   }
-
-  @Override
-  public char[] getMasterSecret() {
-    return this.master;
-  }
-
-  private void chmod(String args, File file) throws IOException {
-    if (isUnixEnv()) {
-      //args and file should never be null.
-      if (args == null || file == null)
-        throw new IOException("nullArg");
-      if (!file.exists())
-        throw new IOException("fileNotFound");
-
-      // " +" regular expression for 1 or more spaces
-      final String[] argsString = args.split(" +");
-      List<String> cmdList = new ArrayList<String>();
-      cmdList.add("/bin/chmod");
-      cmdList.addAll(Arrays.asList(argsString));
-      cmdList.add(file.getAbsolutePath());
-      new ProcessBuilder(cmdList).start();
-    }
-  }
-
-  private boolean isUnixEnv() {
-    return (File.separatorChar == '/');
-  }
-
-  private String generateMasterKey() {
-    char[] chars = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
-      'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
-      'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
-      'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      '2', '3', '4', '5', '6', '7', '8', '9'};
-
-    StringBuffer sb = new StringBuffer();
-    Random r = new Random();
-    for (int i = 0; i < chars.length; i++) {
-      sb.append(chars[r.nextInt(chars.length)]);
-    }
-    return sb.toString();
-  }
-
-  public static void main(String args[]) {
-    String masterKey = "ThisissomeSecretPassPhrasse";
-    String masterKeyLocation = "/var/lib/ambari-server/keys/master";
-    boolean persistMasterKey = false;
-    if (args != null && args.length > 0) {
-      masterKey = args[0];
-      if (args.length > 1)
-        masterKeyLocation = args[1];
-      if (args.length > 2 && !args[2].isEmpty())
-        persistMasterKey = args[2].toLowerCase().equals("true");
-    }
-    MasterKeyService masterKeyService = new MasterKeyServiceImpl
-      (masterKey, masterKeyLocation, persistMasterKey);
-    if (!masterKeyService.isMasterKeyInitialized()) {
-      System.exit(1);
-    }
-    System.exit(0);
-  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
index 19997e7..a173e08 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
@@ -61,7 +61,7 @@ public class KerberosCredential {
   /**
    * The plaintext password value
    */
-  private String password = null;
+  private char[] password = null;
 
   /**
    * A base64-encoded keytab
@@ -94,7 +94,7 @@ public class KerberosCredential {
     if (map != null) {
       Object attribute;
       String principal;
-      String password;
+      char[] password;
       String keytab;
 
       if (prefix == null) {
@@ -105,13 +105,19 @@ public class KerberosCredential {
       principal = (attribute == null) ? null : attribute.toString();
 
       attribute = map.get(prefix + KEY_NAME_PASSWORD);
-      password = (attribute == null) ? null : attribute.toString();
+      if (attribute instanceof char[]) {
+        password = (char[]) attribute;
+      } else if (attribute instanceof String) {
+        password = ((String) attribute).toCharArray();
+      } else {
+        password = null;
+      }
 
       attribute = map.get(prefix + KEY_NAME_KEYTAB);
       keytab = (attribute == null) ? null : attribute.toString();
 
       if (((principal != null) && !principal.isEmpty()) ||
-          ((password != null) && !password.isEmpty()) ||
+          ((password != null) && (password.length > 0)) ||
           ((keytab != null) && !keytab.isEmpty())) {
         credential = new KerberosCredential(principal, password, keytab);
       }
@@ -141,7 +147,7 @@ public class KerberosCredential {
         Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
         cipher.init(Cipher.DECRYPT_MODE, secretKey);
         byte[] plaintext = cipher.doFinal(Base64.decodeBase64(cipherText));
-        return new Gson().fromJson(new String(plaintext), KerberosCredential.class);
+        return fromJSON(new String(plaintext));
       } catch (NoSuchAlgorithmException e) {
         throw new AmbariException("Failed to decrypt cipher text due to invalid encryption algorithm", e);
       } catch (NoSuchPaddingException e) {
@@ -184,7 +190,7 @@ public class KerberosCredential {
       } catch (NoSuchPaddingException e) {
         throw new AmbariException("Failed to encrypt plaintext due to invalid padding scheme algorithm", e);
       } catch (IllegalBlockSizeException e) {
-        throw new AmbariException("Failed to encrypt plaintext due to invalid key", e);
+        throw new AmbariException("The encryption algorithm is unable to process the input data provided.", e);
       } catch (BadPaddingException e) {
         throw new AmbariException("Failed to encrypt plaintext due to unexpected reasons", e);
       } catch (InvalidKeyException e) {
@@ -206,10 +212,10 @@ public class KerberosCredential {
    * Creates a new KerberosCredential
    *
    * @param principal a String containing the principal name for this Kerberos credential
-   * @param password  a String containing the password for this Kerberos credential
+   * @param password  a char array containing the password for this Kerberos credential
    * @param keytab    a String containing the base64 encoded keytab for this Kerberos credential
    */
-  public KerberosCredential(String principal, String password, String keytab) {
+  public KerberosCredential(String principal, char[] password, String keytab) {
     this.principal = principal;
     this.password = password;
     this.keytab = keytab;
@@ -230,16 +236,16 @@ public class KerberosCredential {
   }
 
   /**
-   * @return a String containing the password for this Kerberos credential
+   * @return a char array containing the password for this Kerberos credential
    */
-  public String getPassword() {
+  public char[] getPassword() {
     return password;
   }
 
   /**
-   * @param password a String containing the password for this Kerberos credential
+   * @param password a char array containing the password for this Kerberos credential
    */
-  public void setPassword(String password) {
+  public void setPassword(char[] password) {
     this.password = password;
   }
 
@@ -270,4 +276,28 @@ public class KerberosCredential {
   public String encrypt(byte[] key) throws AmbariException {
     return encrypt(this, key);
   }
+
+  /**
+   * Returns a JSON representation of this KerberosCredential
+   *
+   * @return a String containing the JSON representation of this KerberosCredential
+   */
+  public String toJSON() {
+    return new Gson().toJson(this);
+  }
+
+  /**
+   * Renders a new KerberosCredential from its JSON representation
+   *
+   * @param json a string containing a JSON representation of a KerberosCredential
+   * @return a new KerberosCredential or null if a new KerberosCredential cannot be created
+   */
+  public static KerberosCredential fromJSON(String json) {
+    try {
+      return ((json == null) || json.isEmpty()) ? null : new Gson().fromJson(json, KerberosCredential.class);
+    }
+    catch(JsonSyntaxException e) {
+      return null;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 425aa06..c8b8ca6 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
@@ -503,20 +503,18 @@ public abstract class KerberosOperationHandler {
       throw new KerberosAdminAuthenticationException("The administrator credential must not be null");
     }
 
-    String value;
-
     // Ensure the principal is not null or empty
-    value = administratorCredentials.getPrincipal();
-    if ((value == null) || value.isEmpty()) {
+    String principal = administratorCredentials.getPrincipal();
+    if ((principal == null) || principal.isEmpty()) {
       throw new KerberosAdminAuthenticationException("Must specify a principal but it is null or empty");
     }
 
     // Ensure either the password or the keytab value is not null or empty
-    value = administratorCredentials.getPassword();
-    if ((value == null) || value.isEmpty()) {
-      value = administratorCredentials.getKeytab();
+    char[] password  = administratorCredentials.getPassword();
+    if ((password == null) || (password.length == 0)) {
+      String keytab  = administratorCredentials.getKeytab();
 
-      if ((value == null) || value.isEmpty()) {
+      if ((keytab == null) || keytab.isEmpty()) {
         throw new KerberosAdminAuthenticationException("Must specify either a password or a keytab but both are null or empty");
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/e681f2bf/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 389f1b8..c861b45 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
@@ -23,6 +23,7 @@ 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.agent.ExecutionCommand;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.serveraction.AbstractServerAction;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -59,12 +60,6 @@ public abstract class KerberosServerAction extends AbstractServerAction {
   public static final String DATA_DIRECTORY = "data_directory";
 
   /**
-   * A (command parameter) property name used to hold encrypted data representing the KDC
-   * administrator credentials
-   */
-  public static final String ADMINISTRATOR_CREDENTIAL = "kerberos_admin_credential";
-
-  /**
    * A (command parameter) property name used to hold the default Kerberos realm value.
    */
   public static final String DEFAULT_REALM = "default_realm";
@@ -146,6 +141,12 @@ public abstract class KerberosServerAction extends AbstractServerAction {
   private KerberosIdentityDataFileReaderFactory kerberosIdentityDataFileReaderFactory;
 
   /**
+   * KerberosHelper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
+  /**
    * Given a (command parameter) Map and a property name, attempts to safely retrieve the requested
    * data.
    *
@@ -305,21 +306,6 @@ public abstract class KerberosServerAction extends AbstractServerAction {
     return clusters;
   }
 
-
-  /**
-   * Given a (command parameter) Map, attempts to safely retrieve the "data_directory" property.
-   *
-   * @param commandParameters a Map containing the dictionary of data to interrogate
-   * @return a String indicating the data directory or null (if not found or set)
-   */
-  protected KerberosCredential getAdministratorCredential(Map<String, String> commandParameters) throws AmbariException {
-    Cluster cluster = getCluster();
-
-    // Create the key like we did when we encrypted the data, based on the Cluster objects hashcode.
-    byte[] key = Integer.toHexString(cluster.hashCode()).getBytes();
-    return KerberosCredential.decrypt(getCommandParameterValue(commandParameters, ADMINISTRATOR_CREDENTIAL), key);
-  }
-
   /**
    * Attempts to safely retrieve the "data_directory" property from the this action's relevant
    * command parameters Map.
@@ -355,7 +341,7 @@ public abstract class KerberosServerAction extends AbstractServerAction {
 
     if (commandParameters != null) {
       // Grab the relevant data from this action's command parameters map
-      KerberosCredential administratorCredential = getAdministratorCredential(commandParameters);
+      KerberosCredential administratorCredential = kerberosHelper.getKDCCredentials();
       String defaultRealm = getDefaultRealm(commandParameters);
       KDCType kdcType = getKDCType(commandParameters);
       String dataDirectoryPath = getDataDirectoryPath(commandParameters);