Configuring SSL/TLS communications

From JPPF Documentation version 3.x

Jump to: navigation, search

Contents

Main Page > Configuration guide > Configuring SSL/TLS

A JPPF grid has the ability to use secure connections between its components. This is done by using the SSL/TLS protocols over network connections, and provides security services such as peer authentication, data encryption and data integrity. This documentation aims at describing how to configure secure connections between JPPF servers, nodes and clients. If you wish to learn details of the SSL/TLS protocols in Java, our recommendation is to read about this in the Java Secure Socket Extension (JSSE) Reference Guide.

Additionally, all downloadable JPPF components now come with a predefined set of SSL configuration files, which can be used as-is for testing purposes. These files notably include a truststore and a keystore containing self-signed certificates and private keys. For real-world secure connectivity in JPPF, you will have to provide your own key- and trust- stores, with the proper certificate chains, validated by trusted certificate authorities.

Enabling secure connectivity

In the nodes and clients

Nodes and clients use either secure connections, or non-secure connections, but not both at the same time. Thus, this is determined from a single configuration property in their respective configuration file:

# Enable SSL. Default value is false (disabled)
# If enabled, only SSL/TLS connections are established
jppf.ssl.enabled = true

For a node, this also means that its embedded JMX server will only accept secure connections. Apart from the SSL configuration itself, no other properties are required to enable secure connections: the hosts and ports defined in the configuration or via server discovery will be assumed to be secure. If they are not, no connection will be possible.

In the servers

A JPPF server has the ability to accept both secure and non-secure connections, i.e. this is not a single on/off switch as for nodes and clients. Additionally, there are 3 areas of a JPPF server that can be configured separately: “standard” connections from nodes and clients (grid jobs handling and distributed class loader), connections to other servers and embedded JMX server. These are configured via the following properties in the server's configuration file:

# Port number to which the server listens for secure connections, defaults to 11443
# A negative value indicates that no secure connection is accepted
jppf.ssl.server.port = 11443

# toggle to enable secure connections to remote peer servers, defaults to false
jppf.peer.ssl.enabled = true

# Enabling JMX features via secure connections, defaults to false
jppf.management.ssl.enabled = true

Please note that jppf.ssl.server.port (secure port) comes in addition to jppf.server.port (non secure) and that both can be used together. For instance, if you wish to only accept secure connections, you will have to disable the non-secure connections by specifying a negative port number:

As for the non-secure port, assigning a value of 0 will cause JPPF to dynamically allocate a valid port number.

# disable non-secure connections
jppf.server.port = -1
# enable secure connections
jppf.ssl.server.port = 11443

In a similar way you can use either JMX secure or non-secure connections, or both:

# disable JMX via non-secure connections
jppf.management.enabled = false
# enable JMX via secure connections
jppf.management.ssl.enabled = true
# secure JMX server port
jppf.management.ssl.port = 11193

Locating the SSL configuration

The SSL configuration is loaded separately from the JPPF configuration itself. The effect of this is that it is harder to find for a remote application, and it will not appear in the JPPF monitoring tools and APIs, the goal being to avoid providing information about how JPPF is secured, which would defeat the purpose of securing it in the first place.

Configuration as a file or classpath resource

To specify the location of the SSL configuration as a file, you can use the jppf.ssl.configuration.file property in the JPPF configuration file of the driver, node or client:

# location of the SSL configuration in the file system or classpath
jppf.ssl.configuration.file = config/ssl/ssl.properties

The lookup for the specified file or resource is performed first in the file system, then in the classpath. This allows you for instance to embed a configuration file in a jar file, with the possibility to override it with another file.

Relative paths are relative to the current working directory as specified by System.getProperty("user.dir").

Configuration as an external source

JPPF provides a more sophisticated way to locate its SSL configuration, which requires the implementation of a specific plugin. This is useful in situations where a configuration file is not considered secure enough, or if you need to load the configuration from a centralized location, for instance if you run JPPF in a cloud environment and want to fetch the configuration via a cloud storage facility such as Amazon's S3.

This is done via the jppf.ssl.configuration.source property:

# SSL configuration as an arbitrary source. Value is the fully qualified name
# of an implementation of java.util.concurrent.Callable<InputStream> with optional
# space-separated arguments
jppf.ssl.configuration.source = implementation_of_Callable<InputStream> arg1 ... argN

where implementation_of_Callable<InputStream> is the fully qualified name of a class which implements the interface Callable<InputStream> and which must have either a noarg constructor, or a (String...args) vararg constructor.

For example, the predefined JPPF plugin FileStoreSource is implemented as follows:

package org.jppf.ssl;

import java.io.InputStream;
import java.util.concurrent.Callable;
import org.jppf.utils.FileUtils;

// A secure store source that uses a file as source
public class FileStoreSource implements Callable<InputStream> {

 // Optional arguments that may be specified in the configuration
 private final String[] args;

 public FileStoreSource(final String... args) throws Exception {
  this.args = args;
  if ((args == null) || (args.length == 0))
   throw new SSLConfigurationException("missing parameter: file path");
 }

 @Override
 public InputStream call() throws Exception {
  // lookup in the file system, then in the classpath
  InputStream is = FileUtils.getFileInputStream(args[0]);
  if (is == null)
   throw new SSLConfigurationException("could not find file " + args[0]); 
  return is;
 }
}

We can then use it in the configuration:

jppf.ssl.configuration.source = org.jppf.ssl.FileStoreSource config/ssl/ssl.properties

which is in fact equivalent to:

jppf.ssl.configuration.file = config/ssl/ssl.properties

SSL configuration properties

These properties are defined in the SSL configuration file and represent the information required to create and initialize SSLContext, SSLSocket and SSLEngine objects.

SSLContext protocol

This is the protocol name used in SSLContext.getInstance(String protocol). It is defined as:

# SSLContext protocol, defaults to SSL
jppf.ssl.context.protocol = SSL

A list of valid protocol names is available here.

Enabled protocol versions

This is the list of supported protocol versions, such as returned by SSLEngine.getEnabledProtocols(). It is defined as a list of space-separated names:

# list of space-separated enabled protocols
jppf.ssl.protocols = SSLv2Hello SSLv3

A list of valid protocol versions is available here.

Enabled cipher suites

This is the list of supported protocol versions, such as returned by SSLEngine.getEnabledCipherSuites(). It is defined as a list of space-separated names:

# enabled cipher suites as a list of space-separated values
jppf.ssl.cipher.suites = SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_RC4_128_SHA

A list of supported cipher suites is available here.

Client authentication

The client authentication mode is determined by calling the methods SSLEngine.getWantClientAuth() and SSLEngine.getNeedClientAuth(). It is defined as:

# client authentication mode
# possible values: none | want | need
jppf.ssl.client.auth = none

Key store and associated password

As for the location of the SSL configuration, there are two ways to specify the location of a keystore:

# path to the key store on the file system
jppf.ssl.keystore.file = config/ssl/keystore.ks
# an implementation of Callable<InputStream> with optional space-separated arguments
jppf.ssl.keystore.source = org.jppf.ssl.FileStoreSource config/ssl/keystore.ks

Note that, if both properties are defined, JPPF will first attempt to load the key store from the defined source, then from the specified file path.

In a similar fashion, there are two ways to specify the key store's password: either as a clear text password, or as a password source. This can be done as follows:

# keystore password in clear text
jppf.ssl.keystore.password = password
# keystore password from an arbitrary source
# the source is an implementation of Callable<char[]> with optional parameters
jppf.ssl.keystore.password.source = org.jppf.ssl.PlainTextPassword password

Trust store and associated password

The trust store and its password are defined in the same way as for the key store:

# path to the trust store on the file system
jppf.ssl.truststore.file = config/ssl/truststore.ks
# an implementation of Callable<InputStream> with optional space-separated arguments
jppf.ssl.truststore.source = org.jppf.ssl.FileStoreSource config/ssl/truststore.ks

# keystore password in clear text
jppf.ssl.truststore.password = password
# keystore password from an arbitrary source
# the source is an implementation of Callable<char[]> with optional parameters
jppf.ssl.truststore.password.source = org.jppf.ssl.PlainTextPassword password

Special case: distinct driver trust stores for nodes and clients

In the case when the JPPF driver has mutual authentication enabled (jppf.ssl.client.auth = need”), it might be desirable to use distinct trust stores for the certificates of the nodes and the clients that will connect to the driver. This can be done as follows:

# specify that a separate trust store must be used for client certificates
jppf.ssl.client.distinct.truststore = true  
  
# path to the client trust store on the file system
jppf.ssl.client.truststore.file = config/ssl/truststore_cli.ks
# an implementation of Callable<InputStream> with optional space-separated arguments
jppf.ssl.client.truststore.source = o.j.s.FileStoreSource config/ssl/truststore_cli.ks

# keystore password in clear text
jppf.ssl.client.truststore.password = password
# keystore password from an arbitrary source
# the source is an implementation of Callable<char[]> with opptional parameters
jppf.ssl.client.truststore.password.source = org.jppf.ssl.PlainTextPassword password

In this configuration, a client will not be able to authenticate with the server, even if it uses the same keystore and password as the nodes.

Full SSL configuration example

# SSLContext protocol, defaults to SSL
jppf.ssl.context.protocol = SSL
# list of space-separated enabled protocols
jppf.ssl.protocols = SSLv2Hello SSLv3
# enabled cipher suites as a list of space-separated values
jppf.ssl.cipher.suites = SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_RC4_128_SHA
# client authentication mode; possible values: none | want | need
jppf.ssl.client.auth = none

# path to the key store on the file system.
jppf.ssl.keystore.file = config/ssl/keystore.ks
# keystore password in clear text
jppf.ssl.keystore.password = password

# the trust store location as an arbitrary source:
# an implementation of Callable<InputStream> with optional space-separated arguments
jppf.ssl.truststore.source = org.jppf.ssl.FileStoreSource config/ssl/truststore.ks
# truststore password as an arbitrary source:
# an implementation of Callable<char[]> with optional space-separated arguments
jppf.ssl.truststore.password.source = org.jppf.ssl.PlainTextPassword password
Main Page > Configuration guide > Configuring SSL/TLS

Support This Project Powered by MediaWiki