mirror of https://github.com/apache/lucene.git
SOLR-3854: Allows the test harness to perform two-way SSL handshakes, the two-way SSL will now be randomly selected during test runs. Also, cleaned up some of the code by breaking out the SSLConfig into a separate class. Also try and address failing the statics retained check.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1566515 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fcfc592785
commit
f5a1519069
|
@ -18,16 +18,14 @@
|
||||||
package org.apache.solr.client.solrj.embedded;
|
package org.apache.solr.client.solrj.embedded;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.SortedMap;
|
import java.util.SortedMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.net.URL;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
|
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
|
@ -200,15 +198,6 @@ public class JettySolrRunner {
|
||||||
this.init(solrHome, context, port, stopAtShutdown);
|
this.init(solrHome, context, port, stopAtShutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SSLConfig {
|
|
||||||
public boolean useSsl;
|
|
||||||
public boolean clientAuth;
|
|
||||||
public String keyStore;
|
|
||||||
public String keyStorePassword;
|
|
||||||
public String trustStore;
|
|
||||||
public String trustStorePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(String solrHome, String context, int port, boolean stopAtShutdown) {
|
private void init(String solrHome, String context, int port, boolean stopAtShutdown) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
server = new Server(port);
|
server = new Server(port);
|
||||||
|
@ -232,7 +221,7 @@ public class JettySolrRunner {
|
||||||
// the server as well as any client actions taken by this JVM in
|
// the server as well as any client actions taken by this JVM in
|
||||||
// talking to that server, but for the purposes of testing that should
|
// talking to that server, but for the purposes of testing that should
|
||||||
// be good enough
|
// be good enough
|
||||||
final boolean useSsl = sslConfig == null ? false : sslConfig.useSsl;
|
final boolean useSsl = sslConfig == null ? false : sslConfig.isSSLMode();
|
||||||
final SslContextFactory sslcontext = new SslContextFactory(false);
|
final SslContextFactory sslcontext = new SslContextFactory(false);
|
||||||
sslInit(useSsl, sslcontext);
|
sslInit(useSsl, sslcontext);
|
||||||
|
|
||||||
|
@ -356,20 +345,20 @@ public class JettySolrRunner {
|
||||||
|
|
||||||
private void sslInit(final boolean useSsl, final SslContextFactory sslcontext) {
|
private void sslInit(final boolean useSsl, final SslContextFactory sslcontext) {
|
||||||
if (useSsl && sslConfig != null) {
|
if (useSsl && sslConfig != null) {
|
||||||
if (null != sslConfig.keyStore) {
|
if (null != sslConfig.getKeyStore()) {
|
||||||
sslcontext.setKeyStorePath(sslConfig.keyStore);
|
sslcontext.setKeyStorePath(sslConfig.getKeyStore());
|
||||||
}
|
}
|
||||||
if (null != sslConfig.keyStorePassword) {
|
if (null != sslConfig.getKeyStorePassword()) {
|
||||||
sslcontext.setKeyStorePassword(sslConfig.keyStorePassword);
|
sslcontext.setKeyStorePassword(sslConfig.getKeyStorePassword());
|
||||||
}
|
}
|
||||||
if (null != sslConfig.trustStore) {
|
if (null != sslConfig.getTrustStore()) {
|
||||||
sslcontext.setTrustStore(System
|
sslcontext.setTrustStore(System
|
||||||
.getProperty(sslConfig.trustStore));
|
.getProperty(sslConfig.getTrustStore()));
|
||||||
}
|
}
|
||||||
if (null != sslConfig.trustStorePassword) {
|
if (null != sslConfig.getTrustStorePassword()) {
|
||||||
sslcontext.setTrustStorePassword(sslConfig.trustStorePassword);
|
sslcontext.setTrustStorePassword(sslConfig.getTrustStorePassword());
|
||||||
}
|
}
|
||||||
sslcontext.setNeedClientAuth(sslConfig.clientAuth);
|
sslcontext.setNeedClientAuth(sslConfig.isClientAuthMode());
|
||||||
} else {
|
} else {
|
||||||
boolean jettySsl = Boolean.getBoolean(System.getProperty("tests.jettySsl"));
|
boolean jettySsl = Boolean.getBoolean(System.getProperty("tests.jettySsl"));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.apache.solr.client.solrj.embedded;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SSLConfig {
|
||||||
|
|
||||||
|
private boolean useSsl;
|
||||||
|
private boolean clientAuth;
|
||||||
|
private String keyStore;
|
||||||
|
private String keyStorePassword;
|
||||||
|
private String trustStore;
|
||||||
|
private String trustStorePassword;
|
||||||
|
|
||||||
|
public SSLConfig(boolean useSSL, boolean clientAuth, String keyStore, String keyStorePassword, String trustStore, String trustStorePassword) {
|
||||||
|
this.useSsl = useSSL;
|
||||||
|
this.clientAuth = clientAuth;
|
||||||
|
this.keyStore = keyStore;
|
||||||
|
this.keyStorePassword = keyStorePassword;
|
||||||
|
this.trustStore = trustStore;
|
||||||
|
this.trustStorePassword = trustStorePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUseSSL(boolean useSSL) {
|
||||||
|
this.useSsl = useSSL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientAuth(boolean clientAuth) {
|
||||||
|
this.clientAuth = clientAuth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSSLMode() {
|
||||||
|
return useSsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClientAuthMode() {
|
||||||
|
return clientAuth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyStore() {
|
||||||
|
return keyStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyStorePassword() {
|
||||||
|
return keyStorePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrustStore() {
|
||||||
|
return trustStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrustStorePassword() {
|
||||||
|
return trustStorePassword;
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,7 +45,8 @@ public class OverseerRolesTest extends AbstractFullDistribZkTestBase{
|
||||||
private CloudSolrServer client;
|
private CloudSolrServer client;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
sslConfig = null;
|
// SSL does not work with this feature for some reason
|
||||||
|
ALLOW_SSL = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// does not yet work with ssl
|
// does not yet work with ssl
|
||||||
sslConfig = null;
|
ALLOW_SSL = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
|
|
@ -70,8 +70,8 @@ public class DistributedDebugComponentTest extends SolrJettyTestBase {
|
||||||
|
|
||||||
String urlCollection1 = jetty.getBaseUrl().toString() + "/" + "collection1";
|
String urlCollection1 = jetty.getBaseUrl().toString() + "/" + "collection1";
|
||||||
String urlCollection2 = jetty.getBaseUrl().toString() + "/" + "collection2";
|
String urlCollection2 = jetty.getBaseUrl().toString() + "/" + "collection2";
|
||||||
shard1 = urlCollection1.replaceAll("http" + (sslConfig == null || !sslConfig.useSsl ? "" : "s") + "://", "");
|
shard1 = urlCollection1.replaceAll("https?://", "");
|
||||||
shard2 = urlCollection2.replaceAll("http" + (sslConfig == null || !sslConfig.useSsl ? "" : "s") + "://", "");
|
shard2 = urlCollection2.replaceAll("https?://", "");
|
||||||
|
|
||||||
//create second core
|
//create second core
|
||||||
CoreAdminRequest.Create req = new CoreAdminRequest.Create();
|
CoreAdminRequest.Create req = new CoreAdminRequest.Create();
|
||||||
|
|
|
@ -50,8 +50,8 @@ public class TestRemoteStreaming extends SolrJettyTestBase {
|
||||||
private static final File solrHomeDirectory = new File(TEMP_DIR, "TestRemoteStreaming");
|
private static final File solrHomeDirectory = new File(TEMP_DIR, "TestRemoteStreaming");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// does not yet work with ssl
|
// does not yet work with ssl - uses raw URL
|
||||||
sslConfig = null;
|
ALLOW_SSL = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
|
|
@ -41,11 +41,6 @@ import com.google.common.base.Charsets;
|
||||||
public class CacheHeaderTest extends CacheHeaderTestBase {
|
public class CacheHeaderTest extends CacheHeaderTestBase {
|
||||||
private static final File solrHomeDirectory = new File(TEMP_DIR, "CacheHeaderTest");
|
private static final File solrHomeDirectory = new File(TEMP_DIR, "CacheHeaderTest");
|
||||||
|
|
||||||
static {
|
|
||||||
// does not yet work with ssl
|
|
||||||
sslConfig = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() throws Exception {
|
public static void beforeTest() throws Exception {
|
||||||
setupJettyTestHome(solrHomeDirectory, "collection1");
|
setupJettyTestHome(solrHomeDirectory, "collection1");
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class SolrCmdDistributorTest extends BaseDistributedSearchTestCase {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// no ssl currently because distrib updates read scheme from zk and no zk in this test
|
// no ssl currently because distrib updates read scheme from zk and no zk in this test
|
||||||
sslConfig = null;
|
ALLOW_SSL = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.apache.solr.common.SolrException.ErrorCode;
|
||||||
import org.apache.solr.common.params.CommonParams;
|
import org.apache.solr.common.params.CommonParams;
|
||||||
import org.apache.solr.common.util.NamedList;
|
import org.apache.solr.common.util.NamedList;
|
||||||
import org.apache.solr.util.ExternalPaths;
|
import org.apache.solr.util.ExternalPaths;
|
||||||
|
import org.apache.solr.util.SSLTestConfig;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -506,7 +507,7 @@ public class BasicHttpSolrServerTest extends SolrJettyTestBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A trivial test that verifies the example keystore used for SSL testing can be
|
* A trivial test that verifies the example keystore used for SSL testing can be
|
||||||
* found using the base class. this helps future-proof against hte possibility of
|
* found using the base class. this helps future-proof against the possibility of
|
||||||
* something moving/breaking the keystore path in a way that results in the SSL
|
* something moving/breaking the keystore path in a way that results in the SSL
|
||||||
* randomization logic being forced to silently never use SSL. (We can't enforce
|
* randomization logic being forced to silently never use SSL. (We can't enforce
|
||||||
* this type of check in the base class because then it would not be usable by client
|
* this type of check in the base class because then it would not be usable by client
|
||||||
|
@ -516,7 +517,7 @@ public class BasicHttpSolrServerTest extends SolrJettyTestBase {
|
||||||
assertNotNull("Example keystore is null, meaning that something has changed in the " +
|
assertNotNull("Example keystore is null, meaning that something has changed in the " +
|
||||||
"structure of the example configs and/or ExternalPaths.java - " +
|
"structure of the example configs and/or ExternalPaths.java - " +
|
||||||
"SSL randomization is broken",
|
"SSL randomization is broken",
|
||||||
getExampleKeystoreFile());
|
SSLTestConfig.TEST_KEYSTORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,7 @@ import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.solr.client.solrj.SolrServer;
|
import org.apache.solr.client.solrj.SolrServer;
|
||||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
|
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
|
||||||
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
|
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
|
||||||
import org.apache.solr.client.solrj.embedded.JettySolrRunner.SSLConfig;
|
|
||||||
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
||||||
import org.apache.solr.util.ExternalPaths;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
|
|
@ -24,10 +24,6 @@ import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.security.KeyManagementException;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.UnrecoverableKeyException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -46,11 +42,6 @@ import javax.xml.xpath.XPathExpressionException;
|
||||||
|
|
||||||
import org.apache.commons.codec.Charsets;
|
import org.apache.commons.codec.Charsets;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.http.conn.scheme.Scheme;
|
|
||||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
|
||||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
|
||||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
|
||||||
import org.apache.lucene.analysis.MockAnalyzer;
|
import org.apache.lucene.analysis.MockAnalyzer;
|
||||||
import org.apache.lucene.analysis.MockTokenizer;
|
import org.apache.lucene.analysis.MockTokenizer;
|
||||||
import org.apache.lucene.index.IndexWriterConfig;
|
import org.apache.lucene.index.IndexWriterConfig;
|
||||||
|
@ -58,7 +49,6 @@ import org.apache.lucene.util.IOUtils;
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
import org.apache.lucene.util.QuickPatchThreadsFilter;
|
import org.apache.lucene.util.QuickPatchThreadsFilter;
|
||||||
import org.apache.lucene.util._TestUtil;
|
import org.apache.lucene.util._TestUtil;
|
||||||
import org.apache.solr.client.solrj.embedded.JettySolrRunner.SSLConfig;
|
|
||||||
import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
|
import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
|
||||||
import org.apache.solr.client.solrj.impl.HttpClientUtil;
|
import org.apache.solr.client.solrj.impl.HttpClientUtil;
|
||||||
import org.apache.solr.client.solrj.util.ClientUtils;
|
import org.apache.solr.client.solrj.util.ClientUtils;
|
||||||
|
@ -89,8 +79,8 @@ import org.apache.solr.schema.SchemaField;
|
||||||
import org.apache.solr.search.SolrIndexSearcher;
|
import org.apache.solr.search.SolrIndexSearcher;
|
||||||
import org.apache.solr.servlet.DirectSolrConnection;
|
import org.apache.solr.servlet.DirectSolrConnection;
|
||||||
import org.apache.solr.util.AbstractSolrTestCase;
|
import org.apache.solr.util.AbstractSolrTestCase;
|
||||||
import org.apache.solr.util.ExternalPaths;
|
|
||||||
import org.apache.solr.util.RevertDefaultThreadHandlerRule;
|
import org.apache.solr.util.RevertDefaultThreadHandlerRule;
|
||||||
|
import org.apache.solr.util.SSLTestConfig;
|
||||||
import org.apache.solr.util.TestHarness;
|
import org.apache.solr.util.TestHarness;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -123,7 +113,10 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||||
private static String coreName = ConfigSolrXmlOld.DEFAULT_DEFAULT_CORE_NAME;
|
private static String coreName = ConfigSolrXmlOld.DEFAULT_DEFAULT_CORE_NAME;
|
||||||
public static int DEFAULT_CONNECTION_TIMEOUT = 45000; // default socket connection timeout in ms
|
public static int DEFAULT_CONNECTION_TIMEOUT = 45000; // default socket connection timeout in ms
|
||||||
|
|
||||||
protected static volatile SSLConfig sslConfig = new SSLConfig();
|
// these are meant to be accessed sequentially, but are volatile just to ensure any test
|
||||||
|
// thread will read the latest value
|
||||||
|
protected static volatile boolean ALLOW_SSL = true;
|
||||||
|
protected static volatile SSLTestConfig sslConfig;
|
||||||
|
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static TestRule solrClassRules =
|
public static TestRule solrClassRules =
|
||||||
|
@ -146,31 +139,13 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||||
startTrackingZkClients();
|
startTrackingZkClients();
|
||||||
ignoreException("ignore_exception");
|
ignoreException("ignore_exception");
|
||||||
newRandomConfig();
|
newRandomConfig();
|
||||||
sslConfig = getSSLConfig();
|
|
||||||
|
|
||||||
|
sslConfig = buildSSLConfig();
|
||||||
if(sslConfig != null && sslConfig.useSsl) {
|
//will use ssl specific or default depending on sslConfig
|
||||||
|
HttpClientUtil.setConfigurer(sslConfig.getHttpClientConfigurer());
|
||||||
|
if(isSSLMode()) {
|
||||||
// SolrCloud tests should usually clear this
|
// SolrCloud tests should usually clear this
|
||||||
System.setProperty("urlScheme", "https");
|
System.setProperty("urlScheme", "https");
|
||||||
|
|
||||||
// Turn off two-way SSL since it isn't configured below...
|
|
||||||
sslConfig.clientAuth = false;
|
|
||||||
HttpClientUtil.setConfigurer(new HttpClientConfigurer(){
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
protected void configure(DefaultHttpClient httpClient, SolrParams config) {
|
|
||||||
super.configure(httpClient, config);
|
|
||||||
SchemeRegistry registry = httpClient.getConnectionManager().getSchemeRegistry();
|
|
||||||
// Make sure no tests cheat by using HTTP
|
|
||||||
registry.unregister("http");
|
|
||||||
try {
|
|
||||||
// Don't complain that we are using self-signed certs during the test
|
|
||||||
registry.register(new Scheme("https", 443, new SSLSocketFactory(new TrustSelfSignedStrategy())));
|
|
||||||
} catch (KeyManagementException | UnrecoverableKeyException
|
|
||||||
| NoSuchAlgorithmException | KeyStoreException ex) {
|
|
||||||
throw new IllegalStateException("Unable to setup https scheme for HTTPClient to test SSL.", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,41 +164,16 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||||
System.clearProperty("useCompoundFile");
|
System.clearProperty("useCompoundFile");
|
||||||
System.clearProperty("urlScheme");
|
System.clearProperty("urlScheme");
|
||||||
|
|
||||||
if(sslConfig != null && sslConfig.useSsl) {
|
if(isSSLMode()) {
|
||||||
HttpClientUtil.setConfigurer(new HttpClientConfigurer());
|
HttpClientUtil.setConfigurer(new HttpClientConfigurer());
|
||||||
}
|
}
|
||||||
|
// clean up static
|
||||||
|
sslConfig = null;
|
||||||
IpTables.unblockAllPorts();
|
IpTables.unblockAllPorts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File TEST_KEYSTORE;
|
protected static boolean isSSLMode() {
|
||||||
static {
|
return sslConfig != null && sslConfig.isSSLMode();
|
||||||
TEST_KEYSTORE = (null == ExternalPaths.SOURCE_HOME)
|
|
||||||
? null : new File(ExternalPaths.SOURCE_HOME, "example/etc/solrtest.keystore");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isSSLMode() {
|
|
||||||
return sslConfig != null && sslConfig.useSsl;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void initSSLConfig(SSLConfig sslConfig, String keystorePath) {
|
|
||||||
sslConfig.useSsl = false;
|
|
||||||
sslConfig.clientAuth = false;
|
|
||||||
sslConfig.keyStore = keystorePath;
|
|
||||||
sslConfig.keyStorePassword = "secret";
|
|
||||||
sslConfig.trustStore = keystorePath;
|
|
||||||
sslConfig.trustStorePassword = "secret";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the File object for the example keystore used when this baseclass randomly
|
|
||||||
* uses SSL. May be null ifthis test does not appear to be running as part of the
|
|
||||||
* standard solr distribution and does not have access to the example configs.
|
|
||||||
*
|
|
||||||
* @lucene.internal
|
|
||||||
*/
|
|
||||||
protected static File getExampleKeystoreFile() {
|
|
||||||
return TEST_KEYSTORE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean changedFactory = false;
|
private static boolean changedFactory = false;
|
||||||
|
@ -252,38 +202,19 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SSLConfig getSSLConfig() {
|
private static SSLTestConfig buildSSLConfig() {
|
||||||
// test has disabled
|
// test has been disabled
|
||||||
if (sslConfig == null) {
|
if (!ALLOW_SSL) {
|
||||||
SSLConfig sslConfig = new SSLConfig();
|
return new SSLTestConfig();
|
||||||
return sslConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// only randomize SSL if we are a solr test with access to the example keystore
|
|
||||||
if (null == getExampleKeystoreFile()) {
|
|
||||||
log.info("Solr's example keystore not defined (not a solr test?) skipping SSL randomization");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue("test keystore does not exist, randomized ssl testing broken: " +
|
|
||||||
getExampleKeystoreFile().getAbsolutePath(),
|
|
||||||
getExampleKeystoreFile().exists() );
|
|
||||||
|
|
||||||
SSLConfig sslConfig = new SSLConfig();
|
|
||||||
|
|
||||||
final boolean trySsl = random().nextBoolean();
|
final boolean trySsl = random().nextBoolean();
|
||||||
final boolean trySslClientAuth = false; // TODO: random().nextBoolean();
|
final boolean trySslClientAuth = random().nextBoolean();
|
||||||
|
|
||||||
log.info("Randomized ssl ({}) and clientAuth ({})", trySsl,
|
log.info("Randomized ssl ({}) and clientAuth ({})", trySsl,
|
||||||
trySslClientAuth);
|
trySslClientAuth);
|
||||||
String keystorePath = null == TEST_KEYSTORE ? null : TEST_KEYSTORE
|
|
||||||
.getAbsolutePath();
|
|
||||||
initSSLConfig(sslConfig, keystorePath);
|
|
||||||
|
|
||||||
sslConfig.useSsl = trySsl;
|
return new SSLTestConfig(trySsl, trySslClientAuth);
|
||||||
sslConfig.clientAuth = trySslClientAuth;
|
|
||||||
|
|
||||||
return sslConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static MockTokenizer whitespaceMockTokenizer(Reader input) throws IOException {
|
protected static MockTokenizer whitespaceMockTokenizer(Reader input) throws IOException {
|
||||||
|
|
|
@ -41,13 +41,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.http.params.CoreConnectionPNames;
|
import org.apache.http.params.CoreConnectionPNames;
|
||||||
import org.apache.lucene.util.LuceneTestCase.Slow;
|
import org.apache.lucene.util.LuceneTestCase.Slow;
|
||||||
import org.apache.solr.SolrJettyTestBase;
|
|
||||||
import org.apache.solr.client.solrj.SolrQuery;
|
import org.apache.solr.client.solrj.SolrQuery;
|
||||||
import org.apache.solr.client.solrj.SolrRequest;
|
import org.apache.solr.client.solrj.SolrRequest;
|
||||||
import org.apache.solr.client.solrj.SolrServer;
|
import org.apache.solr.client.solrj.SolrServer;
|
||||||
import org.apache.solr.client.solrj.SolrServerException;
|
import org.apache.solr.client.solrj.SolrServerException;
|
||||||
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
|
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
|
||||||
import org.apache.solr.client.solrj.embedded.JettySolrRunner.SSLConfig;
|
|
||||||
import org.apache.solr.client.solrj.impl.CloudSolrServer;
|
import org.apache.solr.client.solrj.impl.CloudSolrServer;
|
||||||
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
||||||
import org.apache.solr.client.solrj.request.QueryRequest;
|
import org.apache.solr.client.solrj.request.QueryRequest;
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.apache.solr.common.params.MultiMapSolrParams;
|
||||||
import org.apache.solr.common.util.StrUtils;
|
import org.apache.solr.common.util.StrUtils;
|
||||||
import org.apache.solr.servlet.SolrRequestParsers;
|
import org.apache.solr.servlet.SolrRequestParsers;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
@ -38,11 +37,6 @@ abstract public class RestTestBase extends SolrJettyTestBase {
|
||||||
private static final Logger log = LoggerFactory.getLogger(RestTestBase.class);
|
private static final Logger log = LoggerFactory.getLogger(RestTestBase.class);
|
||||||
protected static RestTestHarness restTestHarness;
|
protected static RestTestHarness restTestHarness;
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
// sslConfig = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createJettyAndHarness
|
public static void createJettyAndHarness
|
||||||
(String solrHome, String configFile, String schemaFile, String context,
|
(String solrHome, String configFile, String schemaFile, String context,
|
||||||
boolean stopAtShutdown, SortedMap<ServletHolder,String> extraServlets) throws Exception {
|
boolean stopAtShutdown, SortedMap<ServletHolder,String> extraServlets) throws Exception {
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
package org.apache.solr.util;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.UnrecoverableKeyException;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
|
import org.apache.http.conn.scheme.Scheme;
|
||||||
|
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||||
|
import org.apache.http.conn.ssl.SSLContexts;
|
||||||
|
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.solr.client.solrj.embedded.SSLConfig;
|
||||||
|
import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
|
||||||
|
import org.apache.solr.common.params.SolrParams;
|
||||||
|
import org.eclipse.jetty.util.security.CertificateUtils;
|
||||||
|
|
||||||
|
public class SSLTestConfig extends SSLConfig {
|
||||||
|
public static File TEST_KEYSTORE = ExternalPaths.SOURCE_HOME == null ? null
|
||||||
|
: new File(ExternalPaths.SOURCE_HOME, "example/etc/solrtest.keystore");
|
||||||
|
|
||||||
|
private static String TEST_KEYSTORE_PATH = TEST_KEYSTORE != null
|
||||||
|
&& TEST_KEYSTORE.exists() ? TEST_KEYSTORE.getAbsolutePath() : null;
|
||||||
|
private static String TEST_KEYSTORE_PASSWORD = "secret";
|
||||||
|
private static HttpClientConfigurer DEFAULT_CONFIGURER = new HttpClientConfigurer();
|
||||||
|
|
||||||
|
public SSLTestConfig() {
|
||||||
|
this(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SSLTestConfig(boolean useSSL, boolean clientAuth) {
|
||||||
|
super(useSSL, clientAuth, TEST_KEYSTORE_PATH, TEST_KEYSTORE_PASSWORD, TEST_KEYSTORE_PATH, TEST_KEYSTORE_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SSLTestConfig(boolean useSSL, boolean clientAuth, String keyStore, String keyStorePassword, String trustStore, String trustStorePassword) {
|
||||||
|
super(useSSL, clientAuth, keyStore, keyStorePassword, trustStore, trustStorePassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will provide an HttpClientConfigurer for SSL support (adds https and
|
||||||
|
* removes http schemes) is SSL is enabled, otherwise return the default
|
||||||
|
* configurer
|
||||||
|
*/
|
||||||
|
public HttpClientConfigurer getHttpClientConfigurer() {
|
||||||
|
return isSSLMode() ? new SSLHttpClientConfigurer() : DEFAULT_CONFIGURER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a new SSLContext with the given configuration and allows the uses of
|
||||||
|
* self-signed certificates during testing.
|
||||||
|
*/
|
||||||
|
protected SSLContext buildSSLContext() throws KeyManagementException,
|
||||||
|
UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
|
||||||
|
|
||||||
|
return SSLContexts.custom()
|
||||||
|
.loadKeyMaterial(buildKeyStore(getKeyStore(), getKeyStorePassword()), getKeyStorePassword().toCharArray())
|
||||||
|
.loadTrustMaterial(buildKeyStore(getTrustStore(), getTrustStorePassword()), new TrustSelfSignedStrategy()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected static KeyStore buildKeyStore(String keyStoreLocation, String password) {
|
||||||
|
try {
|
||||||
|
return CertificateUtils.getKeyStore(null, keyStoreLocation, "JKS", null, password);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalStateException("Unable to build KeyStore from file: " + keyStoreLocation, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SSLHttpClientConfigurer extends HttpClientConfigurer {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
protected void configure(DefaultHttpClient httpClient, SolrParams config) {
|
||||||
|
super.configure(httpClient, config);
|
||||||
|
SchemeRegistry registry = httpClient.getConnectionManager().getSchemeRegistry();
|
||||||
|
// Make sure no tests cheat by using HTTP
|
||||||
|
registry.unregister("http");
|
||||||
|
try {
|
||||||
|
registry.register(new Scheme("https", 443, new SSLSocketFactory(buildSSLContext())));
|
||||||
|
} catch (KeyManagementException | UnrecoverableKeyException
|
||||||
|
| NoSuchAlgorithmException | KeyStoreException ex) {
|
||||||
|
throw new IllegalStateException("Unable to setup https scheme for HTTPClient to test SSL.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cleanStatics() {
|
||||||
|
DEFAULT_CONFIGURER = null;
|
||||||
|
TEST_KEYSTORE = null;
|
||||||
|
TEST_KEYSTORE_PASSWORD = null;
|
||||||
|
TEST_KEYSTORE_PATH = null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue