HADOOP-17259. Allow SSLFactory fallback to input config if ssl-*.xml … (#2301)

This commit is contained in:
Xiaoyu Yao 2020-09-21 12:41:06 -07:00 committed by GitHub
parent c8c1cc43d3
commit 6b5d9e2334
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 4 deletions

View File

@ -102,7 +102,7 @@ public enum Mode { CLIENT, SERVER }
public static final String SSLCERTIFICATE = IBM_JAVA?"ibmX509":"SunX509"; public static final String SSLCERTIFICATE = IBM_JAVA?"ibmX509":"SunX509";
public static final String KEYSTORES_FACTORY_CLASS_KEY = public static final String KEYSTORES_FACTORY_CLASS_KEY =
"hadoop.ssl.keystores.factory.class"; "hadoop.ssl.keystores.factory.class";
private Configuration conf; private Configuration conf;
private Mode mode; private Mode mode;
@ -165,6 +165,13 @@ public static Configuration readSSLConfiguration(Configuration conf,
SSL_SERVER_CONF_DEFAULT); SSL_SERVER_CONF_DEFAULT);
} }
sslConf.addResource(sslConfResource); sslConf.addResource(sslConfResource);
// Only fallback to input config if classpath SSL config does not load for
// backward compatibility.
if (sslConf.getResource(sslConfResource) == null) {
LOG.debug("{} can't be loaded form classpath, fallback using SSL" +
" config from input configuration.", sslConfResource);
sslConf = conf;
}
return sslConf; return sslConf;
} }

View File

@ -17,7 +17,14 @@
*/ */
package org.apache.hadoop.security.ssl; package org.apache.hadoop.security.ssl;
import static org.apache.hadoop.security.ssl.FileBasedKeyStoresFactory.SSL_TRUSTSTORE_LOCATION_TPL_KEY;
import static org.apache.hadoop.security.ssl.KeyStoreTestUtil.TRUST_STORE_PASSWORD_DEFAULT; import static org.apache.hadoop.security.ssl.KeyStoreTestUtil.TRUST_STORE_PASSWORD_DEFAULT;
import static org.apache.hadoop.security.ssl.SSLFactory.Mode.CLIENT;
import static org.apache.hadoop.security.ssl.SSLFactory.SSL_CLIENT_CONF_KEY;
import static org.apache.hadoop.security.ssl.SSLFactory.SSL_REQUIRE_CLIENT_CERT_KEY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
@ -66,6 +73,10 @@ public class TestSSLFactory {
+ "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA," + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,"
+ "SSL_RSA_WITH_RC4_128_MD5," + "SSL_RSA_WITH_RC4_128_MD5,"
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
private static final Configuration FAKE_SSL_CONFIG =
KeyStoreTestUtil.createClientSSLConfig("clientKeyStoreLocation",
"keystorePassword", "keyPassword",
"trustStoreLocation", "trustStorePassword");
@BeforeClass @BeforeClass
public static void setUp() throws Exception { public static void setUp() throws Exception {
@ -90,6 +101,55 @@ public void cleanUp() throws Exception {
KeyStoreTestUtil.cleanupSSLConfig(KEYSTORES_DIR, sslConfsDir); KeyStoreTestUtil.cleanupSSLConfig(KEYSTORES_DIR, sslConfsDir);
} }
private String getClientTrustStoreKeyName() {
return FileBasedKeyStoresFactory.resolvePropertyName(
CLIENT, SSL_TRUSTSTORE_LOCATION_TPL_KEY);
}
@Test
public void testNonExistSslClientXml() throws Exception{
Configuration conf = new Configuration(false);
conf.setBoolean(SSL_REQUIRE_CLIENT_CERT_KEY, false);
conf.set(SSL_CLIENT_CONF_KEY, "non-exist-ssl-client.xml");
Configuration sslConf =
SSLFactory.readSSLConfiguration(conf, SSLFactory.Mode.CLIENT);
assertNull(sslConf.getResource("non-exist-ssl-client.xml"));
assertNull(sslConf.get("ssl.client.truststore.location"));
}
@Test
public void testSslConfFallback() throws Exception {
Configuration conf = new Configuration(FAKE_SSL_CONFIG);
// Set non-exist-ssl-client.xml that fails to load.
// This triggers fallback to SSL config from input conf.
conf.set(SSL_CLIENT_CONF_KEY, "non-exist-ssl-client.xml");
Configuration sslConf = SSLFactory.readSSLConfiguration(conf, CLIENT);
// Verify fallback to input conf when ssl conf can't be loaded from
// classpath.
String clientTsLoc = sslConf.get(getClientTrustStoreKeyName());
assertEquals("trustStoreLocation", clientTsLoc);
assertEquals(sslConf, conf);
}
@Test
public void testSslConfClassPathFirst() throws Exception {
// Generate a valid ssl-client.xml into classpath.
// This will be the preferred approach.
Configuration conf = createConfiguration(false, true);
// Injecting fake ssl config into input conf.
conf.addResource(FAKE_SSL_CONFIG);
// Classpath SSL config will be preferred if both input conf and
// the classpath SSL config exist for backward compatibility.
Configuration sslConfLoaded = SSLFactory.readSSLConfiguration(conf, CLIENT);
String clientTsLoc = sslConfLoaded.get(getClientTrustStoreKeyName());
assertNotEquals("trustStoreLocation", clientTsLoc);
assertNotEquals(conf, sslConfLoaded);
}
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void clientMode() throws Exception { public void clientMode() throws Exception {
Configuration conf = createConfiguration(false, true); Configuration conf = createConfiguration(false, true);
@ -452,7 +512,7 @@ private void checkSSLFactoryInitWithPasswords(SSLFactory.Mode mode,
// Create the master configuration for use by the SSLFactory, which by // Create the master configuration for use by the SSLFactory, which by
// default refers to the ssl-server.xml or ssl-client.xml created above. // default refers to the ssl-server.xml or ssl-client.xml created above.
Configuration conf = new Configuration(); Configuration conf = new Configuration();
conf.setBoolean(SSLFactory.SSL_REQUIRE_CLIENT_CERT_KEY, true); conf.setBoolean(SSL_REQUIRE_CLIENT_CERT_KEY, true);
// Try initializing an SSLFactory. // Try initializing an SSLFactory.
SSLFactory sslFactory = new SSLFactory(mode, conf); SSLFactory sslFactory = new SSLFactory(mode, conf);
@ -466,7 +526,7 @@ private void checkSSLFactoryInitWithPasswords(SSLFactory.Mode mode,
@Test @Test
public void testNoClientCertsInitialization() throws Exception { public void testNoClientCertsInitialization() throws Exception {
Configuration conf = createConfiguration(false, true); Configuration conf = createConfiguration(false, true);
conf.unset(SSLFactory.SSL_REQUIRE_CLIENT_CERT_KEY); conf.unset(SSL_REQUIRE_CLIENT_CERT_KEY);
SSLFactory sslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, conf); SSLFactory sslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, conf);
try { try {
sslFactory.init(); sslFactory.init();
@ -478,7 +538,7 @@ public void testNoClientCertsInitialization() throws Exception {
@Test @Test
public void testNoTrustStore() throws Exception { public void testNoTrustStore() throws Exception {
Configuration conf = createConfiguration(false, false); Configuration conf = createConfiguration(false, false);
conf.unset(SSLFactory.SSL_REQUIRE_CLIENT_CERT_KEY); conf.unset(SSL_REQUIRE_CLIENT_CERT_KEY);
SSLFactory sslFactory = new SSLFactory(SSLFactory.Mode.SERVER, conf); SSLFactory sslFactory = new SSLFactory(SSLFactory.Mode.SERVER, conf);
try { try {
sslFactory.init(); sslFactory.init();