QPIDJMS-35: add basic support for SSL to the test peer, add some client integration tests using
it
Project: http://git-wip-us.apache.org/repos/asf/qpid-jms/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-jms/commit/f6520d25
Tree: http://git-wip-us.apache.org/repos/asf/qpid-jms/tree/f6520d25
Diff: http://git-wip-us.apache.org/repos/asf/qpid-jms/diff/f6520d25
Branch: refs/heads/master
Commit: f6520d25d58a10f4a25b305c0e97eccdb2b90a4f
Parents: b589ed7
Author: Robert Gemmell <robbie@apache.org>
Authored: Tue Apr 14 14:14:40 2015 +0100
Committer: Robert Gemmell <robbie@apache.org>
Committed: Tue Apr 14 14:23:58 2015 +0100
----------------------------------------------------------------------
.../integration/ConnectionIntegrationTest.java | 4 +-
.../jms/integration/IntegrationTestFixture.java | 7 +-
.../jms/integration/SessionIntegrationTest.java | 2 +-
.../jms/integration/SslIntegrationTest.java | 192 +++++++++++++++++++
.../qpid/jms/test/testpeer/TestAmqpPeer.java | 15 +-
.../jms/test/testpeer/TestAmqpPeerRunner.java | 30 ++-
6 files changed, 241 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/f6520d25/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
index bda099d..360d3ad 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
@@ -61,7 +61,7 @@ public class ConnectionIntegrationTest extends QpidJmsTestCase {
@Test(timeout = 5000)
public void testCreateConnectionWithClientId() throws Exception {
try (TestAmqpPeer testPeer = new TestAmqpPeer();) {
- Connection connection = testFixture.establishConnecton(testPeer, null, null,
null, true);
+ Connection connection = testFixture.establishConnecton(testPeer, false, null,
null, null, true);
testPeer.expectClose();
connection.close();
}
@@ -112,7 +112,7 @@ public class ConnectionIntegrationTest extends QpidJmsTestCase {
final CountDownLatch done = new CountDownLatch(1);
// Don't set a ClientId, so that the underlying AMQP connection isn't established
yet
- Connection connection = testFixture.establishConnecton(testPeer, null, null,
null, false);
+ Connection connection = testFixture.establishConnecton(testPeer, false, null,
null, null, false);
// Tell the test peer to close the connection when executing its last handler
testPeer.remotelyCloseConnection(true);
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/f6520d25/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
index 8541708..94574d7 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
@@ -50,10 +50,10 @@ public class IntegrationTestFixture {
}
Connection establishConnecton(TestAmqpPeer testPeer, String optionsString, Symbol[] serverCapabilities,
Map<Symbol, Object> serverProperties) throws JMSException {
- return establishConnecton(testPeer, null, serverCapabilities, serverProperties, true);
+ return establishConnecton(testPeer, false, null, serverCapabilities, serverProperties,
true);
}
- Connection establishConnecton(TestAmqpPeer testPeer, String optionsString, Symbol[] serverCapabilities,
Map<Symbol, Object> serverProperties, boolean setClientId) throws JMSException {
+ Connection establishConnecton(TestAmqpPeer testPeer, boolean ssl, String optionsString,
Symbol[] serverCapabilities, Map<Symbol, Object> serverProperties, boolean setClientId)
throws JMSException {
Symbol[] desiredCapabilities = new Symbol[] { AmqpConnection.SOLE_CONNECTION_CAPABILITY
};
testPeer.expectPlainConnect("guest", "guest", desiredCapabilities, serverCapabilities,
serverProperties);
@@ -61,7 +61,8 @@ public class IntegrationTestFixture {
// Each connection creates a session for managing temporary destinations etc
testPeer.expectBegin(true);
- final String baseURI = "amqp://localhost:" + testPeer.getServerPort();
+ String scheme = ssl ? "amqps" : "amqp";
+ final String baseURI = scheme + "://localhost:" + testPeer.getServerPort();
String remoteURI = baseURI;
if (optionsString != null) {
remoteURI = baseURI + optionsString;
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/f6520d25/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SessionIntegrationTest.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SessionIntegrationTest.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SessionIntegrationTest.java
index 89f6ef0..6d9249d 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SessionIntegrationTest.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SessionIntegrationTest.java
@@ -601,7 +601,7 @@ public class SessionIntegrationTest extends QpidJmsTestCase {
public void testCreateDurableTopicSubscriberFailsIfConnectionDoesntHaveExplicitClientID()
throws Exception {
try (TestAmqpPeer testPeer = new TestAmqpPeer();) {
// Create a connection without an explicit clientId
- Connection connection = testFixture.establishConnecton(testPeer, null, null,
null, false);
+ Connection connection = testFixture.establishConnecton(testPeer, false, null,
null, null, false);
connection.start();
testPeer.expectBegin(true);
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/f6520d25/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SslIntegrationTest.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SslIntegrationTest.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SslIntegrationTest.java
new file mode 100644
index 0000000..9ace420
--- /dev/null
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SslIntegrationTest.java
@@ -0,0 +1,192 @@
+/*
+ *
+ * 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.qpid.jms.integration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.test.QpidJmsTestCase;
+import org.apache.qpid.jms.test.testpeer.TestAmqpPeer;
+import org.apache.qpid.jms.transports.TransportSslOptions;
+import org.apache.qpid.jms.transports.TransportSupport;
+import org.junit.Test;
+
+public class SslIntegrationTest extends QpidJmsTestCase {
+
+ private static final String BROKER_JKS_KEYSTORE = "src/test/resources/broker-jks.keystore";
+ private static final String BROKER_JKS_TRUSTSTORE = "src/test/resources/broker-jks.truststore";
+ private static final String CLIENT_MULTI_KEYSTORE = "src/test/resources/client-multiple-keys-jks.keystore";
+ private static final String CLIENT_JKS_TRUSTSTORE = "src/test/resources/client-jks.truststore";
+ private static final String PASSWORD = "password";
+
+ private static final String CLIENT_KEY_ALIAS = "client";
+ private static final String CLIENT_DN = "O=Client,CN=client";
+ private static final String CLIENT2_KEY_ALIAS = "client2";
+ private static final String CLIENT2_DN = "O=Client2,CN=client2";
+
+ private static final String ALIAS_DOES_NOT_EXIST = "alias.does.not.exist";
+ private static final String ALIAS_CA_CERT = "ca";
+
+ private final IntegrationTestFixture testFixture = new IntegrationTestFixture();
+
+ @Test(timeout = 5000)
+ public void testCreateAndCloseSslConnection() throws Exception {
+ TransportSslOptions sslOptions = new TransportSslOptions();
+ sslOptions.setKeyStoreLocation(BROKER_JKS_KEYSTORE);
+ sslOptions.setKeyStorePassword(PASSWORD);
+ sslOptions.setVerifyHost(false);
+
+ SSLContext context = TransportSupport.createSslContext(sslOptions);
+
+ try (TestAmqpPeer testPeer = new TestAmqpPeer(context, false);) {
+ String connOptions = "?transport.trustStoreLocation=" + CLIENT_JKS_TRUSTSTORE
+ "&" +
+ "transport.trustStorePassword=" + PASSWORD;
+ Connection connection = testFixture.establishConnecton(testPeer, true, connOptions,
null, null, true);
+
+ Socket socket = testPeer.getClientSocket();
+ assertTrue(socket instanceof SSLSocket);
+
+ testPeer.expectClose();
+ connection.close();
+ }
+ }
+
+ @Test(timeout = 5000)
+ public void testCreateAndCloseSslConnectionWithClientAuth() throws Exception {
+ TransportSslOptions sslOptions = new TransportSslOptions();
+ sslOptions.setKeyStoreLocation(BROKER_JKS_KEYSTORE);
+ sslOptions.setTrustStoreLocation(BROKER_JKS_TRUSTSTORE);
+ sslOptions.setKeyStorePassword(PASSWORD);
+ sslOptions.setTrustStorePassword(PASSWORD);
+ sslOptions.setVerifyHost(false);
+
+ SSLContext context = TransportSupport.createSslContext(sslOptions);
+
+ try (TestAmqpPeer testPeer = new TestAmqpPeer(context, true);) {
+ String connOptions = "?transport.keyStoreLocation=" + CLIENT_MULTI_KEYSTORE +
"&" +
+ "transport.keyStorePassword=" + PASSWORD + "&" +
+ "transport.trustStoreLocation=" + CLIENT_JKS_TRUSTSTORE
+ "&" +
+ "transport.trustStorePassword=" + PASSWORD;
+ Connection connection = testFixture.establishConnecton(testPeer, true, connOptions,
null, null, true);
+
+ Socket socket = testPeer.getClientSocket();
+ assertTrue(socket instanceof SSLSocket);
+ assertNotNull(((SSLSocket) socket).getSession().getPeerPrincipal());
+
+ testPeer.expectClose();
+ connection.close();
+ }
+ }
+
+ @Test(timeout = 5000)
+ public void testCreateAndCloseSslConnectionWithAlias() throws Exception {
+ doConnectionWithAliasTestImpl(CLIENT_KEY_ALIAS, CLIENT_DN);
+ doConnectionWithAliasTestImpl(CLIENT2_KEY_ALIAS, CLIENT2_DN);
+ }
+
+ private void doConnectionWithAliasTestImpl(String alias, String expectedDN) throws Exception,
JMSException, SSLPeerUnverifiedException, IOException {
+ TransportSslOptions sslOptions = new TransportSslOptions();
+ sslOptions.setKeyStoreLocation(BROKER_JKS_KEYSTORE);
+ sslOptions.setTrustStoreLocation(BROKER_JKS_TRUSTSTORE);
+ sslOptions.setKeyStorePassword(PASSWORD);
+ sslOptions.setTrustStorePassword(PASSWORD);
+ sslOptions.setVerifyHost(false);
+
+ SSLContext context = TransportSupport.createSslContext(sslOptions);
+
+ try (TestAmqpPeer testPeer = new TestAmqpPeer(context, true);) {
+ String connOptions = "?transport.keyStoreLocation=" + CLIENT_MULTI_KEYSTORE +
"&" +
+ "transport.keyStorePassword=" + PASSWORD + "&" +
+ "transport.trustStoreLocation=" + CLIENT_JKS_TRUSTSTORE
+ "&" +
+ "transport.trustStorePassword=" + PASSWORD + "&" +
+ "transport.keyAlias=" + alias;
+ Connection connection = testFixture.establishConnecton(testPeer, true, connOptions,
null, null, true);
+
+ Socket socket = testPeer.getClientSocket();
+ assertTrue(socket instanceof SSLSocket);
+ SSLSession session = ((SSLSocket) socket).getSession();
+
+ Certificate[] peerCertificates = session.getPeerCertificates();
+ assertNotNull(peerCertificates);
+
+ Certificate cert = peerCertificates[0];
+ assertTrue(cert instanceof X509Certificate);
+ String dn = ((X509Certificate)cert).getSubjectX500Principal().getName();
+ assertEquals("Unexpected certificate DN", expectedDN, dn);
+
+ testPeer.expectClose();
+ connection.close();
+ }
+ }
+
+ @Test(timeout = 5000)
+ public void testCreateConnectionWithAliasThatDoesNotExist() throws Exception {
+ doCreateConnectionWithInvalidAliasTestImpl(ALIAS_DOES_NOT_EXIST);
+ }
+
+ @Test(timeout = 5000)
+ public void testCreateConnectionWithAliasThatDoesNotRepresentKeyEntry() throws Exception
{
+ doCreateConnectionWithInvalidAliasTestImpl(ALIAS_CA_CERT);
+ }
+
+ private void doCreateConnectionWithInvalidAliasTestImpl(String alias) throws Exception,
IOException {
+ TransportSslOptions sslOptions = new TransportSslOptions();
+ sslOptions.setKeyStoreLocation(BROKER_JKS_KEYSTORE);
+ sslOptions.setTrustStoreLocation(BROKER_JKS_TRUSTSTORE);
+ sslOptions.setKeyStorePassword(PASSWORD);
+ sslOptions.setTrustStorePassword(PASSWORD);
+ sslOptions.setVerifyHost(false);
+
+ SSLContext context = TransportSupport.createSslContext(sslOptions);
+
+ try (TestAmqpPeer testPeer = new TestAmqpPeer(context, true);) {
+ String connOptions = "?transport.keyStoreLocation=" + CLIENT_MULTI_KEYSTORE +
"&" +
+ "transport.keyStorePassword=" + PASSWORD + "&" +
+ "transport.trustStoreLocation=" + CLIENT_JKS_TRUSTSTORE
+ "&" +
+ "transport.trustStorePassword=" + PASSWORD + "&" +
+ "transport.keyAlias=" + alias;
+
+ // DONT use a test fixture, we will drive it directly (because creating the connection
will fail).
+ JmsConnectionFactory factory = new JmsConnectionFactory("amqps://127.0.0.1:"
+ testPeer.getServerPort() + connOptions);
+ try {
+ factory.createConnection();
+ fail("Expected exception to be thrown");
+ } catch (JMSException jmse) {
+ // Expected
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/f6520d25/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java
index 21c8f8b..b76dffc 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java
@@ -27,12 +27,15 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import java.io.IOException;
+import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+
import org.apache.qpid.jms.provider.amqp.AmqpConnection;
import org.apache.qpid.jms.provider.amqp.AmqpTemporaryDestination;
import org.apache.qpid.jms.provider.amqp.message.AmqpDestinationHelper;
@@ -115,7 +118,12 @@ public class TestAmqpPeer implements AutoCloseable
public TestAmqpPeer() throws IOException
{
- _driverRunnable = new TestAmqpPeerRunner(this);
+ this(null, false);
+ }
+
+ public TestAmqpPeer(SSLContext context, boolean needClientCert) throws IOException
+ {
+ _driverRunnable = new TestAmqpPeerRunner(this, context, needClientCert);
_driverThread = new Thread(_driverRunnable, "MockAmqpPeerThread");
_driverThread.start();
}
@@ -166,6 +174,11 @@ public class TestAmqpPeer implements AutoCloseable
return _driverRunnable.getServerPort();
}
+ public Socket getClientSocket()
+ {
+ return _driverRunnable.getClientSocket();
+ }
+
public void receiveHeader(byte[] header)
{
Handler handler = getFirstHandler();
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/f6520d25/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java
index 10a4fe2..ef93903 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java
@@ -25,6 +25,10 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+
import org.apache.qpid.proton.amqp.Binary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,9 +50,26 @@ class TestAmqpPeerRunner implements Runnable
private volatile Throwable _throwable;
- public TestAmqpPeerRunner(TestAmqpPeer peer) throws IOException
+ public TestAmqpPeerRunner(TestAmqpPeer peer, SSLContext sslContext, boolean needClientCert)
throws IOException
{
- _serverSocket = new ServerSocket(useFixedPort ? PORT : 0);
+ int port = useFixedPort ? PORT : 0;
+
+ if (sslContext == null)
+ {
+ _serverSocket = new ServerSocket(port);
+ }
+ else
+ {
+ SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();
+ _serverSocket = socketFactory.createServerSocket(port);
+
+ SSLServerSocket sslServerSocket = (SSLServerSocket) _serverSocket;
+ if (needClientCert)
+ {
+ sslServerSocket.setNeedClientAuth(true);
+ }
+ }
+
_testFrameParser = new TestFrameParser(peer);
}
@@ -170,4 +191,9 @@ class TestAmqpPeerRunner implements Runnable
return -1;
}
+
+ public Socket getClientSocket()
+ {
+ return _clientSocket;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
|