knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lmc...@apache.org
Subject git commit: refactoring of credential management classes
Date Thu, 23 May 2013 03:03:17 GMT
Updated Branches:
  refs/heads/master 5cd1567c3 -> 47b1d04b1


refactoring of credential management classes

Project: http://git-wip-us.apache.org/repos/asf/incubator-knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-knox/commit/47b1d04b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-knox/tree/47b1d04b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-knox/diff/47b1d04b

Branch: refs/heads/master
Commit: 47b1d04b12399ccc142685d08488e653d86b3c07
Parents: 5cd1567
Author: Larry McCay <lmccay@hortonworks.com>
Authored: Wed May 22 23:02:39 2013 -0400
Committer: Larry McCay <lmccay@hortonworks.com>
Committed: Wed May 22 23:02:39 2013 -0400

----------------------------------------------------------------------
 .../services/security/impl/AESEncryptor.java       |  157 ----------
 .../security/impl/DefaultKeystoreService.java      |  241 +--------------
 .../security/impl/DefaultMasterService.java        |  175 +----------
 gateway-spi/pom.xml                                |    8 +
 .../hadoop/gateway/i18n/GatewaySpiMessages.java    |   34 ++
 .../gateway/services/security/KeystoreService.java |   15 +-
 .../gateway/services/security/MasterService.java   |    4 +-
 .../services/security/impl/AESEncryptor.java       |  152 +++++++++
 .../security/impl/BaseKeystoreService.java         |  240 ++++++++++++++
 .../services/security/impl/CMFKeystoreService.java |  164 ++++++++++
 .../services/security/impl/CMFMasterService.java   |  192 ++++++++++++
 .../security/impl/CMFKeystoreServiceTest.java      |  100 ++++++
 .../security/impl/CMFMasterServiceTest.java        |   59 ++++
 .../security/impl/TestCMFMasterService.java        |   37 +++
 14 files changed, 1011 insertions(+), 567 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
deleted file mode 100644
index 2d7c8ba..0000000
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * 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.hadoop.gateway.services.security.impl;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.spec.KeySpec;
-
-import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.hadoop.gateway.GatewayMessages;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.services.security.EncryptionResult;
-
-public class AESEncryptor {
-  
-  // TODO: randomize the salt
-//  private static final byte[] SALT = {
-//      (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
-//      (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
-//  };
-  private static final int ITERATION_COUNT = 65536;
-  private static final int KEY_LENGTH = 128;
-  private static final GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
-  
-  private Cipher ecipher;
-  private Cipher dcipher;
-  private SecretKey secret;
-  private byte[] salt = null;
-  private char[] passPhrase = null;
- 
-  public AESEncryptor(String passPhrase) {
-      try {
-        this.passPhrase = passPhrase.toCharArray();
-        salt = new byte[8];
-        SecureRandom rnd = new SecureRandom();
-        rnd.nextBytes(salt);
-        
-        SecretKey tmp = getKeyFromPassword(passPhrase);
-        secret = new SecretKeySpec (tmp.getEncoded(), "AES");
- 
-        ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-        ecipher.init(Cipher.ENCRYPT_MODE, secret);
-       
-        dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-        byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
-        dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToEncodePassphrase( e );
-      } catch (NoSuchPaddingException e) {
-        LOG.failedToEncodePassphrase( e );
-      } catch (InvalidKeyException e) {
-        LOG.failedToEncodePassphrase( e );
-      } catch (InvalidParameterSpecException e) {
-        LOG.failedToEncodePassphrase( e );
-      } catch (InvalidAlgorithmParameterException e) {
-        LOG.failedToEncodePassphrase( e );
-      }
-  }
-  
-  AESEncryptor(SecretKey secret) {
-    try {
-      this.secret = new SecretKeySpec (secret.getEncoded(), "AES");
-
-      ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-      ecipher.init(Cipher.ENCRYPT_MODE, secret);
-     
-      dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-      byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
-      dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToEncodePassphrase( e );
-    } catch (NoSuchPaddingException e) {
-      LOG.failedToEncodePassphrase( e );
-    } catch (InvalidKeyException e) {
-      LOG.failedToEncodePassphrase( e );
-    } catch (InvalidParameterSpecException e) {
-      LOG.failedToEncodePassphrase( e );
-    } catch (InvalidAlgorithmParameterException e) {
-      LOG.failedToEncodePassphrase( e );
-    }
-  }
-
-  public SecretKey getKeyFromPassword(String passPhrase) {
-    return getKeyFromPassword(passPhrase, salt);
-  }
-  
-  public SecretKey getKeyFromPassword(String passPhrase, byte[] salt) {
-    SecretKeyFactory factory;
-    SecretKey key = null;
-    try {
-      factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
-      KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
-      key = factory.generateSecret(spec);
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToGenerateKeyFromPassword( e );
-    } catch (InvalidKeySpecException e) {
-      LOG.failedToGenerateKeyFromPassword( e );
-    }
-    
-    return key;
-  }
-
-  public EncryptionResult encrypt(String encrypt) throws Exception {
-      byte[] bytes = encrypt.getBytes("UTF8");
-      EncryptionResult atom = encrypt(bytes);
-      return atom;
-  }
-
-  public EncryptionResult encrypt(byte[] plain) throws Exception {
-    EncryptionResult atom = new EncryptionResult(salt, ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(), ecipher.doFinal(plain));
-    return atom;
-  }
-
-  public String decrypt(String salt, String iv, String cipher) throws Exception {
-    byte[] decrypted = decrypt(salt.getBytes("UTF8"), iv.getBytes("UTF8"), cipher.getBytes("UTF8"));
-    return new String(decrypted, "UTF8");
-  }
-
-  public byte[] decrypt(byte[] salt, byte[] iv, byte[] encrypt) throws Exception {
-    SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
-    secret = new SecretKeySpec(tmp.getEncoded(), "AES");
-    
-    dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-    return dcipher.doFinal(encrypt);
-  }
-  
-  public byte[] decrypt(byte[] encrypt) throws Exception {
-    dcipher.init(Cipher.DECRYPT_MODE, secret);
-    return dcipher.doFinal(encrypt);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
index f776286..4be49ec 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
@@ -18,11 +18,7 @@
 package org.apache.hadoop.gateway.services.security.impl;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.math.BigInteger;
 import java.security.GeneralSecurityException;
 import java.security.Key;
 import java.security.KeyPair;
@@ -30,46 +26,27 @@ import java.security.KeyPairGenerator;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
-import java.util.Date;
 import java.util.Map;
 
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.hadoop.gateway.GatewayMessages;
 import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.services.ServiceLifecycleException;
 import org.apache.hadoop.gateway.services.security.KeystoreService;
 import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
-import org.apache.hadoop.gateway.services.security.MasterService;
+import org.apache.hadoop.gateway.services.Service;
+import org.apache.hadoop.gateway.GatewayMessages;
 
-import sun.security.x509.AlgorithmId;
-import sun.security.x509.CertificateAlgorithmId;
-import sun.security.x509.CertificateIssuerName;
-import sun.security.x509.CertificateSerialNumber;
-import sun.security.x509.CertificateSubjectName;
-import sun.security.x509.CertificateValidity;
-import sun.security.x509.CertificateVersion;
-import sun.security.x509.CertificateX509Key;
-import sun.security.x509.X500Name;
-import sun.security.x509.X509CertImpl;
-import sun.security.x509.X509CertInfo;
 
-public class DefaultKeystoreService implements KeystoreService {
+public class DefaultKeystoreService extends BaseKeystoreService implements KeystoreService, Service {
 
   private static final String TEST_CERT_DN = "CN=hadoop.gateway,OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
   private static final String CREDENTIALS_SUFFIX = "-credentials.jceks";
   private static final String GATEWAY_KEYSTORE = "gateway.jks";
   private static GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
   
-  private MasterService masterService;
-  private String keyStoreDir;
-
   @Override
   public void init(GatewayConfig config, Map<String, String> options)
       throws ServiceLifecycleException {
@@ -128,70 +105,12 @@ public class DefaultKeystoreService implements KeystoreService {
     }  
   }
   
-  /** 
-   * Create a self-signed X.509 Certificate
-   * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
-   * @param pair the KeyPair
-   * @param days how many days from now the Certificate is valid for
-   * @param algorithm the signing algorithm, eg "SHA1withRSA"
-   */ 
-  private X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
-    throws GeneralSecurityException, IOException
-  {
-    PrivateKey privkey = pair.getPrivate();
-    X509CertInfo info = new X509CertInfo();
-    Date from = new Date();
-    Date to = new Date(from.getTime() + days * 86400000l);
-    CertificateValidity interval = new CertificateValidity(from, to);
-    BigInteger sn = new BigInteger(64, new SecureRandom());
-    X500Name owner = new X500Name(dn);
-   
-    info.set(X509CertInfo.VALIDITY, interval);
-    info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
-    info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
-    info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
-    info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
-    info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
-    AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
-    info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
-   
-    // Sign the cert to identify the algorithm that's used.
-    X509CertImpl cert = new X509CertImpl(info);
-    cert.sign(privkey, algorithm);
-   
-    // Update the algorith, and resign.
-    algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
-    info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
-    cert = new X509CertImpl(info);
-    cert.sign(privkey, algorithm);
-    return cert;
-  }   
-
   @Override
   public void createCredentialStoreForCluster(String clusterName) {
     String filename = keyStoreDir + clusterName + CREDENTIALS_SUFFIX;
     createKeystore(filename, "JCEKS");
   }
 
-  private void createKeystore(String filename, String keystoreType) {
-    try {
-      FileOutputStream out = new FileOutputStream( filename );
-      KeyStore ks = KeyStore.getInstance(keystoreType);  
-      ks.load( null, null );  
-      ks.store( out, masterService.getMasterSecret() );
-    } catch (KeyStoreException e) {
-      LOG.failedToCreateKeystore( filename, keystoreType, e );
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToCreateKeystore( filename, keystoreType, e );
-    } catch (CertificateException e) {
-      LOG.failedToCreateKeystore( filename, keystoreType, e );
-    } catch (FileNotFoundException e) {
-      LOG.failedToCreateKeystore( filename, keystoreType, e );
-    } catch (IOException e) {
-      LOG.failedToCreateKeystore( filename, keystoreType, e );
-    }
-  }
-  
   @Override
   public boolean isCredentialStoreForClusterAvailable(String clusterName) throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX  );
@@ -216,37 +135,6 @@ public class DefaultKeystoreService implements KeystoreService {
     }
   }
 
-  private boolean isKeystoreAvailable(final File keyStoreFile, String storeType) throws KeyStoreException, IOException {
-    if ( keyStoreFile.exists() )
-    {
-      FileInputStream input = null;
-      try {
-        final KeyStore  keyStore = KeyStore.getInstance(storeType);
-        input   = new FileInputStream( keyStoreFile );
-        keyStore.load( input, masterService.getMasterSecret() );
-        return true;
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
-      } catch (CertificateException e) {
-        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
-      } catch (IOException e) {
-        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
-        throw e;
-      } catch (KeyStoreException e) {
-        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
-        throw e;
-      }
-      finally {
-          try {
-            input.close();
-          } catch (IOException e) {
-            LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
-          }
-      }
-    }
-    return false;
-  }
-
   @Override
   public Key getKeyForGateway(String alias, char[] passphrase) throws KeystoreServiceException {
     Key key = null;
@@ -270,84 +158,23 @@ public class DefaultKeystoreService implements KeystoreService {
     return getKeystore(keyStoreFile, "JCEKS");
   }
 
-  private KeyStore getKeystore(final File keyStoreFile, String storeType) {
-    KeyStore credStore = null;
+  public void addCredentialForCluster(String clusterName, String alias, String value) {
+    KeyStore ks = getCredentialStoreForCluster(clusterName);
+    addCredential(alias, value, ks);
+    final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX  );
     try {
-      credStore = loadKeyStore( keyStoreFile, masterService.getMasterSecret(), storeType);
-    } catch (CertificateException e) {
-      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+      writeKeystoreToFile(ks, keyStoreFile);
     } catch (KeyStoreException e) {
-      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+      LOG.failedToAddCredentialForCluster( clusterName, e );
     } catch (NoSuchAlgorithmException e) {
-      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+      LOG.failedToAddCredentialForCluster( clusterName, e );
+    } catch (CertificateException e) {
+      LOG.failedToAddCredentialForCluster( clusterName, e );
     } catch (IOException e) {
-      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+      LOG.failedToAddCredentialForCluster( clusterName, 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 );
-   }
-
-   return keyStore;       
-  }
-
-  public void writeKeystoreToFile(final KeyStore keyStore, final File file)
-         throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
-    // TODO: does this really need to be part of the interface?
-    // TODO: backup the keystore on disk before attempting a write and restore on failure
-      final FileOutputStream  out = new FileOutputStream(file);
-      try
-      {
-          keyStore.store( out, masterService.getMasterSecret());
-      }
-      finally
-      {
-          out.close();
-      }
-  }
-
-  public void setMasterService(MasterService ms) {
-    this.masterService = ms;
-  }
-  
-  public void addCredentialForCluster(String clusterName, String alias, String value) {
-    KeyStore ks = getCredentialStoreForCluster(clusterName);
-    if (ks != null) {
-      try {
-        final Key key = new SecretKeySpec(value.getBytes("UTF8"), "AES");
-        ks.setKeyEntry( alias, key, masterService.getMasterSecret(), null);
-        final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX  );
-        writeKeystoreToFile(ks, keyStoreFile);
-      } catch (KeyStoreException e) {
-        LOG.failedToAddCredentialForCluster( clusterName, e );
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToAddCredentialForCluster( clusterName, e );
-      } catch (CertificateException e) {
-        LOG.failedToAddCredentialForCluster( clusterName, e );
-      } catch (IOException e) {
-        LOG.failedToAddCredentialForCluster( clusterName, e );
-      }
-    }
-  }
-
   @Override
   public char[] getCredentialForCluster(String clusterName, String alias) {
     char[] credential = null;
@@ -365,46 +192,4 @@ public class DefaultKeystoreService implements KeystoreService {
     }
     return credential;
   }
-
-  @Override
-  public byte[] getKeyForCluster(String clusterName, String alias) {
-    byte[] key = null;
-    KeyStore ks = getCredentialStoreForCluster(clusterName);
-    if (ks != null) {
-      try {
-        LOG.printClusterAlias( alias );
-        LOG.printMasterServiceIsNull( masterService == null );
-        key = ks.getKey(alias, masterService.getMasterSecret()).getEncoded();
-      } catch (UnrecoverableKeyException e) {
-        LOG.failedToGetKeyForCluster( clusterName, e );
-      } catch (KeyStoreException e) {
-        LOG.failedToGetKeyForCluster( clusterName, e );
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToGetKeyForCluster( clusterName, e );
-      }
-    }
-    return key;
-  }
-
-  @Override
-  public void addKeyForCluster(String clusterName, String alias, byte[] value) {
-    KeyStore ks = getCredentialStoreForCluster(clusterName);
-    if (ks != null) {
-      final Key key = new SecretKeySpec(value, "AES");
-      try {
-        ks.setKeyEntry( alias, key, masterService.getMasterSecret(), null);
-        final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX  );
-        writeKeystoreToFile(ks, keyStoreFile);
-      } catch (KeyStoreException e) {
-        LOG.failedToAddKeyForCluster( clusterName, e );
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToAddKeyForCluster( clusterName, e );
-      } catch (CertificateException e) {
-        LOG.failedToAddKeyForCluster( clusterName, e );
-      } catch (IOException e) {
-        LOG.failedToAddKeyForCluster( clusterName, e );
-      }
-    }
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
index 12ff406..5d2b37f 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
@@ -17,41 +17,23 @@
  */
 package org.apache.hadoop.gateway.services.security.impl;
 
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.net.ntp.TimeStamp;
-import org.apache.hadoop.gateway.GatewayMessages;
 import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.services.ServiceLifecycleException;
-import org.apache.hadoop.gateway.services.security.EncryptionResult;
 import org.apache.hadoop.gateway.services.security.MasterService;
+import org.apache.hadoop.gateway.services.Service;
+import org.apache.hadoop.gateway.GatewayMessages;
 
-import java.io.Console;
 import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Map;
 
-public class DefaultMasterService implements MasterService {
-
-  private static final String MASTER_PASSPHRASE = "masterpassphrase";
-  private static final String MASTER_PERSISTENCE_TAG = "#1.0# " + TimeStamp.getCurrentTime().toDateString();
+public class DefaultMasterService extends CMFMasterService implements MasterService, Service {
   private static final GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
-  private char[] master = null;
-  private AESEncryptor aes = new AESEncryptor(MASTER_PASSPHRASE);
 
-  /* (non-Javadoc)
-   * @see org.apache.hadoop.gateway.services.security.impl.MasterService#getMasterSecret()
-   */
-  @Override
-  public char[] getMasterSecret() {
-    // TODO: check permission call here
-    return this.master;
+  public DefaultMasterService() {
+    super("gateway");
   }
-  
+
   @Override
   public void init(GatewayConfig config, Map<String,String> options) throws ServiceLifecycleException {
     // for testing only
@@ -59,125 +41,13 @@ public class DefaultMasterService implements MasterService {
       this.master = options.get("master").toCharArray();
     }
     else {
-      File masterFile = new File(config.getGatewayHomeDir() + File.separator + "conf" + File.separator + "security", "master");
-      if (masterFile.exists()) {
-        try {
-          initializeFromMaster(masterFile);
-        } catch (Exception e) {
-          // TODO Auto-generated catch block
-          throw new ServiceLifecycleException("Unable to load the persisted master secret.", e);
-        }
-      }
-      else {
-        if(options.get( "persist-master").equals("true")) {
-          displayWarning(true);
-        }
-        else {
-          displayWarning(false);
-        }
-        promptUser();
-        if(options.get( "persist-master").equals("true")) {
-          persistMaster(master, masterFile);
-        }
-      }
+      boolean persisting = options.get( "persist-master").equals("true");
+      String securityDir = config.getGatewayHomeDir() + File.separator + "conf" + File.separator + "security";
+      String filename = "master";
+      setupMasterSecret(securityDir, filename, persisting);
     }
   }
   
-  private void promptUser() {
-    Console c = System.console();
-    if (c == null) {
-        System.err.println("No console.");
-        System.exit(1);
-    }
-
-    boolean noMatch;
-    do {
-        char [] newPassword1 = c.readPassword("Enter master secret: ");
-        char [] newPassword2 = c.readPassword("Enter master secret again: ");
-        noMatch = ! Arrays.equals(newPassword1, newPassword2);
-        if (noMatch) {
-            c.format("Passwords don't match. Try again.%n");
-        } else {
-            this.master = Arrays.copyOf(newPassword1, newPassword1.length);
-        }
-        Arrays.fill(newPassword1, ' ');
-        Arrays.fill(newPassword2, ' ');
-    } while (noMatch);
-  }
-
-  private void displayWarning(boolean persisting) {
-    Console c = System.console();
-    if (c == null) {
-        System.err.println("No console.");
-        System.exit(1);
-    }
-    if (persisting) {
-      c.printf("***************************************************************************************************\n");
-      c.printf("You have indicated that you would like to persist the master secret for this gateway instance.\n");
-      c.printf("Be aware that this is less secure than manually entering the secret on startup.\n");
-      c.printf("The persisted file will be encrypted and primarily protected through OS permissions.\n");
-      c.printf("***************************************************************************************************\n");
-    }
-    else {
-      c.printf("***************************************************************************************************\n");
-      c.printf("Be aware that you will need to enter your master secret for future starts exactly as you do here.\n");
-      c.printf("This secret is needed to access protected resources for the gateway process.\n");
-      c.printf("The master secret must be protected, kept secret and not stored in clear text anywhere.\n");
-      c.printf("***************************************************************************************************\n");
-    }
-  }
-
-  private void persistMaster(char[] master, 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.failedToPersistMasterSecret( e );
-    }
-  }
-
-  private EncryptionResult encryptMaster(char[] master) {
-    // TODO Auto-generated method stub
-    try {
-      return aes.encrypt(new String(master));
-    } catch (Exception e) {
-      // need to ensure that we don't persist now
-      LOG.failedToEncryptMasterSecret( e );
-    }
-    return null;
-  }
-
-  private void initializeFromMaster(File masterFile) throws Exception {
-    try {
-      List<String> lines = FileUtils.readLines(masterFile, "UTF8");
-      String tag = lines.get(0);
-      LOG.loadingFromPersistentMaster( tag );
-      String line = new String(Base64.decodeBase64(lines.get(1)));
-      String[] parts = line.split("::");
-//System.out.println("salt: " + parts[0] + " : " + Base64.decodeBase64(parts[0]));
-//System.out.println("iv: " + parts[1]);
-//System.out.println("cipher: " + parts[2]);
-      this.master = new String(aes.decrypt(Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])), "UTF8").toCharArray();
-    } catch (IOException e) {
-      LOG.failedToInitializeFromPersistentMaster( masterFile.getName(), e );
-      throw e;
-    } catch (Exception e) {
-      LOG.failedToInitializeFromPersistentMaster( masterFile.getName(), e );
-      throw e;
-    }
-  }
 
   @Override
   public void start() throws ServiceLifecycleException {
@@ -187,29 +57,4 @@ public class DefaultMasterService implements MasterService {
   public void stop() throws ServiceLifecycleException {
   }
   
-  private void chmod(String args, File file) throws IOException
-  {
-      // TODO: move to Java 7 NIO support to add windows as well
-      // TODO: look into the following for Windows: Runtime.getRuntime().exec("attrib -r myFile");
-      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 == '/');
-  }
-  
 }

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-spi/pom.xml b/gateway-spi/pom.xml
index 655041b..ff5c5d1 100644
--- a/gateway-spi/pom.xml
+++ b/gateway-spi/pom.xml
@@ -81,6 +81,14 @@
             <groupId>org.jboss.shrinkwrap.descriptors</groupId>
             <artifactId>shrinkwrap-descriptors-impl-javaee</artifactId>
         </dependency>
+        <dependency>
+            <groupId>commons-net</groupId>
+            <artifactId>commons-net</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>junit</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
index 835194d..6234ef2 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
@@ -30,4 +30,38 @@ public interface GatewaySpiMessages {
 
   @Message( level = MessageLevel.ERROR, text = "Failed to execute filter: {0}" )
   void failedToExecuteFilter( @StackTrace( level = MessageLevel.DEBUG ) Throwable t );
+  
+  @Message( level = MessageLevel.ERROR, text = "Failed to encrypt passphrase: {0}" )
+  void failedToEncryptPassphrase( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to generate secret key from password: {0}" )
+  void failedToGenerateKeyFromPassword( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+  
+  @Message( level = MessageLevel.ERROR, text = "Failed to create keystore [filename={0}, type={1}]: {2}" )
+  void failedToCreateKeystore( String fileName, String keyStoreType, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+  
+  @Message( level = MessageLevel.ERROR, text = "Failed to load keystore [filename={0}, type={1}]: {2}" )
+  void failedToLoadKeystore( String fileName, String keyStoreType, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+  
+  @Message( level = MessageLevel.ERROR, text = "Failed to add credential: {1}" )
+  void failedToAddCredential( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to get credential: {1}" )
+  void failedToGetCredential(@StackTrace( level = MessageLevel.DEBUG ) Exception e);
+  
+  @Message( level = MessageLevel.ERROR, text = "Failed to persist master secret: {0}" )
+  void failedToPersistMasterSecret( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to encrypt master secret: {0}" )
+  void failedToEncryptMasterSecret( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to initialize master service from persistent master {0}: {1}" )
+  void failedToInitializeFromPersistentMaster( String masterFileName, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to add self signed certificate for Gateway {0}: {1}" )
+  void failedToAddSeflSignedCertForGateway( String alias, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to get key {0}: {1}" )
+  void failedToGetKey(String alias, @StackTrace( level = MessageLevel.DEBUG ) Exception e);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
index 848a522..7e9dade 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
@@ -17,17 +17,10 @@
  */
 package org.apache.hadoop.gateway.services.security;
 
-import java.io.File;
-import java.io.IOException;
 import java.security.Key;
 import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
 
-import org.apache.hadoop.gateway.services.Service;
-
-public interface KeystoreService extends Service {
+public interface KeystoreService {
 
   public void createKeystoreForGateway();
 
@@ -49,10 +42,4 @@ public interface KeystoreService extends Service {
 
   public char[] getCredentialForCluster(String clusterName, String alias);
 
-  public void writeKeystoreToFile(final KeyStore keyStore, final File file)
-      throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException;
-
-  public byte[] getKeyForCluster(String clusterName, String alias);
-
-  public void addKeyForCluster(String clusterName, String alias, byte[] key);
 }

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
index cf2c962..6d42dfe 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
@@ -17,9 +17,7 @@
  */
 package org.apache.hadoop.gateway.services.security;
 
-import org.apache.hadoop.gateway.services.Service;
-
-public interface MasterService extends Service {
+public interface MasterService {
 
   public abstract char[] getMasterSecret();
 

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
new file mode 100644
index 0000000..f6ff910
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
@@ -0,0 +1,152 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.KeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.security.EncryptionResult;
+
+public class AESEncryptor {
+  private static final GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class );
+  
+  private static final int ITERATION_COUNT = 65536;
+  private static final int KEY_LENGTH = 128;
+  
+  private Cipher ecipher;
+  private Cipher dcipher;
+  private SecretKey secret;
+  private byte[] salt = null;
+  private char[] passPhrase = null;
+ 
+  public AESEncryptor(String passPhrase) {
+      try {
+        this.passPhrase = passPhrase.toCharArray();
+        salt = new byte[8];
+        SecureRandom rnd = new SecureRandom();
+        rnd.nextBytes(salt);
+        
+        SecretKey tmp = getKeyFromPassword(passPhrase);
+        secret = new SecretKeySpec (tmp.getEncoded(), "AES");
+ 
+        ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        ecipher.init(Cipher.ENCRYPT_MODE, secret);
+       
+        dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
+        dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (NoSuchPaddingException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (InvalidKeyException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (InvalidParameterSpecException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (InvalidAlgorithmParameterException e) {
+        LOG.failedToEncryptPassphrase( e );
+      }
+  }
+  
+  AESEncryptor(SecretKey secret) {
+    try {
+      this.secret = new SecretKeySpec (secret.getEncoded(), "AES");
+
+      ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+      ecipher.init(Cipher.ENCRYPT_MODE, secret);
+     
+      dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+      byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
+      dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (NoSuchPaddingException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (InvalidKeyException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (InvalidParameterSpecException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (InvalidAlgorithmParameterException e) {
+      LOG.failedToEncryptPassphrase( e );
+    }
+  }
+
+  public SecretKey getKeyFromPassword(String passPhrase) {
+    return getKeyFromPassword(passPhrase, salt);
+  }
+  
+  public SecretKey getKeyFromPassword(String passPhrase, byte[] salt) {
+    SecretKeyFactory factory;
+    SecretKey key = null;
+    try {
+      factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+      KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
+      key = factory.generateSecret(spec);
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToGenerateKeyFromPassword( e );
+    } catch (InvalidKeySpecException e) {
+      LOG.failedToGenerateKeyFromPassword( e );
+    }
+    
+    return key;
+  }
+
+  public EncryptionResult encrypt(String encrypt) throws Exception {
+      byte[] bytes = encrypt.getBytes("UTF8");
+      EncryptionResult atom = encrypt(bytes);
+      return atom;
+  }
+
+  public EncryptionResult encrypt(byte[] plain) throws Exception {
+    EncryptionResult atom = new EncryptionResult(salt, ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(), ecipher.doFinal(plain));
+    return atom;
+  }
+
+  public String decrypt(String salt, String iv, String cipher) throws Exception {
+    byte[] decrypted = decrypt(salt.getBytes("UTF8"), iv.getBytes("UTF8"), cipher.getBytes("UTF8"));
+    return new String(decrypted, "UTF8");
+  }
+
+  public byte[] decrypt(byte[] salt, byte[] iv, byte[] encrypt) throws Exception {
+    SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
+    secret = new SecretKeySpec(tmp.getEncoded(), "AES");
+    
+    dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
+    return dcipher.doFinal(encrypt);
+  }
+  
+  public byte[] decrypt(byte[] encrypt) throws Exception {
+    dcipher.init(Cipher.DECRYPT_MODE, secret);
+    return dcipher.doFinal(encrypt);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/BaseKeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/BaseKeystoreService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/BaseKeystoreService.java
new file mode 100644
index 0000000..13b16ae
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/BaseKeystoreService.java
@@ -0,0 +1,240 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.security.MasterService;
+
+
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.CertificateAlgorithmId;
+import sun.security.x509.CertificateIssuerName;
+import sun.security.x509.CertificateSerialNumber;
+import sun.security.x509.CertificateSubjectName;
+import sun.security.x509.CertificateValidity;
+import sun.security.x509.CertificateVersion;
+import sun.security.x509.CertificateX509Key;
+import sun.security.x509.X500Name;
+import sun.security.x509.X509CertImpl;
+import sun.security.x509.X509CertInfo;
+
+public class BaseKeystoreService {
+  private static GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class );
+
+  protected MasterService masterService;
+  protected String keyStoreDir;
+
+  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 );
+       }
+      
+       return keyStore;       
+      }
+
+  /** 
+   * Create a self-signed X.509 Certificate
+   * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
+   * @param pair the KeyPair
+   * @param days how many days from now the Certificate is valid for
+   * @param algorithm the signing algorithm, eg "SHA1withRSA"
+   */
+  protected X509Certificate generateCertificate(String dn, KeyPair pair, int days,
+      String algorithm) throws GeneralSecurityException, IOException {
+        PrivateKey privkey = pair.getPrivate();
+        X509CertInfo info = new X509CertInfo();
+        Date from = new Date();
+        Date to = new Date(from.getTime() + days * 86400000l);
+        CertificateValidity interval = new CertificateValidity(from, to);
+        BigInteger sn = new BigInteger(64, new SecureRandom());
+        X500Name owner = new X500Name(dn);
+      
+        info.set(X509CertInfo.VALIDITY, interval);
+        info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
+        info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
+        info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
+        info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
+        info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
+        AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
+        info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
+      
+        // Sign the cert to identify the algorithm that's used.
+        X509CertImpl cert = new X509CertImpl(info);
+        cert.sign(privkey, algorithm);
+      
+        // Update the algorith, and resign.
+        algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
+        info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
+        cert = new X509CertImpl(info);
+        cert.sign(privkey, algorithm);
+        return cert;
+      }
+
+  protected void createKeystore(String filename, String keystoreType) {
+    try {
+      FileOutputStream out = new FileOutputStream( filename );
+      KeyStore ks = KeyStore.getInstance(keystoreType);  
+      ks.load( null, null );  
+      ks.store( out, masterService.getMasterSecret() );
+    } catch (KeyStoreException e) {
+      LOG.failedToCreateKeystore( filename, keystoreType, e );
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToCreateKeystore( filename, keystoreType, e );
+    } catch (CertificateException e) {
+      LOG.failedToCreateKeystore( filename, keystoreType, e );
+    } catch (FileNotFoundException e) {
+      LOG.failedToCreateKeystore( filename, keystoreType, e );
+    } catch (IOException e) {
+      LOG.failedToCreateKeystore( filename, keystoreType, e );
+    }
+  }
+
+  protected boolean isKeystoreAvailable(final File keyStoreFile, String storeType) throws KeyStoreException, IOException {
+    if ( keyStoreFile.exists() )
+    {
+      FileInputStream input = null;
+      try {
+        final KeyStore  keyStore = KeyStore.getInstance(storeType);
+        input   = new FileInputStream( keyStoreFile );
+        keyStore.load( input, masterService.getMasterSecret() );
+        return true;
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+      } catch (CertificateException e) {
+        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+      } catch (IOException e) {
+        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+        throw e;
+      } catch (KeyStoreException e) {
+        LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+        throw e;
+      }
+      finally {
+          try {
+            input.close();
+          } catch (IOException e) {
+            LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+          }
+      }
+    }
+    return false;
+  }
+
+  protected KeyStore getKeystore(final File keyStoreFile, String storeType) {
+    KeyStore credStore = null;
+    try {
+      credStore = loadKeyStore( keyStoreFile, masterService.getMasterSecret(), storeType);
+    } catch (CertificateException e) {
+      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+    } catch (KeyStoreException e) {
+      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+    } catch (IOException e) {
+      LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
+    }
+    return credStore;
+  }
+
+  public BaseKeystoreService() {
+    super();
+  }
+
+  protected void addCredential(String alias, String value, KeyStore ks) {
+    if (ks != null) {
+      try {
+        final Key key = new SecretKeySpec(value.getBytes("UTF8"), "AES");
+        ks.setKeyEntry( alias, key, masterService.getMasterSecret(), null);
+      } catch (KeyStoreException e) {
+        LOG.failedToAddCredential(e);
+      } catch (IOException e) {
+        LOG.failedToAddCredential(e);
+      }
+    }
+  }
+
+  protected char[] getCredential(String alias, char[] credential, KeyStore ks) {
+    if (ks != null) {
+      try {
+        credential = new String(ks.getKey(alias, masterService.getMasterSecret()).getEncoded()).toCharArray();
+      } catch (UnrecoverableKeyException e) {
+        LOG.failedToGetCredential(e);
+      } catch (KeyStoreException e) {
+        LOG.failedToGetCredential(e);
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToGetCredential(e);
+      }
+    }
+    return credential;
+  }
+
+  protected void writeKeystoreToFile(final KeyStore keyStore, final File file)
+      throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+     // TODO: backup the keystore on disk before attempting a write and restore on failure
+     final FileOutputStream  out = new FileOutputStream(file);
+     try
+     {
+         keyStore.store( out, masterService.getMasterSecret());
+     }
+     finally
+     {
+         out.close();
+     }
+  }
+
+  public void setMasterService(MasterService ms) {
+    this.masterService = ms;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreService.java
new file mode 100644
index 0000000..344391e
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreService.java
@@ -0,0 +1,164 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
+
+
+public class CMFKeystoreService extends BaseKeystoreService {
+  private static GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class );
+
+  private static final String TEST_CERT_DN = "CN=hadoop,OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
+  private static final String CREDENTIALS_SUFFIX = "-credentials.jceks";
+
+  private String serviceName = null;
+  
+  public CMFKeystoreService(String keystoreDir, String serviceName)
+      throws ServiceLifecycleException {
+    this.serviceName = serviceName;
+    this.keyStoreDir = keystoreDir + File.separator;
+    File ksd = new File(this.keyStoreDir);
+    if (!ksd.exists()) {
+      ksd.mkdirs();
+    }
+  }
+
+  public void createKeystore() {
+    String filename = keyStoreDir + serviceName + ".jks";
+    createKeystore(filename, "JKS");
+  }
+
+  public KeyStore getKeystore() {
+    final File  keyStoreFile = new File( keyStoreDir + serviceName  );
+    return getKeystore(keyStoreFile, "JKS");
+  }
+  
+  public void addSelfSignedCert(String alias, char[] passphrase) {
+    KeyPairGenerator keyPairGenerator;
+    try {
+      keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+      keyPairGenerator.initialize(1024);  
+      KeyPair KPair = keyPairGenerator.generateKeyPair();
+      X509Certificate cert = generateCertificate(TEST_CERT_DN, KPair, 365, "SHA1withRSA");
+
+      KeyStore privateKS = getKeystore();
+      privateKS.setKeyEntry(alias, KPair.getPrivate(),  
+          passphrase,  
+          new java.security.cert.Certificate[]{cert});  
+      
+      writeKeystoreToFile(privateKS, new File( keyStoreDir + serviceName  ));
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToAddSeflSignedCertForGateway(alias, e);
+    } catch (GeneralSecurityException e) {
+      LOG.failedToAddSeflSignedCertForGateway(alias, e);
+    } catch (IOException e) {
+      LOG.failedToAddSeflSignedCertForGateway(alias, e);
+    }  
+  }
+  
+  public void createCredentialStore() {
+    String filename = keyStoreDir + serviceName + CREDENTIALS_SUFFIX;
+    createKeystore(filename, "JCEKS");
+  }
+
+  public boolean isCredentialStoreAvailable() throws KeystoreServiceException {
+    final File  keyStoreFile = new File( keyStoreDir + serviceName + CREDENTIALS_SUFFIX  );
+    try {
+      return isKeystoreAvailable(keyStoreFile, "JCEKS");
+    } catch (KeyStoreException e) {
+      throw new KeystoreServiceException(e);
+    } catch (IOException e) {
+      throw new KeystoreServiceException(e);
+    }
+  }
+
+  public boolean isKeystoreAvailable() throws KeystoreServiceException {
+    final File  keyStoreFile = new File( keyStoreDir + serviceName + ".jks" );
+    try {
+      return isKeystoreAvailable(keyStoreFile, "JKS");
+    } catch (KeyStoreException e) {
+      throw new KeystoreServiceException(e);
+    } catch (IOException e) {
+      throw new KeystoreServiceException(e);
+    }
+  }
+
+  public Key getKey(String alias, char[] passphrase) throws KeystoreServiceException {
+    Key key = null;
+    KeyStore ks = getKeystore();
+    if (ks != null) {
+      try {
+        key = ks.getKey(alias, passphrase);
+      } catch (UnrecoverableKeyException e) {
+        // TODO Auto-generated catch block
+        LOG.failedToGetKey(alias, e);
+      } catch (KeyStoreException e) {
+        LOG.failedToGetKey(alias, e);
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToGetKey(alias, e);
+      }
+    }
+    return key;
+  }  
+  
+  public KeyStore getCredentialStore() {
+    final File  keyStoreFile = new File( keyStoreDir + serviceName + CREDENTIALS_SUFFIX  );
+    return getKeystore(keyStoreFile, "JCEKS");
+  }
+
+  public void addCredential(String alias, String value) {
+    KeyStore ks = getCredentialStore();
+    addCredential(alias, value, ks);
+    final File  keyStoreFile = new File( keyStoreDir + serviceName + CREDENTIALS_SUFFIX  );
+    try {
+      writeKeystoreToFile(ks, keyStoreFile);
+    } catch (KeyStoreException e) {
+      LOG.failedToAddCredential(e);
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToAddCredential(e);
+    } catch (CertificateException e) {
+      LOG.failedToAddCredential(e);
+    } catch (IOException e) {
+      LOG.failedToAddCredential(e);
+    }
+  }
+
+  public char[] getCredential(String alias) {
+    char[] credential = null;
+    KeyStore ks = getCredentialStore();
+    credential = getCredential(alias, credential, ks);
+    return credential;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
new file mode 100644
index 0000000..cd353e7
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
@@ -0,0 +1,192 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+import java.io.Console;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.net.ntp.TimeStamp;
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.security.EncryptionResult;
+
+public class CMFMasterService {
+  private static GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class );
+
+  private static final String MASTER_PASSPHRASE = "masterpassphrase";
+  private static final String MASTER_PERSISTENCE_TAG = "#1.0# " + TimeStamp.getCurrentTime().toDateString();
+  protected char[] master = null;
+  protected String serviceName = null;
+  private AESEncryptor aes = new AESEncryptor(MASTER_PASSPHRASE);
+
+  public CMFMasterService(String serviceName) {
+    super();
+    this.serviceName = serviceName;
+  }
+
+  public char[] getMasterSecret() {
+    return this.master;
+  }
+
+  protected void setupMasterSecret(String securityDir, boolean persisting) throws ServiceLifecycleException {
+    setupMasterSecret(securityDir, serviceName + "-master", persisting);
+  }
+
+  protected void setupMasterSecret(String securityDir, String filename, boolean persisting) throws ServiceLifecycleException {
+    File masterFile = new File(securityDir, filename);
+    if (masterFile.exists()) {
+      try {
+        initializeFromMaster(masterFile);
+      } catch (Exception e) {
+        // TODO Auto-generated catch block
+        throw new ServiceLifecycleException("Unable to load the persisted master secret.", e);
+      }
+    }
+    else {
+      displayWarning(persisting);
+      promptUser();
+      if(persisting) {
+        persistMaster(master, masterFile);
+      }
+    }
+  }
+
+  protected void promptUser() {
+    Console c = System.console();
+    if (c == null) {
+        System.err.println("No console.");
+        System.exit(1);
+    }
+  
+    boolean noMatch;
+    do {
+        char [] newPassword1 = c.readPassword("Enter master secret: ");
+        char [] newPassword2 = c.readPassword("Enter master secret again: ");
+        noMatch = ! Arrays.equals(newPassword1, newPassword2);
+        if (noMatch) {
+            c.format("Passwords don't match. Try again.%n");
+        } else {
+            this.master = Arrays.copyOf(newPassword1, newPassword1.length);
+        }
+        Arrays.fill(newPassword1, ' ');
+        Arrays.fill(newPassword2, ' ');
+    } while (noMatch);
+  }
+
+  protected void displayWarning(boolean persisting) {
+    Console c = System.console();
+    if (c == null) {
+        System.err.println("No console.");
+        System.exit(1);
+    }
+    if (persisting) {
+      c.printf("***************************************************************************************************\n");
+      c.printf("You have indicated that you would like to persist the master secret for this service instance.\n");
+      c.printf("Be aware that this is less secure than manually entering the secret on startup.\n");
+      c.printf("The persisted file will be encrypted and primarily protected through OS permissions.\n");
+      c.printf("***************************************************************************************************\n");
+    }
+    else {
+      c.printf("***************************************************************************************************\n");
+      c.printf("Be aware that you will need to enter your master secret for future starts exactly as you do here.\n");
+      c.printf("This secret is needed to access protected resources for the service process.\n");
+      c.printf("The master secret must be protected, kept secret and not stored in clear text anywhere.\n");
+      c.printf("***************************************************************************************************\n");
+    }
+  }
+
+  protected void persistMaster(char[] master, 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.failedToPersistMasterSecret(e);
+    }
+  }
+
+  private EncryptionResult encryptMaster(char[] master) {
+    // TODO Auto-generated method stub
+    try {
+      return aes.encrypt(new String(master));
+    } catch (Exception e) {
+      LOG.failedToEncryptMasterSecret(e);
+    }
+    return null;
+  }
+
+  protected void initializeFromMaster(File masterFile) throws Exception {
+      try {
+        List<String> lines = FileUtils.readLines(masterFile, "UTF8");
+        String tag = lines.get(0);
+        // TODO: log - if appropriate - at least at finest level
+        System.out.println("Loading from persistent master: " + tag);
+        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();
+      } catch (IOException e) {
+        LOG.failedToInitializeFromPersistentMaster(masterFile.getName(), e);
+        throw e;
+      } catch (Exception e) {
+        LOG.failedToInitializeFromPersistentMaster(masterFile.getName(), e);
+        throw e;
+      }
+    }
+
+  private void chmod(String args, File file) throws IOException {
+      // TODO: move to Java 7 NIO support to add windows as well
+      // TODO: look into the following for Windows: Runtime.getRuntime().exec("attrib -r myFile");
+      if (isUnixEnv()) {
+          //args and file should never be null.
+          if (args == null || file == null) 
+            throw new IllegalArgumentException("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 == '/');
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreServiceTest.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreServiceTest.java b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreServiceTest.java
new file mode 100644
index 0000000..6c31b67
--- /dev/null
+++ b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFKeystoreServiceTest.java
@@ -0,0 +1,100 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
+import org.apache.hadoop.gateway.services.security.MasterService;
+import org.apache.hadoop.test.category.FastTests;
+import org.apache.hadoop.test.category.UnitTests;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+*
+*/
+@Category( { UnitTests.class, FastTests.class } )
+public class CMFKeystoreServiceTest {
+  CMFKeystoreService ks;
+
+  @Before
+  public void setup() {
+    try {
+      ks = new CMFKeystoreService(".", "ambari");
+      ks.setMasterService(new MasterService() {
+
+        public void init(GatewayConfig config, Map<String, String> options)
+            throws ServiceLifecycleException {
+          // TODO Auto-generated method stub
+          
+        }
+
+        public void start() throws ServiceLifecycleException {
+          // TODO Auto-generated method stub
+          
+        }
+
+        public void stop() throws ServiceLifecycleException {
+          // TODO Auto-generated method stub
+          
+        }
+
+        public char[] getMasterSecret() {
+          // TODO Auto-generated method stub
+          return "testmaster".toCharArray();
+        }
+        
+      });
+    } catch (ServiceLifecycleException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+  }
+  
+  @Test
+  public void testCredentialStore() {
+    try {
+      ks.createKeystore();
+      assertTrue(ks.isKeystoreAvailable());
+      ks.createCredentialStore();
+      assertTrue(ks.isCredentialStoreAvailable());
+      ks.addCredential("aliasName", "secretValue");
+      char[] secret = ks.getCredential("aliasName");
+      assertTrue(new String(secret).equals("secretValue"));
+      ks.addCredential("encrypt_url", "sdkgfksdgfjkhsdjkfhb");
+      File file = new File("ambari-credentials.jceks");
+      assertTrue(file.exists());
+      file.delete();
+      file = new File("ambari.jks");
+      assertTrue(file.exists());
+      file.delete();
+    } catch (KeystoreServiceException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+      fail();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterServiceTest.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterServiceTest.java b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterServiceTest.java
new file mode 100644
index 0000000..72d1121
--- /dev/null
+++ b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterServiceTest.java
@@ -0,0 +1,59 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+import java.io.File;
+
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.test.category.FastTests;
+import org.apache.hadoop.test.category.UnitTests;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+*
+*/
+@Category( { UnitTests.class, FastTests.class } )
+public class CMFMasterServiceTest {
+  TestCMFMasterService ms = null;
+
+  @Before
+  public void setup() {
+    ms = new TestCMFMasterService("ambari");
+  }
+  
+  @Test
+  public void testMasterService() {
+    try {
+      ms.setupMasterSecret(".", true);
+      System.out.println("MASTER: " + new String(ms.getMasterSecret()));
+      assertTrue(new String(ms.getMasterSecret()).equals("testmastersecret"));
+      File file = new File("ambari-master");
+      assertTrue(file.exists());
+      file.delete();
+    } catch (ServiceLifecycleException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+      fail();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/47b1d04b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/TestCMFMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/TestCMFMasterService.java b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/TestCMFMasterService.java
new file mode 100644
index 0000000..ce76a61
--- /dev/null
+++ b/gateway-spi/src/test/java/org/apache/hadoop/gateway/services/security/impl/TestCMFMasterService.java
@@ -0,0 +1,37 @@
+/**
+ * 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.hadoop.gateway.services.security.impl;
+
+
+public class TestCMFMasterService extends CMFMasterService {
+
+  public TestCMFMasterService(String serviceName) {
+    super(serviceName);
+  }
+
+  @Override
+  protected void promptUser() {
+    master = "testmastersecret".toCharArray();
+  }
+
+  @Override
+  protected void displayWarning(boolean persisting) {
+  }
+  
+  
+}
\ No newline at end of file


Mime
View raw message