You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by kr...@apache.org on 2016/05/04 16:17:36 UTC
[45/50] lucene-solr:jira/solr-8593: SOLR-5776: refactor SSLConfig so
that SSLTestConfig can provide SSLContexts using a NullSecureRandom to
prevent SSL tests from blocking on entropy starved machines
SOLR-5776: refactor SSLConfig so that SSLTestConfig can provide SSLContexts using a NullSecureRandom to prevent SSL tests from blocking on entropy starved machines
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/9677e2c5
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/9677e2c5
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/9677e2c5
Branch: refs/heads/jira/solr-8593
Commit: 9677e2c54bbc66283f3f4341a4e1166006069fc3
Parents: 6ef0f21
Author: Chris Hostetter <ho...@apache.org>
Authored: Tue May 3 14:01:23 2016 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Tue May 3 15:31:53 2016 -0700
----------------------------------------------------------------------
.../solr/client/solrj/embedded/SSLConfig.java | 71 +++++++++-----
.../org/apache/solr/util/SSLTestConfig.java | 99 +++++++++++++++++++-
2 files changed, 144 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9677e2c5/solr/core/src/java/org/apache/solr/client/solrj/embedded/SSLConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/client/solrj/embedded/SSLConfig.java b/solr/core/src/java/org/apache/solr/client/solrj/embedded/SSLConfig.java
index f777951..60f383c 100644
--- a/solr/core/src/java/org/apache/solr/client/solrj/embedded/SSLConfig.java
+++ b/solr/core/src/java/org/apache/solr/client/solrj/embedded/SSLConfig.java
@@ -77,38 +77,63 @@ public class SSLConfig {
/**
* Returns an SslContextFactory that should be used by a jetty server based on the specified
- * configuration, or null if no SSL should be used.
+ * SSLConfig param which may be null.
*
- * The specified sslConfig will be completely ignored if the "tests.jettySsl" system property is
- * true - in which case standard "javax.net.ssl.*" system properties will be used instead, along
- * with "tests.jettySsl.clientAuth"
+ * if the SSLConfig param is non-null, then this method will return the results of
+ * {@link #createContextFactory()}.
*
- * @see #isSSLMode
+ * If the SSLConfig param is null, then this method will return null unless the
+ * <code>tests.jettySsl</code> system property is true, in which case standard "javax.net.ssl.*"
+ * system properties will be used instead, along with "tests.jettySsl.clientAuth".
+ *
+ * @see #createContextFactory()
*/
public static SslContextFactory createContextFactory(SSLConfig sslConfig) {
- if (sslConfig == null) {
- if (Boolean.getBoolean("tests.jettySsl")) {
- return configureSslFromSysProps();
- }
- return null;
+ if (sslConfig != null) {
+ return sslConfig.createContextFactory();
}
+ // else...
+ if (Boolean.getBoolean("tests.jettySsl")) {
+ return configureSslFromSysProps();
+ }
+ // else...
+ return null;
+ }
+
+ /**
+ * Returns an SslContextFactory that should be used by a jetty server based on this SSLConfig instance,
+ * or null if SSL should not be used.
+ *
+ * The default implementation generates a simple factory according to the keystore, truststore,
+ * and clientAuth properties of this object.
+ *
+ * @see #getKeyStore
+ * @see #getKeyStorePassword
+ * @see #isClientAuthMode
+ * @see #getTrustStore
+ * @see #getTrustStorePassword
+ */
+ public SslContextFactory createContextFactory() {
- if (!sslConfig.isSSLMode())
- return null;
-
+ if (! isSSLMode()) {
+ return null;
+ }
+ // else...
+
SslContextFactory factory = new SslContextFactory(false);
- if (sslConfig.getKeyStore() != null)
- factory.setKeyStorePath(sslConfig.getKeyStore());
- if (sslConfig.getKeyStorePassword() != null)
- factory.setKeyStorePassword(sslConfig.getKeyStorePassword());
- factory.setNeedClientAuth(sslConfig.isClientAuthMode());
+ if (getKeyStore() != null)
+ factory.setKeyStorePath(getKeyStore());
+ if (getKeyStorePassword() != null)
+ factory.setKeyStorePassword(getKeyStorePassword());
+
+ factory.setNeedClientAuth(isClientAuthMode());
- if (sslConfig.isClientAuthMode()) {
- if (sslConfig.getTrustStore() != null)
- factory.setTrustStorePath(sslConfig.getTrustStore());
- if (sslConfig.getTrustStorePassword() != null)
- factory.setTrustStorePassword(sslConfig.getTrustStorePassword());
+ if (isClientAuthMode()) {
+ if (getTrustStore() != null)
+ factory.setTrustStorePath(getTrustStore());
+ if (getTrustStorePassword() != null)
+ factory.setTrustStorePassword(getTrustStorePassword());
}
return factory;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9677e2c5/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java
index 9049618..9d65a88 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java
@@ -21,6 +21,8 @@ import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.SecureRandomSpi;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.SSLContext;
@@ -40,8 +42,10 @@ import org.apache.solr.client.solrj.embedded.SSLConfig;
import org.apache.solr.client.solrj.impl.HttpClientUtil;
import org.apache.solr.client.solrj.impl.HttpClientUtil.SchemaRegistryProvider;
import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
+
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.CertificateUtils;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SSLTestConfig extends SSLConfig {
public static File TEST_KEYSTORE = ExternalPaths.SERVER_HOME == null ? null
@@ -82,7 +86,10 @@ public class SSLTestConfig extends SSLConfig {
/**
* Builds a new SSLContext for HTTP <b>clients</b> to use when communicating with servers which have
- * been configured based on the settings of this object. Also explicitly allows the use of self-signed
+ * been configured based on the settings of this object.
+ *
+ * NOTE: Uses a completely insecure {@link SecureRandom} instance to prevent tests from blocking
+ * due to lack of entropy, also explicitly allows the use of self-signed
* certificates (since that's what is almost always used during testing).
*/
public SSLContext buildClientSSLContext() throws KeyManagementException,
@@ -91,7 +98,8 @@ public class SSLTestConfig extends SSLConfig {
assert isSSLMode();
SSLContextBuilder builder = SSLContexts.custom();
-
+ builder.setSecureRandom(NullSecureRandom.INSTANCE);
+
// NOTE: KeyStore & TrustStore are swapped because they are from configured from server perspective...
// we are a client - our keystore contains the keys the server trusts, and vice versa
builder.loadTrustMaterial(buildKeyStore(getKeyStore(), getKeyStorePassword()), new TrustSelfSignedStrategy()).build();
@@ -105,6 +113,54 @@ public class SSLTestConfig extends SSLConfig {
}
/**
+ * Builds a new SSLContext for jetty servers which have been configured based on the settings of
+ * this object.
+ *
+ * NOTE: Uses a completely insecure {@link SecureRandom} instance to prevent tests from blocking
+ * due to lack of entropy, also explicitly allows the use of self-signed
+ * certificates (since that's what is almost always used during testing).
+ * almost always used during testing).
+ */
+ public SSLContext buildServerSSLContext() throws KeyManagementException,
+ UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
+
+ assert isSSLMode();
+
+ SSLContextBuilder builder = SSLContexts.custom();
+ builder.setSecureRandom(NullSecureRandom.INSTANCE);
+
+ builder.loadKeyMaterial(buildKeyStore(getKeyStore(), getKeyStorePassword()), getKeyStorePassword().toCharArray());
+
+ if (isClientAuthMode()) {
+ builder.loadTrustMaterial(buildKeyStore(getTrustStore(), getTrustStorePassword()), new TrustSelfSignedStrategy()).build();
+
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * Returns an SslContextFactory using {@link buildServerSSLContext} if SSL should be used, else returns null.
+ */
+ @Override
+ public SslContextFactory createContextFactory() {
+ if (!isSSLMode()) {
+ return null;
+ }
+ // else...
+
+
+ SslContextFactory factory = new SslContextFactory(false);
+ try {
+ factory.setSslContext(buildServerSSLContext());
+ } catch (Exception e) {
+ throw new RuntimeException("ssl context init failure: " + e.getMessage(), e);
+ }
+ factory.setNeedClientAuth(isClientAuthMode());
+ return factory;
+ }
+
+ /**
* Constructs a KeyStore using the specified filename and password
*/
protected static KeyStore buildKeyStore(String keyStoreLocation, String password) {
@@ -202,5 +258,42 @@ public class SSLTestConfig extends SSLConfig {
System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");
}
-
+
+ /**
+ * A mocked up instance of SecureRandom that always does the minimal amount of work to generate
+ * "random" numbers. This is to prevent blocking issues that arise in platform default
+ * SecureRandom instances due to too many instances / not enough random entropy.
+ * Tests do not need secure SSL.
+ */
+ private static class NullSecureRandom extends SecureRandom {
+ public static final SecureRandom INSTANCE = new NullSecureRandom();
+
+ /** SPI Used to init all instances */
+ private static final SecureRandomSpi NULL_SPI = new SecureRandomSpi() {
+ /** NOOP: returns new uninitialized byte[] */
+ public byte[] engineGenerateSeed(int numBytes) {
+ return new byte[numBytes];
+ }
+ /** NOOP */
+ public void engineNextBytes(byte[] bytes) { /* NOOP */ }
+ /** NOOP */
+ public void engineSetSeed(byte[] seed) { /* NOOP */ }
+ };
+
+ private NullSecureRandom() {
+ super(NULL_SPI, null) ;
+ }
+
+ /** NOOP: returns new uninitialized byte[] */
+ public byte[] generateSeed(int numBytes) {
+ return new byte[numBytes];
+ }
+ /** NOOP */
+ synchronized public void nextBytes(byte[] bytes) { /* NOOP */ }
+ /** NOOP */
+ synchronized public void setSeed(byte[] seed) { /* NOOP */ }
+ /** NOOP */
+ synchronized public void setSeed(long seed) { /* NOOP */ }
+
+ }
}