Skip to content
Permalink
Browse files
[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 <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
Reviewed-by: Hussain Towaileb <hussainht@gmail.com>
  • Loading branch information
mhubail committed Nov 13, 2020
1 parent c402e3a commit 09af527e949da84b0b4ba46efb2c552d003072d1
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 35 deletions.
@@ -444,7 +444,8 @@ public synchronized void exportMetadataNodeStub() throws RemoteException {
// 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 {
@@ -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>
@@ -21,23 +21,72 @@

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();
}
}
}
@@ -49,7 +49,7 @@ public static IAsterixStateProxy registerRemoteObject(INetworkSecurityManager ne
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 {
@@ -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
@@ -25,11 +25,12 @@

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) {
@@ -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 void setConfiguration(INetworkSecurityConfig config) {
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 @@ private KeyStore loadKeyStoreFromFile(char[] password) {
}
}

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 @@ private KeyStore loadTrustStoreFromFile(char[] password) {
}
}

private char[] getKeyStorePassword() {
private static char[] getKeyStorePassword(INetworkSecurityConfig config) {
final String pass = config.getKeyStorePassword();
return pass == null || pass.isEmpty() ? null : pass.toCharArray();
}

0 comments on commit 09af527

Please sign in to comment.