HADOOP-14341. Support multi-line value for ssl.server.exclude.cipher.list. Contributed by John Zhuge.

This commit is contained in:
John Zhuge 2017-04-21 02:10:33 -07:00
parent e4c32bccde
commit 9ccb849eb6
6 changed files with 33 additions and 28 deletions

View File

@ -25,6 +25,8 @@ import java.util.regex.Pattern;
import static org.apache.hadoop.fs.CommonConfigurationKeys.*; import static org.apache.hadoop.fs.CommonConfigurationKeys.*;
import org.apache.hadoop.util.StringUtils;
/** /**
* Tool for redacting sensitive information when displaying config parameters. * Tool for redacting sensitive information when displaying config parameters.
* *
@ -43,7 +45,7 @@ public class ConfigRedactor {
HADOOP_SECURITY_SENSITIVE_CONFIG_KEYS, HADOOP_SECURITY_SENSITIVE_CONFIG_KEYS,
HADOOP_SECURITY_SENSITIVE_CONFIG_KEYS_DEFAULT); HADOOP_SECURITY_SENSITIVE_CONFIG_KEYS_DEFAULT);
List<String> sensitiveRegexes = List<String> sensitiveRegexes =
Arrays.asList(sensitiveRegexList.trim().split("[,\\s]+")); Arrays.asList(StringUtils.getTrimmedStrings(sensitiveRegexList));
compiledPatterns = new ArrayList<Pattern>(); compiledPatterns = new ArrayList<Pattern>();
for (String regex : sensitiveRegexes) { for (String regex : sensitiveRegexes) {
Pattern p = Pattern.compile(regex); Pattern p = Pattern.compile(regex);

View File

@ -73,6 +73,7 @@ import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.security.ssl.SSLFactory; import org.apache.hadoop.security.ssl.SSLFactory;
import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.Shell; import org.apache.hadoop.util.Shell;
import org.apache.hadoop.util.StringUtils;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
@ -471,7 +472,8 @@ public final class HttpServer2 implements FilterContainer {
sslContextFactory.setTrustStorePassword(trustStorePassword); sslContextFactory.setTrustStorePassword(trustStorePassword);
} }
if(null != excludeCiphers && !excludeCiphers.isEmpty()) { if(null != excludeCiphers && !excludeCiphers.isEmpty()) {
sslContextFactory.setExcludeCipherSuites(excludeCiphers.split(",")); sslContextFactory.setExcludeCipherSuites(
StringUtils.getTrimmedStrings(excludeCiphers));
LOG.info("Excluded Cipher List:" + excludeCiphers); LOG.info("Excluded Cipher List:" + excludeCiphers);
} }

View File

@ -39,7 +39,6 @@ import java.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
/** /**
@ -140,13 +139,11 @@ public class SSLFactory implements ConnectionConfigurator {
enabledProtocols = conf.getStrings(SSL_ENABLED_PROTOCOLS_KEY, enabledProtocols = conf.getStrings(SSL_ENABLED_PROTOCOLS_KEY,
SSL_ENABLED_PROTOCOLS_DEFAULT); SSL_ENABLED_PROTOCOLS_DEFAULT);
String excludeCiphersConf = excludeCiphers = Arrays.asList(
sslConf.get(SSL_SERVER_EXCLUDE_CIPHER_LIST, ""); sslConf.getTrimmedStrings(SSL_SERVER_EXCLUDE_CIPHER_LIST));
if (excludeCiphersConf.isEmpty()) { if (LOG.isDebugEnabled()) {
excludeCiphers = new LinkedList<String>(); LOG.debug("will exclude cipher suites: {}",
} else { StringUtils.join(",", excludeCiphers));
LOG.debug("will exclude cipher suites: {}", excludeCiphersConf);
excludeCiphers = Arrays.asList(excludeCiphersConf.split(","));
} }
} }

View File

@ -440,10 +440,11 @@ public class StringUtils {
} }
/** /**
* Splits a comma separated value <code>String</code>, trimming leading and * Splits a comma or newline separated value <code>String</code>, trimming
* trailing whitespace on each value. * leading and trailing whitespace on each value.
* *
* @param str a comma separated <code>String</code> with values, may be null * @param str a comma or newline separated <code>String</code> with values,
* may be null
* @return an array of <code>String</code> values, empty array if null String * @return an array of <code>String</code> values, empty array if null String
* input * input
*/ */
@ -452,7 +453,7 @@ public class StringUtils {
return emptyStringArray; return emptyStringArray;
} }
return str.trim().split("\\s*,\\s*"); return str.trim().split("\\s*[,\n]\\s*");
} }
final public static String[] emptyStringArray = {}; final public static String[] emptyStringArray = {};

View File

@ -41,6 +41,7 @@ import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.ssl.KeyStoreTestUtil; import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
import org.apache.hadoop.security.ssl.SSLFactory; import org.apache.hadoop.security.ssl.SSLFactory;
import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.StringUtils;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -62,21 +63,21 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
private static String sslConfDir; private static String sslConfDir;
private static SSLFactory clientSslFactory; private static SSLFactory clientSslFactory;
private static final String excludeCiphers = "TLS_ECDHE_RSA_WITH_RC4_128_SHA," private static final String excludeCiphers = "TLS_ECDHE_RSA_WITH_RC4_128_SHA,"
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA," + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, \n"
+ "SSL_RSA_WITH_DES_CBC_SHA," + "SSL_RSA_WITH_DES_CBC_SHA,"
+ "SSL_DHE_RSA_WITH_DES_CBC_SHA," + "SSL_DHE_RSA_WITH_DES_CBC_SHA, "
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5," + "SSL_RSA_EXPORT_WITH_RC4_40_MD5,\t \n"
+ "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 \t";
private static final String oneEnabledCiphers = excludeCiphers private static final String oneEnabledCiphers = excludeCiphers
+ ",TLS_RSA_WITH_AES_128_CBC_SHA"; + ",TLS_RSA_WITH_AES_128_CBC_SHA";
private static final String exclusiveEnabledCiphers private static final String exclusiveEnabledCiphers
= "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," = "\tTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, \n"
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA," + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,"
+ "TLS_RSA_WITH_AES_128_CBC_SHA," + "TLS_RSA_WITH_AES_128_CBC_SHA,"
+ "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA," + "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "
+ "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA," + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,"
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA," + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA,\t\n "
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
@BeforeClass @BeforeClass
@ -169,7 +170,7 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory(); SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory();
PrefferedCipherSSLSocketFactory testPreferredCipherSSLSocketF PrefferedCipherSSLSocketFactory testPreferredCipherSSLSocketF
= new PrefferedCipherSSLSocketFactory(sslSocketF, = new PrefferedCipherSSLSocketFactory(sslSocketF,
excludeCiphers.split(",")); StringUtils.getTrimmedStrings(excludeCiphers));
conn.setSSLSocketFactory(testPreferredCipherSSLSocketF); conn.setSSLSocketFactory(testPreferredCipherSSLSocketF);
assertFalse("excludedCipher list is empty", excludeCiphers.isEmpty()); assertFalse("excludedCipher list is empty", excludeCiphers.isEmpty());
try { try {
@ -193,7 +194,7 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory(); SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory();
PrefferedCipherSSLSocketFactory testPreferredCipherSSLSocketF PrefferedCipherSSLSocketFactory testPreferredCipherSSLSocketF
= new PrefferedCipherSSLSocketFactory(sslSocketF, = new PrefferedCipherSSLSocketFactory(sslSocketF,
oneEnabledCiphers.split(",")); StringUtils.getTrimmedStrings(oneEnabledCiphers));
conn.setSSLSocketFactory(testPreferredCipherSSLSocketF); conn.setSSLSocketFactory(testPreferredCipherSSLSocketF);
assertFalse("excludedCipher list is empty", oneEnabledCiphers.isEmpty()); assertFalse("excludedCipher list is empty", oneEnabledCiphers.isEmpty());
try { try {
@ -219,7 +220,7 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory(); SSLSocketFactory sslSocketF = clientSslFactory.createSSLSocketFactory();
PrefferedCipherSSLSocketFactory testPreferredCipherSSLSocketF PrefferedCipherSSLSocketFactory testPreferredCipherSSLSocketF
= new PrefferedCipherSSLSocketFactory(sslSocketF, = new PrefferedCipherSSLSocketFactory(sslSocketF,
exclusiveEnabledCiphers.split(",")); StringUtils.getTrimmedStrings(exclusiveEnabledCiphers));
conn.setSSLSocketFactory(testPreferredCipherSSLSocketF); conn.setSSLSocketFactory(testPreferredCipherSSLSocketF);
assertFalse("excludedCipher list is empty", assertFalse("excludedCipher list is empty",
exclusiveEnabledCiphers.isEmpty()); exclusiveEnabledCiphers.isEmpty());

View File

@ -25,6 +25,7 @@ import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.alias.CredentialProviderFactory; import org.apache.hadoop.security.alias.CredentialProviderFactory;
import org.apache.hadoop.security.alias.JavaKeyStoreProvider; import org.apache.hadoop.security.alias.JavaKeyStoreProvider;
import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.StringUtils;
import org.apache.log4j.Level; import org.apache.log4j.Level;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -57,10 +58,10 @@ public class TestSSLFactory {
new File(BASEDIR).getAbsolutePath(); new File(BASEDIR).getAbsolutePath();
private String sslConfsDir; private String sslConfsDir;
private static final String excludeCiphers = "TLS_ECDHE_RSA_WITH_RC4_128_SHA," private static final String excludeCiphers = "TLS_ECDHE_RSA_WITH_RC4_128_SHA,"
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA," + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, \n"
+ "SSL_RSA_WITH_DES_CBC_SHA," + "SSL_RSA_WITH_DES_CBC_SHA,"
+ "SSL_DHE_RSA_WITH_DES_CBC_SHA," + "SSL_DHE_RSA_WITH_DES_CBC_SHA, "
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5," + "SSL_RSA_EXPORT_WITH_RC4_40_MD5,\t \n"
+ "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";
@ -190,7 +191,8 @@ public class TestSSLFactory {
SSLEngine serverSSLEngine = serverSSLFactory.createSSLEngine(); SSLEngine serverSSLEngine = serverSSLFactory.createSSLEngine();
SSLEngine clientSSLEngine = clientSSLFactory.createSSLEngine(); SSLEngine clientSSLEngine = clientSSLFactory.createSSLEngine();
// client selects cipher suites excluded by server // client selects cipher suites excluded by server
clientSSLEngine.setEnabledCipherSuites(excludeCiphers.split(",")); clientSSLEngine.setEnabledCipherSuites(
StringUtils.getTrimmedStrings(excludeCiphers));
// use the same buffer size for server and client. // use the same buffer size for server and client.
SSLSession session = clientSSLEngine.getSession(); SSLSession session = clientSSLEngine.getSession();