package water; import water.network.SSLContextException; import water.network.SSLSocketChannelFactory; import water.util.Log; import java.io.IOException; import java.nio.channels.ByteChannel; import java.nio.channels.SocketChannel; /** * Takes care of security. * * In the long run this class should manage all security aspects of H2O but currently some parts are handled * in other parts of the codebase. * * An instance of this class should be instantiated for each H2O object * and should follow its lifecycle. * * At this stage we support a simple shared secret, handshake based, authentication, which can be turned * on with the h2o_ssl_enabled parameter. Should the communicating nodes not share a common shared secret * communication between them will not be possible. While using this parameter the user should *not* enable * the useUDP parameter, we do not support UDP encryption at this stage and all UDP datagrams will be * sent in an unencrypted form! * * Current state of data encryption: * * - HTTP for FlowUI - currently we rely on Jetty's SSL capabilities, authentication can be performed with * hash login, ldap login or kerberos. The location of secret keys used byt Jetty's SSL server should be * passed to the jks parameter. * * - inter node communication - all TCP based communication is being authenticated and encrypted using SSL * using JSSE (Java Secure Socket Extension) when then h2o_ssl_enabled parameter is passed. Keystore related * parameter should also be used as per the documentation. Secure UDP communication through DTLS is not supported * at this point in time thus useUDP should not be used for SSL enabled clouds. * * - in-memory data encryption - currently not supported, using an encrypted drive is recommended * at least for the swap partition. * * - data saved to disk - currently not supported, using an encrypted drive is recommended * */ public class H2OSecurityManager { private volatile static H2OSecurityManager INSTANCE = null; public final boolean securityEnabled; private SSLSocketChannelFactory sslSocketChannelFactory; private H2OSecurityManager() { this.securityEnabled = H2O.ARGS.internal_security_conf != null; try { if (null != H2O.ARGS.internal_security_conf) { this.sslSocketChannelFactory = new SSLSocketChannelFactory(); Log.info("H2O node running in encrypted mode using config file [" + H2O.ARGS.internal_security_conf + "]"); } else { Log.info("H2O node running in unencrypted mode."); } } catch (SSLContextException e) { Log.err("Node initialized with SSL enabled but failed to create SSLContext. " + "Node initialization aborted."); Log.err(e); H2O.exit(1); } } public ByteChannel wrapServerChannel(SocketChannel channel) throws IOException { return sslSocketChannelFactory.wrapServerChannel(channel); } public ByteChannel wrapClientChannel(SocketChannel channel, String host, int port) throws IOException { return sslSocketChannelFactory.wrapClientChannel(channel, host, port); } public static H2OSecurityManager instance() { if(null == INSTANCE) { synchronized (H2OSecurityManager.class) { if (null == INSTANCE) { INSTANCE = new H2OSecurityManager(); } } } return INSTANCE; } }