HADOOP-10933. FileBasedKeyStoresFactory Should use Configuration.getPassword for SSL Passwords. (lmccay via tucu)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1616008 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2d7dcff6f4
commit
a6cfaab5aa
|
@ -532,6 +532,9 @@ Release 2.6.0 - UNRELEASED
|
||||||
|
|
||||||
HADOOP-10918. JMXJsonServlet fails when used within Tomcat. (tucu)
|
HADOOP-10918. JMXJsonServlet fails when used within Tomcat. (tucu)
|
||||||
|
|
||||||
|
HADOOP-10933. FileBasedKeyStoresFactory Should use Configuration.getPassword
|
||||||
|
for SSL Passwords. (lmccay via tucu)
|
||||||
|
|
||||||
Release 2.5.0 - UNRELEASED
|
Release 2.5.0 - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
|
|
@ -150,7 +150,7 @@ public class FileBasedKeyStoresFactory implements KeyStoresFactory {
|
||||||
}
|
}
|
||||||
String passwordProperty =
|
String passwordProperty =
|
||||||
resolvePropertyName(mode, SSL_KEYSTORE_PASSWORD_TPL_KEY);
|
resolvePropertyName(mode, SSL_KEYSTORE_PASSWORD_TPL_KEY);
|
||||||
String keystorePassword = conf.get(passwordProperty, "");
|
String keystorePassword = getPassword(conf, passwordProperty, "");
|
||||||
if (keystorePassword.isEmpty()) {
|
if (keystorePassword.isEmpty()) {
|
||||||
throw new GeneralSecurityException("The property '" + passwordProperty +
|
throw new GeneralSecurityException("The property '" + passwordProperty +
|
||||||
"' has not been set in the ssl configuration file.");
|
"' has not been set in the ssl configuration file.");
|
||||||
|
@ -160,7 +160,8 @@ public class FileBasedKeyStoresFactory implements KeyStoresFactory {
|
||||||
// Key password defaults to the same value as store password for
|
// Key password defaults to the same value as store password for
|
||||||
// compatibility with legacy configurations that did not use a separate
|
// compatibility with legacy configurations that did not use a separate
|
||||||
// configuration property for key password.
|
// configuration property for key password.
|
||||||
keystoreKeyPassword = conf.get(keyPasswordProperty, keystorePassword);
|
keystoreKeyPassword = getPassword(
|
||||||
|
conf, keyPasswordProperty, keystorePassword);
|
||||||
LOG.debug(mode.toString() + " KeyStore: " + keystoreLocation);
|
LOG.debug(mode.toString() + " KeyStore: " + keystoreLocation);
|
||||||
|
|
||||||
InputStream is = new FileInputStream(keystoreLocation);
|
InputStream is = new FileInputStream(keystoreLocation);
|
||||||
|
@ -191,7 +192,7 @@ public class FileBasedKeyStoresFactory implements KeyStoresFactory {
|
||||||
if (!truststoreLocation.isEmpty()) {
|
if (!truststoreLocation.isEmpty()) {
|
||||||
String passwordProperty = resolvePropertyName(mode,
|
String passwordProperty = resolvePropertyName(mode,
|
||||||
SSL_TRUSTSTORE_PASSWORD_TPL_KEY);
|
SSL_TRUSTSTORE_PASSWORD_TPL_KEY);
|
||||||
String truststorePassword = conf.get(passwordProperty, "");
|
String truststorePassword = getPassword(conf, passwordProperty, "");
|
||||||
if (truststorePassword.isEmpty()) {
|
if (truststorePassword.isEmpty()) {
|
||||||
throw new GeneralSecurityException("The property '" + passwordProperty +
|
throw new GeneralSecurityException("The property '" + passwordProperty +
|
||||||
"' has not been set in the ssl configuration file.");
|
"' has not been set in the ssl configuration file.");
|
||||||
|
@ -217,6 +218,21 @@ public class FileBasedKeyStoresFactory implements KeyStoresFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getPassword(Configuration conf, String alias, String defaultPass) {
|
||||||
|
String password = defaultPass;
|
||||||
|
try {
|
||||||
|
char[] passchars = conf.getPassword(alias);
|
||||||
|
if (passchars != null) {
|
||||||
|
password = new String(passchars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ioe) {
|
||||||
|
LOG.warn("Exception while trying to get password for alias " + alias +
|
||||||
|
": " + ioe.getMessage());
|
||||||
|
}
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases any resources being used.
|
* Releases any resources being used.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
package org.apache.hadoop.security.ssl;
|
package org.apache.hadoop.security.ssl;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.security.alias.CredentialProvider;
|
||||||
|
import org.apache.hadoop.security.alias.CredentialProviderFactory;
|
||||||
|
import org.apache.hadoop.security.alias.JavaKeyStoreProvider;
|
||||||
|
|
||||||
import sun.security.x509.AlgorithmId;
|
import sun.security.x509.AlgorithmId;
|
||||||
import sun.security.x509.CertificateAlgorithmId;
|
import sun.security.x509.CertificateAlgorithmId;
|
||||||
import sun.security.x509.CertificateIssuerName;
|
import sun.security.x509.CertificateIssuerName;
|
||||||
|
@ -382,4 +386,41 @@ public class KeyStoreTestUtil {
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void provisionPasswordsToCredentialProvider() throws Exception {
|
||||||
|
File testDir = new File(System.getProperty("test.build.data",
|
||||||
|
"target/test-dir"));
|
||||||
|
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
final String ourUrl =
|
||||||
|
JavaKeyStoreProvider.SCHEME_NAME + "://file/" + testDir + "/test.jks";
|
||||||
|
|
||||||
|
File file = new File(testDir, "test.jks");
|
||||||
|
file.delete();
|
||||||
|
conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl);
|
||||||
|
|
||||||
|
CredentialProvider provider =
|
||||||
|
CredentialProviderFactory.getProviders(conf).get(0);
|
||||||
|
char[] keypass = {'k', 'e', 'y', 'p', 'a', 's', 's'};
|
||||||
|
char[] storepass = {'s', 't', 'o', 'r', 'e', 'p', 'a', 's', 's'};
|
||||||
|
|
||||||
|
// create new aliases
|
||||||
|
try {
|
||||||
|
provider.createCredentialEntry(
|
||||||
|
FileBasedKeyStoresFactory.resolvePropertyName(SSLFactory.Mode.SERVER,
|
||||||
|
FileBasedKeyStoresFactory.SSL_KEYSTORE_PASSWORD_TPL_KEY),
|
||||||
|
storepass);
|
||||||
|
|
||||||
|
provider.createCredentialEntry(
|
||||||
|
FileBasedKeyStoresFactory.resolvePropertyName(SSLFactory.Mode.SERVER,
|
||||||
|
FileBasedKeyStoresFactory.SSL_KEYSTORE_KEYPASSWORD_TPL_KEY),
|
||||||
|
keypass);
|
||||||
|
|
||||||
|
// write out so that it can be found in checks
|
||||||
|
provider.flush();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,14 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.security.ssl;
|
package org.apache.hadoop.security.ssl;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.FileUtil;
|
import org.apache.hadoop.fs.FileUtil;
|
||||||
|
import org.apache.hadoop.security.alias.CredentialProvider;
|
||||||
|
import org.apache.hadoop.security.alias.CredentialProviderFactory;
|
||||||
|
import org.apache.hadoop.security.alias.JavaKeyStoreProvider;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -211,6 +217,13 @@ public class TestSSLFactory {
|
||||||
"password", "password", null);
|
"password", "password", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerCredProviderPasswords() throws Exception {
|
||||||
|
KeyStoreTestUtil.provisionPasswordsToCredentialProvider();
|
||||||
|
checkSSLFactoryInitWithPasswords(SSLFactory.Mode.SERVER,
|
||||||
|
"storepass", "keypass", null, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that SSLFactory initialization is successful with the given
|
* Checks that SSLFactory initialization is successful with the given
|
||||||
* arguments. This is a helper method for writing test cases that cover
|
* arguments. This is a helper method for writing test cases that cover
|
||||||
|
@ -218,7 +231,7 @@ public class TestSSLFactory {
|
||||||
* It takes care of bootstrapping a keystore, a truststore, and SSL client or
|
* It takes care of bootstrapping a keystore, a truststore, and SSL client or
|
||||||
* server configuration. Then, it initializes an SSLFactory. If no exception
|
* server configuration. Then, it initializes an SSLFactory. If no exception
|
||||||
* is thrown, then initialization was successful.
|
* is thrown, then initialization was successful.
|
||||||
*
|
*
|
||||||
* @param mode SSLFactory.Mode mode to test
|
* @param mode SSLFactory.Mode mode to test
|
||||||
* @param password String store password to set on keystore
|
* @param password String store password to set on keystore
|
||||||
* @param keyPassword String key password to set on keystore
|
* @param keyPassword String key password to set on keystore
|
||||||
|
@ -231,6 +244,34 @@ public class TestSSLFactory {
|
||||||
private void checkSSLFactoryInitWithPasswords(SSLFactory.Mode mode,
|
private void checkSSLFactoryInitWithPasswords(SSLFactory.Mode mode,
|
||||||
String password, String keyPassword, String confPassword,
|
String password, String keyPassword, String confPassword,
|
||||||
String confKeyPassword) throws Exception {
|
String confKeyPassword) throws Exception {
|
||||||
|
checkSSLFactoryInitWithPasswords(mode, password, keyPassword,
|
||||||
|
confPassword, confKeyPassword, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that SSLFactory initialization is successful with the given
|
||||||
|
* arguments. This is a helper method for writing test cases that cover
|
||||||
|
* different combinations of settings for the store password and key password.
|
||||||
|
* It takes care of bootstrapping a keystore, a truststore, and SSL client or
|
||||||
|
* server configuration. Then, it initializes an SSLFactory. If no exception
|
||||||
|
* is thrown, then initialization was successful.
|
||||||
|
*
|
||||||
|
* @param mode SSLFactory.Mode mode to test
|
||||||
|
* @param password String store password to set on keystore
|
||||||
|
* @param keyPassword String key password to set on keystore
|
||||||
|
* @param confPassword String store password to set in SSL config file, or null
|
||||||
|
* to avoid setting in SSL config file
|
||||||
|
* @param confKeyPassword String key password to set in SSL config file, or
|
||||||
|
* null to avoid setting in SSL config file
|
||||||
|
* @param useCredProvider boolean to indicate whether passwords should be set
|
||||||
|
* into the config or not. When set to true nulls are set and aliases are
|
||||||
|
* expected to be resolved through credential provider API through the
|
||||||
|
* Configuration.getPassword method
|
||||||
|
* @throws Exception for any error
|
||||||
|
*/
|
||||||
|
private void checkSSLFactoryInitWithPasswords(SSLFactory.Mode mode,
|
||||||
|
String password, String keyPassword, String confPassword,
|
||||||
|
String confKeyPassword, boolean useCredProvider) throws Exception {
|
||||||
String keystore = new File(KEYSTORES_DIR, "keystore.jks").getAbsolutePath();
|
String keystore = new File(KEYSTORES_DIR, "keystore.jks").getAbsolutePath();
|
||||||
String truststore = new File(KEYSTORES_DIR, "truststore.jks")
|
String truststore = new File(KEYSTORES_DIR, "truststore.jks")
|
||||||
.getAbsolutePath();
|
.getAbsolutePath();
|
||||||
|
@ -249,10 +290,25 @@ public class TestSSLFactory {
|
||||||
// Create SSL configuration file, for either server or client.
|
// Create SSL configuration file, for either server or client.
|
||||||
final String sslConfFileName;
|
final String sslConfFileName;
|
||||||
final Configuration sslConf;
|
final Configuration sslConf;
|
||||||
|
|
||||||
|
// if the passwords are provisioned in a cred provider then don't set them
|
||||||
|
// in the configuration properly - expect them to be resolved through the
|
||||||
|
// provider
|
||||||
|
if (useCredProvider) {
|
||||||
|
confPassword = null;
|
||||||
|
confKeyPassword = null;
|
||||||
|
}
|
||||||
if (mode == SSLFactory.Mode.SERVER) {
|
if (mode == SSLFactory.Mode.SERVER) {
|
||||||
sslConfFileName = "ssl-server.xml";
|
sslConfFileName = "ssl-server.xml";
|
||||||
sslConf = KeyStoreTestUtil.createServerSSLConfig(keystore, confPassword,
|
sslConf = KeyStoreTestUtil.createServerSSLConfig(keystore, confPassword,
|
||||||
confKeyPassword, truststore);
|
confKeyPassword, truststore);
|
||||||
|
if (useCredProvider) {
|
||||||
|
File testDir = new File(System.getProperty("test.build.data",
|
||||||
|
"target/test-dir"));
|
||||||
|
final String ourUrl =
|
||||||
|
JavaKeyStoreProvider.SCHEME_NAME + "://file/" + testDir + "/test.jks";
|
||||||
|
sslConf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sslConfFileName = "ssl-client.xml";
|
sslConfFileName = "ssl-client.xml";
|
||||||
sslConf = KeyStoreTestUtil.createClientSSLConfig(keystore, confPassword,
|
sslConf = KeyStoreTestUtil.createClientSSLConfig(keystore, confPassword,
|
||||||
|
|
Loading…
Reference in New Issue