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]

Reply via email to