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.

For a node, this also means that its embedded JMX server will only accept secure connections.
This has an impact on the driver configuration: since the driver connects to the node's JMX server, it will be considered a SSL client from the JMX perspective.
It means the driver will need to have the proper node certificate in its trust store.

1.3 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:

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.

2 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.

2.1 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").

2.2 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:

Lastly, the format of the key store is specified with the following property:

# The key store format to use. When unspecified, it defaults to the value of
# KeyStore.getDefaultType(). For instance on the Oracle JVM it will be 'JKS',
# on Android's Dalvik it will be BKS, etc.
jppf.ssl.keystore.type = JKS

Note that, depending on the environment on which a node is executing, you may need to use different formats for the node's key store (if using mutual authentication) and for the driver's key store.
For instance, if the node is running on Android, the "JKS" format, which is the default on the Oracle JVM, will not be supported and the key store will need to be converted to e.g. BKS (BouncyCastle KeyStore), which is the default on Android.

3.6 Trust store and associated password

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

As for the key store, the format of the trust store is specified with the following property:

# the format to use for the trust store. When unspecified, it defaults to the
# value of KeyStore.getDefaultType(). For instance on the Oracle JVM it will be
# 'JKS', on Android's Dalvik it will be BKS, etc.
jppf.ssl.truststore.type = JKS

3.7 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
# the format to use for the client trust store. When unspecified, it defaults to
# the value of KeyStore.getDefaultType(). For instance on the Oracle JVM it will
# be 'JKS', on Android's Dalvik it will be BKS, etc.
jppf.ssl.client.truststore.type = JKS

In this configuration, a client will not be able to authenticate with the server if it uses a copy of the node's keystore.