This is an automated email from the ASF dual-hosted git repository.

krisden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 4576656  KNOX-1756 - Knox Gateway TLS Keystore and Alias Should be 
Configurable (#56)
4576656 is described below

commit 45766567d15ec814e6379dcce9e93043a0ffef91
Author: Robert Levas <[email protected]>
AuthorDate: Mon Feb 25 10:29:07 2019 -0500

    KNOX-1756 - Knox Gateway TLS Keystore and Alias Should be Configurable (#56)
---
 .../apache/knox/gateway/pac4j/Pac4jMessages.java   |   6 +-
 .../pac4j/filter/Pac4jDispatcherFilter.java        |  25 +++--
 .../org/apache/knox/gateway/GatewayServer.java     |   3 +-
 .../gateway/config/impl/GatewayConfigImpl.java     |  77 ++++++++++++-
 .../gateway/services/DefaultGatewayServices.java   |  16 +--
 .../impl/DefaultServiceRegistryService.java        |   4 +-
 .../security/impl/DefaultAliasService.java         |  45 +++++++-
 .../security/impl/DefaultCryptoService.java        |  10 +-
 .../security/impl/DefaultKeystoreService.java      |  79 +++++++++-----
 .../services/security/impl/JettySSLService.java    |  31 ++++--
 .../services/security/impl/RemoteAliasService.java |  42 +++++++-
 .../token/impl/DefaultTokenAuthorityService.java   |  12 +--
 .../java/org/apache/knox/gateway/util/KnoxCLI.java | 111 +++++++++++++++----
 .../gateway/config/impl/GatewayConfigImplTest.java |  55 ++++++++++
 .../services/security/CryptoServiceTest.java       |  15 +++
 .../impl/DefaultTokenAuthorityServiceTest.java     |  66 ++++++++----
 .../apache/knox/gateway/websockets/BadUrlTest.java |  77 ++++++++++++-
 .../knox/gateway/websockets/WebsocketEchoTest.java |  76 ++++++++++++-
 .../WebsocketMultipleConnectionTest.java           |  76 ++++++++++++-
 .../gateway/service/knoxtoken/TokenResource.java   |   4 +-
 .../apache/knox/gateway/config/GatewayConfig.java  | 100 +++++++++++++++++
 .../gateway/services/security/AliasService.java    |   6 ++
 .../gateway/services/security/CryptoService.java   |   4 +-
 .../gateway/services/security/KeystoreService.java |   6 ++
 .../knox/gateway/services/security/SSLService.java |   2 +-
 .../security/impl/BaseKeystoreService.java         |  16 +--
 .../services/security/impl/CMFKeystoreService.java |  16 +--
 .../security/impl/X509CertificateUtil.java         |  16 +++
 .../org/apache/knox/gateway/GatewayTestConfig.java | 119 ++++++++++++++++++---
 29 files changed, 952 insertions(+), 163 deletions(-)

diff --git 
a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
 
b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
index 56840c0..250d7be 100644
--- 
a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
+++ 
b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
@@ -45,6 +45,10 @@ public interface Pac4jMessages {
   void unableToGenerateAPasswordForEncryption(Exception e);
 
   @Message( level = MessageLevel.INFO, text =
-      "No private key passphrase alias found. Defaulting to master. Exception 
encountered: {0}")
+      "No private key passphrase alias found. Defaulting to master secret. 
Exception encountered: {0}")
   void noPrivateKeyPasshraseProvisioned(Exception e);
+
+  @Message( level = MessageLevel.ERROR, text =
+      "No keystore password alias found. Defaulting to master secret. 
Exception encountered: {0}")
+  void noKeystorePasswordProvisioned(Exception e);
 }
diff --git 
a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
 
b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
index 6393672..b220718 100644
--- 
a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
+++ 
b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
@@ -223,8 +223,19 @@ public class Pac4jDispatcherFilter implements Filter {
       properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PATH,
           keystoreService.getKeystorePath());
 
-      properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PASSWORD,
-          new String(masterService.getMasterSecret()));
+      // check for provisioned alias for keystore password
+      char[] giksp = null;
+      try {
+        giksp = aliasService.getGatewayIdentityKeystorePassword();
+      } catch (AliasServiceException e) {
+        log.noKeystorePasswordProvisioned(e);
+      }
+      if (giksp == null) {
+        // no alias provisioned then use the master
+        giksp = masterService.getMasterSecret();
+      }
+      properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PASSWORD, new 
String(giksp));
+
       // check for provisioned alias for private key
       char[] gip = null;
       try {
@@ -233,15 +244,11 @@ public class Pac4jDispatcherFilter implements Filter {
       catch(AliasServiceException ase) {
         log.noPrivateKeyPasshraseProvisioned(ase);
       }
-      if (gip != null) {
-        properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD,
-            new String(gip));
-      }
-      else {
+      if (gip == null) {
         // no alias provisioned then use the master
-        properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD,
-            new String(masterService.getMasterSecret()));
+        gip = masterService.getMasterSecret();
       }
+      properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD, new 
String(gip));
     }
   }
 
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
index a935933..b5f6aa6 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
@@ -370,8 +370,7 @@ public class GatewayServer {
       httpsConfig.setSecurePort( connectorPort );
       httpsConfig.addCustomizer( new SecureRequestCustomizer() );
       SSLService ssl = services.getService("SSLService");
-      String keystoreFileName = config.getGatewaySecurityDir() + 
File.separatorChar + "keystores" + File.separatorChar + "gateway.jks";
-      SslContextFactory sslContextFactory = 
(SslContextFactory)ssl.buildSslContextFactory( keystoreFileName );
+      SslContextFactory sslContextFactory = 
(SslContextFactory)ssl.buildSslContextFactory( 
config.getIdentityKeystorePath(), config.getIdentityKeystoreType(), 
config.getIdentityKeyAlias() );
       connector = new ServerConnector( server, sslContextFactory, new 
HttpConnectionFactory( httpsConfig ) );
     } else {
       connector = new ServerConnector( server );
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
index 5060831..cedf6cf 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
@@ -33,6 +33,7 @@ import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.UnknownHostException;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -427,6 +428,11 @@ public class GatewayConfigImpl extends Configuration 
implements GatewayConfig {
   }
 
   @Override
+  public String getGatewayKeystoreDir() {
+    return Paths.get(getGatewaySecurityDir(), 
"keystores").toAbsolutePath().toString();
+  }
+
+  @Override
   public InetSocketAddress getGatewayAddress() throws UnknownHostException {
     String host = getGatewayHost();
     int port = getGatewayPort();
@@ -644,13 +650,82 @@ public class GatewayConfigImpl extends Configuration 
implements GatewayConfig {
   }
 
   @Override
+  public String getIdentityKeystorePath() {
+    String keystorePath = get(IDENTITY_KEYSTORE_PATH);
+    if(StringUtils.isEmpty(keystorePath)) {
+      keystorePath = Paths.get(getGatewayKeystoreDir(), 
DEFAULT_GATEWAY_KEYSTORE_NAME).toAbsolutePath().toString();
+    }
+    return keystorePath;
+  }
+
+  @Override
+  public String getIdentityKeystoreType() {
+    return get(IDENTITY_KEYSTORE_TYPE, DEFAULT_IDENTITY_KEYSTORE_TYPE);
+  }
+
+  @Override
+  public String getIdentityKeystorePasswordAlias() {
+    return get(IDENTITY_KEYSTORE_PASSWORD_ALIAS, 
DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS);
+  }
+
+  @Override
+  public String getIdentityKeyAlias() {
+    return get(IDENTITY_KEY_ALIAS, DEFAULT_IDENTITY_KEY_ALIAS);
+  }
+
+  @Override
+  public String getIdentityKeyPassphraseAlias() {
+    return get(IDENTITY_KEY_PASSPHRASE_ALIAS, 
DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS);
+  }
+
+  @Override
   public String getSigningKeystoreName() {
     return get(SIGNING_KEYSTORE_NAME);
   }
 
   @Override
+  public String getSigningKeystorePath() {
+    if (getSigningKeystoreName() == null) {
+      return getIdentityKeystorePath();
+    } else {
+      return Paths.get(getGatewayKeystoreDir(), 
getSigningKeystoreName()).toAbsolutePath().toString();
+    }
+  }
+
+  @Override
+  public String getSigningKeystoreType() {
+    if (getSigningKeystoreName() == null) {
+      return getIdentityKeystoreType();
+    } else {
+      return get(SIGNING_KEYSTORE_TYPE, DEFAULT_SIGNING_KEYSTORE_TYPE);
+    }
+  }
+
+  @Override
   public String getSigningKeyAlias() {
-    return get(SIGNING_KEY_ALIAS);
+    if (getSigningKeystoreName() == null) {
+      return getIdentityKeyAlias();
+    } else {
+      return get(SIGNING_KEY_ALIAS, DEFAULT_SIGNING_KEY_ALIAS);
+    }
+  }
+
+  @Override
+  public String getSigningKeystorePasswordAlias() {
+    if (getSigningKeystoreName() == null) {
+      return getIdentityKeystorePasswordAlias();
+    } else {
+      return get(SIGNING_KEYSTORE_PASSWORD_ALIAS, 
DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS);
+    }
+  }
+
+  @Override
+  public String getSigningKeyPassphraseAlias() {
+    if (getSigningKeystoreName() == null) {
+      return getIdentityKeyPassphraseAlias();
+    } else {
+      return get(SIGNING_KEY_PASSPHRASE_ALIAS, 
DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS);
+    }
   }
 
   @Override
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
index 52ff41b..d9c5a73 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
@@ -101,13 +101,6 @@ public class DefaultGatewayServices implements 
GatewayServices {
     crypto.init(config, options);
     services.put(CRYPTO_SERVICE, crypto);
 
-    DefaultTokenAuthorityService ts = new DefaultTokenAuthorityService();
-    ts.setAliasService(alias);
-    ts.setKeystoreService(ks);
-    ts.init(config, options);
-    // prolly should not allow the token service to be looked up?
-    services.put(TOKEN_SERVICE, ts);
-
     JettySSLService ssl = new JettySSLService();
     ssl.setAliasService(alias);
     ssl.setKeystoreService(ks);
@@ -115,6 +108,15 @@ public class DefaultGatewayServices implements 
GatewayServices {
     ssl.init(config, options);
     services.put(SSL_SERVICE, ssl);
 
+    // The DefaultTokenAuthorityService needs to be initialized after the 
JettySSLService to ensure
+    // that the signing keystore is available for it.
+    DefaultTokenAuthorityService ts = new DefaultTokenAuthorityService();
+    ts.setAliasService(alias);
+    ts.setKeystoreService(ks);
+    ts.init(config, options);
+    // prolly should not allow the token service to be looked up?
+    services.put(TOKEN_SERVICE, ts);
+
     DefaultServiceRegistryService sr = new DefaultServiceRegistryService();
     sr.setCryptoService( crypto );
     sr.init( config, options );
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/registry/impl/DefaultServiceRegistryService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/registry/impl/DefaultServiceRegistryService.java
index 34f1697..124c9d9 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/registry/impl/DefaultServiceRegistryService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/registry/impl/DefaultServiceRegistryService.java
@@ -63,7 +63,7 @@ public class DefaultServiceRegistryService implements 
ServiceRegistry, Service {
   @Override
   public String getRegistrationCode(String clusterName) {
     String code = generateRegCode(16);
-    byte[] signature = crypto.sign("SHA256withRSA","gateway-identity",code);
+    byte[] signature = crypto.sign("SHA256withRSA", code);
     String encodedSig = Base64.encodeBase64URLSafeString(signature);
 
     return code + "::" + encodedSig;
@@ -93,7 +93,7 @@ public class DefaultServiceRegistryService implements 
ServiceRegistry, Service {
     String[] parts = regCode.split("::");
 
     // part one is the code and part two is the signature
-    boolean verified = crypto.verify("SHA256withRSA", "gateway-identity", 
parts[0], Base64.decodeBase64(parts[1]));
+    boolean verified = crypto.verify("SHA256withRSA", parts[0], 
Base64.decodeBase64(parts[1]));
     if (verified) {
       Map<String,RegEntry> clusterServices = registry.get(clusterName);
       if (clusterServices == null) {
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultAliasService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultAliasService.java
index bddfb88..2f0dae5 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultAliasService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultAliasService.java
@@ -39,14 +39,14 @@ import org.apache.knox.gateway.util.PasswordUtils;
 public class DefaultAliasService implements AliasService {
   private static final GatewayMessages LOG = MessagesFactory.get( 
GatewayMessages.class );
 
-  private static final String GATEWAY_IDENTITY_PASSPHRASE = 
"gateway-identity-passphrase";
-
   private KeystoreService keystoreService;
   private MasterService masterService;
+  private GatewayConfig config;
 
   @Override
   public void init(GatewayConfig config, Map<String, String> options)
       throws ServiceLifecycleException {
+    this.config = config;
   }
 
   @Override
@@ -59,8 +59,47 @@ public class DefaultAliasService implements AliasService {
 
   @Override
   public char[] getGatewayIdentityPassphrase() throws AliasServiceException {
-    char[] passphrase = 
getPasswordFromAliasForGateway(GATEWAY_IDENTITY_PASSPHRASE);
+    char[] passphrase = 
getPasswordFromAliasForGateway(config.getIdentityKeyPassphraseAlias());
+    if (passphrase == null) {
+      // Fall back to the keystore password if a key-specific password was not 
explicitly set.
+      passphrase = getGatewayIdentityKeystorePassword();
+    }
+    if (passphrase == null) {
+      // Use the master password if not password was found
+      passphrase = masterService.getMasterSecret();
+    }
+    return passphrase;
+  }
+
+  @Override
+  public char[] getGatewayIdentityKeystorePassword() throws 
AliasServiceException {
+    char[] passphrase = 
getPasswordFromAliasForGateway(config.getIdentityKeystorePasswordAlias());
+    if (passphrase == null) {
+      // Use the master password if not password was found
+      passphrase = masterService.getMasterSecret();
+    }
+    return passphrase;
+  }
+
+  @Override
+  public char[] getSigningKeyPassphrase() throws AliasServiceException {
+    char[] passphrase = 
getPasswordFromAliasForGateway(config.getSigningKeyPassphraseAlias());
+    if (passphrase == null) {
+      // Fall back to the keystore password if a key-specific password was not 
explicitly set.
+      passphrase = getSigningKeystorePassword();
+    }
+    if (passphrase == null) {
+      // Use the master password if not password was found
+      passphrase = masterService.getMasterSecret();
+    }
+    return passphrase;
+  }
+
+  @Override
+  public char[] getSigningKeystorePassword() throws AliasServiceException {
+    char[] passphrase = 
getPasswordFromAliasForGateway(config.getSigningKeystorePasswordAlias());
     if (passphrase == null) {
+      // Use the master password if not password was found
       passphrase = masterService.getMasterSecret();
     }
     return passphrase;
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
index 3cf3cb6..3aea783 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
@@ -129,14 +129,14 @@ public class DefaultCryptoService implements 
CryptoService {
   }
 
   @Override
-  public boolean verify(String algorithm, String alias, String signed, byte[] 
signature) {
+  public boolean verify(String algorithm, String signed, byte[] signature) {
     boolean verified = false;
     try {
       Signature sig=Signature.getInstance(algorithm);
-      
sig.initVerify(ks.getKeystoreForGateway().getCertificate(alias).getPublicKey());
+      sig.initVerify(ks.getCertificateForGateway().getPublicKey());
       sig.update(signed.getBytes(StandardCharsets.UTF_8));
       verified = sig.verify(signature);
-    } catch (SignatureException | KeystoreServiceException | KeyStoreException 
| InvalidKeyException | NoSuchAlgorithmException e) {
+    } catch (SignatureException | KeystoreServiceException | 
InvalidKeyException | NoSuchAlgorithmException | KeyStoreException e) {
       LOG.failedToVerifySignature( e );
     }
     LOG.signatureVerified( verified );
@@ -144,11 +144,11 @@ public class DefaultCryptoService implements 
CryptoService {
   }
 
   @Override
-  public byte[] sign(String algorithm, String alias, String payloadToSign) {
+  public byte[] sign(String algorithm, String payloadToSign) {
     try {
       char[] passphrase;
       passphrase = as.getGatewayIdentityPassphrase();
-      PrivateKey privateKey = (PrivateKey) ks.getKeyForGateway(alias, 
passphrase);
+      PrivateKey privateKey = (PrivateKey) ks.getKeyForGateway(passphrase);
       Signature signature = Signature.getInstance(algorithm);
       signature.initSign(privateKey);
       signature.update(payloadToSign.getBytes(StandardCharsets.UTF_8));
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
index 947b4a8..d62d1ff 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
@@ -17,6 +17,7 @@
  */
 package org.apache.knox.gateway.services.security.impl;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.knox.gateway.GatewayMessages;
 import org.apache.knox.gateway.GatewayResources;
 import org.apache.knox.gateway.config.GatewayConfig;
@@ -31,6 +32,7 @@ import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
 import java.security.GeneralSecurityException;
 import java.security.Key;
 import java.security.KeyPair;
@@ -39,6 +41,7 @@ import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.text.MessageFormat;
@@ -55,13 +58,14 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
 
   private static final String dnTemplate = 
"CN={0},OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
   private static final String CREDENTIALS_SUFFIX = "-credentials.jceks";
-  public static final String GATEWAY_KEYSTORE = "gateway.jks";
+  private static final String NO_CLUSTER_NAME = "__gateway";
   private static final String CERT_GEN_MODE = "hadoop.gateway.cert.gen.mode";
   private static final String CERT_GEN_MODE_LOCALHOST = "localhost";
   private static final String CERT_GEN_MODE_HOSTNAME = "hostname";
   private static GatewayMessages LOG = MessagesFactory.get( 
GatewayMessages.class );
   private static GatewayResources RES = ResourcesFactory.get( 
GatewayResources.class );
 
+  private GatewayConfig config;
   private String signingKeystoreName;
   private String signingKeyAlias;
   private Map<String, Map<String, String>> cache = new ConcurrentHashMap<>();
@@ -75,7 +79,9 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
     readLock = lock.readLock();
     writeLock = lock.writeLock();
 
-    this.keyStoreDir = config.getGatewaySecurityDir() + File.separator + 
"keystores" + File.separator;
+    this.config = config;
+
+    this.keyStoreDir = config.getGatewayKeystoreDir();
     File ksd = new File(this.keyStoreDir);
     if (!ksd.exists()) {
       if( !ksd.mkdirs() ) {
@@ -123,7 +129,7 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
     writeLock.lock();
     try {
       String filename = getKeystorePath();
-      createKeystore(filename, "JKS");
+      createKeystore(filename, config.getIdentityKeystoreType(), 
getKeystorePassword(config.getIdentityKeystorePasswordAlias()));
     } finally {
       writeLock.unlock();
     }
@@ -131,10 +137,10 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
 
   @Override
   public KeyStore getKeystoreForGateway() throws KeystoreServiceException {
-    final File  keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE  );
+    final File  keyStoreFile = new File( config.getIdentityKeystorePath() );
     readLock.lock();
     try {
-      return getKeystore(keyStoreFile, "JKS");
+      return getKeystore(keyStoreFile, config.getIdentityKeystoreType(), 
getKeystorePassword(config.getIdentityKeystorePasswordAlias()));
     }
     finally {
       readLock.unlock();
@@ -148,13 +154,17 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
 
   @Override
   public KeyStore getSigningKeystore(String keystoreName) throws 
KeystoreServiceException {
-    File  keyStoreFile;
+    File keyStoreFile;
+    String keyStoreType;
+    char[] password;
     if(keystoreName != null) {
-      keyStoreFile = new File(keyStoreDir + keystoreName + ".jks");
-    } else if (signingKeystoreName != null) {
-      keyStoreFile = new File(keyStoreDir + signingKeystoreName);
+      keyStoreFile = new File(keyStoreDir, keystoreName + ".jks");
+      keyStoreType = "jks";
+      password = masterService.getMasterSecret();
     } else {
-      keyStoreFile = new File(keyStoreDir + GATEWAY_KEYSTORE);
+      keyStoreFile = new File(config.getSigningKeystorePath());
+      keyStoreType = config.getSigningKeystoreType();
+      password = getKeystorePassword(config.getSigningKeystorePasswordAlias());
     }
 
     // make sure the keystore exists
@@ -163,7 +173,7 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
     }
     readLock.lock();
     try {
-      return getKeystore(keyStoreFile, "JKS");
+      return getKeystore(keyStoreFile, keyStoreType, password);
     }
     finally {
       readLock.unlock();
@@ -209,7 +219,7 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
             passphrase,
             new java.security.cert.Certificate[]{cert});
 
-        writeKeystoreToFile(privateKS, new File( keyStoreDir + 
GATEWAY_KEYSTORE  ));
+        writeKeystoreToFile(privateKS, new File( 
config.getIdentityKeystorePath() ), 
getKeystorePassword(config.getIdentityKeystorePasswordAlias()));
         //writeCertificateToFile( cert, new File( keyStoreDir + alias + ".pem" 
) );
       } catch (GeneralSecurityException | IOException e) {
         LOG.failedToAddSeflSignedCertForGateway( alias, e );
@@ -230,10 +240,10 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
 
   @Override
   public void createCredentialStoreForCluster(String clusterName) throws 
KeystoreServiceException {
-    String filename = keyStoreDir + clusterName + CREDENTIALS_SUFFIX;
+    String filename = Paths.get(keyStoreDir, clusterName + 
CREDENTIALS_SUFFIX).toString();
     writeLock.lock();
     try {
-      createKeystore(filename, "JCEKS");
+      createKeystore(filename, "JCEKS", masterService.getMasterSecret());
     }
     finally {
       writeLock.unlock();
@@ -243,11 +253,11 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
   @Override
   public boolean isCredentialStoreForClusterAvailable(String clusterName) 
throws KeystoreServiceException {
     boolean rc;
-    final File  keyStoreFile = new File( keyStoreDir + clusterName + 
CREDENTIALS_SUFFIX  );
+    final File  keyStoreFile = new File( keyStoreDir, clusterName + 
CREDENTIALS_SUFFIX  );
     readLock.lock();
     try {
       try {
-        rc = isKeystoreAvailable(keyStoreFile, "JCEKS");
+        rc = isKeystoreAvailable(keyStoreFile, "JCEKS", 
masterService.getMasterSecret());
       } catch (KeyStoreException | IOException e) {
         throw new KeystoreServiceException(e);
       }
@@ -261,11 +271,11 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
   @Override
   public boolean isKeystoreForGatewayAvailable() throws 
KeystoreServiceException {
     boolean rc;
-    final File  keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE  );
+    final File  keyStoreFile = new File( config.getIdentityKeystorePath() );
     readLock.lock();
     try {
       try {
-        rc = isKeystoreAvailable(keyStoreFile, "JKS");
+        rc = isKeystoreAvailable(keyStoreFile, 
config.getIdentityKeystoreType(), 
getKeystorePassword(config.getIdentityKeystorePasswordAlias()));
       } catch (KeyStoreException | IOException e) {
         throw new KeystoreServiceException(e);
       }
@@ -301,6 +311,17 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
   }
 
   @Override
+  public Key getKeyForGateway(char[] passphrase) throws 
KeystoreServiceException {
+    return getKeyForGateway(config.getIdentityKeyAlias(), passphrase);
+  }
+
+  @Override
+  public Certificate getCertificateForGateway() throws 
KeystoreServiceException, KeyStoreException {
+    KeyStore ks = getKeystoreForGateway();
+    return (ks == null) ? null : 
ks.getCertificate(config.getIdentityKeyAlias());
+  }
+
+  @Override
   public Key getSigningKey(String alias, char[] passphrase) throws 
KeystoreServiceException {
     return getSigningKey(null, alias, passphrase);
   }
@@ -332,10 +353,10 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
   @Override
   public KeyStore getCredentialStoreForCluster(String clusterName)
       throws KeystoreServiceException {
-    final File  keyStoreFile = new File( keyStoreDir + clusterName + 
CREDENTIALS_SUFFIX  );
+    final File  keyStoreFile = new File( keyStoreDir, clusterName + 
CREDENTIALS_SUFFIX  );
     readLock.lock();
     try {
-      return getKeystore(keyStoreFile, "JCEKS");
+      return getKeystore(keyStoreFile, "JCEKS", 
masterService.getMasterSecret());
     }
     finally {
       readLock.unlock();
@@ -350,9 +371,9 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
       removeFromCache(clusterName, alias);
       KeyStore ks = getCredentialStoreForCluster(clusterName);
       addCredential(alias, value, ks);
-      final File  keyStoreFile = new File( keyStoreDir + clusterName + 
CREDENTIALS_SUFFIX  );
+      final File  keyStoreFile = new File( keyStoreDir, clusterName + 
CREDENTIALS_SUFFIX  );
       try {
-        writeKeystoreToFile(ks, keyStoreFile);
+        writeKeystoreToFile(ks, keyStoreFile, masterService.getMasterSecret());
       } catch (KeyStoreException | IOException | CertificateException | 
NoSuchAlgorithmException e) {
         LOG.failedToAddCredentialForCluster( clusterName, e );
       }
@@ -395,14 +416,14 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
 
   @Override
   public void removeCredentialForCluster(String clusterName, String alias) 
throws KeystoreServiceException {
-    final File  keyStoreFile = new File( keyStoreDir + clusterName + 
CREDENTIALS_SUFFIX  );
+    final File  keyStoreFile = new File( keyStoreDir, clusterName + 
CREDENTIALS_SUFFIX  );
     writeLock.lock();
     try {
       removeFromCache(clusterName, alias);
       KeyStore ks = getCredentialStoreForCluster(clusterName);
       removeCredential(alias, ks);
       try {
-        writeKeystoreToFile(ks, keyStoreFile);
+        writeKeystoreToFile(ks, keyStoreFile, masterService.getMasterSecret());
       } catch (KeyStoreException | IOException | CertificateException | 
NoSuchAlgorithmException e) {
         LOG.failedToRemoveCredentialForCluster(clusterName, e);
       }
@@ -450,6 +471,14 @@ public class DefaultKeystoreService extends 
BaseKeystoreService implements
 
   @Override
   public String getKeystorePath() {
-    return keyStoreDir + GATEWAY_KEYSTORE;
+    return config.getIdentityKeystorePath();
+  }
+
+  private char[] getKeystorePassword(String alias) throws 
KeystoreServiceException {
+    char[] password = null;
+    if (StringUtils.isNotEmpty(alias)) {
+      password = getCredentialForCluster(NO_CLUSTER_NAME, alias);
+    }
+    return (password == null) ? masterService.getMasterSecret() : password;
   }
 }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/JettySSLService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/JettySSLService.java
index b9e5c0c..1e07823 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/JettySSLService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/JettySSLService.java
@@ -62,7 +62,6 @@ public class JettySSLService implements SSLService {
   private boolean clientAuthNeeded;
   private boolean trustAllCerts;
   private String truststorePath;
-  private String keystoreType;
   private String trustStoreType;
   private boolean clientAuthWanted;
 
@@ -112,17 +111,16 @@ public class JettySSLService implements SSLService {
         if (passphrase == null) {
           passphrase = ms.getMasterSecret();
         }
-        ks.addSelfSignedCertForGateway("gateway-identity", passphrase);
+        ks.addSelfSignedCertForGateway(config.getIdentityKeyAlias(), 
passphrase);
       }
       else {
         log.keyStoreForGatewayFoundNotCreating();
       }
-      logAndValidateCertificate();
+      logAndValidateCertificate(config);
     } catch (KeystoreServiceException e) {
-      throw new ServiceLifecycleException("Keystore was not loaded properly - 
the provided (or persisted) master secret may not match the password for the 
keystore.", e);
+      throw new ServiceLifecycleException("The identity keystore was not 
loaded properly - the provided password may not match the password for the 
keystore.", e);
     }
 
-    keystoreType = config.getKeystoreType();
     sslIncludeCiphers = config.getIncludedSSLCiphers();
     sslExcludeCiphers = config.getExcludedSSLCiphers();
     sslExcludeProtocols = config.getExcludedSSLProtocols();
@@ -133,11 +131,11 @@ public class JettySSLService implements SSLService {
     trustStoreType = config.getTruststoreType();
   }
 
-  private void logAndValidateCertificate() throws ServiceLifecycleException {
+  private void logAndValidateCertificate(GatewayConfig config) throws 
ServiceLifecycleException {
     // let's log the hostname (CN) and cert expiry from the gateway's public 
cert to aid in SSL debugging
     Certificate cert;
     try {
-      cert = as.getCertificateForGateway("gateway-identity");
+      cert = as.getCertificateForGateway(config.getIdentityKeyAlias());
     } catch (AliasServiceException e) {
       throw new ServiceLifecycleException("Cannot Retreive Gateway SSL 
Certificate. Server will not start.", e);
     }
@@ -167,13 +165,26 @@ public class JettySSLService implements SSLService {
   }
 
   @Override
-  public Object buildSslContextFactory(String keystoreFileName ) throws 
KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+  public Object buildSslContextFactory(String keystoreFileName, String 
keystoreType, String alias) throws KeyStoreException, IOException, 
CertificateException, NoSuchAlgorithmException {
     SslContextFactory sslContextFactory = new SslContextFactory( true );
-    sslContextFactory.setCertAlias( "gateway-identity" );
+    sslContextFactory.setCertAlias( alias );
     sslContextFactory.setKeyStoreType(keystoreType);
     sslContextFactory.setKeyStorePath(keystoreFileName);
     char[] master = ms.getMasterSecret();
-    sslContextFactory.setKeyStorePassword(new String(master));
+
+    char[] keystorePasswordChars = null;
+    try {
+      keystorePasswordChars = as.getGatewayIdentityKeystorePassword();
+    } catch (AliasServiceException e) {
+      log.creatingKeyStoreForGateway();
+      // nop - default passphrase will be used
+    }
+    if(keystorePasswordChars == null) {
+      // If a keystore password was not set, use the master password
+      keystorePasswordChars = master;
+    }
+    sslContextFactory.setKeyStorePassword(new String(keystorePasswordChars));
+
     char[] keypass = null;
     try {
       keypass = as.getGatewayIdentityPassphrase();
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/RemoteAliasService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/RemoteAliasService.java
index 4cd2160..bf41432 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/RemoteAliasService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/RemoteAliasService.java
@@ -63,7 +63,6 @@ public class RemoteAliasService implements AliasService {
       PATH_KNOX_SECURITY + "/topology";
   public static final String PATH_SEPARATOR = "/";
   public static final String DEFAULT_CLUSTER_NAME = "__gateway";
-  public static final String GATEWAY_IDENTITY_PASSPHRASE = 
"gateway-identity-passphrase";
 
   private static final GatewayMessages LOG = 
MessagesFactory.get(GatewayMessages.class);
   // N.B. This is ZooKeeper-specific, and should be abstracted when another 
registry is supported
@@ -379,15 +378,43 @@ public class RemoteAliasService implements AliasService {
 
   @Override
   public char[] getGatewayIdentityPassphrase() throws AliasServiceException {
-    char[] passphrase = getPasswordFromAliasForGateway(
-        GATEWAY_IDENTITY_PASSPHRASE);
+    char[] passphrase = 
getPasswordFromAliasForGateway(config.getIdentityKeyPassphraseAlias());
     if (passphrase == null) {
+      // Fall back to the keystore password if a key-specific password was not 
explicitly set.
+      passphrase = getGatewayIdentityKeystorePassword();
+    }
+    if (passphrase == null) {
+      // Use the master password if not password was found
+      passphrase = ms.getMasterSecret();
+    }
+    return passphrase;
+  }
+
+  @Override
+  public char[] getGatewayIdentityKeystorePassword() throws 
AliasServiceException {
+    return getKeystorePassword(config.getIdentityKeystorePasswordAlias());
+  }
+
+  @Override
+  public char[] getSigningKeyPassphrase() throws AliasServiceException {
+    char[] passphrase = 
getPasswordFromAliasForGateway(config.getSigningKeyPassphraseAlias());
+    if (passphrase == null) {
+      // Fall back to the keystore password if a key-specific password was not 
explicitly set.
+      passphrase = getSigningKeystorePassword();
+    }
+    if (passphrase == null) {
+      // Use the master password if not password was found
       passphrase = ms.getMasterSecret();
     }
     return passphrase;
   }
 
   @Override
+  public char[] getSigningKeystorePassword() throws AliasServiceException {
+    return getKeystorePassword(config.getSigningKeystorePasswordAlias());
+  }
+
+  @Override
   public void generateAliasForGateway(final String alias)
       throws AliasServiceException {
     generateAliasForCluster(DEFAULT_CLUSTER_NAME, alias);
@@ -515,6 +542,15 @@ public class RemoteAliasService implements AliasService {
         remoteClient);
   }
 
+  private char[] getKeystorePassword(String alias) throws 
AliasServiceException {
+    char[] passphrase = getPasswordFromAliasForGateway(alias);
+    if (passphrase == null) {
+      passphrase = ms.getMasterSecret();
+    }
+    return passphrase;
+  }
+
+
   /**
    * Encrypt the clear text with master password.
    * @param clear clear text to be encrypted
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
index 6034889..190d0dc 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
@@ -49,7 +49,6 @@ import com.nimbusds.jose.crypto.RSASSAVerifier;
 
 public class DefaultTokenAuthorityService implements JWTokenAuthority, Service 
{
 
-  private static final String SIGNING_KEY_PASSPHRASE = 
"signing.key.passphrase";
   private static final Set<String> SUPPORTED_SIG_ALGS = new HashSet<>();
   private AliasService as;
   private KeystoreService ks;
@@ -158,11 +157,8 @@ public class DefaultTokenAuthorityService implements 
JWTokenAuthority, Service {
     if(signingKeyPassphrase != null) {
       return signingKeyPassphrase;
     }
-    char[] phrase = as.getPasswordFromAliasForGateway(SIGNING_KEY_PASSPHRASE);
-    if (phrase == null) {
-      phrase = as.getGatewayIdentityPassphrase();
-    }
-    return phrase;
+
+    return as.getSigningKeyPassphrase();
   }
 
   private String getSigningKeyAlias(String signingKeystoreAlias) {
@@ -172,7 +168,7 @@ public class DefaultTokenAuthorityService implements 
JWTokenAuthority, Service {
     if(signingKeyAlias != null) {
       return signingKeyAlias;
     }
-    return "gateway-identity";
+    return GatewayConfig.DEFAULT_SIGNING_KEY_ALIAS;
   }
 
   @Override
@@ -214,7 +210,7 @@ public class DefaultTokenAuthorityService implements 
JWTokenAuthority, Service {
     RSAPrivateKey key;
     char[] passphrase;
     try {
-      passphrase = as.getPasswordFromAliasForGateway(SIGNING_KEY_PASSPHRASE);
+      passphrase = as.getSigningKeyPassphrase();
       if (passphrase != null) {
         key = (RSAPrivateKey) 
ks.getSigningKey(getSigningKeyAlias(signingKeyAlias),
             passphrase);
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
index 309f0ed..33e6dbd 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
@@ -75,7 +75,11 @@ import java.io.PrintStream;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyStoreException;
 import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -590,8 +594,9 @@ public class KnoxCLI extends Configured implements Tool {
             out.println("No keystore has been created for the gateway. Please 
use the create-cert command or populate with a CA signed cert of your own.");
           }
 
-          Certificate cert = 
ks.getKeystoreForGateway().getCertificate("gateway-identity");
-          String keyStoreDir = getGatewayConfig().getGatewaySecurityDir() + 
File.separator + "keystores" + File.separator;
+          GatewayConfig config = getGatewayConfig();
+          Certificate cert = 
ks.getKeystoreForGateway().getCertificate(config.getIdentityKeyAlias());
+          String keyStoreDir = config.getGatewayKeystoreDir() + File.separator;
           File ksd = new File(keyStoreDir);
           if (!ksd.exists()) {
             if (!ksd.mkdirs()) {
@@ -616,7 +621,7 @@ public class KnoxCLI extends Configured implements Tool {
             out.println("Invalid type for export file provided. Export has not 
been done. Please use: [PEM|JKS|JCEKS|PKCS12] default value is PEM.");
           }
         } catch (KeystoreServiceException e) {
-          throw new ServiceLifecycleException("Keystore was not loaded 
properly - the provided (or persisted) master secret may not match the password 
for the keystore.", e);
+          throw new ServiceLifecycleException("The identity keystore was not 
loaded properly - the provided password may not match the password for the 
keystore.", e);
         }
       }
     }
@@ -629,14 +634,15 @@ public class KnoxCLI extends Configured implements Tool {
 
  public class CertCreateCommand extends Command {
 
-  public static final String USAGE = "create-cert [--hostname h]";
-  public static final String DESC = "The create-cert command creates and 
populates\n" +
-                                    "a gateway.jks keystore with a self-signed 
certificate\n" +
-                                    "to be used as the gateway identity. It 
also adds an alias\n" +
-                                    "to the __gateway-credentials.jceks 
credential store for the\n" +
-                                    "key passphrase.";
+  public static final String USAGE = "create-cert [--force] [--hostname h]";
+  public static final String DESC = "The create-cert command populates the 
configured identity\n" +
+                                    "keystore with a self-signed certificate 
to be used as the\n" +
+                                    "gateway identity. If a cert exists and it 
is determined to\n" +
+                                    "not have been generated by Knox, --force 
must be specified\n" +
+                                    "to overwrite it.  If a self-signed cert 
is created, a\n" +
+                                    "password for the key will be generated 
and stored in the\n" +
+                                    "__gateway-credentials.jceks credential 
store.";
   private static final String GATEWAY_CREDENTIAL_STORE_NAME = "__gateway";
-  private static final String GATEWAY_IDENTITY_PASSPHRASE = 
"gateway-identity-passphrase";
 
    public CertCreateCommand() {
    }
@@ -652,8 +658,7 @@ public class KnoxCLI extends Configured implements Tool {
          if 
(!ks.isCredentialStoreForClusterAvailable(GATEWAY_CREDENTIAL_STORE_NAME)) {
 //           log.creatingCredentialStoreForGateway();
            ks.createCredentialStoreForCluster(GATEWAY_CREDENTIAL_STORE_NAME);
-         }
-         else {
+         } else {
 //           log.credentialStoreForGatewayFoundNotCreating();
          }
          // LET'S NOT GENERATE A DIFFERENT KEY PASSPHRASE BY DEFAULT ANYMORE
@@ -661,7 +666,7 @@ public class KnoxCLI extends Configured implements Tool {
          // THEY CAN ADD THE ALIAS EXPLICITLY WITH THE CLI
          //as.generateAliasForCluster(GATEWAY_CREDENTIAL_STORE_NAME, 
GATEWAY_IDENTITY_PASSPHRASE);
        } catch (KeystoreServiceException e) {
-         throw new ServiceLifecycleException("Keystore was not loaded properly 
- the provided (or persisted) master secret may not match the password for the 
keystore.", e);
+         throw new ServiceLifecycleException("Keystore was not loaded properly 
- the stored password may not match the password for the keystore.", e);
        }
 
        try {
@@ -672,20 +677,84 @@ public class KnoxCLI extends Configured implements Tool {
          else {
 //           log.keyStoreForGatewayFoundNotCreating();
          }
-         char[] passphrase = 
as.getPasswordFromAliasForCluster(GATEWAY_CREDENTIAL_STORE_NAME, 
GATEWAY_IDENTITY_PASSPHRASE);
-         if (passphrase == null) {
-           MasterService ms = services.getService("MasterService");
-           passphrase = ms.getMasterSecret();
-         }
-         ks.addSelfSignedCertForGateway("gateway-identity", passphrase, 
hostname);
+
+
+         GatewayConfig config = getGatewayConfig();
+
+         if ( !isForceRequired(config, ks) || force) {
+           char[] passphrase = as.getGatewayIdentityPassphrase();
+           if (passphrase == null) {
+             MasterService ms = services.getService("MasterService");
+             passphrase = ms.getMasterSecret();
+           }
+           ks.addSelfSignedCertForGateway(config.getIdentityKeyAlias(), 
passphrase, hostname);
 //         logAndValidateCertificate();
-         out.println("Certificate gateway-identity has been successfully 
created.");
+           out.println("Certificate " + config.getIdentityKeyAlias() + " has 
been successfully created.");
+         } else {
+           // require --force to replace...
+           out.println("A non-self-signed certificate has already been 
installed in the configured keystore. " +
+               "Please use --force if you wish to overwrite it with a 
generated self-signed certificate.");
+         }
        } catch (KeystoreServiceException e) {
-         throw new ServiceLifecycleException("Keystore was not loaded properly 
- the provided (or persisted) master secret may not match the password for the 
keystore.", e);
+         throw new ServiceLifecycleException("The identity keystore was not 
loaded properly - the provided password may not match the password for the 
keystore.", e);
        }
      }
    }
 
+   /**
+    * Determines if <code>--force</code> should be used inorder to not 
accidentally overwrite a
+    * real certificate.
+    * <p>
+    * <p>
+    * All of the following must be met for <code>--force</code> to <b>NOT</b> 
be required:
+    * <ul>
+    * <li>The path to the keystore file is the default path: <code>[Gateway 
Keystore Directory]/gateway.jks</code></li>
+    * <li>The alias name for the key is the default name: 
<code>gateway-identity</code></li>
+    * <li>The relevant certificate does not exist or is self-signed</li>
+    * <li>The relevant certificate has a subject name ending in 
"OU=Test,O=Hadoop,L=Test,ST=Test,C=US"</li>
+    * </ul>
+    *
+    * @param config the Gateway configuration
+    * @param ks     a {@link KeystoreService} implementation
+    * @return <code>true</code> if <code>--force</code> is required; otherwise 
<code>false</code>
+    */
+   private boolean isForceRequired(GatewayConfig config, KeystoreService ks) {
+
+     // Test the path of the keystore file
+     Path defaultKeystorePath = Paths.get(config.getGatewayKeystoreDir(), 
GatewayConfig.DEFAULT_GATEWAY_KEYSTORE_NAME).toAbsolutePath();
+     Path actualKeystorePath = 
Paths.get(config.getIdentityKeystorePath()).toAbsolutePath();
+     if (!defaultKeystorePath.equals(actualKeystorePath)) {
+       // The path is not the default path: --force is required
+       return true;
+     }
+
+     // Test the alias name for the key
+     if 
(!GatewayConfig.DEFAULT_IDENTITY_KEY_ALIAS.equals(config.getIdentityKeyAlias()))
 {
+       // The alias name for the key is not the default name 
(gateway-identity): --force is required
+       return true;
+     }
+
+     // Test the certificate
+     try {
+       Certificate certificate = ks.getCertificateForGateway();
+
+       if (certificate instanceof X509Certificate) {
+         if (!X509CertificateUtil.isSelfSignedCertificate(certificate)) {
+           // The relevant certificate exists and is not self-signed: --force 
is required
+           return true;
+         } else if (!((X509Certificate) 
certificate).getSubjectDN().getName().matches(".*?,\\s*OU=Test,\\s*O=Hadoop,\\s*L=Test,\\s*ST=Test,\\s*C=US"))
 {
+           // The subject name of certificate does not end with 
"OU=Test,O=Hadoop,L=Test,ST=Test,C=US": --force is required
+           return true;
+         }
+       }
+     } catch (KeyStoreException | KeystoreServiceException e) {
+       // A certificate was (probably) not previously created...
+     }
+
+     // All indicators point to a previously created test certificate: --force 
is not required
+     return false;
+   }
+
    @Override
    public String getUsage() {
      return USAGE + ":\n\n" + DESC;
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
index ffd9ac3..dd85793 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java
@@ -16,10 +16,12 @@
  */
 package org.apache.knox.gateway.config.impl;
 
+import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.test.TestUtils;
 import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 
+import java.nio.file.Paths;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -32,6 +34,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 
@@ -292,5 +295,57 @@ public class GatewayConfigImplTest {
     assertTrue(names.contains("default"));
   }
 
+  // KNOX-1756
+  @Test
+  public void testCustomIdentityKeystoreOptions() {
+    GatewayConfigImpl config = new GatewayConfigImpl();
+
+    // Validate default options (backwards compatibility)
+    assertEquals("gateway-identity", config.getIdentityKeyAlias());
+    assertEquals("gateway-identity-passphrase", 
config.getIdentityKeyPassphraseAlias());
+    assertEquals("gateway-identity", config.getSigningKeyAlias());
+    assertEquals("gateway-identity-passphrase", 
config.getSigningKeyPassphraseAlias());
+    assertNull(config.getSigningKeystoreName());
+
+    // Validate default options (new)
+    assertEquals(GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS, 
config.getIdentityKeystorePasswordAlias());
+    assertEquals(GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_TYPE, 
config.getIdentityKeystoreType());
+    assertEquals(Paths.get(config.getGatewayKeystoreDir(), 
"gateway.jks").toAbsolutePath().toString(),
+        config.getIdentityKeystorePath());
+
+    // By default the signing keystore name will not be set, so the values 
will be taken from the identity's configs
+    assertEquals(config.getIdentityKeystorePath(), 
config.getSigningKeystorePath());
+    assertEquals(config.getIdentityKeystorePasswordAlias(), 
config.getSigningKeystorePasswordAlias());
+    assertEquals(config.getIdentityKeystoreType(), 
config.getSigningKeystoreType());
+    assertEquals(config.getIdentityKeyAlias(), config.getSigningKeyAlias());
+    assertEquals(config.getIdentityKeyPassphraseAlias(), 
config.getSigningKeyPassphraseAlias());
+
+    String tlsKeystorePath = Paths.get("custom", "keystore", "path", 
"keystore.p12").toString();
+
+    // Validate changed options
+    config.set("gateway.tls.key.alias", "custom_key_alias");
+    config.set("gateway.tls.key.passphrase.alias", 
"custom_key_passphrase_alias");
+    config.set("gateway.tls.keystore.path", tlsKeystorePath);
+    config.set("gateway.tls.keystore.type", "PKCS12");
+    config.set("gateway.tls.keystore.password.alias", 
"custom_keystore_password_alias");
+
+    config.set("gateway.signing.key.alias", "custom_key_alias");
+    config.set("gateway.signing.key.passphrase.alias", 
"custom_key_passphrase_alias");
+    config.set("gateway.signing.keystore.name", "custom_keystore_name");
+    config.set("gateway.signing.keystore.type", "PKCS12");
+    config.set("gateway.signing.keystore.password.alias", 
"custom_keystore_password_alias");
+
+    assertEquals("custom_key_alias", config.getIdentityKeyAlias());
+    assertEquals("custom_key_passphrase_alias", 
config.getIdentityKeyPassphraseAlias());
+    assertEquals(tlsKeystorePath, config.getIdentityKeystorePath());
+    assertEquals("PKCS12", config.getIdentityKeystoreType());
+    assertEquals("custom_keystore_password_alias", 
config.getIdentityKeystorePasswordAlias());
+
+    assertEquals("custom_key_alias", config.getSigningKeyAlias());
+    assertEquals("custom_key_passphrase_alias", 
config.getSigningKeyPassphraseAlias());
+    assertEquals("custom_keystore_name", config.getSigningKeystoreName());
+    assertEquals("PKCS12", config.getSigningKeystoreType());
+    assertEquals("custom_keystore_password_alias", 
config.getSigningKeystorePasswordAlias());
+  }
 
 }
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/security/CryptoServiceTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/security/CryptoServiceTest.java
index 3204630..c0dd1a1 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/security/CryptoServiceTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/security/CryptoServiceTest.java
@@ -105,6 +105,21 @@ public class CryptoServiceTest {
       public char[] getGatewayIdentityPassphrase() throws 
AliasServiceException {
         return null;
       }
+
+      @Override
+      public char[] getGatewayIdentityKeystorePassword() throws 
AliasServiceException {
+        return null;
+      }
+
+      @Override
+      public char[] getSigningKeyPassphrase() throws AliasServiceException {
+        return new char[0];
+      }
+
+      @Override
+      public char[] getSigningKeystorePassword() throws AliasServiceException {
+        return new char[0];
+      }
     };
     cs = new DefaultCryptoService();
     ((DefaultCryptoService)cs).setAliasService(as);
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
index 4b0ea28..07faa11 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
@@ -52,15 +52,20 @@ public class DefaultTokenAuthorityServiceTest {
       basedir = new File(".").getCanonicalPath();
     }
 
-    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes");
-    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks");
+    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes").anyTimes();
+    EasyMock.expect(config.getGatewayKeystoreDir()).andReturn(basedir + 
"/target/test-classes/keystores").anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks").anyTimes();
+    EasyMock.expect(config.getSigningKeystorePath()).andReturn(basedir + 
"/target/test-classes/keystores/server-keystore.jks").anyTimes();
+    
EasyMock.expect(config.getSigningKeystorePasswordAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeyPassphraseAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreType()).andReturn("jks").anyTimes();
     
EasyMock.expect(config.getSigningKeyAlias()).andReturn("server").anyTimes();
 
     MasterService ms = EasyMock.createNiceMock(MasterService.class);
     EasyMock.expect(ms.getMasterSecret()).andReturn("horton".toCharArray());
 
     AliasService as = EasyMock.createNiceMock(AliasService.class);
-    
EasyMock.expect(as.getGatewayIdentityPassphrase()).andReturn("horton".toCharArray());
+    
EasyMock.expect(as.getSigningKeyPassphrase()).andReturn("horton".toCharArray()).anyTimes();
 
     EasyMock.replay(principal, config, ms, as);
 
@@ -93,15 +98,20 @@ public class DefaultTokenAuthorityServiceTest {
       basedir = new File(".").getCanonicalPath();
     }
 
-    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes");
-    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks");
+    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes").anyTimes();
+    EasyMock.expect(config.getGatewayKeystoreDir()).andReturn(basedir + 
"/target/test-classes/keystores").anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks").anyTimes();
+    EasyMock.expect(config.getSigningKeystorePath()).andReturn(basedir + 
"/target/test-classes/keystores/server-keystore.jks").anyTimes();
+    
EasyMock.expect(config.getSigningKeystorePasswordAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeyPassphraseAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreType()).andReturn("jks").anyTimes();
     
EasyMock.expect(config.getSigningKeyAlias()).andReturn("server").anyTimes();
 
     MasterService ms = EasyMock.createNiceMock(MasterService.class);
     EasyMock.expect(ms.getMasterSecret()).andReturn("horton".toCharArray());
 
     AliasService as = EasyMock.createNiceMock(AliasService.class);
-    
EasyMock.expect(as.getGatewayIdentityPassphrase()).andReturn("horton".toCharArray());
+    
EasyMock.expect(as.getSigningKeyPassphrase()).andReturn("horton".toCharArray()).anyTimes();
 
     EasyMock.replay(principal, config, ms, as);
 
@@ -135,15 +145,20 @@ public class DefaultTokenAuthorityServiceTest {
       basedir = new File(".").getCanonicalPath();
     }
 
-    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes");
-    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks");
+    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes").anyTimes();
+    EasyMock.expect(config.getGatewayKeystoreDir()).andReturn(basedir + 
"/target/test-classes/keystores").anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks").anyTimes();
+    EasyMock.expect(config.getSigningKeystorePath()).andReturn(basedir + 
"/target/test-classes/keystores/server-keystore.jks").anyTimes();
+    
EasyMock.expect(config.getSigningKeystorePasswordAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeyPassphraseAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreType()).andReturn("jks").anyTimes();
     
EasyMock.expect(config.getSigningKeyAlias()).andReturn("server").anyTimes();
 
     MasterService ms = EasyMock.createNiceMock(MasterService.class);
     EasyMock.expect(ms.getMasterSecret()).andReturn("horton".toCharArray());
 
     AliasService as = EasyMock.createNiceMock(AliasService.class);
-    
EasyMock.expect(as.getGatewayIdentityPassphrase()).andReturn("horton".toCharArray());
+    
EasyMock.expect(as.getSigningKeyPassphrase()).andReturn("horton".toCharArray()).anyTimes();
 
     EasyMock.replay(principal, config, ms, as);
 
@@ -176,15 +191,20 @@ public class DefaultTokenAuthorityServiceTest {
       basedir = new File(".").getCanonicalPath();
     }
 
-    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes");
-    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks");
+    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes").anyTimes();
+    EasyMock.expect(config.getGatewayKeystoreDir()).andReturn(basedir + 
"/target/test-classes/keystores").anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks").anyTimes();
+    EasyMock.expect(config.getSigningKeystorePath()).andReturn(basedir + 
"/target/test-classes/keystores/server-keystore.jks").anyTimes();
+    
EasyMock.expect(config.getSigningKeystorePasswordAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeyPassphraseAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreType()).andReturn("jks").anyTimes();
     
EasyMock.expect(config.getSigningKeyAlias()).andReturn("server").anyTimes();
 
     MasterService ms = EasyMock.createNiceMock(MasterService.class);
     EasyMock.expect(ms.getMasterSecret()).andReturn("horton".toCharArray());
 
     AliasService as = EasyMock.createNiceMock(AliasService.class);
-    
EasyMock.expect(as.getGatewayIdentityPassphrase()).andReturn("horton".toCharArray());
+    
EasyMock.expect(as.getSigningKeyPassphrase()).andReturn("horton".toCharArray()).anyTimes();
 
     EasyMock.replay(principal, config, ms, as);
 
@@ -218,15 +238,20 @@ public class DefaultTokenAuthorityServiceTest {
       basedir = new File(".").getCanonicalPath();
     }
 
-    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes");
-    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks");
+    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes").anyTimes();
+    EasyMock.expect(config.getGatewayKeystoreDir()).andReturn(basedir + 
"/target/test-classes/keystores").anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks").anyTimes();
+    EasyMock.expect(config.getSigningKeystorePath()).andReturn(basedir + 
"/target/test-classes/keystores/server-keystore.jks").anyTimes();
+    
EasyMock.expect(config.getSigningKeystorePasswordAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeyPassphraseAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreType()).andReturn("jks").anyTimes();
     
EasyMock.expect(config.getSigningKeyAlias()).andReturn("server").anyTimes();
 
     MasterService ms = EasyMock.createNiceMock(MasterService.class);
     EasyMock.expect(ms.getMasterSecret()).andReturn("horton".toCharArray());
 
     AliasService as = EasyMock.createNiceMock(AliasService.class);
-    
EasyMock.expect(as.getGatewayIdentityPassphrase()).andReturn("horton".toCharArray());
+    
EasyMock.expect(as.getSigningKeyPassphrase()).andReturn("horton".toCharArray()).anyTimes();
 
     EasyMock.replay(principal, config, ms, as);
 
@@ -266,15 +291,20 @@ public class DefaultTokenAuthorityServiceTest {
       basedir = new File(".").getCanonicalPath();
     }
 
-    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes");
-    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks");
+    EasyMock.expect(config.getGatewaySecurityDir()).andReturn(basedir + 
"/target/test-classes").anyTimes();
+    EasyMock.expect(config.getGatewayKeystoreDir()).andReturn(basedir + 
"/target/test-classes/keystores").anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreName()).andReturn("server-keystore.jks").anyTimes();
+    EasyMock.expect(config.getSigningKeystorePath()).andReturn(basedir + 
"/target/test-classes/keystores/server-keystore.jks").anyTimes();
+    
EasyMock.expect(config.getSigningKeystorePasswordAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeyPassphraseAlias()).andReturn(GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS).anyTimes();
+    
EasyMock.expect(config.getSigningKeystoreType()).andReturn("jks").anyTimes();
     
EasyMock.expect(config.getSigningKeyAlias()).andReturn("server").anyTimes();
 
     MasterService ms = EasyMock.createNiceMock(MasterService.class);
     EasyMock.expect(ms.getMasterSecret()).andReturn("horton".toCharArray());
 
     AliasService as = EasyMock.createNiceMock(AliasService.class);
-    
EasyMock.expect(as.getGatewayIdentityPassphrase()).andReturn("horton".toCharArray());
+    
EasyMock.expect(as.getSigningKeyPassphrase()).andReturn("horton".toCharArray()).anyTimes();
 
     EasyMock.replay(principal, config, ms, as);
 
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
index 7d3a6be..456d548 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
@@ -17,6 +17,13 @@
  */
 package org.apache.knox.gateway.websockets;
 
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEYSTORE_TYPE;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_TYPE;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS;
+
 import com.mycila.xmltool.XMLDoc;
 import com.mycila.xmltool.XMLTag;
 import org.apache.commons.io.FileUtils;
@@ -50,6 +57,8 @@ import java.io.OutputStream;
 import java.net.URI;
 import java.net.URL;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -67,6 +76,8 @@ import java.util.concurrent.TimeUnit;
  */
 public class BadUrlTest {
 
+  private static final String TEST_KEY_ALIAS = "test-identity";
+
   /**
    * Non-existant backend websocket server
    */
@@ -90,6 +101,10 @@ public class BadUrlTest {
   private static URI serverUri;
 
   private static File topoDir;
+  private static Path dataDir;
+  private static Path securityDir;
+  private static Path keystoresDir;
+  private static Path keystoreFile;
 
   public BadUrlTest() {
     super();
@@ -97,6 +112,12 @@ public class BadUrlTest {
 
   @BeforeClass
   public static void setUpBeforeClass() throws Exception {
+    topoDir = createDir();
+    dataDir = Paths.get(topoDir.getAbsolutePath(), "data").toAbsolutePath();
+    securityDir = dataDir.resolve("security");
+    keystoresDir = securityDir.resolve("keystores");
+    keystoreFile = keystoresDir.resolve("tls.jks");
+
     startGatewayServer();
   }
 
@@ -170,7 +191,6 @@ public class BadUrlTest {
       throws IOException {
     services = new DefaultGatewayServices();
 
-    topoDir = createDir();
     URL serviceUrl = ClassLoader.getSystemResource("websocket-services");
 
     final File descriptor = new File(topoDir, "websocket.xml");
@@ -200,9 +220,6 @@ public class BadUrlTest {
     EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048")
         .anyTimes();
 
-    EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
-        .andReturn(topoDir.toString()).anyTimes();
-
     /* Websocket configs */
     EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true)
         .anyTimes();
@@ -240,6 +257,58 @@ public class BadUrlTest {
             .andReturn(Collections.emptyList())
             .anyTimes();
 
+    EasyMock.expect(gatewayConfig.getGatewayDataDir())
+        .andReturn(dataDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
+        .andReturn(securityDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getGatewayKeystoreDir())
+        .andReturn(keystoresDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystorePath())
+        .andReturn(keystoreFile.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystoreType())
+        .andReturn(DEFAULT_IDENTITY_KEYSTORE_TYPE)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystorePasswordAlias())
+        .andReturn(DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeyAlias())
+        .andReturn(TEST_KEY_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeyPassphraseAlias())
+        .andReturn(DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystorePasswordAlias())
+        .andReturn(DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeyPassphraseAlias())
+        .andReturn(DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystorePath())
+        .andReturn(keystoreFile.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystoreType())
+        .andReturn(DEFAULT_SIGNING_KEYSTORE_TYPE)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeyAlias())
+        .andReturn(TEST_KEY_ALIAS)
+        .anyTimes();
+
     EasyMock.replay(gatewayConfig);
 
     try {
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
index 80c6458..076d084 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
@@ -48,6 +48,8 @@ import java.io.OutputStream;
 import java.net.URI;
 import java.net.URL;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -56,6 +58,12 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEYSTORE_TYPE;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_TYPE;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
@@ -80,6 +88,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
  * @since 0.10
  */
 public class WebsocketEchoTest {
+  private static final String TEST_KEY_ALIAS = "test-identity";
 
   /**
    * Simulate backend websocket
@@ -108,6 +117,10 @@ public class WebsocketEchoTest {
   private static URI serverUri;
 
   private static File topoDir;
+  private static Path dataDir;
+  private static Path securityDir;
+  private static Path keystoresDir;
+  private static Path keystoreFile;
 
   public WebsocketEchoTest() {
     super();
@@ -115,6 +128,12 @@ public class WebsocketEchoTest {
 
   @BeforeClass
   public static void setUpBeforeClass() throws Exception {
+    topoDir = createDir();
+    dataDir = Paths.get(topoDir.getAbsolutePath(), "data").toAbsolutePath();
+    securityDir = dataDir.resolve("security");
+    keystoresDir = securityDir.resolve("keystores");
+    keystoreFile = keystoresDir.resolve("tls.jks");
+
     startWebsocketServer();
     startGatewayServer();
   }
@@ -255,7 +274,6 @@ public class WebsocketEchoTest {
   private static void setupGatewayConfig(final String backend) throws 
IOException {
     services = new DefaultGatewayServices();
 
-    topoDir = createDir();
     URL serviceUrl = ClassLoader.getSystemResource("websocket-services");
 
     final File descriptor = new File(topoDir, "websocket.xml");
@@ -285,9 +303,6 @@ public class WebsocketEchoTest {
     EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048")
         .anyTimes();
 
-    EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
-        .andReturn(topoDir.toString()).anyTimes();
-
     /* Websocket configs */
     EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true)
         .anyTimes();
@@ -325,6 +340,59 @@ public class WebsocketEchoTest {
             .andReturn(Collections.emptyList())
             .anyTimes();
 
+    EasyMock.expect(gatewayConfig.getGatewayDataDir())
+        .andReturn(dataDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
+        .andReturn(securityDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getGatewayKeystoreDir())
+        .andReturn(keystoresDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystorePath())
+        .andReturn(keystoreFile.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystoreType())
+        .andReturn(DEFAULT_IDENTITY_KEYSTORE_TYPE)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystorePasswordAlias())
+        .andReturn(DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeyAlias())
+        .andReturn(TEST_KEY_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeyPassphraseAlias())
+        .andReturn(DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystorePasswordAlias())
+        .andReturn(DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeyPassphraseAlias())
+        .andReturn(DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystorePath())
+        .andReturn(keystoreFile.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystoreType())
+        .andReturn(DEFAULT_SIGNING_KEYSTORE_TYPE)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeyAlias())
+        .andReturn(TEST_KEY_ALIAS)
+        .anyTimes();
+
+
     EasyMock.replay(gatewayConfig);
 
     try {
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
index ce064eb..2637922 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
@@ -17,6 +17,13 @@
  */
 package org.apache.knox.gateway.websockets;
 
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEYSTORE_TYPE;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEYSTORE_TYPE;
+import static 
org.apache.knox.gateway.config.GatewayConfig.DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS;
+
 import com.mycila.xmltool.XMLDoc;
 import com.mycila.xmltool.XMLTag;
 import org.apache.commons.io.FileUtils;
@@ -52,6 +59,8 @@ import java.io.OutputStream;
 import java.net.URI;
 import java.net.URL;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -66,6 +75,8 @@ import java.util.concurrent.TimeUnit;
  *
  */
 public class WebsocketMultipleConnectionTest {
+  private static final String TEST_KEY_ALIAS = "test-identity";
+
   /**
    * Simulate backend websocket
    */
@@ -93,6 +104,10 @@ public class WebsocketMultipleConnectionTest {
   private static URI serverUri;
 
   private static File topoDir;
+  private static Path dataDir;
+  private static Path securityDir;
+  private static Path keystoresDir;
+  private static Path keystoreFile;
 
   /**
    * Maximum number of open connections to test.
@@ -105,6 +120,11 @@ public class WebsocketMultipleConnectionTest {
 
   @BeforeClass
   public static void startServers() throws Exception {
+    topoDir = createDir();
+    dataDir = Paths.get(topoDir.getAbsolutePath(), "data").toAbsolutePath();
+    securityDir = dataDir.resolve("security");
+    keystoresDir = securityDir.resolve("keystores");
+    keystoreFile = keystoresDir.resolve("tls.jks");
 
     startWebsocketServer();
     startGatewayServer();
@@ -231,7 +251,6 @@ public class WebsocketMultipleConnectionTest {
       throws IOException {
     services = new DefaultGatewayServices();
 
-    topoDir = createDir();
     URL serviceUrl = ClassLoader.getSystemResource("websocket-services");
 
     final File descriptor = new File(topoDir, "websocket.xml");
@@ -261,9 +280,6 @@ public class WebsocketMultipleConnectionTest {
     EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048")
         .anyTimes();
 
-    EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
-        .andReturn(topoDir.toString()).anyTimes();
-
     /* Websocket configs */
     EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true)
         .anyTimes();
@@ -301,6 +317,58 @@ public class WebsocketMultipleConnectionTest {
             .andReturn(Collections.emptyList())
             .anyTimes();
 
+    EasyMock.expect(gatewayConfig.getGatewayDataDir())
+        .andReturn(dataDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
+        .andReturn(securityDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getGatewayKeystoreDir())
+        .andReturn(keystoresDir.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystorePath())
+        .andReturn(keystoreFile.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystoreType())
+        .andReturn(DEFAULT_IDENTITY_KEYSTORE_TYPE)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeystorePasswordAlias())
+        .andReturn(DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeyAlias())
+        .andReturn(TEST_KEY_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getIdentityKeyPassphraseAlias())
+        .andReturn(DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystorePasswordAlias())
+        .andReturn(DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeyPassphraseAlias())
+        .andReturn(DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystorePath())
+        .andReturn(keystoreFile.toString())
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeystoreType())
+        .andReturn(DEFAULT_SIGNING_KEYSTORE_TYPE)
+        .anyTimes();
+
+    EasyMock.expect(gatewayConfig.getSigningKeyAlias())
+        .andReturn(TEST_KEY_ALIAS)
+        .anyTimes();
+
     EasyMock.replay(gatewayConfig);
 
     try {
diff --git 
a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
 
b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
index c9362f5..2719c63 100644
--- 
a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
+++ 
b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
@@ -178,11 +178,11 @@ public class TokenResource {
     long expires = getExpiry();
 
     if (endpointPublicCert == null) {
-      // acquire PEM for gateway-identity of this gateway instance
+      // acquire PEM for gateway identity of this gateway instance
       KeystoreService ks = 
services.getService(GatewayServices.KEYSTORE_SERVICE);
       if (ks != null) {
         try {
-          Certificate cert = 
ks.getKeystoreForGateway().getCertificate("gateway-identity");
+          Certificate cert = ks.getCertificateForGateway();
           byte[] bytes = cert.getEncoded();
           //Base64 encoder = new Base64(76, "\n".getBytes("ASCII"));
           endpointPublicCert = Base64.encodeBase64String(bytes);
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java 
b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java
index c13ece5..93f17ac 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java
@@ -39,8 +39,27 @@ public interface GatewayConfig {
   String KRB5_DEBUG = "sun.security.krb5.debug";
   String KRB5_LOGIN_CONFIG = "java.security.auth.login.config";
   String KRB5_USE_SUBJECT_CREDS_ONLY = 
"javax.security.auth.useSubjectCredsOnly";
+
+  String IDENTITY_KEYSTORE_PASSWORD_ALIAS = 
"gateway.tls.keystore.password.alias";
+  String IDENTITY_KEYSTORE_PATH = "gateway.tls.keystore.path";
+  String IDENTITY_KEYSTORE_TYPE = "gateway.tls.keystore.type";
+  String IDENTITY_KEY_ALIAS = "gateway.tls.key.alias";
+  String IDENTITY_KEY_PASSPHRASE_ALIAS = "gateway.tls.key.passphrase.alias";
+  String DEFAULT_IDENTITY_KEYSTORE_TYPE = "JKS";
+  String DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS = 
"gateway-identity-keystore-password";
+  String DEFAULT_IDENTITY_KEY_ALIAS = "gateway-identity";
+  String DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS = "gateway-identity-passphrase";
+  String DEFAULT_GATEWAY_KEYSTORE_NAME = "gateway.jks";
+
   String SIGNING_KEYSTORE_NAME = "gateway.signing.keystore.name";
+  String SIGNING_KEYSTORE_PASSWORD_ALIAS = 
"gateway.signing.keystore.password.alias";
+  String SIGNING_KEYSTORE_TYPE = "gateway.signing.keystore.type";
   String SIGNING_KEY_ALIAS = "gateway.signing.key.alias";
+  String SIGNING_KEY_PASSPHRASE_ALIAS = "gateway.signing.key.passphrase.alias";
+  String DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS = "signing.keystore.password";
+  String DEFAULT_SIGNING_KEYSTORE_TYPE = "JKS";
+  String DEFAULT_SIGNING_KEY_ALIAS = "gateway-identity";
+  String DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS = "signing.key.passphrase";
 
   String REMOTE_CONFIG_REGISTRY_TYPE = "type";
   String REMOTE_CONFIG_REGISTRY_ADDRESS = "address";
@@ -94,6 +113,16 @@ public interface GatewayConfig {
 
   String getGatewaySecurityDir();
 
+  /**
+   * Returns the path to the Gateway's keystore directory
+   * <p>
+   * This path is generally calculated to be a subdirectory named "keystores" 
under the configured
+   * "security" directory. However, it may be possible for it to be configured 
as something else.
+   *
+   * @return the path to the Gateway's keystore directory
+   */
+  String getGatewayKeystoreDir();
+
   String getGatewayDeploymentDir();
 
   InetSocketAddress getGatewayAddress() throws UnknownHostException;
@@ -158,10 +187,81 @@ public interface GatewayConfig {
 
   long getGatewayIdleTimeout();
 
+  /**
+   * Returns the configured value for the path to the keystore holding the key 
and certificate for the
+   * Gateway's TLS identity.
+   *
+   * @return a path to the keystore file; or <code>null</code> if not set
+   */
+  String getIdentityKeystorePath();
+
+  /**
+   * Returns the configured value for the type of the keystore holding the 
Gateway's identity.
+   *
+   * @return a keystore type
+   */
+  String getIdentityKeystoreType();
+
+  /**
+   * Returns the configured value for the alias name to use when to looking up 
the Gateway's identity
+   * keystore's password.
+   *
+   * @return an alias name
+   */
+  String getIdentityKeystorePasswordAlias();
+
+  /**
+   * Returns the configured value for the alias name to use when to looking up 
the Gateway's identity
+   * from the Gateway's identity keystore.
+   *
+   * @return an alias name
+   */
+  String getIdentityKeyAlias();
+
+  /**
+   * Returns the configured value for the alias name to use when to looking up 
the Gateway's identity
+   * key's password.
+   *
+   * @return an alias name
+   */
+  String getIdentityKeyPassphraseAlias();
+
   String getSigningKeystoreName();
 
+  /**
+   * Returns the calculated value for the path to the keystore holding the key 
and certificate for the
+   * Gateway's signing key.
+   *
+   * @return a path to the keystore file; or <code>null</code> if not set
+   */
+  String getSigningKeystorePath();
+
+  /**
+   * Returns the configured value for the type of the keystore holding the 
Gateway's signing key.
+   *
+   * @return a keystore type
+   */
+  String getSigningKeystoreType();
+
   String getSigningKeyAlias();
 
+  /**
+   * Returns the configured value for the alias name to use when to looking up 
the Gateway's signing
+   * keystore's password.
+   *
+   * @return an alias name
+   */
+  String getSigningKeystorePasswordAlias();
+
+  /**
+   * Returns the configured value for the alias name to use when to looking up 
the signing key's
+   * password.
+   *
+   * @return an alias name
+   */
+  String getSigningKeyPassphraseAlias();
+
+
   List<String> getGlobalRulesServices();
 
   /**
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/AliasService.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/AliasService.java
index 29fdc44..7a7f76d 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/AliasService.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/AliasService.java
@@ -47,6 +47,12 @@ public interface AliasService extends Service {
 
   char[] getGatewayIdentityPassphrase() throws AliasServiceException;
 
+  char[] getGatewayIdentityKeystorePassword() throws AliasServiceException;
+
+  char[] getSigningKeyPassphrase() throws AliasServiceException;
+
+  char[] getSigningKeystorePassword() throws AliasServiceException;
+
   void generateAliasForGateway(String alias)
       throws AliasServiceException;
 
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/CryptoService.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/CryptoService.java
index e2ccd2a..0e927bd 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/CryptoService.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/CryptoService.java
@@ -28,7 +28,7 @@ public interface CryptoService extends Service {
 
   byte[] decryptForCluster(String clusterName, String alias, byte[] 
cipherText, byte[] iv, byte[] salt);
 
-  boolean verify(String algorithm, String alias, String payloadToSign, byte[] 
signaturePayload);
+  boolean verify(String algorithm, String payloadToSign, byte[] 
signaturePayload);
 
-  byte[] sign(String algorithm, String alias, String payloadToSign);
+  byte[] sign(String algorithm, String payloadToSign);
 }
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/KeystoreService.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/KeystoreService.java
index 5c21d90..a1a843f 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/KeystoreService.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/KeystoreService.java
@@ -19,6 +19,8 @@ package org.apache.knox.gateway.services.security;
 
 import java.security.Key;
 import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
 
 public interface KeystoreService {
 
@@ -36,6 +38,10 @@ public interface KeystoreService {
 
   Key getKeyForGateway(String alias, char[] passphrase) throws 
KeystoreServiceException;
 
+  Key getKeyForGateway(char[] passphrase) throws KeystoreServiceException;
+
+  Certificate getCertificateForGateway() throws KeystoreServiceException, 
KeyStoreException;
+
   Key getSigningKey(String alias, char[] passphrase) throws 
KeystoreServiceException;
 
   Key getSigningKey(String keystoreName, String alias, char[] passphrase) 
throws KeystoreServiceException;
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/SSLService.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/SSLService.java
index 5704d32..3a6874d 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/SSLService.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/SSLService.java
@@ -25,5 +25,5 @@ import java.security.cert.CertificateException;
 import org.apache.knox.gateway.services.Service;
 
 public interface SSLService extends Service {
-  Object buildSslContextFactory(String gatewayHomeDir) throws 
KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException;
+  Object buildSslContextFactory(String keystoreFileName, String keystoreType, 
String alias) throws KeyStoreException, IOException, CertificateException, 
NoSuchAlgorithmException;
 }
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/BaseKeystoreService.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/BaseKeystoreService.java
index d69b678..ffa5759 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/BaseKeystoreService.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/BaseKeystoreService.java
@@ -78,22 +78,22 @@ public class BaseKeystoreService {
     return Files.newOutputStream( file.toPath() );
   }
 
-  protected void createKeystore(String filename, String keystoreType) throws 
KeystoreServiceException {
+  protected void createKeystore(String filename, String keystoreType, char[] 
password) throws KeystoreServiceException {
     try (OutputStream out = createKeyStoreFile( filename )) {
       KeyStore ks = KeyStore.getInstance(keystoreType);
       ks.load( null, null );
-      ks.store( out, masterService.getMasterSecret() );
+      ks.store( out, password );
     } catch (NoSuchAlgorithmException | CertificateException | 
KeyStoreException | IOException e) {
       LOG.failedToCreateKeystore( filename, keystoreType, e );
       throw new KeystoreServiceException(e);
     }
   }
 
-  protected boolean isKeystoreAvailable(final File keyStoreFile, String 
storeType) throws KeyStoreException, IOException {
+  protected boolean isKeystoreAvailable(final File keyStoreFile, String 
storeType, char[] password) throws KeyStoreException, IOException {
     if ( keyStoreFile.exists() ) {
       try (InputStream input = Files.newInputStream(keyStoreFile.toPath())){
         final KeyStore keyStore = KeyStore.getInstance(storeType);
-        keyStore.load( input, masterService.getMasterSecret() );
+        keyStore.load( input, password );
         return true;
       } catch (NoSuchAlgorithmException | CertificateException e) {
         LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
@@ -105,10 +105,10 @@ public class BaseKeystoreService {
     return false;
   }
 
-  protected KeyStore getKeystore(final File keyStoreFile, String storeType) 
throws KeystoreServiceException {
+  protected KeyStore getKeystore(final File keyStoreFile, String storeType, 
char[] password) throws KeystoreServiceException {
     KeyStore credStore;
     try {
-      credStore = loadKeyStore( keyStoreFile, masterService.getMasterSecret(), 
storeType);
+      credStore = loadKeyStore( keyStoreFile, password, storeType);
     } catch (CertificateException | IOException | NoSuchAlgorithmException | 
KeyStoreException e) {
       LOG.failedToLoadKeystore( keyStoreFile.getName(), storeType, e );
       throw new KeystoreServiceException(e);
@@ -164,11 +164,11 @@ public class BaseKeystoreService {
     }
   }
 
-  protected void writeKeystoreToFile(final KeyStore keyStore, final File file)
+  protected void writeKeystoreToFile(final KeyStore keyStore, final File file, 
char[] password)
       throws KeyStoreException, IOException, NoSuchAlgorithmException, 
CertificateException {
      // TODO: backup the keystore on disk before attempting a write and 
restore on failure
      try( OutputStream out = Files.newOutputStream(file.toPath()) ) {
-         keyStore.store( out, masterService.getMasterSecret() );
+         keyStore.store( out, password );
      }
   }
 
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFKeystoreService.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFKeystoreService.java
index 854ccd0..8d86eab 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFKeystoreService.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFKeystoreService.java
@@ -55,12 +55,12 @@ public class CMFKeystoreService extends BaseKeystoreService 
{
 
   public void createKeystore() throws KeystoreServiceException {
     String filename = keyStoreDir + serviceName + ".jks";
-    createKeystore(filename, "JKS");
+    createKeystore(filename, "JKS", masterService.getMasterSecret());
   }
 
   public KeyStore getKeystore() throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + serviceName  );
-    return getKeystore(keyStoreFile, "JKS");
+    return getKeystore(keyStoreFile, "JKS", masterService.getMasterSecret());
   }
 
   public void addSelfSignedCert(String alias, char[] passphrase)
@@ -77,7 +77,7 @@ public class CMFKeystoreService extends BaseKeystoreService {
         privateKS.setKeyEntry(alias, KPair.getPrivate(),
           passphrase,
           new java.security.cert.Certificate[]{cert});
-        writeKeystoreToFile(privateKS, new File( keyStoreDir + serviceName  ));
+        writeKeystoreToFile(privateKS, new File( keyStoreDir + serviceName  ), 
masterService.getMasterSecret());
       } else {
         throw new IOException("Unable to open gateway keystore.");
       }
@@ -88,13 +88,13 @@ public class CMFKeystoreService extends BaseKeystoreService 
{
 
   public void createCredentialStore() throws KeystoreServiceException {
     String filename = keyStoreDir + serviceName + CREDENTIALS_SUFFIX;
-    createKeystore(filename, "JCEKS");
+    createKeystore(filename, "JCEKS", masterService.getMasterSecret());
   }
 
   public boolean isCredentialStoreAvailable() throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + serviceName + 
CREDENTIALS_SUFFIX  );
     try {
-      return isKeystoreAvailable(keyStoreFile, "JCEKS");
+      return isKeystoreAvailable(keyStoreFile, "JCEKS", 
masterService.getMasterSecret());
     } catch (KeyStoreException | IOException e) {
       throw new KeystoreServiceException(e);
     }
@@ -103,7 +103,7 @@ public class CMFKeystoreService extends BaseKeystoreService 
{
   public boolean isKeystoreAvailable() throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + serviceName + ".jks" );
     try {
-      return isKeystoreAvailable(keyStoreFile, "JKS");
+      return isKeystoreAvailable(keyStoreFile, "JKS", 
masterService.getMasterSecret());
     } catch (KeyStoreException | IOException e) {
       throw new KeystoreServiceException(e);
     }
@@ -124,7 +124,7 @@ public class CMFKeystoreService extends BaseKeystoreService 
{
 
   public KeyStore getCredentialStore() throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + serviceName + 
CREDENTIALS_SUFFIX  );
-    return getKeystore(keyStoreFile, "JCEKS");
+    return getKeystore(keyStoreFile, "JCEKS", masterService.getMasterSecret());
   }
 
   public void addCredential(String alias, String value) throws 
KeystoreServiceException {
@@ -132,7 +132,7 @@ public class CMFKeystoreService extends BaseKeystoreService 
{
     addCredential(alias, value, ks);
     final File  keyStoreFile = new File( keyStoreDir + serviceName + 
CREDENTIALS_SUFFIX  );
     try {
-      writeKeystoreToFile(ks, keyStoreFile);
+      writeKeystoreToFile(ks, keyStoreFile, masterService.getMasterSecret());
     } catch (KeyStoreException | NoSuchAlgorithmException | 
CertificateException | IOException e) {
       LOG.failedToAddCredential(e);
     }
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/X509CertificateUtil.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/X509CertificateUtil.java
index 8e0a370..7e9e20c 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/X509CertificateUtil.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/X509CertificateUtil.java
@@ -312,5 +312,21 @@ public class X509CertificateUtil {
     writeCertificateToKeyStore(cert, file, "pkcs12");
   }
 
+  /**
+   * Tests the X509 certificate to see if it was self-signed.
+   * <p>
+   * The certificate is determined to be self-signed if the subject DN is the 
same as the issuer DN
+   *
+   * @param certificate the {@link X509Certificate} to test
+   * @return <code>true</code> if the X509 certficate is self-signed; 
otherwise <code>false</code>
+   */
+  public static boolean isSelfSignedCertificate(Certificate certificate) {
+    if (certificate instanceof X509Certificate) {
+      X509Certificate x509Certificate = (X509Certificate) certificate;
+      return 
x509Certificate.getSubjectDN().equals(x509Certificate.getIssuerDN());
+    } else {
+      return false;
+    }
+  }
 }
 
diff --git 
a/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
 
b/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
index ed89a2f..35b0ce9 100644
--- 
a/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
+++ 
b/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java
@@ -22,9 +22,11 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
 
-import java.io.File;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -44,15 +46,15 @@ public class GatewayTestConfig extends Configuration 
implements GatewayConfig {
   public static final int DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT = 60000;
   public static final int DEFAULT_WEBSOCKET_IDLE_TIMEOUT = 300000;
 
-  private String gatewayHomeDir = "gateway-home";
+  private Path gatewayHomePath = Paths.get("gateway-home");
   private String hadoopConfDir = "hadoop";
   private String gatewayHost = "localhost";
   private int gatewayPort;
   private String gatewayPath = "gateway";
   private boolean hadoopKerberosSecured;
-  private String kerberosConfig = "/etc/knox/conf/krb5.conf";
+  private String kerberosConfig;
   private boolean kerberosDebugEnabled;
-  private String kerberosLoginConfig = "/etc/knox/conf/krb5JAASLogin.conf";
+  private String kerberosLoginConfig;
   private String frontendUrl;
   private boolean xForwardedEnabled = true;
   private String gatewayApplicationsDir;
@@ -68,37 +70,80 @@ public class GatewayTestConfig extends Configuration 
implements GatewayConfig {
   private int backupVersionLimit = -1;
   private long backupAgeLimit = -1;
 
+  public GatewayTestConfig() {
+
+    Iterable<Path> paths = FileSystems.getDefault().getRootDirectories();
+    Path rootPath = null;
+    for (Path path : paths) {
+      rootPath = path;
+    }
+    if (rootPath == null) {
+      rootPath = Paths.get("/");
+    }
+
+    // /etc/knox/conf
+    Path etcConfKnoxPath = 
rootPath.resolve("etc").resolve("knox").resolve("conf");
+
+    // /etc/knox/conf/krb5.conf
+    kerberosConfig = etcConfKnoxPath.resolve("krb5.conf").toString();
+
+    // /etc/knox/conf/krb5JAASLogin.conf
+    kerberosLoginConfig = 
etcConfKnoxPath.resolve("krb5JAASLogin.conf").toString();
+  }
+
+
   public void setGatewayHomeDir( String gatewayHomeDir ) {
-    this.gatewayHomeDir = gatewayHomeDir;
+    this.gatewayHomePath = Paths.get(gatewayHomeDir);
   }
 
   public String getGatewayHomeDir() {
-    return this.gatewayHomeDir;
+    return gatewayHomePath.toString();
   }
 
   @Override
   public String getGatewayConfDir() {
-    return gatewayHomeDir;
+    return getGatewayConfPath().toString();
+  }
+
+  private Path getGatewayConfPath() {
+    return gatewayHomePath.resolve("conf");
   }
 
   @Override
   public String getGatewayDataDir() {
-    return gatewayHomeDir;
+    return getGatewayDataPath().toString();
+  }
+
+  private Path getGatewayDataPath() {
+    return gatewayHomePath.resolve("data");
   }
 
   @Override
   public String getGatewaySecurityDir() {
-    return gatewayHomeDir + "/security";
+    return getGatewaySecurityPath().toString();
+  }
+
+  private Path getGatewaySecurityPath() {
+    return getGatewayDataPath().resolve("security");
+  }
+
+  @Override
+  public String getGatewayKeystoreDir() {
+    return getGatewayKeystorePath().toString();
+  }
+
+  private Path getGatewayKeystorePath() {
+    return getGatewayDataPath().resolve("keystores");
   }
 
   @Override
   public String getGatewayTopologyDir() {
-    return gatewayHomeDir + "/topologies";
+    return gatewayHomePath.resolve("topologies").toString();
   }
 
   @Override
   public String getGatewayDeploymentDir() {
-    return gatewayHomeDir + "/deployments";
+    return gatewayHomePath.resolve("deployments").toString();
   }
 
   @Override
@@ -136,6 +181,31 @@ public class GatewayTestConfig extends Configuration 
implements GatewayConfig {
   }
 
   @Override
+  public String getIdentityKeystorePath() {
+    return 
getGatewayKeystorePath().resolve(DEFAULT_GATEWAY_KEYSTORE_NAME).toString();
+  }
+
+  @Override
+  public String getIdentityKeystoreType() {
+    return DEFAULT_IDENTITY_KEYSTORE_TYPE;
+  }
+
+  @Override
+  public String getIdentityKeystorePasswordAlias() {
+    return DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS;
+  }
+
+  @Override
+  public String getIdentityKeyAlias() {
+    return DEFAULT_IDENTITY_KEY_ALIAS;
+  }
+
+  @Override
+  public String getIdentityKeyPassphraseAlias() {
+    return DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS;
+  }
+
+  @Override
   public boolean isSSLEnabled() {
     return sslEnabled;
   }
@@ -268,8 +338,7 @@ public class GatewayTestConfig extends Configuration 
implements GatewayConfig {
     if( gatewayServicesDir != null ) {
       return gatewayServicesDir;
     } else {
-      File targetDir = new File( System.getProperty( "user.dir" ), 
"target/services" );
-      return targetDir.getPath();
+      return Paths.get(System.getProperty("user.dir"), "target", 
"services").toString();
     }
   }
 
@@ -282,7 +351,7 @@ public class GatewayTestConfig extends Configuration 
implements GatewayConfig {
     if( gatewayApplicationsDir != null ) {
       return gatewayApplicationsDir;
     } else {
-      return getGatewayConfDir() + "/applications";
+      return getGatewayConfPath().resolve("applications").toString();
     }
   }
 
@@ -377,8 +446,28 @@ public class GatewayTestConfig extends Configuration 
implements GatewayConfig {
   }
 
   @Override
+  public String getSigningKeystorePath() {
+    return 
getGatewayKeystorePath().resolve(DEFAULT_GATEWAY_KEYSTORE_NAME).toString();
+  }
+
+  @Override
+  public String getSigningKeystoreType() {
+    return DEFAULT_SIGNING_KEYSTORE_TYPE;
+  }
+
+  @Override
   public String getSigningKeyAlias() {
-    return null;
+    return DEFAULT_SIGNING_KEY_ALIAS;
+  }
+
+  @Override
+  public String getSigningKeystorePasswordAlias() {
+    return DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS;
+  }
+
+  @Override
+  public String getSigningKeyPassphraseAlias() {
+    return DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS;
   }
 
   @Override

Reply via email to