PROTON-1405: add ability to pass in the SSLContext to use, as opposed to the configuration to create one
This closes #4
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java
index 24b101c..279d934 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java
@@ -18,6 +18,7 @@
*/
package org.apache.qpid.proton.engine;
+import javax.net.ssl.SSLContext;
import org.apache.qpid.proton.engine.impl.ssl.SslDomainImpl;
/**
@@ -142,4 +143,19 @@
void allowUnsecuredClient(boolean allowUnsecured);
boolean allowUnsecuredClient();
+
+ /**
+ * Sets an SSLContext for use when establishing SSL transport. Setting a context this way overrides alternate
+ * configuration that might otherwise have been used to create a context, such as key and trust store paths.
+ *
+ *@param sslContext the context to use
+ */
+ void setSslContext(SSLContext sslContext);
+
+ /**
+ * Returns the SSLContext set by {@link #setSslContext(SSLContext)}.
+ *
+ * @return the SSLContext, or null if none was set.
+ */
+ SSLContext getSslContext();
}
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java
index 583e3ca..9e7201c 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.qpid.proton.engine.impl.ssl;
+import javax.net.ssl.SSLContext;
import org.apache.qpid.proton.ProtonUnsupportedOperationException;
import org.apache.qpid.proton.engine.ProtonJSslDomain;
import org.apache.qpid.proton.engine.SslDomain;
@@ -32,6 +33,7 @@
private String _privateKeyPassword;
private String _trustedCaDb;
private boolean _allowUnsecuredClient;
+ private SSLContext _sslContext;
private final SslEngineFacadeFactory _sslEngineFacadeFactory = new SslEngineFacadeFactory();
@@ -79,6 +81,18 @@
}
@Override
+ public void setSslContext(SSLContext sslContext)
+ {
+ _sslContext = sslContext;
+ }
+
+ @Override
+ public SSLContext getSslContext()
+ {
+ return _sslContext;
+ }
+
+ @Override
public void setPeerAuthentication(VerifyMode verifyMode)
{
if(verifyMode == VerifyMode.VERIFY_PEER_NAME)
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java
index f6346aa..64eb2ca 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java
@@ -265,7 +265,11 @@
private SSLContext getOrCreateSslContext(SslDomain sslDomain)
{
- if(_sslContext == null)
+ if(_sslContext == null && sslDomain.getSslContext() != null)
+ {
+ _sslContext = sslDomain.getSslContext();
+ }
+ else if(_sslContext == null)
{
if(_logger.isLoggable(Level.FINE))
{
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java b/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java
new file mode 100644
index 0000000..b426d3f
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/SslTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.proton.systemtests.engine;
+
+import static org.apache.qpid.proton.engine.EndpointState.ACTIVE;
+import static org.apache.qpid.proton.engine.EndpointState.UNINITIALIZED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.qpid.proton.Proton;
+import org.apache.qpid.proton.amqp.transport.ErrorCondition;
+import org.apache.qpid.proton.engine.Connection;
+import org.apache.qpid.proton.engine.Endpoint;
+import org.apache.qpid.proton.engine.EndpointState;
+import org.apache.qpid.proton.engine.SslDomain;
+import org.apache.qpid.proton.engine.SslDomain.Mode;
+import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
+import org.apache.qpid.proton.engine.Transport;
+import org.junit.Test;
+
+public class SslTest
+{
+ private static final String SERVER_PKCS12_KEYSTORE = "src/test/resources/server-pkcs12.keystore";
+ private static final String SERVER_PKCS12_TRUSTSTORE = "src/test/resources/server-pkcs12.truststore";
+ private static final String CLIENT_PKCS12_KEYSTORE = "src/test/resources/client-pkcs12.keystore";
+ private static final String CLIENT_PKCS12_TRUSTSTORE = "src/test/resources/client-pkcs12.truststore";
+ private static final String PASSWORD = "password";
+
+ private static final String SERVER_CONTAINER = "serverContainer";
+ private static final String CLIENT_CONTAINER = "clientContainer";
+
+ private final Transport _clientTransport = Proton.transport();
+ private final Transport _serverTransport = Proton.transport();
+
+ private final TransportPumper _pumper = new TransportPumper(_clientTransport, _serverTransport);
+
+ private final Connection _clientConnection = Proton.connection();
+ private final Connection _serverConnection = Proton.connection();
+
+ @Test
+ public void testOpenConnectionOverSslTransports() throws Exception
+ {
+ SslDomain clientSslDomain = SslDomain.Factory.create();
+ clientSslDomain.init(Mode.CLIENT);
+ clientSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER);
+ SSLContext clientSslContext = createSslContext(CLIENT_PKCS12_KEYSTORE, PASSWORD, CLIENT_PKCS12_TRUSTSTORE, PASSWORD);
+ clientSslDomain.setSslContext(clientSslContext);
+ _clientTransport.ssl(clientSslDomain);
+
+ SslDomain serverSslDomain = SslDomain.Factory.create();
+ serverSslDomain.init(Mode.SERVER);
+ serverSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER);
+ SSLContext serverSslContext = createSslContext(SERVER_PKCS12_KEYSTORE, PASSWORD, SERVER_PKCS12_TRUSTSTORE, PASSWORD);
+ serverSslDomain.setSslContext(serverSslContext);
+ _serverTransport.ssl(serverSslDomain);
+
+ _clientConnection.setContainer(CLIENT_CONTAINER);
+ _serverConnection.setContainer(SERVER_CONTAINER);
+
+ _clientTransport.bind(_clientConnection);
+ _serverTransport.bind(_serverConnection);
+
+ assertConditions(_clientTransport);
+ assertConditions(_serverTransport);
+
+ _clientConnection.open();
+
+ assertEndpointState(_clientConnection, ACTIVE, UNINITIALIZED);
+ assertEndpointState(_serverConnection, UNINITIALIZED, UNINITIALIZED);
+
+ assertConditions(_clientTransport);
+ assertConditions(_serverTransport);
+
+ _pumper.pumpAll();
+
+ assertEndpointState(_clientConnection, ACTIVE, UNINITIALIZED);
+ assertEndpointState(_serverConnection, UNINITIALIZED, ACTIVE);
+
+ assertConditions(_clientTransport);
+ assertConditions(_serverTransport);
+
+ _serverConnection.open();
+
+ assertEndpointState(_clientConnection, ACTIVE, UNINITIALIZED);
+ assertEndpointState(_serverConnection, ACTIVE, ACTIVE);
+
+ assertConditions(_clientTransport);
+ assertConditions(_serverTransport);
+
+ _pumper.pumpAll();
+
+ assertEndpointState(_clientConnection, ACTIVE, ACTIVE);
+ assertEndpointState(_serverConnection, ACTIVE, ACTIVE);
+
+ assertConditions(_clientTransport);
+ assertConditions(_serverTransport);
+ }
+
+ private void assertConditions(Transport transport)
+ {
+ ErrorCondition remoteCondition = transport.getRemoteCondition();
+ if (remoteCondition != null)
+ {
+ assertNull(remoteCondition.getCondition());
+ }
+
+ ErrorCondition condition = transport.getCondition();
+ if (condition != null)
+ {
+ assertNull(condition.getCondition());
+ }
+ }
+
+ private SSLContext createSslContext(String keyStoreLocation, String keyStorePassword,
+ String trustStoreLocation, String trustStorePassword) throws Exception
+ {
+ SSLContext context = SSLContext.getInstance("TLS");
+
+ KeyManagerFactory keyFact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ TrustManagerFactory trustFact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ try (InputStream in = new FileInputStream(new File(keyStoreLocation));)
+ {
+ keyStore.load(in, keyStorePassword.toCharArray());
+ }
+ keyFact.init(keyStore, keyStorePassword.toCharArray());
+
+ KeyStore trustStore = KeyStore.getInstance("PKCS12");
+ try (InputStream in = new FileInputStream(new File(trustStoreLocation));)
+ {
+ trustStore.load(in, trustStorePassword.toCharArray());
+ }
+ trustFact.init(trustStore);
+
+ context.init(keyFact.getKeyManagers(), trustFact.getTrustManagers(), new SecureRandom());
+
+ return context;
+ }
+
+ private void assertEndpointState(Endpoint endpoint, EndpointState localState, EndpointState remoteState)
+ {
+ assertEquals("Unexpected local state", localState, endpoint.getLocalState());
+ assertEquals("Unexpected remote state", remoteState, endpoint.getRemoteState());
+ }
+}
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportPumper.java b/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportPumper.java
index fd1d198..d03f0df 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportPumper.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportPumper.java
@@ -19,9 +19,12 @@
*/
package org.apache.qpid.proton.systemtests.engine;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
import org.apache.qpid.proton.engine.Transport;
+import org.apache.qpid.proton.engine.TransportResult;
public class TransportPumper
{
@@ -60,13 +63,26 @@
private int pumpOnce(Transport transportFrom, String fromRole, Transport transportTo, String toRole)
{
- final byte[] output = new byte[1024];
- int outputLength = transportFrom.output(output, 0, output.length);
+ int outputLength = transportFrom.pending();
if (outputLength > 0)
{
- int numberConsumedByServer = transportTo.input(output, 0, outputLength);
- assertEquals("Expecting " + toRole + " to consume all of " + fromRole + "'s output", outputLength, numberConsumedByServer);
+ ByteBuffer outputBuffer = transportFrom.head();
+
+ int remaining = outputBuffer.remaining();
+ assertTrue("Unexpected remaining in buffer: " + remaining + " vs " + outputLength, remaining >= outputLength);
+
+ byte[] output = new byte[remaining];
+ outputBuffer.get(output);
+
+ transportFrom.pop(remaining);
+
+ ByteBuffer inputBuffer = transportTo.getInputBuffer();
+ inputBuffer.put(output, 0, output.length);
+
+ TransportResult result = transportTo.processInput();
+ result.checkIsOk();
}
+
return outputLength;
}
diff --git a/proton-j/src/test/resources/README.txt b/proton-j/src/test/resources/README.txt
new file mode 100644
index 0000000..1a4516e
--- /dev/null
+++ b/proton-j/src/test/resources/README.txt
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+# The various PKCS12 SSL stores and certificates were created with the following commands:
+# Seems to require the JDK8 keytool.
+
+# Clean up existing files
+# -----------------------
+rm -f *.crt *.csr *.keystore *.truststore
+
+# Create a key and self-signed certificate for the CA, to sign certificate requests and use for trust:
+# ----------------------------------------------------------------------------------------------------
+keytool -storetype pkcs12 -keystore ca-pkcs12.keystore -storepass password -keypass password -alias ca -genkey -dname "O=My Trusted Inc.,CN=my-ca.org" -validity 9999 -ext bc:c=ca:true
+keytool -storetype pkcs12 -keystore ca-pkcs12.keystore -storepass password -alias ca -exportcert -rfc > ca.crt
+
+# Create a key pair for the server, and sign it with the CA:
+# ----------------------------------------------------------
+keytool -storetype pkcs12 -keystore server-pkcs12.keystore -storepass password -keypass password -alias server -genkey -dname "O=Server,CN=localhost" -validity 9999 -ext bc=ca:false -ext eku=sA
+
+keytool -storetype pkcs12 -keystore server-pkcs12.keystore -storepass password -alias server -certreq -file server.csr
+keytool -storetype pkcs12 -keystore ca-pkcs12.keystore -storepass password -alias ca -gencert -rfc -infile server.csr -outfile server.crt -validity 9999 -ext bc=ca:false -ext eku=sA
+
+keytool -storetype pkcs12 -keystore server-pkcs12.keystore -storepass password -keypass password -importcert -alias ca -file ca.crt -noprompt
+keytool -storetype pkcs12 -keystore server-pkcs12.keystore -storepass password -keypass password -importcert -alias server -file server.crt
+
+# Create trust store for the server, import the CA cert:
+# -------------------------------------------------------
+keytool -storetype pkcs12 -keystore server-pkcs12.truststore -storepass password -keypass password -importcert -alias ca -file ca.crt -noprompt
+
+# Create a key pair for a client, and sign it with the CA:
+# ----------------------------------------------------------
+keytool -storetype pkcs12 -keystore client-pkcs12.keystore -storepass password -keypass password -alias client -genkey -dname "O=Client,CN=client" -validity 9999 -ext bc=ca:false -ext eku=cA
+
+keytool -storetype pkcs12 -keystore client-pkcs12.keystore -storepass password -alias client -certreq -file client.csr
+keytool -storetype pkcs12 -keystore ca-pkcs12.keystore -storepass password -alias ca -gencert -rfc -infile client.csr -outfile client.crt -validity 9999 -ext bc=ca:false -ext eku=cA
+
+keytool -storetype pkcs12 -keystore client-pkcs12.keystore -storepass password -keypass password -importcert -alias ca -file ca.crt -noprompt
+keytool -storetype pkcs12 -keystore client-pkcs12.keystore -storepass password -keypass password -importcert -alias client -file client.crt
+
+# Create trust store for the client, import the CA cert:
+# -------------------------------------------------------
+keytool -storetype pkcs12 -keystore client-pkcs12.truststore -storepass password -keypass password -importcert -alias ca -file ca.crt -noprompt
+
diff --git a/proton-j/src/test/resources/ca-pkcs12.keystore b/proton-j/src/test/resources/ca-pkcs12.keystore
new file mode 100644
index 0000000..8518594
--- /dev/null
+++ b/proton-j/src/test/resources/ca-pkcs12.keystore
Binary files differ
diff --git a/proton-j/src/test/resources/ca.crt b/proton-j/src/test/resources/ca.crt
new file mode 100644
index 0000000..ccd8f09
--- /dev/null
+++ b/proton-j/src/test/resources/ca.crt
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICyTCCAoegAwIBAgIEaAYSUTALBgcqhkjOOAQDBQAwLjESMBAGA1UEAxMJbXktY2Eub3JnMRgw
+FgYDVQQKEw9NeSBUcnVzdGVkIEluYy4wHhcNMTcwMjE3MTc1MjMwWhcNNDQwNzA0MTc1MjMwWjAu
+MRIwEAYDVQQDEwlteS1jYS5vcmcxGDAWBgNVBAoTD015IFRydXN0ZWQgSW5jLjCCAbcwggEsBgcq
+hkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6
+v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPF
+HsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfh
+oIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88J
+MozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2Ze
+gHtVJWQBTDv+z0kqA4GEAAKBgDoxX28C4+6GPhU0tRIeg0aPrz/5HllZwa20GAaKynloG9eIsfHU
+YjoQNSBlkRYtrEAPnD/V1UVlSDhw4hgGbbtCfLtRW5roU/3der29/cJQgDrT6nKk0YhHlMplROpb
+QyZ0nsjtmpx47s3yTp4PDNuQ01//7xaom4/3NSTKsZtqozIwMDAPBgNVHRMBAf8EBTADAQH/MB0G
+A1UdDgQWBBRCc/g0sUmH3EsNis029c9biR3HpDALBgcqhkjOOAQDBQADLwAwLAIUEBP/U+V5dZ+4
+zHPMl4+OJrF2cP0CFCEjdq+u04mVQRjXY2depfJVFdY/
+-----END CERTIFICATE-----
diff --git a/proton-j/src/test/resources/client-pkcs12.keystore b/proton-j/src/test/resources/client-pkcs12.keystore
new file mode 100644
index 0000000..ffddc8f
--- /dev/null
+++ b/proton-j/src/test/resources/client-pkcs12.keystore
Binary files differ
diff --git a/proton-j/src/test/resources/client-pkcs12.truststore b/proton-j/src/test/resources/client-pkcs12.truststore
new file mode 100644
index 0000000..94980f2
--- /dev/null
+++ b/proton-j/src/test/resources/client-pkcs12.truststore
Binary files differ
diff --git a/proton-j/src/test/resources/client.crt b/proton-j/src/test/resources/client.crt
new file mode 100644
index 0000000..ad7c13b
--- /dev/null
+++ b/proton-j/src/test/resources/client.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIC7TCCAqugAwIBAgIEdIsOFTALBgcqhkjOOAQDBQAwLjESMBAGA1UEAxMJbXktY2Eub3JnMRgw
+FgYDVQQKEw9NeSBUcnVzdGVkIEluYy4wHhcNMTcwMjE3MTc1MjMzWhcNNDQwNzA0MTc1MjMzWjAi
+MQ8wDQYDVQQDEwZjbGllbnQxDzANBgNVBAoTBkNsaWVudDCCAbcwggEsBgcqhkjOOAQBMIIBHwKB
+gQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeB
+O4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1
+864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4
+V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyN
+KOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kq
+A4GEAAKBgARwR4H7ol+67WtN32jb3aJwf6fFo+5PirqLWFQeupLmf74yvx/YsTncDaxndBb/hUpy
+P0BdizE8NMN6qbu2j8Nbb6nBpM8SA6uve2T/07mTgFnOiEpD8nOWfgxHsDXncQDxtwi+EpfIp0pl
+HKR0JapmnJfZeMApa0pTc/RYaCXHo2IwYDAfBgNVHSMEGDAWgBRCc/g0sUmH3EsNis029c9biR3H
+pDAJBgNVHRMEAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB0GA1UdDgQWBBQf0HHCQbYVQI5XgCRS
+8EnbLfSRYjALBgcqhkjOOAQDBQADLwAwLAIUcNM9zzJfxoVRGsxoT5ntSCZPkbMCFD4YCU2oHD5r
+0MdlA8iNp9DUb4pi
+-----END CERTIFICATE-----
diff --git a/proton-j/src/test/resources/client.csr b/proton-j/src/test/resources/client.csr
new file mode 100644
index 0000000..5006c90
--- /dev/null
+++ b/proton-j/src/test/resources/client.csr
@@ -0,0 +1,13 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICVjCCAhQCAQAwIjEPMA0GA1UEAxMGY2xpZW50MQ8wDQYDVQQKEwZDbGllbnQwggG3MIIBLAYH
+KoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bT
+xR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD3
+4aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fP
+CTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8Gkotm
+XoB7VSVkAUw7/s9JKgOBhAACgYAEcEeB+6Jfuu1rTd9o292icH+nxaPuT4q6i1hUHrqS5n++Mr8f
+2LE53A2sZ3QW/4VKcj9AXYsxPDTDeqm7to/DW2+pwaTPEgOrr3tk/9O5k4BZzohKQ/Jzln4MR7A1
+53EA8bcIvhKXyKdKZRykdCWqZpyX2XjAKWtKU3P0WGglx6AwMC4GCSqGSIb3DQEJDjEhMB8wHQYD
+VR0OBBYEFB/QccJBthVAjleAJFLwSdst9JFiMAsGByqGSM44BAMFAAMvADAsAhR/BRqoPI9dFwO8
+pcy+9OS9we85jgIURWkIHmeMXeQnqiLwehzPoDYrH2c=
+-----END NEW CERTIFICATE REQUEST-----
diff --git a/proton-j/src/test/resources/server-pkcs12.keystore b/proton-j/src/test/resources/server-pkcs12.keystore
new file mode 100644
index 0000000..dd2e212
--- /dev/null
+++ b/proton-j/src/test/resources/server-pkcs12.keystore
Binary files differ
diff --git a/proton-j/src/test/resources/server-pkcs12.truststore b/proton-j/src/test/resources/server-pkcs12.truststore
new file mode 100644
index 0000000..04798ec
--- /dev/null
+++ b/proton-j/src/test/resources/server-pkcs12.truststore
Binary files differ
diff --git a/proton-j/src/test/resources/server.crt b/proton-j/src/test/resources/server.crt
new file mode 100644
index 0000000..ed0eed6
--- /dev/null
+++ b/proton-j/src/test/resources/server.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIC8TCCAq+gAwIBAgIELDFSBjALBgcqhkjOOAQDBQAwLjESMBAGA1UEAxMJbXktY2Eub3JnMRgw
+FgYDVQQKEw9NeSBUcnVzdGVkIEluYy4wHhcNMTcwMjE3MTc1MjMyWhcNNDQwNzA0MTc1MjMyWjAl
+MRIwEAYDVQQDEwlsb2NhbGhvc3QxDzANBgNVBAoTBlNlcnZlcjCCAbgwggEsBgcqhkjOOAQBMIIB
+HwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tV
+bNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaR
+MvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yr
+XDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqL
+VHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+
+z0kqA4GFAAKBgQDoMxMn1KARYyWpGTEIlACWODH0Gj76WxhhpknIN7HWBrC6mgzcS+CHZ17gVrxI
+mVx2tNWzEdwi0RvYHvp23QRyw/L6FgHyJ9GCSfLuNbsYZiFnQz80LTNFNP+CT2unpV5PafT6zYQ0
+HljoBZeE8E1uHlET8EKSYLaMGnjSDIVicqNiMGAwHwYDVR0jBBgwFoAUQnP4NLFJh9xLDYrNNvXP
+W4kdx6QwCQYDVR0TBAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQU82oygO6LZOal
+7o4zHYpvpjAYWhIwCwYHKoZIzjgEAwUAAy8AMCwCFEZFFgcMl8M5VnE7m8v9axovwkQaAhQgiRI0
+D9VhWSz+xcSb6eGnyrz1Dw==
+-----END CERTIFICATE-----
diff --git a/proton-j/src/test/resources/server.csr b/proton-j/src/test/resources/server.csr
new file mode 100644
index 0000000..92e6d0b
--- /dev/null
+++ b/proton-j/src/test/resources/server.csr
@@ -0,0 +1,13 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICWjCCAhgCAQAwJTESMBAGA1UEAxMJbG9jYWxob3N0MQ8wDQYDVQQKEwZTZXJ2ZXIwggG4MIIB
+LAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZ
+PY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7
+g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKB
+gQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgW
+E7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8G
+kotmXoB7VSVkAUw7/s9JKgOBhQACgYEA6DMTJ9SgEWMlqRkxCJQAljgx9Bo++lsYYaZJyDex1gaw
+upoM3Evgh2de4Fa8SJlcdrTVsxHcItEb2B76dt0EcsPy+hYB8ifRgkny7jW7GGYhZ0M/NC0zRTT/
+gk9rp6VeT2n0+s2ENB5Y6AWXhPBNbh5RE/BCkmC2jBp40gyFYnKgMDAuBgkqhkiG9w0BCQ4xITAf
+MB0GA1UdDgQWBBTzajKA7otk5qXujjMdim+mMBhaEjALBgcqhkjOOAQDBQADLwAwLAIUe/6CarVG
+IB2yNSH9EIso3vmJiuoCFEOFcHlZnVE6ttWis06H76IEaAtt
+-----END NEW CERTIFICATE REQUEST-----