This is an automated email from the ASF dual-hosted git repository.
tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git
The following commit(s) were added to refs/heads/main by this push:
new 82222347 PROTON-2727 Allow reading key and trust store files from
class path
82222347 is described below
commit 8222234737d7e24dc17d54bbfaa67ace69f12b95
Author: Timothy Bish <[email protected]>
AuthorDate: Tue Mar 19 17:41:04 2024 -0400
PROTON-2727 Allow reading key and trust store files from class path
Use prefix notation to indicate that a store is to be found on the class
path, prefix is 'classpath:' and add some tests for that case.
---
.../client/transport/netty4/SslSupport.java | 34 ++++++++++++++++--
.../client/transport/netty5/SslSupport.java | 31 ++++++++++++++--
.../protonj2/client/impl/SslConnectionTest.java | 25 ++++++++++---
.../client/transport/netty4/SslTransportTest.java | 42 ++++++++++++++++++++++
.../client/transport/netty5/SslTransportTest.java | 42 ++++++++++++++++++++++
5 files changed, 164 insertions(+), 10 deletions(-)
diff --git
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty4/SslSupport.java
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty4/SslSupport.java
index 5dd5c23d..02f4e868 100644
---
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty4/SslSupport.java
+++
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty4/SslSupport.java
@@ -16,8 +16,8 @@
*/
package org.apache.qpid.protonj2.client.transport.netty4;
-import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -56,6 +56,10 @@ public final class SslSupport {
private static final Logger LOG =
LoggerFactory.getLogger(SslSupport.class);
+ public static final String FROM_CLASSPATH_PREFIX = "classpath:";
+ public static final String FROM_FILE_PREFIX = "file:";
+ public static final String FROM_FILE_URL_PREFIX = "file://";
+
/**
* Determines if Netty OpenSSL support is available and applicable based
on the configuration
* in the given TransportOptions instance.
@@ -437,11 +441,35 @@ public final class SslSupport {
}
private static KeyStore loadStore(String storePath, final String password,
String storeType) throws Exception {
- KeyStore store = KeyStore.getInstance(storeType);
- try (InputStream in = new FileInputStream(new File(storePath));) {
+ final KeyStore store = KeyStore.getInstance(storeType);
+
+ try (InputStream in = openStoreAtLocation(storePath)) {
store.load(in, password != null ? password.toCharArray() : null);
+ } catch (Exception ex) {
+ LOG.trace("Caught Error loading store: {}", ex.getMessage(), ex);
+ throw ex;
}
return store;
}
+
+ private static InputStream openStoreAtLocation(final String storePath)
throws IOException {
+ final InputStream stream;
+
+ if (storePath.startsWith(FROM_CLASSPATH_PREFIX)) {
+ stream =
Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath.substring(FROM_CLASSPATH_PREFIX.length()));
+ } else if (storePath.startsWith(FROM_FILE_URL_PREFIX)) {
+ stream = new
FileInputStream(storePath.substring(FROM_FILE_URL_PREFIX.length()));
+ } else if (storePath.startsWith(FROM_FILE_PREFIX)) {
+ stream = new
FileInputStream(storePath.substring(FROM_FILE_PREFIX.length()));
+ } else {
+ stream = new FileInputStream(storePath);
+ }
+
+ if (stream == null) {
+ throw new IOException("Could no locate KeyStore at location: " +
storePath);
+ }
+
+ return stream;
+ }
}
diff --git
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java
index 88acd345..4d1ffe3c 100644
---
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java
+++
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java
@@ -16,8 +16,8 @@
*/
package org.apache.qpid.protonj2.client.transport.netty5;
-import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -56,6 +56,10 @@ public final class SslSupport {
private static final Logger LOG =
LoggerFactory.getLogger(SslSupport.class);
+ public static final String FROM_CLASSPATH_PREFIX = "classpath:";
+ public static final String FROM_FILE_PREFIX = "file:";
+ public static final String FROM_FILE_URL_PREFIX = "file://";
+
/**
* Determines if Netty OpenSSL support is available and applicable based
on the configuration
* in the given TransportOptions instance.
@@ -438,10 +442,33 @@ public final class SslSupport {
private static KeyStore loadStore(String storePath, final String password,
String storeType) throws Exception {
KeyStore store = KeyStore.getInstance(storeType);
- try (InputStream in = new FileInputStream(new File(storePath));) {
+ try (InputStream in = openStoreAtLocation(storePath)) {
store.load(in, password != null ? password.toCharArray() : null);
+ } catch (Exception ex) {
+ LOG.trace("Caught Error loading store: {}", ex.getMessage(), ex);
+ throw ex;
}
return store;
}
+
+ private static InputStream openStoreAtLocation(final String storePath)
throws IOException {
+ final InputStream stream;
+
+ if (storePath.startsWith(FROM_CLASSPATH_PREFIX)) {
+ stream =
Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath.substring(FROM_CLASSPATH_PREFIX.length()));
+ } else if (storePath.startsWith(FROM_FILE_URL_PREFIX)) {
+ stream = new
FileInputStream(storePath.substring(FROM_FILE_URL_PREFIX.length()));
+ } else if (storePath.startsWith(FROM_FILE_PREFIX)) {
+ stream = new
FileInputStream(storePath.substring(FROM_FILE_PREFIX.length()));
+ } else {
+ stream = new FileInputStream(storePath);
+ }
+
+ if (stream == null) {
+ throw new IOException("Could no locate KeyStore at location: " +
storePath);
+ }
+
+ return stream;
+ }
}
diff --git
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
index c0f61a9c..93c5c395 100644
---
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
+++
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
@@ -66,6 +66,7 @@ public class SslConnectionTest extends
ImperativeClientTestCase {
private static final String BROKER_PKCS12_TRUSTSTORE =
"src/test/resources/broker-pkcs12.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 CLIENT_JKS_TRUSTSTORE_CLASSPATH =
"classpath:client-jks.truststore";
private static final String CLIENT_PKCS12_TRUSTSTORE =
"src/test/resources/client-pkcs12.truststore";
private static final String OTHER_CA_TRUSTSTORE =
"src/test/resources/other-ca-jks.truststore";
private static final String CLIENT_JKS_KEYSTORE =
"src/test/resources/client-jks.keystore";
@@ -100,7 +101,12 @@ public class SslConnectionTest extends
ImperativeClientTestCase {
@Test
public void testCreateAndCloseSslConnectionJDK() throws Exception {
- testCreateAndCloseSslConnection(false);
+ testCreateAndCloseSslConnection(false, false);
+ }
+
+ @Test
+ public void testCreateAndCloseSslConnectionJDKTrustStoreOnClasspath()
throws Exception {
+ testCreateAndCloseSslConnection(false, true);
}
@Test
@@ -108,10 +114,18 @@ public class SslConnectionTest extends
ImperativeClientTestCase {
assumeTrue(OpenSsl.isAvailable());
assumeTrue(OpenSsl.supportsKeyManagerFactory());
- testCreateAndCloseSslConnection(true);
+ testCreateAndCloseSslConnection(true, false);
}
- private void testCreateAndCloseSslConnection(boolean openSSL) throws
Exception {
+ @Test
+ public void testCreateAndCloseSslConnectionOpenSSLTrustStoreOnClasspath()
throws Exception {
+ assumeTrue(OpenSsl.isAvailable());
+ assumeTrue(OpenSsl.supportsKeyManagerFactory());
+
+ testCreateAndCloseSslConnection(true, true);
+ }
+
+ private void testCreateAndCloseSslConnection(boolean openSSL, boolean
storeFromClassPath) throws Exception {
ProtonTestServerOptions serverOptions = serverOptions();
serverOptions.setSecure(true);
serverOptions.setKeyStoreLocation(BROKER_JKS_KEYSTORE);
@@ -124,11 +138,12 @@ public class SslConnectionTest extends
ImperativeClientTestCase {
peer.expectClose().respond();
peer.start();
- URI remoteURI = peer.getServerURI();
+ final URI remoteURI = peer.getServerURI();
+ final String storeLocation = storeFromClassPath ?
CLIENT_JKS_TRUSTSTORE_CLASSPATH : CLIENT_JKS_TRUSTSTORE;
ConnectionOptions clientOptions = connectionOptions();
clientOptions.sslOptions()
- .trustStoreLocation(CLIENT_JKS_TRUSTSTORE)
+ .trustStoreLocation(storeLocation)
.trustStorePassword(PASSWORD)
.allowNativeSSL(openSSL);
diff --git
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty4/SslTransportTest.java
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty4/SslTransportTest.java
index 42401424..cc8d3ed3 100644
---
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty4/SslTransportTest.java
+++
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty4/SslTransportTest.java
@@ -52,6 +52,8 @@ public class SslTransportTest extends TcpTransportTest {
public static final String CLIENT_MULTI_KEYSTORE =
"src/test/resources/client-multiple-keys-jks.keystore";
public static final String CLIENT_TRUSTSTORE =
"src/test/resources/client-jks.truststore";
public static final String OTHER_CA_TRUSTSTORE =
"src/test/resources/other-ca-jks.truststore";
+ public static final String SERVER_CLASSPATH_KEYSTORE =
"classpath:broker-jks.keystore";
+ public static final String SERVER_CLASSPATH_TRUSTSTORE =
"classpath:broker-jks.truststore";
public static final String CLIENT_KEY_ALIAS = "client";
public static final String CLIENT_DN = "O=Client,CN=client";
@@ -210,6 +212,31 @@ public class SslTransportTest extends TcpTransportTest {
assertTrue(exceptions.isEmpty());
}
+ @Test
+ public void testConnectToServerWithServerClasspathStores() throws
Exception {
+ try (NettyEchoServer server = createEchoServer()) {
+ server.start();
+
+ final int port = server.getServerPort();
+
+ Transport transport = createTransport(createTransportOptions(),
createServerClasspathSSLOptions());
+ try {
+ transport.connect(HOSTNAME, port, testListener).awaitConnect();
+ LOG.info("Connection established to test server: {}:{}",
HOSTNAME, port);
+ } catch (Exception e) {
+ fail("Should not have failed to connect to the server at " +
HOSTNAME + ":" + port + " but got exception: " + e);
+ }
+
+ assertTrue(transport.isConnected());
+ assertTrue(transport.isSecure());
+
+ transport.close();
+ }
+
+ logTransportErrors();
+ assertTrue(exceptions.isEmpty());
+ }
+
@Test
public void testConnectWithNeedClientAuth() throws Exception {
try (NettyEchoServer server = createEchoServer(true)) {
@@ -386,4 +413,19 @@ public class SslTransportTest extends TcpTransportTest {
return options;
}
+
+ protected SslOptions createServerClasspathSSLOptions() {
+ SslOptions options = new SslOptions();
+
+ // Run the server in JDK mode for now to validate cross compatibility
+ options.sslEnabled(true);
+ options.keyStoreLocation(SERVER_CLASSPATH_KEYSTORE);
+ options.keyStorePassword(PASSWORD);
+ options.trustStoreLocation(SERVER_CLASSPATH_TRUSTSTORE);
+ options.trustStorePassword(PASSWORD);
+ options.storeType(KEYSTORE_TYPE);
+ options.verifyHost(false);
+
+ return options;
+ }
}
diff --git
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java
index c7e0c118..6083305f 100644
---
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java
+++
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java
@@ -52,6 +52,8 @@ public class SslTransportTest extends TcpTransportTest {
public static final String CLIENT_MULTI_KEYSTORE =
"src/test/resources/client-multiple-keys-jks.keystore";
public static final String CLIENT_TRUSTSTORE =
"src/test/resources/client-jks.truststore";
public static final String OTHER_CA_TRUSTSTORE =
"src/test/resources/other-ca-jks.truststore";
+ public static final String SERVER_CLASSPATH_KEYSTORE =
"classpath:broker-jks.keystore";
+ public static final String SERVER_CLASSPATH_TRUSTSTORE =
"classpath:broker-jks.truststore";
public static final String CLIENT_KEY_ALIAS = "client";
public static final String CLIENT_DN = "O=Client,CN=client";
@@ -210,6 +212,31 @@ public class SslTransportTest extends TcpTransportTest {
assertTrue(exceptions.isEmpty());
}
+ @Test
+ public void testConnectToServerWithServerClasspathStores() throws
Exception {
+ try (NettyEchoServer server = createEchoServer()) {
+ server.start();
+
+ final int port = server.getServerPort();
+
+ Transport transport = createTransport(createTransportOptions(),
createServerClasspathSSLOptions());
+ try {
+ transport.connect(HOSTNAME, port, testListener).awaitConnect();
+ LOG.info("Connection established to test server: {}:{}",
HOSTNAME, port);
+ } catch (Exception e) {
+ fail("Should not have failed to connect to the server at " +
HOSTNAME + ":" + port + " but got exception: " + e);
+ }
+
+ assertTrue(transport.isConnected());
+ assertTrue(transport.isSecure());
+
+ transport.close();
+ }
+
+ logTransportErrors();
+ assertTrue(exceptions.isEmpty());
+ }
+
@Test
public void testConnectWithNeedClientAuth() throws Exception {
try (NettyEchoServer server = createEchoServer(true)) {
@@ -390,4 +417,19 @@ public class SslTransportTest extends TcpTransportTest {
return options;
}
+
+ protected SslOptions createServerClasspathSSLOptions() {
+ SslOptions options = new SslOptions();
+
+ // Run the server in JDK mode for now to validate cross compatibility
+ options.sslEnabled(true);
+ options.keyStoreLocation(SERVER_CLASSPATH_KEYSTORE);
+ options.keyStorePassword(PASSWORD);
+ options.trustStoreLocation(SERVER_CLASSPATH_TRUSTSTORE);
+ options.trustStorePassword(PASSWORD);
+ options.storeType(KEYSTORE_TYPE);
+ options.verifyHost(false);
+
+ return options;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]