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

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

commit 09af527e949da84b0b4ba46efb2c552d003072d1
Author: Murtadha Hubail <[email protected]>
AuthorDate: Wed Nov 11 23:56:48 2020 +0300

    [NO ISSUE][NET] Use Custom Factory For RMI Client Sockets
    
    - user model changes: no
    - storage format changes: no
    - interface changes: yes
    
    Details:
    
    - Make INetworkSecurityConfig serializable to send it as part
      of the RMI client socket factory.
    - Use custom SSL socket factory for RMI client sockets.
    - Do not set Java's global truststore properties.
    - Make NetworkSecurityManager#newSSLContext static.
    
    Change-Id: I8dd5d370d968b85a44c5007bced1a6abece36030
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/8844
    Integration-Tests: Jenkins <[email protected]>
    Tested-by: Jenkins <[email protected]>
    Reviewed-by: Murtadha Hubail <[email protected]>
    Reviewed-by: Hussain Towaileb <[email protected]>
---
 .../apache/asterix/app/nc/NCAppRuntimeContext.java |  3 +-
 asterixdb/asterix-metadata/pom.xml                 |  4 ++
 .../apache/asterix/metadata/RMIClientFactory.java  | 59 ++++++++++++++++++++--
 .../metadata/bootstrap/AsterixStateProxy.java      |  2 +-
 .../api/network/INetworkSecurityConfig.java        |  3 +-
 .../ipc/security/NetworkSecurityConfig.java        |  3 +-
 .../ipc/security/NetworkSecurityManager.java       | 52 +++++++++----------
 7 files changed, 91 insertions(+), 35 deletions(-)

diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
index 13ca95d..7829b75 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
@@ -444,7 +444,8 @@ public class NCAppRuntimeContext implements 
INcApplicationContext {
             // our client socket factory when SSL is enabled
             if (networkSecurityManager.getConfiguration().isSslEnabled()) {
                 final RMIServerFactory serverSocketFactory = new 
RMIServerFactory(networkSecurityManager);
-                final RMIClientFactory clientSocketFactory = new 
RMIClientFactory(true);
+                final RMIClientFactory clientSocketFactory =
+                        new 
RMIClientFactory(networkSecurityManager.getConfiguration());
                 metadataNodeStub = (IMetadataNode) 
UnicastRemoteObject.exportObject(MetadataNode.INSTANCE,
                         getMetadataProperties().getMetadataPort(), 
clientSocketFactory, serverSocketFactory);
             } else {
diff --git a/asterixdb/asterix-metadata/pom.xml 
b/asterixdb/asterix-metadata/pom.xml
index d14d8d5..f4c471d 100644
--- a/asterixdb/asterix-metadata/pom.xml
+++ b/asterixdb/asterix-metadata/pom.xml
@@ -178,5 +178,9 @@
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-hdfs-client</artifactId>
     </dependency>
+      <dependency>
+      <groupId>org.apache.hyracks</groupId>
+      <artifactId>hyracks-ipc</artifactId>
+    </dependency>
   </dependencies>
 </project>
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 ac2ecd0..515e763 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
@@ -21,23 +21,72 @@ package org.apache.asterix.metadata;
 
 import java.io.IOException;
 import java.io.Serializable;
+import java.net.InetAddress;
 import java.net.Socket;
 import java.rmi.server.RMIClientSocketFactory;
 
 import javax.net.SocketFactory;
 import javax.net.ssl.SSLSocketFactory;
 
+import org.apache.hyracks.api.network.INetworkSecurityConfig;
+import org.apache.hyracks.ipc.security.NetworkSecurityManager;
+
 public class RMIClientFactory implements RMIClientSocketFactory, Serializable {
+
     private static final long serialVersionUID = -3874278041718817394L;
+    private final INetworkSecurityConfig config;
+    private transient SocketFactory socketFactory;
 
-    private final boolean sslEnabled;
+    public RMIClientFactory(INetworkSecurityConfig config) {
+        this.config = config;
 
-    public RMIClientFactory(boolean sslEnabled) {
-        this.sslEnabled = sslEnabled;
     }
 
     public Socket createSocket(String host, int port) throws IOException {
-        final SocketFactory factory = sslEnabled ? 
SSLSocketFactory.getDefault() : SocketFactory.getDefault();
-        return factory.createSocket(host, port);
+        synchronized (this) {
+            if (socketFactory == null) {
+                socketFactory = config.isSslEnabled() ? new 
RMITrustedClientSSLSocketFactory(config)
+                        : SocketFactory.getDefault();
+            }
+        }
+        return socketFactory.createSocket(host, port);
+    }
+
+    private static class RMITrustedClientSSLSocketFactory extends 
SSLSocketFactory {
+
+        protected SSLSocketFactory factory;
+
+        public RMITrustedClientSSLSocketFactory(INetworkSecurityConfig config) 
{
+            this.factory = 
NetworkSecurityManager.newSSLContext(config).getSocketFactory();
+        }
+
+        public Socket createSocket(InetAddress host, int port) throws 
IOException {
+            return this.factory.createSocket(host, port);
+        }
+
+        public Socket createSocket(String host, int port) throws IOException {
+            return this.factory.createSocket(host, port);
+        }
+
+        public Socket createSocket(String host, int port, InetAddress 
localHost, int localPort) throws IOException {
+            return this.factory.createSocket(host, port, localHost, localPort);
+        }
+
+        public Socket createSocket(InetAddress address, int port, InetAddress 
localAddress, int localPort)
+                throws IOException {
+            return this.factory.createSocket(address, port, localAddress, 
localPort);
+        }
+
+        public Socket createSocket(Socket socket, String host, int port, 
boolean autoClose) throws IOException {
+            return this.factory.createSocket(socket, host, port, autoClose);
+        }
+
+        public String[] getDefaultCipherSuites() {
+            return this.factory.getDefaultCipherSuites();
+        }
+
+        public String[] getSupportedCipherSuites() {
+            return this.factory.getSupportedCipherSuites();
+        }
     }
 }
diff --git 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
index d6af749..2104fdf 100644
--- 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
+++ 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
@@ -49,7 +49,7 @@ public class AsterixStateProxy implements IAsterixStateProxy {
         if (networkSecurityManager.getConfiguration().isSslEnabled()) {
             final RMIServerFactory serverSocketFactory = new 
RMIServerFactory(networkSecurityManager);
             final RMIClientFactory clientSocketFactory =
-                    new 
RMIClientFactory(networkSecurityManager.getConfiguration().isSslEnabled());
+                    new 
RMIClientFactory(networkSecurityManager.getConfiguration());
             stub = (IAsterixStateProxy) UnicastRemoteObject.exportObject(cc, 
metadataCallbackPort, clientSocketFactory,
                     serverSocketFactory);
         } else {
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 772ee9f..9c65eea 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
@@ -19,9 +19,10 @@
 package org.apache.hyracks.api.network;
 
 import java.io.File;
+import java.io.Serializable;
 import java.security.KeyStore;
 
-public interface INetworkSecurityConfig {
+public interface INetworkSecurityConfig extends Serializable {
 
     /**
      * Indicates if SSL is enabled
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 7f02830..25ea787 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
@@ -25,11 +25,12 @@ import 
org.apache.hyracks.api.network.INetworkSecurityConfig;
 
 public class NetworkSecurityConfig implements INetworkSecurityConfig {
 
+    private static final long serialVersionUID = -1914030130038989199L;
     private final boolean sslEnabled;
     private final File keyStoreFile;
     private final File trustStoreFile;
     private final String keyStorePassword;
-    private final KeyStore keyStore;
+    private final transient KeyStore keyStore;
 
     private NetworkSecurityConfig(boolean sslEnabled, String keyStoreFile, 
String keyStorePassword,
             String trustStoreFile, KeyStore keyStore) {
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 0c8d429..b7c0d0f 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
@@ -37,37 +37,16 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
 
     private volatile INetworkSecurityConfig config;
     private final ISocketChannelFactory sslSocketFactory;
-    private static final String TSL_VERSION = "TLSv1.2";
+    public static final String TSL_VERSION = "TLSv1.2";
 
     public NetworkSecurityManager(INetworkSecurityConfig config) {
         this.config = config;
-        if (config.isSslEnabled()) {
-            System.setProperty("javax.net.ssl.trustStore", 
config.getTrustStoreFile().getAbsolutePath());
-            System.setProperty("javax.net.ssl.trustStorePassword", 
config.getKeyStorePassword());
-        }
         sslSocketFactory = new SslSocketChannelFactory(this);
     }
 
     @Override
     public SSLContext newSSLContext() {
-        try {
-            final char[] password = getKeyStorePassword();
-            KeyStore engineKeyStore = config.getKeyStore();
-            if (engineKeyStore == null) {
-                engineKeyStore = loadKeyStoreFromFile(password);
-            }
-            final String defaultAlgorithm = 
KeyManagerFactory.getDefaultAlgorithm();
-            KeyManagerFactory keyManagerFactory = 
KeyManagerFactory.getInstance(defaultAlgorithm);
-            TrustManagerFactory trustManagerFactory = 
TrustManagerFactory.getInstance(defaultAlgorithm);
-            keyManagerFactory.init(engineKeyStore, password);
-            final KeyStore trustStore = loadTrustStoreFromFile(password);
-            trustManagerFactory.init(trustStore);
-            SSLContext ctx = SSLContext.getInstance(TSL_VERSION);
-            ctx.init(keyManagerFactory.getKeyManagers(), 
trustManagerFactory.getTrustManagers(), new SecureRandom());
-            return ctx;
-        } catch (Exception ex) {
-            throw new IllegalStateException("Failed to create SSLEngine", ex);
-        }
+        return newSSLContext(config);
     }
 
     @Override
@@ -97,7 +76,28 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
         this.config = config;
     }
 
-    private KeyStore loadKeyStoreFromFile(char[] password) {
+    public static SSLContext newSSLContext(INetworkSecurityConfig config) {
+        try {
+            final char[] password = getKeyStorePassword(config);
+            KeyStore engineKeyStore = config.getKeyStore();
+            if (engineKeyStore == null) {
+                engineKeyStore = loadKeyStoreFromFile(password, config);
+            }
+            final String defaultAlgorithm = 
KeyManagerFactory.getDefaultAlgorithm();
+            KeyManagerFactory keyManagerFactory = 
KeyManagerFactory.getInstance(defaultAlgorithm);
+            TrustManagerFactory trustManagerFactory = 
TrustManagerFactory.getInstance(defaultAlgorithm);
+            keyManagerFactory.init(engineKeyStore, password);
+            final KeyStore trustStore = loadTrustStoreFromFile(password, 
config);
+            trustManagerFactory.init(trustStore);
+            SSLContext ctx = SSLContext.getInstance(TSL_VERSION);
+            ctx.init(keyManagerFactory.getKeyManagers(), 
trustManagerFactory.getTrustManagers(), new SecureRandom());
+            return ctx;
+        } catch (Exception ex) {
+            throw new IllegalStateException("Failed to create SSLEngine", ex);
+        }
+    }
+
+    private static KeyStore loadKeyStoreFromFile(char[] password, 
INetworkSecurityConfig config) {
         try {
             final KeyStore ks = 
KeyStore.getInstance(KeyStore.getDefaultType());
             ks.load(new FileInputStream(config.getKeyStoreFile()), password);
@@ -107,7 +107,7 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
         }
     }
 
-    private KeyStore loadTrustStoreFromFile(char[] password) {
+    private static KeyStore loadTrustStoreFromFile(char[] password, 
INetworkSecurityConfig config) {
         try {
             final KeyStore ks = 
KeyStore.getInstance(KeyStore.getDefaultType());
             ks.load(new FileInputStream(config.getTrustStoreFile()), password);
@@ -117,7 +117,7 @@ public class NetworkSecurityManager implements 
INetworkSecurityManager {
         }
     }
 
-    private char[] getKeyStorePassword() {
+    private static char[] getKeyStorePassword(INetworkSecurityConfig config) {
         final String pass = config.getKeyStorePassword();
         return pass == null || pass.isEmpty() ? null : pass.toCharArray();
     }

Reply via email to