This is an automated email from the ASF dual-hosted git repository.

ritik pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git

commit de80a9cbbf164f51eb435ddd21c65d3a747319f5
Author: Michael Blow <[email protected]>
AuthorDate: Wed Oct 9 21:19:47 2024 -0400

    [NO ISSUE][HYR][NET] Extend SSL engine API to indicate client use
    
    Ext-ref: MB-52099
    Change-Id: Id46266849ded6d0ea632293e829aed78396e0ea1
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18950
    Tested-by: Jenkins <[email protected]>
    Reviewed-by: Michael Blow <[email protected]>
    Reviewed-by: Murtadha Hubail <[email protected]>
---
 .../external/library/ExternalLibraryManager.java   |  8 ++--
 .../apache/asterix/metadata/RMIClientFactory.java  |  2 +-
 .../apache/asterix/metadata/RMIServerFactory.java  |  2 +-
 hyracks-fullstack/hyracks/hyracks-api/pom.xml      |  4 ++
 .../api/network/INetworkSecurityConfig.java        | 40 +++++++++++++---
 .../api/network/INetworkSecurityManager.java       |  4 +-
 hyracks-fullstack/hyracks/hyracks-ipc/pom.xml      |  4 ++
 .../ipc/security/NetworkSecurityConfig.java        | 30 ++++++++++--
 .../ipc/security/NetworkSecurityManager.java       | 56 +++++++++++-----------
 .../ipc/sockets/SslSocketChannelFactory.java       |  6 +--
 10 files changed, 105 insertions(+), 51 deletions(-)

diff --git 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
index 050d9f0071..174369542a 100755
--- 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
+++ 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
@@ -48,6 +48,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.zip.ZipEntry;
@@ -657,11 +658,10 @@ public class ExternalLibraryManager implements 
ILibraryManager, ILifeCycleCompon
             final INetworkSecurityConfig configuration = 
networkSecurityManager.getConfiguration();
             KeyStore trustStore = 
KeyStore.getInstance(KeyStore.getDefaultType());
             try (FileInputStream trustStoreFile = new 
FileInputStream(configuration.getTrustStoreFile())) {
-                String ksPassword = configuration.getKeyStorePassword();
-                trustStore.load(trustStoreFile,
-                        ksPassword == null || ksPassword.isEmpty() ? null : 
ksPassword.toCharArray());
+                Optional<char[]> ksPassword = 
configuration.getKeyStorePassword();
+                trustStore.load(trustStoreFile, ksPassword.orElse(null));
             }
-            SSLContext sslcontext = 
NetworkSecurityManager.newSSLContext(configuration);
+            SSLContext sslcontext = 
NetworkSecurityManager.newSSLContext(configuration, false);
             SSLConnectionSocketFactory sslsf = new 
SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1.2" },
                     null, 
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
             return HttpClients.custom().setSSLSocketFactory(sslsf).build();
diff --git 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIClientFactory.java
 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIClientFactory.java
index ce459e27f7..da802a74f0 100644
--- 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIClientFactory.java
+++ 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIClientFactory.java
@@ -68,7 +68,7 @@ public class RMIClientFactory implements 
RMIClientSocketFactory, Serializable {
         protected SSLSocketFactory factory;
 
         public RMITrustedClientSSLSocketFactory(INetworkSecurityConfig config) 
{
-            this.factory = 
NetworkSecurityManager.newSSLContext(config).getSocketFactory();
+            this.factory = NetworkSecurityManager.newSSLContext(config, 
false).getSocketFactory();
         }
 
         public Socket createSocket(InetAddress host, int port) throws 
IOException {
diff --git 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIServerFactory.java
 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIServerFactory.java
index 6a0edc00e1..845324a157 100644
--- 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIServerFactory.java
+++ 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/RMIServerFactory.java
@@ -46,7 +46,7 @@ public class RMIServerFactory implements 
RMIServerSocketFactory {
     public ServerSocket createServerSocket(int port) throws IOException {
         ServerSocketFactory socketFactory;
         if (securityManager.getConfiguration().isSslEnabled()) {
-            socketFactory = 
securityManager.newSSLContext().getServerSocketFactory();
+            socketFactory = 
securityManager.newSSLContext(false).getServerSocketFactory();
         } else {
             socketFactory = ServerSocketFactory.getDefault();
         }
diff --git a/hyracks-fullstack/hyracks/hyracks-api/pom.xml 
b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
index 7a4eb58cf9..eee03f3570 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
@@ -105,5 +105,9 @@
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-handler</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityConfig.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityConfig.java
index 7fc0335c5c..e581c5a00f 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityConfig.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityConfig.java
@@ -24,6 +24,8 @@ import java.net.InetAddress;
 import java.security.KeyStore;
 import java.util.Optional;
 
+import io.netty.handler.ssl.ClientAuth;
+
 public interface INetworkSecurityConfig extends Serializable {
 
     /**
@@ -33,26 +35,52 @@ public interface INetworkSecurityConfig extends 
Serializable {
      */
     boolean isSslEnabled();
 
+    /**
+     * Indicates how to handle client authentication when ssl is enabled
+     */
+    ClientAuth getClientAuth();
+
     /**
      * Gets the key store to be used for secured connections
      *
-     * @return the key store to be used
+     * @return the key store to be used, if present
      */
-    KeyStore getKeyStore();
+    Optional<KeyStore> getKeyStore();
 
     /**
-     * Gets a key store file to be used if {@link 
INetworkSecurityConfig#getKeyStore()} returns null.
+     * Gets a key store file, password pair to be used if {@link 
INetworkSecurityConfig#getKeyStore()} returns empty.
      *
      * @return the key store file
      */
     File getKeyStoreFile();
 
     /**
-     * Gets the password for the key store file.
+     * Gets a password to be used to unlock or check integrity of the key 
store.
+     *
+     * @return the key store password, or {@link Optional#empty()}
+     */
+    Optional<char[]> getKeyStorePassword();
+
+    /**
+     * Gets the client key store to be used for client auth, if applicable.
+     *
+     * @return the client key store to be used for client auth, or {@link 
Optional#empty()}
+     */
+    Optional<KeyStore> getClientKeyStore();
+
+    /**
+     * Gets a client key store file to be used if {@link 
INetworkSecurityConfig#getClientKeyStore()} returns empty.
+     *
+     * @return the key store file
+     */
+    File getClientKeyStoreFile();
+
+    /**
+     * Gets a password to be used to unlock or check integrity of the client 
key store.
      *
-     * @return the password to the key store file
+     * @return the client key store password, or {@link Optional#empty()}
      */
-    String getKeyStorePassword();
+    Optional<char[]> getClientKeyStorePassword();
 
     /**
      * Gets the trust store to be used for validating certificates of secured 
connections
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityManager.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityManager.java
index eb52436d4e..8462f915d1 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityManager.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/network/INetworkSecurityManager.java
@@ -28,14 +28,14 @@ public interface INetworkSecurityManager {
      *
      * @return a new ssl context
      */
-    SSLContext newSSLContext();
+    SSLContext newSSLContext(boolean clientMode);
 
     /**
      * Creates a new ssl engine based on the current configuration of this 
{@link INetworkSecurityManager}
      *
      * @return a new ssl engine
      */
-    SSLEngine newSSLEngine();
+    SSLEngine newSSLEngine(boolean clientMode);
 
     /**
      * Sets the configuration to be used for this {@link 
INetworkSecurityManager}
diff --git a/hyracks-fullstack/hyracks/hyracks-ipc/pom.xml 
b/hyracks-fullstack/hyracks/hyracks-ipc/pom.xml
index 939f48709e..8157554ed1 100644
--- a/hyracks-fullstack/hyracks/hyracks-ipc/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-ipc/pom.xml
@@ -67,5 +67,9 @@
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-handler</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityConfig.java
 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityConfig.java
index bfcd623900..a8bd087dd4 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityConfig.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityConfig.java
@@ -31,6 +31,8 @@ import java.util.Optional;
 
 import org.apache.hyracks.api.network.INetworkSecurityConfig;
 
+import io.netty.handler.ssl.ClientAuth;
+
 public class NetworkSecurityConfig implements INetworkSecurityConfig {
 
     private static final long serialVersionUID = 2L;
@@ -67,19 +69,39 @@ public class NetworkSecurityConfig implements 
INetworkSecurityConfig {
         return sslEnabled;
     }
 
+    @Override
+    public ClientAuth getClientAuth() {
+        return ClientAuth.NONE;
+    }
+
     @Override
     public File getKeyStoreFile() {
         return keyStoreFile;
     }
 
     @Override
-    public String getKeyStorePassword() {
-        return keyStorePassword;
+    public Optional<char[]> getKeyStorePassword() {
+        return keyStorePassword != null ? 
Optional.of(keyStorePassword.toCharArray()) : Optional.empty();
     }
 
     @Override
-    public KeyStore getKeyStore() {
-        return keyStore;
+    public Optional<KeyStore> getKeyStore() {
+        return Optional.ofNullable(keyStore);
+    }
+
+    @Override
+    public Optional<KeyStore> getClientKeyStore() {
+        return Optional.empty();
+    }
+
+    @Override
+    public File getClientKeyStoreFile() {
+        return null;
+    }
+
+    @Override
+    public Optional<char[]> getClientKeyStorePassword() {
+        return Optional.empty();
     }
 
     @Override
diff --git 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityManager.java
 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityManager.java
index db524ca3d5..d8f5cff225 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityManager.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/security/NetworkSecurityManager.java
@@ -18,6 +18,7 @@
  */
 package org.apache.hyracks.ipc.security;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.security.KeyStore;
 import java.security.SecureRandom;
@@ -37,7 +38,7 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
 
     private volatile INetworkSecurityConfig config;
     protected final ISocketChannelFactory sslSocketFactory;
-    public static final String TSL_VERSION = "TLSv1.2";
+    public static final String TLS_VERSION = "TLSv1.2";
 
     public NetworkSecurityManager(INetworkSecurityConfig config) {
         this.config = config;
@@ -45,15 +46,16 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
     }
 
     @Override
-    public SSLContext newSSLContext() {
-        return newSSLContext(config);
+    public SSLContext newSSLContext(boolean clientMode) {
+        return newSSLContext(config, clientMode);
     }
 
     @Override
-    public SSLEngine newSSLEngine() {
+    public SSLEngine newSSLEngine(boolean clientMode) {
         try {
-            SSLContext ctx = newSSLContext();
-            return ctx.createSSLEngine();
+            SSLEngine sslEngine = newSSLContext(clientMode).createSSLEngine();
+            sslEngine.setUseClientMode(clientMode);
+            return sslEngine;
         } catch (Exception ex) {
             throw new IllegalStateException("Failed to create SSLEngine", ex);
         }
@@ -76,12 +78,22 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
         this.config = config;
     }
 
-    public static SSLContext newSSLContext(INetworkSecurityConfig config) {
+    public static SSLContext newSSLContext(INetworkSecurityConfig config, 
boolean clientMode) {
         try {
-            final char[] password = getKeyStorePassword(config);
-            KeyStore engineKeyStore = config.getKeyStore();
-            if (engineKeyStore == null) {
-                engineKeyStore = loadKeyStoreFromFile(password, config);
+            KeyStore engineKeyStore;
+            final char[] password;
+            if (clientMode) {
+                password = config.getClientKeyStorePassword().orElse(null);
+                engineKeyStore = config.getClientKeyStore().orElse(null);
+                if (engineKeyStore == null) {
+                    engineKeyStore = loadKeyStoreFromFile(password, 
config.getClientKeyStoreFile());
+                }
+            } else {
+                password = config.getKeyStorePassword().orElse(null);
+                engineKeyStore = config.getKeyStore().orElse(null);
+                if (engineKeyStore == null) {
+                    engineKeyStore = loadKeyStoreFromFile(password, 
config.getKeyStoreFile());
+                }
             }
             final String defaultAlgorithm = 
KeyManagerFactory.getDefaultAlgorithm();
             KeyManagerFactory keyManagerFactory = 
KeyManagerFactory.getInstance(defaultAlgorithm);
@@ -89,10 +101,10 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
             keyManagerFactory.init(engineKeyStore, password);
             KeyStore trustStore = config.getTrustStore();
             if (trustStore == null) {
-                trustStore = loadTrustStoreFromFile(password, config);
+                trustStore = loadKeyStoreFromFile(password, 
config.getTrustStoreFile());
             }
             trustManagerFactory.init(trustStore);
-            SSLContext ctx = SSLContext.getInstance(TSL_VERSION);
+            SSLContext ctx = SSLContext.getInstance(TLS_VERSION);
             ctx.init(keyManagerFactory.getKeyManagers(), 
trustManagerFactory.getTrustManagers(), new SecureRandom());
             return ctx;
         } catch (Exception ex) {
@@ -100,28 +112,14 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
         }
     }
 
-    private static KeyStore loadKeyStoreFromFile(char[] password, 
INetworkSecurityConfig config) {
+    private static KeyStore loadKeyStoreFromFile(char[] password, File 
keystoreFile) {
         try {
             final KeyStore ks = 
KeyStore.getInstance(KeyStore.getDefaultType());
-            ks.load(new FileInputStream(config.getKeyStoreFile()), password);
+            ks.load(new FileInputStream(keystoreFile), password);
             return ks;
         } catch (Exception e) {
             throw new IllegalStateException("failed to load key store", e);
         }
     }
 
-    private static KeyStore loadTrustStoreFromFile(char[] password, 
INetworkSecurityConfig config) {
-        try {
-            final KeyStore ks = 
KeyStore.getInstance(KeyStore.getDefaultType());
-            ks.load(new FileInputStream(config.getTrustStoreFile()), password);
-            return ks;
-        } catch (Exception e) {
-            throw new IllegalStateException("failed to load trust store", e);
-        }
-    }
-
-    private static char[] getKeyStorePassword(INetworkSecurityConfig config) {
-        final String pass = config.getKeyStorePassword();
-        return pass == null || pass.isEmpty() ? null : pass.toCharArray();
-    }
 }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/sockets/SslSocketChannelFactory.java
 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/sockets/SslSocketChannelFactory.java
index 2a2fb62830..0e4b9da5b5 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/sockets/SslSocketChannelFactory.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-ipc/src/main/java/org/apache/hyracks/ipc/sockets/SslSocketChannelFactory.java
@@ -36,15 +36,13 @@ public class SslSocketChannelFactory implements 
ISocketChannelFactory {
 
     @Override
     public ISocketChannel createServerChannel(SocketChannel socketChannel) {
-        final SSLEngine sslEngine = networkSecurityManager.newSSLEngine();
-        sslEngine.setUseClientMode(false);
+        final SSLEngine sslEngine = networkSecurityManager.newSSLEngine(false);
         return new SslSocketChannel(socketChannel, sslEngine);
     }
 
     @Override
     public ISocketChannel createClientChannel(SocketChannel socketChannel) {
-        final SSLEngine sslEngine = networkSecurityManager.newSSLEngine();
-        sslEngine.setUseClientMode(true);
+        final SSLEngine sslEngine = networkSecurityManager.newSSLEngine(true);
         return new SslSocketChannel(socketChannel, sslEngine);
     }
 }

Reply via email to