diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java index 65a63e5337..ebb274a1d8 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java @@ -642,7 +642,7 @@ public class NettyConnector extends AbstractConnector { String realTrustStorePath, String realTrustStorePassword) throws Exception { - SslContext context = SSLSupport.createNettyContext(realKeyStoreProvider, realKeyStorePath, realKeyStorePassword, realTrustStoreProvider, realTrustStorePath, realTrustStorePassword, sslProvider); + SslContext context = SSLSupport.createNettyClientContext(realKeyStoreProvider, realKeyStorePath, realKeyStorePassword, realTrustStoreProvider, realTrustStorePath, realTrustStorePassword, sslProvider, trustAll); Subject subject = null; if (kerb5Config != null) { diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java index 297b294ec6..85c2c50609 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java @@ -29,7 +29,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.security.AccessController; import java.security.KeyStore; -import java.security.PrivateKey; import java.security.PrivilegedAction; import java.security.SecureRandom; import java.security.Security; @@ -39,7 +38,6 @@ import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXBuilderParameters; import java.security.cert.X509CertSelector; -import java.security.cert.X509Certificate; import java.util.Collection; import io.netty.handler.ssl.SslContext; @@ -112,12 +110,26 @@ public class SSLSupport { final String sslProvider) throws Exception { KeyStore keyStore = SSLSupport.loadKeystore(keystoreProvider, keystorePath, keystorePassword); - String alias = keyStore.aliases().nextElement(); - PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keystorePassword.toCharArray()); - X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); - return SslContextBuilder.forServer(privateKey, certificate).sslProvider(SslProvider.valueOf(sslProvider)).trustManager(SSLSupport.loadTrustManagerFactory(trustStoreProvider, trustStorePath, trustStorePassword, false, null)).build(); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, keystorePassword.toCharArray()); + return SslContextBuilder.forServer(keyManagerFactory).sslProvider(SslProvider.valueOf(sslProvider)).trustManager(SSLSupport.loadTrustManagerFactory(trustStoreProvider, trustStorePath, trustStorePassword, false, null)).build(); } + public static SslContext createNettyClientContext(final String keystoreProvider, + final String keystorePath, + final String keystorePassword, + final String trustStoreProvider, + final String trustStorePath, + final String trustStorePassword, + final String sslProvider, + final boolean trustAll ) throws Exception { + KeyStore keyStore = SSLSupport.loadKeystore(keystoreProvider, keystorePath, keystorePassword); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, keystorePassword.toCharArray()); + return SslContextBuilder.forClient().sslProvider(SslProvider.valueOf(sslProvider)).keyManager(keyManagerFactory).trustManager(SSLSupport.loadTrustManagerFactory(trustStoreProvider, trustStorePath, trustStorePassword, trustAll, null)).build(); + } + + public static String[] parseCommaSeparatedListIntoArray(String suites) { String[] cipherSuites = suites.split(","); for (int i = 0; i < cipherSuites.length; i++) { diff --git a/tests/integration-tests/pom.xml b/tests/integration-tests/pom.xml index 0558075876..b8ff029756 100644 --- a/tests/integration-tests/pom.xml +++ b/tests/integration-tests/pom.xml @@ -396,6 +396,13 @@ org.jgroups jgroups + + + + io.netty + netty-tcnative-boringssl-static + 2.0.7.Final + diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWayOpenSSLServerTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWayOpenSSLServerTest.java new file mode 100644 index 0000000000..dac87fcfd2 --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWayOpenSSLServerTest.java @@ -0,0 +1,346 @@ +/* + * 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. + */ +package org.apache.activemq.artemis.tests.integration.ssl; + +import io.netty.handler.ssl.SslHandler; +import org.apache.activemq.artemis.api.core.ActiveMQException; +import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException; +import org.apache.activemq.artemis.api.core.Interceptor; +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.api.core.TransportConfiguration; +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.api.core.client.ClientConsumer; +import org.apache.activemq.artemis.api.core.client.ClientMessage; +import org.apache.activemq.artemis.api.core.client.ClientProducer; +import org.apache.activemq.artemis.api.core.client.ClientSession; +import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; +import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; +import org.apache.activemq.artemis.core.protocol.core.Packet; +import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl; +import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor; +import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnection; +import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; +import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; +import org.apache.activemq.artemis.utils.RandomUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import javax.net.ssl.SSLPeerUnverifiedException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Test connecting to a server running with OpenSSL TLS from a client that is running with JDK TLS + */ +@RunWith(value = Parameterized.class) +public class CoreClientOverTwoWayOpenSSLServerTest extends ActiveMQTestBase { + + @Parameterized.Parameters(name = "storeType={0}") + public static Collection getParameters() { + return Arrays.asList(new Object[][]{{"JCEKS"}, {"JKS"}}); + } + + public CoreClientOverTwoWayOpenSSLServerTest(String storeType) { + this.storeType = storeType; + SERVER_SIDE_KEYSTORE = "openssl-server-side-keystore." + storeType.toLowerCase(); + SERVER_SIDE_TRUSTSTORE = "openssl-server-side-truststore." + storeType.toLowerCase(); + CLIENT_SIDE_TRUSTSTORE = "openssl-client-side-truststore." + storeType.toLowerCase(); + CLIENT_SIDE_KEYSTORE = "openssl-client-side-keystore." + storeType.toLowerCase(); + } + + public static final SimpleString QUEUE = new SimpleString("QueueOverSSL"); + + /** + * These artifacts are required for testing 2-way SSL with open SSL - note the EC key and ECDSA signature to comply with what OpenSSL offers + * + * Commands to create the JKS artifacts: + * keytool -genkey -keystore openssl-client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-client-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore openssl-server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore openssl-server-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore openssl-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore verified-openssl-client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore verified-openssl-client-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore verified-openssl-server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * + * Commands to create the JCEKS artifacts: + * keytool -genkey -keystore openssl-client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore openssl-server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore openssl-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore openssl-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore verified-openssl-client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore verified-openssl-client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore verified-openssl-server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + */ + + private String storeType; + private String SERVER_SIDE_KEYSTORE; + private String SERVER_SIDE_TRUSTSTORE; + private String CLIENT_SIDE_TRUSTSTORE; + private String CLIENT_SIDE_KEYSTORE; + private final String PASSWORD = "secureexample"; + + private ActiveMQServer server; + + private TransportConfiguration tc; + + private class MyInterceptor implements Interceptor { + + @Override + public boolean intercept(final Packet packet, final RemotingConnection connection) throws ActiveMQException { + if (packet.getType() == PacketImpl.SESS_SEND) { + try { + if (connection.getTransportConnection() instanceof NettyConnection) { + System.out.println("Passed through...."); + NettyConnection nettyConnection = (NettyConnection) connection.getTransportConnection(); + SslHandler sslHandler = (SslHandler) nettyConnection.getChannel().pipeline().get("ssl"); + Assert.assertNotNull(sslHandler); + Assert.assertNotNull(sslHandler.engine().getSession()); + Assert.assertNotNull(sslHandler.engine().getSession().getPeerCertificateChain()); + } + } catch (SSLPeerUnverifiedException e) { + Assert.fail(e.getMessage()); + } + } + return true; + } + } + + @Test + public void testTwoWaySSL() throws Exception { + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + //tc.getParams().put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + ClientSession session = sf.createSession(false, true, true); + session.createQueue(CoreClientOverTwoWayOpenSSLServerTest.QUEUE, CoreClientOverTwoWayOpenSSLServerTest.QUEUE, false); + ClientProducer producer = session.createProducer(CoreClientOverTwoWayOpenSSLServerTest.QUEUE); + + ClientMessage message = createTextMessage(session, text); + producer.send(message); + + ClientConsumer consumer = session.createConsumer(CoreClientOverTwoWayOpenSSLServerTest.QUEUE); + session.start(); + + ClientMessage m = consumer.receive(1000); + Assert.assertNotNull(m); + Assert.assertEquals(text, m.getBodyBuffer().readString()); + } + + @Test + public void testTwoWaySSLVerifyClientHost() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + acceptor.getConfiguration().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_TRUSTSTORE); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + ClientSession session = sf.createSession(false, true, true); + session.createQueue(CoreClientOverTwoWayOpenSSLServerTest.QUEUE, CoreClientOverTwoWayOpenSSLServerTest.QUEUE, false); + ClientProducer producer = session.createProducer(CoreClientOverTwoWayOpenSSLServerTest.QUEUE); + + ClientMessage message = createTextMessage(session, text); + producer.send(message); + + ClientConsumer consumer = session.createConsumer(CoreClientOverTwoWayOpenSSLServerTest.QUEUE); + session.start(); + + ClientMessage m = consumer.receive(1000); + Assert.assertNotNull(m); + Assert.assertEquals(text, m.getBodyBuffer().readString()); + } + + @Test + public void testTwoWaySSLVerifyClientHostNegative() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + ClientSessionFactory sf = createSessionFactory(locator); + fail("Creating a session here should fail due to a certificate with a CN that doesn't match the host name."); + } catch (ActiveMQNotConnectedException se) { + // ignore + } + } + + @Test + public void testTwoWaySSLVerifyClientTrustAllTrue() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + //Set trust all so this should work even with no trust store set + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUST_ALL_PROP_NAME, true); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + sf.close(); + } + + @Test + public void testTwoWaySSLVerifyClientTrustAllTrueByURI() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + //Set trust all so this should work even with no trust store set + StringBuilder uri = new StringBuilder("tcp://" + tc.getParams().get(TransportConstants.HOST_PROP_NAME).toString() + + ":" + tc.getParams().get(TransportConstants.PORT_PROP_NAME).toString()); + + uri.append("?").append(TransportConstants.SSL_ENABLED_PROP_NAME).append("=true"); + uri.append("&").append(TransportConstants.TRUST_ALL_PROP_NAME).append("=true"); + uri.append("&").append(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME).append("=").append(storeType); + uri.append("&").append(TransportConstants.KEYSTORE_PATH_PROP_NAME).append("=").append(CLIENT_SIDE_KEYSTORE); + uri.append("&").append(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME).append("=").append(PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocator(uri.toString())); + ClientSessionFactory sf = createSessionFactory(locator); + sf.close(); + } + + @Test + public void testTwoWaySSLVerifyClientTrustAllFalse() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + //Trust all defaults to false so this should fail with no trust store set + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + ClientSessionFactory sf = createSessionFactory(locator); + fail("Creating a session here should fail due to no trust store being set"); + } catch (ActiveMQNotConnectedException se) { + // ignore + } + } + + @Test + public void testTwoWaySSLWithoutClientKeyStore() throws Exception { + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + createSessionFactory(locator); + Assert.fail(); + } catch (ActiveMQNotConnectedException se) { + //ok + } catch (ActiveMQException e) { + Assert.fail("Invalid Exception type:" + e.getType()); + } + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + Map params = new HashMap<>(); + params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + params.put(TransportConstants.SSL_PROVIDER, TransportConstants.OPENSSL_PROVIDER); + params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE); + params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, SERVER_SIDE_TRUSTSTORE); + params.put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params, "nettySSL")); + server = createServer(false, config); + server.start(); + waitForServerToStart(server); + tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY); + } +} diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWayOpenSSLTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWayOpenSSLTest.java new file mode 100644 index 0000000000..cb8c73dd27 --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWayOpenSSLTest.java @@ -0,0 +1,351 @@ +/* + * 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. + */ +package org.apache.activemq.artemis.tests.integration.ssl; + +import io.netty.handler.ssl.SslHandler; +import org.apache.activemq.artemis.api.core.ActiveMQException; +import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException; +import org.apache.activemq.artemis.api.core.Interceptor; +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.api.core.TransportConfiguration; +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.api.core.client.ClientConsumer; +import org.apache.activemq.artemis.api.core.client.ClientMessage; +import org.apache.activemq.artemis.api.core.client.ClientProducer; +import org.apache.activemq.artemis.api.core.client.ClientSession; +import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; +import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; +import org.apache.activemq.artemis.core.protocol.core.Packet; +import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl; +import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor; +import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnection; +import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; +import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; +import org.apache.activemq.artemis.utils.RandomUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import javax.net.ssl.SSLPeerUnverifiedException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Testing connection where client and server are running OpenSSL TLS + */ +@RunWith(value = Parameterized.class) +public class CoreClientOverTwoWayOpenSSLTest extends ActiveMQTestBase { + + @Parameterized.Parameters(name = "storeType={0}") + public static Collection getParameters() { + return Arrays.asList(new Object[][]{{"JCEKS"}, {"JKS"}}); + } + + public CoreClientOverTwoWayOpenSSLTest(String storeType) { + this.storeType = storeType; + SERVER_SIDE_KEYSTORE = "openssl-server-side-keystore." + storeType.toLowerCase(); + SERVER_SIDE_TRUSTSTORE = "openssl-server-side-truststore." + storeType.toLowerCase(); + CLIENT_SIDE_TRUSTSTORE = "openssl-client-side-truststore." + storeType.toLowerCase(); + CLIENT_SIDE_KEYSTORE = "openssl-client-side-keystore." + storeType.toLowerCase(); + } + + public static final SimpleString QUEUE = new SimpleString("QueueOverSSL"); + + /** + * These artifacts are required for testing 2-way SSL with open SSL - note the EC key and ECDSA signature to comply with what OpenSSL offers + * + * Commands to create the JKS artifacts: + * keytool -genkey -keystore openssl-client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-client-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore openssl-server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore openssl-server-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore openssl-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore verified-openssl-client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore verified-openssl-client-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore verified-openssl-server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * + * Commands to create the JCEKS artifacts: + * keytool -genkey -keystore openssl-client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore openssl-server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore openssl-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore openssl-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore openssl-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore verified-openssl-client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg EC -sigalg SHA256withECDSA + * keytool -export -keystore verified-openssl-client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore verified-openssl-server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + */ + + private String storeType; + private String SERVER_SIDE_KEYSTORE; + private String SERVER_SIDE_TRUSTSTORE; + private String CLIENT_SIDE_TRUSTSTORE; + private String CLIENT_SIDE_KEYSTORE; + private final String PASSWORD = "secureexample"; + + private ActiveMQServer server; + + private TransportConfiguration tc; + + private class MyInterceptor implements Interceptor { + + @Override + public boolean intercept(final Packet packet, final RemotingConnection connection) throws ActiveMQException { + if (packet.getType() == PacketImpl.SESS_SEND) { + try { + if (connection.getTransportConnection() instanceof NettyConnection) { + System.out.println("Passed through...."); + NettyConnection nettyConnection = (NettyConnection) connection.getTransportConnection(); + SslHandler sslHandler = (SslHandler) nettyConnection.getChannel().pipeline().get("ssl"); + Assert.assertNotNull(sslHandler); + Assert.assertNotNull(sslHandler.engine().getSession()); + Assert.assertNotNull(sslHandler.engine().getSession().getPeerCertificateChain()); + } + } catch (SSLPeerUnverifiedException e) { + Assert.fail(e.getMessage()); + } + } + return true; + } + } + + @Test + public void testTwoWaySSL() throws Exception { + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.SSL_PROVIDER, TransportConstants.OPENSSL_PROVIDER); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + //tc.getParams().put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + ClientSession session = sf.createSession(false, true, true); + session.createQueue(CoreClientOverTwoWayOpenSSLTest.QUEUE, CoreClientOverTwoWayOpenSSLTest.QUEUE, false); + ClientProducer producer = session.createProducer(CoreClientOverTwoWayOpenSSLTest.QUEUE); + + ClientMessage message = createTextMessage(session, text); + producer.send(message); + + ClientConsumer consumer = session.createConsumer(CoreClientOverTwoWayOpenSSLTest.QUEUE); + session.start(); + + ClientMessage m = consumer.receive(1000); + Assert.assertNotNull(m); + Assert.assertEquals(text, m.getBodyBuffer().readString()); + } + + @Test + public void testTwoWaySSLVerifyClientHost() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + acceptor.getConfiguration().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_TRUSTSTORE); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.SSL_PROVIDER, TransportConstants.OPENSSL_PROVIDER); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + ClientSession session = sf.createSession(false, true, true); + session.createQueue(CoreClientOverTwoWayOpenSSLTest.QUEUE, CoreClientOverTwoWayOpenSSLTest.QUEUE, false); + ClientProducer producer = session.createProducer(CoreClientOverTwoWayOpenSSLTest.QUEUE); + + ClientMessage message = createTextMessage(session, text); + producer.send(message); + + ClientConsumer consumer = session.createConsumer(CoreClientOverTwoWayOpenSSLTest.QUEUE); + session.start(); + + ClientMessage m = consumer.receive(1000); + Assert.assertNotNull(m); + Assert.assertEquals(text, m.getBodyBuffer().readString()); + } + + @Test + public void testTwoWaySSLVerifyClientHostNegative() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.SSL_PROVIDER, TransportConstants.OPENSSL_PROVIDER); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + ClientSessionFactory sf = createSessionFactory(locator); + fail("Creating a session here should fail due to a certificate with a CN that doesn't match the host name."); + } catch (ActiveMQNotConnectedException se) { + // ignore + } + } + + @Test + public void testTwoWaySSLVerifyClientTrustAllTrue() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + //Set trust all so this should work even with no trust store set + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.SSL_PROVIDER, TransportConstants.OPENSSL_PROVIDER); + tc.getParams().put(TransportConstants.TRUST_ALL_PROP_NAME, true); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + sf.close(); + } + + @Test + public void testTwoWaySSLVerifyClientTrustAllTrueByURI() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + //Set trust all so this should work even with no trust store set + StringBuilder uri = new StringBuilder("tcp://" + tc.getParams().get(TransportConstants.HOST_PROP_NAME).toString() + + ":" + tc.getParams().get(TransportConstants.PORT_PROP_NAME).toString()); + + uri.append("?").append(TransportConstants.SSL_ENABLED_PROP_NAME).append("=true"); + uri.append("&").append(TransportConstants.SSL_PROVIDER).append("=").append(TransportConstants.OPENSSL_PROVIDER); + uri.append("&").append(TransportConstants.TRUST_ALL_PROP_NAME).append("=true"); + uri.append("&").append(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME).append("=").append(storeType); + uri.append("&").append(TransportConstants.KEYSTORE_PATH_PROP_NAME).append("=").append(CLIENT_SIDE_KEYSTORE); + uri.append("&").append(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME).append("=").append(PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocator(uri.toString())); + ClientSessionFactory sf = createSessionFactory(locator); + sf.close(); + } + + @Test + public void testTwoWaySSLVerifyClientTrustAllFalse() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + //Trust all defaults to false so this should fail with no trust store set + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + ClientSessionFactory sf = createSessionFactory(locator); + fail("Creating a session here should fail due to no trust store being set"); + } catch (ActiveMQNotConnectedException se) { + // ignore + } + } + + @Test + public void testTwoWaySSLWithoutClientKeyStore() throws Exception { + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + createSessionFactory(locator); + Assert.fail(); + } catch (ActiveMQNotConnectedException se) { + //ok + } catch (ActiveMQException e) { + Assert.fail("Invalid Exception type:" + e.getType()); + } + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + Map params = new HashMap<>(); + params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + params.put(TransportConstants.SSL_PROVIDER, TransportConstants.OPENSSL_PROVIDER); + params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE); + params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, SERVER_SIDE_TRUSTSTORE); + params.put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params, "nettySSL")); + server = createServer(false, config); + server.start(); + waitForServerToStart(server); + tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY); + } +} diff --git a/tests/unit-tests/src/test/resources/openssl-client-side-keystore.jceks b/tests/unit-tests/src/test/resources/openssl-client-side-keystore.jceks new file mode 100644 index 0000000000..787213710c Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-client-side-keystore.jceks differ diff --git a/tests/unit-tests/src/test/resources/openssl-client-side-keystore.jks b/tests/unit-tests/src/test/resources/openssl-client-side-keystore.jks new file mode 100644 index 0000000000..fd644568e3 Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-client-side-keystore.jks differ diff --git a/tests/unit-tests/src/test/resources/openssl-client-side-truststore.jceks b/tests/unit-tests/src/test/resources/openssl-client-side-truststore.jceks new file mode 100644 index 0000000000..9881cebdbb Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-client-side-truststore.jceks differ diff --git a/tests/unit-tests/src/test/resources/openssl-client-side-truststore.jks b/tests/unit-tests/src/test/resources/openssl-client-side-truststore.jks new file mode 100644 index 0000000000..3ef44dc4bc Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-client-side-truststore.jks differ diff --git a/tests/unit-tests/src/test/resources/openssl-server-side-keystore.jceks b/tests/unit-tests/src/test/resources/openssl-server-side-keystore.jceks new file mode 100644 index 0000000000..d54310159c Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-server-side-keystore.jceks differ diff --git a/tests/unit-tests/src/test/resources/openssl-server-side-keystore.jks b/tests/unit-tests/src/test/resources/openssl-server-side-keystore.jks new file mode 100644 index 0000000000..0a26208761 Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-server-side-keystore.jks differ diff --git a/tests/unit-tests/src/test/resources/openssl-server-side-truststore.jceks b/tests/unit-tests/src/test/resources/openssl-server-side-truststore.jceks new file mode 100644 index 0000000000..9ebd0c75bc Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-server-side-truststore.jceks differ diff --git a/tests/unit-tests/src/test/resources/openssl-server-side-truststore.jks b/tests/unit-tests/src/test/resources/openssl-server-side-truststore.jks new file mode 100644 index 0000000000..89217a3815 Binary files /dev/null and b/tests/unit-tests/src/test/resources/openssl-server-side-truststore.jks differ diff --git a/tests/unit-tests/src/test/resources/verified-openssl-client-side-keystore.jceks b/tests/unit-tests/src/test/resources/verified-openssl-client-side-keystore.jceks new file mode 100644 index 0000000000..fc8c4cc4d1 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-openssl-client-side-keystore.jceks differ diff --git a/tests/unit-tests/src/test/resources/verified-openssl-client-side-keystore.jks b/tests/unit-tests/src/test/resources/verified-openssl-client-side-keystore.jks new file mode 100644 index 0000000000..d60a9e7bab Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-openssl-client-side-keystore.jks differ diff --git a/tests/unit-tests/src/test/resources/verified-openssl-server-side-truststore.jceks b/tests/unit-tests/src/test/resources/verified-openssl-server-side-truststore.jceks new file mode 100644 index 0000000000..c91e3f2e5a Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-openssl-server-side-truststore.jceks differ diff --git a/tests/unit-tests/src/test/resources/verified-openssl-server-side-truststore.jks b/tests/unit-tests/src/test/resources/verified-openssl-server-side-truststore.jks new file mode 100644 index 0000000000..22fda4bb41 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-openssl-server-side-truststore.jks differ