Repository: knox
Updated Branches:
refs/heads/master c7f28551f -> fe84b0456
KNOX-1230 - Many Concurrent Requests to Knox causes URL Mangling
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/fe84b045
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/fe84b045
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/fe84b045
Branch: refs/heads/master
Commit: fe84b04561f6131ddc0593fb811cd1bfba21316d
Parents: c7f2855
Author: Larry McCay <lmccay@hortonworks.com>
Authored: Fri Mar 30 11:26:57 2018 -0400
Committer: Larry McCay <lmccay@hortonworks.com>
Committed: Fri Mar 30 11:26:57 2018 -0400
----------------------------------------------------------------------
.../SecureQueryDecryptProcessor.java | 30 +-
.../SecureQueryEncryptProcessor.java | 21 +-
.../securequery/SecureQueryMessages.java | 5 +
.../security/impl/DefaultCryptoService.java | 20 +-
.../security/impl/DefaultKeystoreService.java | 399 +++++++++++++------
.../dispatch/AbstractGatewayDispatch.java | 4 +-
.../knox/gateway/dispatch/DefaultDispatch.java | 2 +-
.../gateway/dispatch/GatewayDispatchFilter.java | 56 +--
.../security/impl/CMFMasterService.java | 4 +-
.../security/impl/ConfigurableEncryptor.java | 91 +----
10 files changed, 376 insertions(+), 256 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
index 3cccc4d..77e990e 100644
--- a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
+++ b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
@@ -18,13 +18,14 @@
package org.apache.knox.gateway.securequery;
import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
-import org.apache.knox.gateway.services.GatewayServices;
-import org.apache.knox.gateway.services.security.CryptoService;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.services.security.EncryptionResult;
+import org.apache.knox.gateway.services.security.impl.ConfigurableEncryptor;
import org.apache.knox.gateway.util.urltemplate.Builder;
import org.apache.knox.gateway.util.urltemplate.Query;
import org.apache.knox.gateway.util.urltemplate.Template;
@@ -36,10 +37,10 @@ import java.util.StringTokenizer;
public class SecureQueryDecryptProcessor implements
UrlRewriteStepProcessor<SecureQueryDecryptDescriptor> {
+ private static SecureQueryMessages log = MessagesFactory.get( SecureQueryMessages.class
);
private static final String ENCRYPTED_PARAMETER_NAME = "_";
- private String clusterName;
- private CryptoService cryptoService;
+ private ConfigurableEncryptor encryptor = null;
@Override
public String getType() {
@@ -48,9 +49,8 @@ public class SecureQueryDecryptProcessor implements
@Override
public void initialize( UrlRewriteEnvironment environment, SecureQueryDecryptDescriptor
descriptor ) throws Exception {
- clusterName = environment.getAttribute( GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE );
- GatewayServices services = environment.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
- cryptoService = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
+ encryptor = new ConfigurableEncryptor("encryptQueryString");
+ encryptor.init((GatewayConfig)environment.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE));
}
@Override
@@ -107,13 +107,17 @@ public class SecureQueryDecryptProcessor implements
String decode( String string ) throws UnsupportedEncodingException {
byte[] bytes = Base64.decodeBase64( string );
EncryptionResult result = EncryptionResult.fromByteArray(bytes);
- byte[] clear = cryptoService.decryptForCluster(clusterName,
- "encryptQueryString",
- result.cipher,
- result.iv,
- result.salt);
+ byte[] clear = null;
+ try {
+ clear = encryptor.decrypt(
+ result.salt,
+ result.iv,
+ result.cipher);
+ } catch (Exception e) {
+ log.unableToDecryptValue(e);
+ }
if (clear != null) {
- return new String(clear);
+ return new String(clear, "UTF-8");
}
return null;
}
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
index 5e44d20..f24b539 100644
--- a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
+++ b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
@@ -18,13 +18,14 @@
package org.apache.knox.gateway.securequery;
import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
-import org.apache.knox.gateway.services.GatewayServices;
-import org.apache.knox.gateway.services.security.CryptoService;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.services.security.EncryptionResult;
+import org.apache.knox.gateway.services.security.impl.ConfigurableEncryptor;
import org.apache.knox.gateway.util.urltemplate.Parser;
import org.apache.knox.gateway.util.urltemplate.Template;
@@ -33,10 +34,10 @@ import java.io.UnsupportedEncodingException;
public class SecureQueryEncryptProcessor
implements UrlRewriteStepProcessor<SecureQueryEncryptDescriptor> {
+ private static SecureQueryMessages log = MessagesFactory.get( SecureQueryMessages.class
);
private static final String ENCRYPTED_PARAMETER_NAME = "_";
- private String clusterName;
- private CryptoService cryptoService = null;
+ private ConfigurableEncryptor encryptor;
@Override
public String getType() {
@@ -45,9 +46,8 @@ public class SecureQueryEncryptProcessor
@Override
public void initialize( UrlRewriteEnvironment environment, SecureQueryEncryptDescriptor
descriptor ) throws Exception {
- clusterName = environment.getAttribute( GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE );
- GatewayServices services = environment.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
- cryptoService = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
+ encryptor = new ConfigurableEncryptor("encryptQueryString");
+ encryptor.init((GatewayConfig)environment.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE));
}
@Override
@@ -77,7 +77,12 @@ public class SecureQueryEncryptProcessor
}
private String encode( String string ) throws UnsupportedEncodingException {
- EncryptionResult result = cryptoService.encryptForCluster(clusterName, "encryptQueryString",
string.getBytes("UTF-8"));
+ EncryptionResult result = null;
+ try {
+ result = encryptor.encrypt(string);
+ } catch (Exception e) {
+ log.unableToEncryptValue(e);
+ }
string = Base64.encodeBase64URLSafeString(result.toByteAray());
return string;
}
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
index 2375011..c7990f2 100644
--- a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
+++ b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
@@ -28,4 +28,9 @@ public interface SecureQueryMessages {
@Message( level = MessageLevel.ERROR, text = "Failed to create or verify the presence of
a password for query string encryption: {0}" )
void unableCreatePasswordForEncryption(@StackTrace( level = MessageLevel.DEBUG ) Exception
e);
+ @Message( level = MessageLevel.ERROR, text = "Failed to encrypt a sensitive value due to
an exception: {0}" )
+ void unableToEncryptValue(@StackTrace( level = MessageLevel.ERROR ) Exception e);
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to decrypt a sensitive value due to
an exception: {0}" )
+ void unableToDecryptValue(@StackTrace( level = MessageLevel.ERROR ) Exception e);
}
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
----------------------------------------------------------------------
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 f47a17b..584255e 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
@@ -122,13 +122,16 @@ public class DefaultCryptoService implements CryptoService {
@Override
public byte[] decryptForCluster(String clusterName, String alias, byte[] cipherText, byte[]
iv, byte[] salt) {
try {
- final char[] password = as.getPasswordFromAliasForCluster(clusterName, alias);
- if (password != null) {
- try {
- return getEncryptor(clusterName,password ).decrypt( salt, iv, cipherText);
- } catch (Exception e) {
- LOG.failedToDecryptPasswordForCluster( clusterName, e );
- }
+ char[] password = null;
+ ConfigurableEncryptor encryptor = null;
+ password = as.getPasswordFromAliasForCluster(clusterName, alias);
+ if (password != null) {
+ encryptor = getEncryptor(clusterName,password );
+ try {
+ return encryptor.decrypt( salt, iv, cipherText);
+ } catch (Exception e) {
+ LOG.failedToDecryptPasswordForCluster( clusterName, e );
+ }
}
else {
LOG.failedToDecryptCipherForClusterNullPassword( clusterName );
@@ -167,7 +170,8 @@ public class DefaultCryptoService implements CryptoService {
@Override
public byte[] sign(String algorithm, String alias, String payloadToSign) {
try {
- char[] passphrase = as.getGatewayIdentityPassphrase();
+ char[] passphrase = null;
+ passphrase = as.getGatewayIdentityPassphrase();
PrivateKey privateKey = (PrivateKey) ks.getKeyForGateway(alias, passphrase);
Signature signature = Signature.getInstance(algorithm);
signature.initSign(privateKey);
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
----------------------------------------------------------------------
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 5d4bd27..f4cf523 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
@@ -29,6 +29,7 @@ import org.apache.knox.gateway.services.security.KeystoreServiceException;
import java.io.File;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.security.GeneralSecurityException;
import java.security.Key;
@@ -41,7 +42,12 @@ import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
+import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
public class DefaultKeystoreService extends BaseKeystoreService implements
KeystoreService, Service {
@@ -57,10 +63,17 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
private String signingKeystoreName = null;
private String signingKeyAlias = null;
+ private Map<String, Map<String, String>> cache = new ConcurrentHashMap<String,Map<String,
String>>();
+ private Lock readLock = null;
+ private Lock writeLock = null;
@Override
public void init(GatewayConfig config, Map<String, String> options)
throws ServiceLifecycleException {
+ ReadWriteLock lock = new ReentrantReadWriteLock(true);
+ readLock = lock.readLock();
+ writeLock = lock.writeLock();
+
this.keyStoreDir = config.getGatewaySecurityDir() + File.separator + "keystores" + File.separator;
File ksd = new File(this.keyStoreDir);
if (!ksd.exists()) {
@@ -106,20 +119,31 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
@Override
public void createKeystoreForGateway() throws KeystoreServiceException {
- String filename = getKeystorePath();
- createKeystore(filename, "JKS");
+ writeLock.lock();
+ try {
+ String filename = getKeystorePath();
+ createKeystore(filename, "JKS");
+ }
+ finally {
+ writeLock.unlock();
+ }
}
@Override
public KeyStore getKeystoreForGateway() throws KeystoreServiceException {
final File keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE );
- return getKeystore(keyStoreFile, "JKS");
+ readLock.lock();
+ try {
+ return getKeystore(keyStoreFile, "JKS");
+ }
+ finally {
+ readLock.unlock();
+ }
}
@Override
public KeyStore getSigningKeystore() throws KeystoreServiceException {
File keyStoreFile = null;
-
if (signingKeystoreName == null) {
keyStoreFile = new File(keyStoreDir + GATEWAY_KEYSTORE);
}
@@ -130,53 +154,70 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
throw new KeystoreServiceException("Configured signing keystore does not exist.");
}
}
- return getKeystore(keyStoreFile, "JKS");
+ readLock.lock();
+ try {
+ return getKeystore(keyStoreFile, "JKS");
+ }
+ finally {
+ readLock.unlock();
+ }
}
@Override
public void addSelfSignedCertForGateway(String alias, char[] passphrase) throws KeystoreServiceException
{
- addSelfSignedCertForGateway(alias, passphrase, null);
+ writeLock.lock();
+ try {
+ addSelfSignedCertForGateway(alias, passphrase, null);
+ }
+ finally {
+ writeLock.unlock();
+ }
}
@Override
public void addSelfSignedCertForGateway(String alias, char[] passphrase, String hostname)
throws KeystoreServiceException {
-
- KeyPairGenerator keyPairGenerator;
+ writeLock.lock();
try {
- keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- keyPairGenerator.initialize(1024);
- KeyPair KPair = keyPairGenerator.generateKeyPair();
- if (hostname == null) {
- hostname = System.getProperty(CERT_GEN_MODE, CERT_GEN_MODE_LOCALHOST);
- }
- X509Certificate cert = null;
- if(hostname.equals(CERT_GEN_MODE_HOSTNAME)) {
- String dn = buildDistinguishedName(InetAddress.getLocalHost().getHostName());
- cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
- }
- else {
- String dn = buildDistinguishedName(hostname);
- cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+ KeyPairGenerator keyPairGenerator;
+ try {
+ keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(1024);
+ KeyPair KPair = keyPairGenerator.generateKeyPair();
+ if (hostname == null) {
+ hostname = System.getProperty(CERT_GEN_MODE, CERT_GEN_MODE_LOCALHOST);
+ }
+ X509Certificate cert = null;
+ if(hostname.equals(CERT_GEN_MODE_HOSTNAME)) {
+ String dn = buildDistinguishedName(InetAddress.getLocalHost().getHostName());
+ cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+ }
+ else {
+ String dn = buildDistinguishedName(hostname);
+ cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+ }
+
+ KeyStore privateKS = getKeystoreForGateway();
+ privateKS.setKeyEntry(alias, KPair.getPrivate(),
+ passphrase,
+ new java.security.cert.Certificate[]{cert});
+
+ writeKeystoreToFile(privateKS, new File( keyStoreDir + GATEWAY_KEYSTORE ));
+ //writeCertificateToFile( cert, new File( keyStoreDir + alias + ".pem" ) );
+ } catch (NoSuchAlgorithmException e) {
+ LOG.failedToAddSeflSignedCertForGateway( alias, e );
+ throw new KeystoreServiceException(e);
+ } catch (GeneralSecurityException e) {
+ LOG.failedToAddSeflSignedCertForGateway( alias, e );
+ throw new KeystoreServiceException(e);
+ } catch (IOException e) {
+ LOG.failedToAddSeflSignedCertForGateway( alias, e );
+ throw new KeystoreServiceException(e);
}
-
- KeyStore privateKS = getKeystoreForGateway();
- privateKS.setKeyEntry(alias, KPair.getPrivate(),
- passphrase,
- new java.security.cert.Certificate[]{cert});
-
- writeKeystoreToFile(privateKS, new File( keyStoreDir + GATEWAY_KEYSTORE ));
- //writeCertificateToFile( cert, new File( keyStoreDir + alias + ".pem" ) );
- } catch (NoSuchAlgorithmException e) {
- LOG.failedToAddSeflSignedCertForGateway( alias, e );
- throw new KeystoreServiceException(e);
- } catch (GeneralSecurityException e) {
- LOG.failedToAddSeflSignedCertForGateway( alias, e );
- throw new KeystoreServiceException(e);
- } catch (IOException e) {
- LOG.failedToAddSeflSignedCertForGateway( alias, e );
- throw new KeystoreServiceException(e);
- }
+ }
+ finally {
+ writeLock.unlock();
+ }
}
private String buildDistinguishedName(String hostname) {
@@ -190,147 +231,255 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
@Override
public void createCredentialStoreForCluster(String clusterName) throws KeystoreServiceException
{
String filename = keyStoreDir + clusterName + CREDENTIALS_SUFFIX;
- createKeystore(filename, "JCEKS");
+ writeLock.lock();
+ try {
+ createKeystore(filename, "JCEKS");
+ }
+ finally {
+ writeLock.unlock();
+ }
}
@Override
public boolean isCredentialStoreForClusterAvailable(String clusterName) throws KeystoreServiceException
{
boolean rc = false;
final File keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX
);
+ readLock.lock();
try {
- rc = isKeystoreAvailable(keyStoreFile, "JCEKS");
- } catch (KeyStoreException e) {
- throw new KeystoreServiceException(e);
- } catch (IOException e) {
- throw new KeystoreServiceException(e);
+ try {
+ rc = isKeystoreAvailable(keyStoreFile, "JCEKS");
+ } catch (KeyStoreException e) {
+ throw new KeystoreServiceException(e);
+ } catch (IOException e) {
+ throw new KeystoreServiceException(e);
+ }
+ return rc;
+ }
+ finally {
+ readLock.unlock();
}
- return rc;
}
@Override
public boolean isKeystoreForGatewayAvailable() throws KeystoreServiceException {
boolean rc = false;
final File keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE );
+ readLock.lock();
try {
- rc = isKeystoreAvailable(keyStoreFile, "JKS");
- } catch (KeyStoreException e) {
- throw new KeystoreServiceException(e);
- } catch (IOException e) {
- throw new KeystoreServiceException(e);
+ try {
+ rc = isKeystoreAvailable(keyStoreFile, "JKS");
+ } catch (KeyStoreException e) {
+ throw new KeystoreServiceException(e);
+ } catch (IOException e) {
+ throw new KeystoreServiceException(e);
+ }
+ return rc;
+ }
+ finally {
+ readLock.unlock();
}
- return rc;
}
@Override
public Key getKeyForGateway(String alias, char[] passphrase) throws KeystoreServiceException
{
Key key = null;
- KeyStore ks = getKeystoreForGateway();
- 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 );
+ readLock.lock();
+ try {
+ KeyStore ks = getKeystoreForGateway();
+ 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;
+ }
+ finally {
+ readLock.unlock();
}
- 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 );
+ readLock.lock();
+ try {
+ 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;
+ }
+ finally {
+ readLock.unlock();
}
- return key;
}
public KeyStore getCredentialStoreForCluster(String clusterName)
throws KeystoreServiceException {
final File keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX
);
- return getKeystore(keyStoreFile, "JCEKS");
+ readLock.lock();
+ try {
+ return getKeystore(keyStoreFile, "JCEKS");
+ }
+ finally {
+ readLock.unlock();
+ }
}
public void addCredentialForCluster(String clusterName, String alias, String value)
throws KeystoreServiceException {
- KeyStore ks = getCredentialStoreForCluster(clusterName);
- addCredential(alias, value, ks);
- final File keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX
);
+ writeLock.lock();
try {
- writeKeystoreToFile(ks, keyStoreFile);
- } catch (KeyStoreException e) {
- LOG.failedToAddCredentialForCluster( clusterName, e );
- } catch (NoSuchAlgorithmException e) {
- LOG.failedToAddCredentialForCluster( clusterName, e );
- } catch (CertificateException e) {
- LOG.failedToAddCredentialForCluster( clusterName, e );
- } catch (IOException e) {
- LOG.failedToAddCredentialForCluster( clusterName, e );
+ removeFromCache(clusterName, alias);
+ KeyStore ks = getCredentialStoreForCluster(clusterName);
+ addCredential(alias, value, ks);
+ final File keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX
);
+ try {
+ writeKeystoreToFile(ks, keyStoreFile);
+ } catch (KeyStoreException e) {
+ LOG.failedToAddCredentialForCluster( clusterName, e );
+ } catch (NoSuchAlgorithmException e) {
+ LOG.failedToAddCredentialForCluster( clusterName, e );
+ } catch (CertificateException e) {
+ LOG.failedToAddCredentialForCluster( clusterName, e );
+ } catch (IOException e) {
+ LOG.failedToAddCredentialForCluster( clusterName, e );
+ }
+ } finally {
+ writeLock.unlock();
}
}
-
+
@Override
public char[] getCredentialForCluster(String clusterName, String alias)
throws KeystoreServiceException {
char[] credential = null;
- KeyStore ks = getCredentialStoreForCluster(clusterName);
- if (ks != null) {
- try {
- char[] masterSecret = masterService.getMasterSecret();
- Key credentialKey = ks.getKey( alias, masterSecret );
- if (credentialKey != null) {
- byte[] credentialBytes = credentialKey.getEncoded();
- String credentialString = new String( credentialBytes );
- credential = credentialString.toCharArray();
+ readLock.lock();
+ try {
+ credential = checkCache(clusterName, alias);
+ if (credential == null) {
+ KeyStore ks = getCredentialStoreForCluster(clusterName);
+ if (ks != null) {
+ try {
+ char[] masterSecret = masterService.getMasterSecret();
+ Key credentialKey = ks.getKey( alias, masterSecret );
+ if (credentialKey != null) {
+ byte[] credentialBytes = credentialKey.getEncoded();
+ String credentialString = new String( credentialBytes, "UTF-8" );
+ credential = credentialString.toCharArray();
+ addToCache(clusterName, alias, credentialString);
+ }
+ } catch (UnrecoverableKeyException e) {
+ LOG.failedToGetCredentialForCluster( clusterName, e );
+ } catch (KeyStoreException e) {
+ LOG.failedToGetCredentialForCluster( clusterName, e );
+ } catch (NoSuchAlgorithmException e) {
+ LOG.failedToGetCredentialForCluster( clusterName, e );
+ } catch (UnsupportedEncodingException e) {
+ LOG.failedToGetCredentialForCluster( clusterName, e );
+ }
+
}
- } catch (UnrecoverableKeyException e) {
- LOG.failedToGetCredentialForCluster( clusterName, e );
- } catch (KeyStoreException e) {
- LOG.failedToGetCredentialForCluster( clusterName, e );
- } catch (NoSuchAlgorithmException e) {
- LOG.failedToGetCredentialForCluster( clusterName, e );
}
+ return credential;
+ }
+ finally {
+ readLock.unlock();
}
- return credential;
}
-
@Override
public void removeCredentialForCluster(String clusterName, String alias) throws KeystoreServiceException
{
- KeyStore ks = getCredentialStoreForCluster(clusterName);
- removeCredential(alias, ks);
final File keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX
);
+ writeLock.lock();
try {
- writeKeystoreToFile(ks, keyStoreFile);
- } catch (KeyStoreException e) {
- LOG.failedToRemoveCredentialForCluster(clusterName, e);
- } catch (NoSuchAlgorithmException e) {
- LOG.failedToRemoveCredentialForCluster(clusterName, e);
- } catch (CertificateException e) {
- LOG.failedToRemoveCredentialForCluster(clusterName, e);
- } catch (IOException e) {
- LOG.failedToRemoveCredentialForCluster(clusterName, e);
+ removeFromCache(clusterName, alias);
+ KeyStore ks = getCredentialStoreForCluster(clusterName);
+ removeCredential(alias, ks);
+ try {
+ writeKeystoreToFile(ks, keyStoreFile);
+ } catch (KeyStoreException e) {
+ LOG.failedToRemoveCredentialForCluster(clusterName, e);
+ } catch (NoSuchAlgorithmException e) {
+ LOG.failedToRemoveCredentialForCluster(clusterName, e);
+ } catch (CertificateException e) {
+ LOG.failedToRemoveCredentialForCluster(clusterName, e);
+ } catch (IOException e) {
+ LOG.failedToRemoveCredentialForCluster(clusterName, e);
+ }
}
+ finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Called only from within critical sections of other methods above.
+ * @param clusterName
+ * @param alias
+ * @return
+ */
+ private char[] checkCache(String clusterName, String alias) {
+ char[] c = null;
+ String cred = null;
+ HashMap<String, String> clusterCache = (HashMap<String, String>) cache.get(clusterName);
+ if (clusterCache == null) {
+ return null;
+ }
+ cred = clusterCache.get(alias);
+ if (cred != null) {
+ c = cred.toCharArray();
+ }
+ return c;
+ }
+
+ /**
+ * Called only from within critical sections of other methods above.
+ * @param clusterName
+ * @param alias
+ * @param credentialString
+ */
+ private void addToCache(String clusterName, String alias, String credentialString) {
+ HashMap<String, String> clusterCache = (HashMap<String, String>) cache.get(clusterName);
+ if (clusterCache == null) {
+ clusterCache = new HashMap<String, String>();
+ }
+ clusterCache.put(alias, credentialString);
+ }
+
+ /**
+ * Called only from within critical sections of other methods above.
+ * @param clusterName
+ * @param alias
+ */
+ private void removeFromCache(String clusterName, String alias) {
+ HashMap<String, String> clusterCache = (HashMap<String, String>) cache.get(clusterName);
+ if (clusterCache == null) {
+ return;
+ }
+ clusterCache.remove(alias);
}
@Override
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
index 0377142..d89a1dd 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
@@ -70,12 +70,12 @@ public abstract class AbstractGatewayDispatch implements Dispatch {
}
@Override
- public HttpClient getHttpClient() {
+ synchronized public HttpClient getHttpClient() {
return client;
}
@Override
- public void setHttpClient(HttpClient client) {
+ synchronized public void setHttpClient(HttpClient client) {
this.client = client;
}
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
index c2c1b53..4f8c82f 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
@@ -127,7 +127,7 @@ public class DefaultDispatch extends AbstractGatewayDispatch {
// Hadoop cluster not Kerberos enabled
addCredentialsToRequest( outboundRequest );
}
- inboundResponse = client.execute( outboundRequest );
+ inboundResponse = getHttpClient().execute( outboundRequest );
int statusCode = inboundResponse.getStatusLine().getStatusCode();
if( statusCode != 201 ) {
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
index 8bef80d..8f3399a 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
@@ -41,6 +41,8 @@ public class GatewayDispatchFilter extends AbstractGatewayFilter {
protected static final SpiGatewayMessages LOG = MessagesFactory.get(SpiGatewayMessages.class);
+ private final Object lock = new Object();
+
private Dispatch dispatch;
private HttpClient httpClient;
@@ -59,41 +61,49 @@ public class GatewayDispatchFilter extends AbstractGatewayFilter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
super.init(filterConfig);
- if (dispatch == null) {
- String dispatchImpl = filterConfig.getInitParameter("dispatch-impl");
- dispatch = newInstanceFromName(dispatchImpl);
- }
- ConfigurationInjectorBuilder.configuration().target(dispatch).source(filterConfig).inject();
- HttpClientFactory httpClientFactory;
- String httpClientFactoryClass = filterConfig.getInitParameter("httpClientFactory");
- if (httpClientFactoryClass != null) {
- httpClientFactory = newInstanceFromName(httpClientFactoryClass);
- } else {
- httpClientFactory = new DefaultHttpClientFactory();
+ synchronized(lock) {
+ if (dispatch == null) {
+ String dispatchImpl = filterConfig.getInitParameter("dispatch-impl");
+ dispatch = newInstanceFromName(dispatchImpl);
+ }
+ ConfigurationInjectorBuilder.configuration().target(dispatch).source(filterConfig).inject();
+ HttpClientFactory httpClientFactory;
+ String httpClientFactoryClass = filterConfig.getInitParameter("httpClientFactory");
+ if (httpClientFactoryClass != null) {
+ httpClientFactory = newInstanceFromName(httpClientFactoryClass);
+ } else {
+ httpClientFactory = new DefaultHttpClientFactory();
+ }
+ httpClient = httpClientFactory.createHttpClient(filterConfig);
+ dispatch.setHttpClient(httpClient);
+ dispatch.init();
}
- httpClient = httpClientFactory.createHttpClient(filterConfig);
- dispatch.setHttpClient(httpClient);
- dispatch.init();
}
@Override
public void destroy() {
- dispatch.destroy();
- try {
- if (httpClient instanceof CloseableHttpClient) {
- ((CloseableHttpClient) httpClient).close();
+ synchronized(lock) {
+ dispatch.destroy();
+ try {
+ if (httpClient instanceof CloseableHttpClient) {
+ ((CloseableHttpClient) httpClient).close();
+ }
+ } catch ( IOException e ) {
+ LOG.errorClosingHttpClient(e);
}
- } catch ( IOException e ) {
- LOG.errorClosingHttpClient(e);
}
}
public Dispatch getDispatch() {
- return dispatch;
+ synchronized(lock) {
+ return dispatch;
+ }
}
public void setDispatch(Dispatch dispatch) {
- this.dispatch = dispatch;
+ synchronized(lock) {
+ this.dispatch = dispatch;
+ }
}
@Override
@@ -102,7 +112,7 @@ public class GatewayDispatchFilter extends AbstractGatewayFilter {
Adapter adapter = METHOD_ADAPTERS.get(method);
if ( adapter != null ) {
try {
- adapter.doMethod(dispatch, request, response);
+ adapter.doMethod(getDispatch(), request, response);
} catch ( URISyntaxException e ) {
throw new ServletException(e);
}
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
index 15919f8..b39e6ab 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
@@ -167,7 +167,9 @@ public class CMFMasterService {
LOG.loadingFromPersistentMaster( tag );
String line = new String(Base64.decodeBase64(lines.get(1)));
String[] parts = line.split("::");
- this.master = new String(encryptor.decrypt(Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]),
Base64.decodeBase64(parts[2])), "UTF8").toCharArray();
+ this.master = new String(encryptor.decrypt(Base64.decodeBase64(parts[0]),
+ Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])),
+ "UTF8").toCharArray();
} catch (IOException e) {
LOG.failedToInitializeFromPersistentMaster(masterFile.getName(), e);
throw e;
http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
index b576f29..ed7feac 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
@@ -17,16 +17,12 @@
*/
package org.apache.knox.gateway.services.security.impl;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
-import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
@@ -44,10 +40,6 @@ public class ConfigurableEncryptor {
private static final int ITERATION_COUNT = 65536;
private static final int KEY_LENGTH = 128;
- private Cipher ecipher;
- private Cipher dcipher;
- private SecretKey secret;
- private byte[] salt = null;
private char[] passPhrase = null;
private String alg = "AES";
private String pbeAlg = "PBKDF2WithHmacSHA1";
@@ -57,60 +49,12 @@ public class ConfigurableEncryptor {
private int keyLength = KEY_LENGTH;
public ConfigurableEncryptor(String passPhrase) {
- try {
- this.passPhrase = passPhrase.toCharArray();
- salt = new byte[saltSize];
- SecureRandom rnd = new SecureRandom();
- rnd.nextBytes(salt);
-
- SecretKey tmp = getKeyFromPassword(passPhrase);
- secret = new SecretKeySpec (tmp.getEncoded(), alg);
-
- ecipher = Cipher.getInstance(transformation);
- ecipher.init(Cipher.ENCRYPT_MODE, secret);
-
- dcipher = Cipher.getInstance(transformation);
- byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
- dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
- } catch (NoSuchAlgorithmException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (NoSuchPaddingException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (InvalidKeyException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (InvalidParameterSpecException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (InvalidAlgorithmParameterException e) {
- LOG.failedToEncryptPassphrase( e );
- }
- }
-
- ConfigurableEncryptor(SecretKey secret) {
- try {
- this.secret = new SecretKeySpec (secret.getEncoded(), alg);
-
- ecipher = Cipher.getInstance(transformation);
- ecipher.init(Cipher.ENCRYPT_MODE, secret);
-
- dcipher = Cipher.getInstance(transformation);
- byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
- dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
- } catch (NoSuchAlgorithmException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (NoSuchPaddingException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (InvalidKeyException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (InvalidParameterSpecException e) {
- LOG.failedToEncryptPassphrase( e );
- } catch (InvalidAlgorithmParameterException e) {
- LOG.failedToEncryptPassphrase( e );
- }
+ this.passPhrase = passPhrase.toCharArray();
}
public void init(GatewayConfig config) {
if (config != null) {
- String alg = config.getAlgorithm();
+ String alg = config.getAlgorithm();
if (alg != null) {
this.alg = alg;
}
@@ -137,10 +81,6 @@ public class ConfigurableEncryptor {
}
}
- public SecretKey getKeyFromPassword(String passPhrase) {
- return getKeyFromPassword(passPhrase, salt);
- }
-
public SecretKey getKeyFromPassword(String passPhrase, byte[] salt) {
SecretKeyFactory factory;
SecretKey key = null;
@@ -158,31 +98,32 @@ public class ConfigurableEncryptor {
}
public EncryptionResult encrypt(String encrypt) throws Exception {
- byte[] bytes = encrypt.getBytes("UTF8");
+ byte[] bytes = encrypt.getBytes("UTF-8");
EncryptionResult atom = encrypt(bytes);
return atom;
}
public EncryptionResult encrypt(byte[] plain) throws Exception {
- EncryptionResult atom = new EncryptionResult(salt, ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
ecipher.doFinal(plain));
- return atom;
- }
+ byte[] salt = new byte[saltSize];
+ SecureRandom rnd = new SecureRandom();
+ rnd.nextBytes(salt);
- public String decrypt(String salt, String iv, String cipher) throws Exception {
- byte[] decrypted = decrypt(salt.getBytes("UTF8"), iv.getBytes("UTF8"), cipher.getBytes("UTF8"));
- return new String(decrypted, "UTF8");
+ SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
+ SecretKey secret = new SecretKeySpec(tmp.getEncoded(), alg);
+ Cipher ecipher = Cipher.getInstance(transformation);
+ ecipher.init(Cipher.ENCRYPT_MODE, secret);
+ EncryptionResult atom = new EncryptionResult(salt,
+ ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
+ ecipher.doFinal(plain));
+ return atom;
}
public byte[] decrypt(byte[] salt, byte[] iv, byte[] encrypt) throws Exception {
SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
- secret = new SecretKeySpec(tmp.getEncoded(), alg);
+ SecretKey secret = new SecretKeySpec(tmp.getEncoded(), alg);
+ Cipher dcipher = Cipher.getInstance(transformation);
dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
return dcipher.doFinal(encrypt);
}
-
- public byte[] decrypt(byte[] encrypt) throws Exception {
- dcipher.init(Cipher.DECRYPT_MODE, secret);
- return dcipher.doFinal(encrypt);
- }
}
|