You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2016/03/16 02:23:38 UTC

knox git commit: KNOX-631 - Config Driven Keystore for Signing and Validation Certs in KnoxSSO

Repository: knox
Updated Branches:
  refs/heads/master 7edeac5d8 -> 51194fbbe


KNOX-631 - Config Driven Keystore for Signing and Validation Certs in KnoxSSO

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

Branch: refs/heads/master
Commit: 51194fbbe5662b16bd644d64faa450e43f771c80
Parents: 7edeac5
Author: Larry McCay <lm...@hortonworks.com>
Authored: Tue Mar 15 21:23:22 2016 -0400
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Tue Mar 15 21:23:22 2016 -0400

----------------------------------------------------------------------
 .../gateway/config/impl/GatewayConfigImpl.java  |  9 +++
 .../security/impl/DefaultKeystoreService.java   | 72 +++++++++++++++++++-
 .../impl/DefaultTokenAuthorityService.java      | 47 +++++++++++--
 .../hadoop/gateway/config/GatewayConfig.java    |  6 ++
 .../services/ServiceLifecycleException.java     |  1 -
 .../services/security/KeystoreService.java      |  6 +-
 .../security/KeystoreServiceException.java      |  3 +
 .../hadoop/gateway/GatewayTestConfig.java       | 16 +++++
 .../hadoop/gateway/GatewayTestConfig.java       | 16 +++++
 9 files changed, 166 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
index 4c0d769..711efc8 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
@@ -563,4 +563,13 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
     return d;
   }
 
+  @Override
+  public String getSigningKeystoreName() {
+    return get(SIGNING_KEYSTORE_NAME);
+  }
+
+  @Override
+  public String getSigningKeyAlias() {
+    return get(SIGNING_KEY_ALIAS);
+  }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
index 4500230..e70da53 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
@@ -55,6 +55,9 @@ public class DefaultKeystoreService extends BaseKeystoreService implements Keyst
   private static GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
   private static GatewayResources RES = ResourcesFactory.get( GatewayResources.class );
 
+  private String signingKeystoreName = null;
+  private String signingKeyAlias = null;
+
   @Override
   public void init(GatewayConfig config, Map<String, String> options)
       throws ServiceLifecycleException {
@@ -65,6 +68,32 @@ public class DefaultKeystoreService extends BaseKeystoreService implements Keyst
         throw new ServiceLifecycleException( RES.failedToCreateKeyStoreDirectory( ksd.getAbsolutePath() ) );
       }
     }
+
+    signingKeystoreName = config.getSigningKeystoreName();
+    // ensure that the keystore actually exists and fail to start if not
+    if (signingKeystoreName != null) {
+      File sks = new File(this.keyStoreDir, signingKeystoreName);
+      if (!sks.exists()) {
+        throw new ServiceLifecycleException("Configured signing keystore does not exist.");
+      }
+      signingKeyAlias = config.getSigningKeyAlias();
+      if (signingKeyAlias != null) {
+        // ensure that the signing key alias exists in the configured keystore
+        KeyStore ks;
+        try {
+          ks = getSigningKeystore();
+          if (ks != null) {
+            if (!ks.containsAlias(signingKeyAlias)) {
+              throw new ServiceLifecycleException("Configured signing key alias does not exist.");
+            }
+          }
+        } catch (KeystoreServiceException e) {
+          throw new ServiceLifecycleException("Unable to get the configured signing keystore.", e);
+        } catch (KeyStoreException e) {
+          throw new ServiceLifecycleException("Signing keystore has not been loaded.", e);
+        }
+      }
+    }
   }
 
   @Override
@@ -86,7 +115,24 @@ public class DefaultKeystoreService extends BaseKeystoreService implements Keyst
     final File  keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE  );
     return getKeystore(keyStoreFile, "JKS");
   }
-  
+
+  @Override
+  public KeyStore getSigningKeystore() throws KeystoreServiceException {
+    File  keyStoreFile = null;
+
+    if (signingKeystoreName == null) {
+      keyStoreFile = new File(keyStoreDir + GATEWAY_KEYSTORE);
+    }
+    else {
+      keyStoreFile = new File(keyStoreDir + signingKeystoreName);
+      // make sure the keystore exists
+      if (!keyStoreFile.exists()) {
+        throw new KeystoreServiceException("Configured signing keystore does not exist.");
+      }
+    }
+    return getKeystore(keyStoreFile, "JKS");
+  }
+
   @Override
   public void addSelfSignedCertForGateway(String alias, char[] passphrase) throws KeystoreServiceException {
     addSelfSignedCertForGateway(alias, passphrase, null);
@@ -196,7 +242,29 @@ public class DefaultKeystoreService extends BaseKeystoreService implements Keyst
     }
     return key;
   }  
-  
+
+  @Override
+  public Key getSigningKey(String alias, char[] passphrase) throws KeystoreServiceException {
+    Key key = null;
+    KeyStore ks = getSigningKeystore();
+    if (passphrase == null) {
+      passphrase = masterService.getMasterSecret();
+      LOG.assumingKeyPassphraseIsMaster();
+    }
+    if (ks != null) {
+      try {
+        key = ks.getKey(alias, passphrase);
+      } catch (UnrecoverableKeyException e) {
+        LOG.failedToGetKeyForGateway( alias, e );
+      } catch (KeyStoreException e) {
+        LOG.failedToGetKeyForGateway( alias, e );
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToGetKeyForGateway( alias, e );
+      }
+    }
+    return key;
+  }
+
   public KeyStore getCredentialStoreForCluster(String clusterName) 
       throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX  );

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
index 3fbc789..bd54956 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
@@ -45,9 +45,11 @@ import com.nimbusds.jose.crypto.RSASSASigner;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 
 public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
-  
+
+  private static String SIGNING_KEY_PASSPHRASE = "signing.key.passphrase";
   private AliasService as = null;
   private KeystoreService ks = null;
+  String signingKeyAlias = null;
 
   public void setKeystoreService(KeystoreService ks) {
     this.ks = ks;
@@ -108,7 +110,6 @@ public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
     claimArray[0] = "KNOXSSO";
     claimArray[1] = p.getName();
     claimArray[2] = null;
-    // TODO: make the validity period configurable
     if (expires == -1) {
       claimArray[3] = Long.toString( ( System.currentTimeMillis() ) + 30000);
     }
@@ -122,12 +123,12 @@ public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
       RSAPrivateKey key;
       char[] passphrase = null;
       try {
-        passphrase = as.getGatewayIdentityPassphrase();
+        passphrase = getSigningKeyPassphrase();
       } catch (AliasServiceException e) {
         throw new TokenServiceException(e);
       }
       try {
-        key = (RSAPrivateKey) ks.getKeyForGateway("gateway-identity", 
+        key = (RSAPrivateKey) ks.getSigningKey(getSigningKeyAlias(),
             passphrase);
         JWSSigner signer = new RSASSASigner(key);
         token.sign(signer);
@@ -138,17 +139,32 @@ public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
     else {
       throw new TokenServiceException("Cannot issue token - Unsupported algorithm");
     }
-    
+
     return token;
   }
 
+  private char[] getSigningKeyPassphrase() throws AliasServiceException {
+    char[] phrase = as.getPasswordFromAliasForGateway(SIGNING_KEY_PASSPHRASE);
+    if (phrase == null) {
+      phrase = as.getGatewayIdentityPassphrase();
+    }
+    return phrase;
+  }
+
+  private String getSigningKeyAlias() {
+    if (signingKeyAlias == null) {
+      return "gateway-identity";
+    }
+    return signingKeyAlias;
+  }
+
   @Override
   public boolean verifyToken(JWTToken token)
       throws TokenServiceException {
     boolean rc = false;
     PublicKey key;
     try {
-      key = ks.getKeystoreForGateway().getCertificate("gateway-identity").getPublicKey();
+      key = ks.getSigningKeystore().getCertificate(getSigningKeyAlias()).getPublicKey();
       JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) key);
       // TODO: interrogate the token for issuer claim in order to determine the public key to use for verification
       // consider jwk for specifying the key too
@@ -167,6 +183,25 @@ public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
     if (as == null || ks == null) {
       throw new ServiceLifecycleException("Alias or Keystore service is not set");
     }
+    signingKeyAlias = config.getSigningKeyAlias();
+
+    @SuppressWarnings("unused")
+    RSAPrivateKey key;
+    char[] passphrase = null;
+    try {
+      passphrase = as.getPasswordFromAliasForGateway(SIGNING_KEY_PASSPHRASE);
+      if (passphrase != null) {
+        key = (RSAPrivateKey) ks.getSigningKey(getSigningKeyAlias(),
+            passphrase);
+        if (key == null) {
+          throw new ServiceLifecycleException("Provisioned passphrase cannot be used to acquire signing key.");
+        }
+      }
+    } catch (AliasServiceException e) {
+      throw new ServiceLifecycleException("Provisioned signing key passphrase cannot be acquired.", e);
+    } catch (KeystoreServiceException e) {
+      throw new ServiceLifecycleException("Provisioned signing key passphrase cannot be acquired.", e);
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
index 91bd64c..5558578 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
@@ -38,6 +38,8 @@ public interface GatewayConfig {
   public static final String KRB5_DEBUG = "sun.security.krb5.debug";
   public static final String KRB5_LOGIN_CONFIG = "java.security.auth.login.config";
   public static final String KRB5_USE_SUBJECT_CREDS_ONLY = "javax.security.auth.useSubjectCredsOnly";
+  public static final String SIGNING_KEYSTORE_NAME = "gateway.signing.keystore.name";
+  public static final String SIGNING_KEY_ALIAS = "gateway.signing.key.alias";
 
   /**
    * The location of the gateway configuration.
@@ -133,4 +135,8 @@ public interface GatewayConfig {
 
   long getGatewayDeploymentsBackupAgeLimit();
 
+  String getSigningKeystoreName();
+
+  String getSigningKeyAlias();
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/ServiceLifecycleException.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/ServiceLifecycleException.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/ServiceLifecycleException.java
index 11dd81f..a7f2a3c 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/ServiceLifecycleException.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/ServiceLifecycleException.java
@@ -27,5 +27,4 @@ public class ServiceLifecycleException extends Exception {
   public ServiceLifecycleException(String message, Exception e) {
     super(message, e);
   }
-
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
index 6ed8990..f85dd35 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
@@ -29,9 +29,13 @@ public interface KeystoreService {
   void addSelfSignedCertForGateway(String alias, char[] passphrase, String hostname) throws KeystoreServiceException;
 
   public KeyStore getKeystoreForGateway() throws KeystoreServiceException;
-  
+
+  public KeyStore getSigningKeystore() throws KeystoreServiceException;
+
   public Key getKeyForGateway(String alias, char[] passphrase) throws KeystoreServiceException;
 
+  public Key getSigningKey(String alias, char[] passphrase) throws KeystoreServiceException;
+
   public void createCredentialStoreForCluster(String clusterName) throws KeystoreServiceException;
   
   public boolean isCredentialStoreForClusterAvailable(String clusterName) throws KeystoreServiceException;

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreServiceException.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreServiceException.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreServiceException.java
index 52fd26a..ef8d704 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreServiceException.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreServiceException.java
@@ -24,4 +24,7 @@ public class KeystoreServiceException extends Exception {
     super(e);
   }
 
+  public KeystoreServiceException(String message) {
+    super(message);
+  }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-test-release/webhdfs-kerb-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
----------------------------------------------------------------------
diff --git a/gateway-test-release/webhdfs-kerb-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java b/gateway-test-release/webhdfs-kerb-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
index 03ce5dc..e5be4be 100644
--- a/gateway-test-release/webhdfs-kerb-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
+++ b/gateway-test-release/webhdfs-kerb-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
@@ -319,4 +319,20 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig {
     return Long.MAX_VALUE;
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.config.GatewayConfig#getSigningKeystoreName()
+   */
+  @Override
+  public String getSigningKeystoreName() {
+    return null;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.config.GatewayConfig#getSigningKeyAlias()
+   */
+  @Override
+  public String getSigningKeyAlias() {
+    return null;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/51194fbb/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
index 1d97a54..cd71e7f 100644
--- a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
+++ b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
@@ -371,4 +371,20 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig {
     backupAgeLimit = newBackupAgeLimit;
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.config.GatewayConfig#getSigningKeystoreName()
+   */
+  @Override
+  public String getSigningKeystoreName() {
+    return null;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.config.GatewayConfig#getSigningKeyAlias()
+   */
+  @Override
+  public String getSigningKeyAlias() {
+    return null;
+  }
+
 }