Integrating OpenSSL / BoringSSL
TLS in Java is normally provided by the Java runtime (JRE). However, the performance overhead can be significant; even with AES intrinsics enabled. If you are using an x86_64 system (Linux, Mac, Windows), Hazelcast supports native integration for TLS which can provide significant performance improvements. There are two supported native TLS libraries available through netty-tcnative libraries:
-
OpenSSL
-
dynamically linked
-
prerequisites:
libapr
,openssl
packages installed on your system
-
-
BoringSSL - Google managed fork of the OpenSSL
-
statically linked
-
easier to get started with
-
benefits: reduced code footprint, additional features
-
The native TLS integration can be used on clients and/or members. For best performance, it is recommended to install on a client and member and configure the appropriate cipher suite(s).
Check the netty-tcnative page for installation details.
Netty Libraries
For native TLS integration in Java, the Netty library is used.
Make sure the following libraries from the Netty framework and their dependencies are on the classpath:
-
netty-handler
-
one of
tc-native
implementations-
either BoringSSL:
netty-tcnative-boringssl-static
-
or OpenSSL:
netty-tcnative
(for given OS architecture)
-
The netty-handler and tcnative artifacts have different versioning strategies.
It is important that the these versions are compatible. The safe way
is to download the netty-<version>.tar.bz2 file
from the Netty website and check which
netty-tcnative version is used for that Netty release. Other possibility
is to use import netty-bom in Maven for dependency management.
|
Using BoringSSL
The statically linked BoringSSL binaries are included within the netty-tcnative
libraries. There is no need to install additional software on supported systems.
Example Maven dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>${netty.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</dependency>
</dependencies>
Using OpenSSL
-
Install OpenSSL. Make sure that you are installing 1.0.1 or newer release. See its documentation at github.com/openssl.
-
Install Apache Portable Runtime (APR) library. See apr.apache.org.
For RHEL:
sudo yum -y install apr openssl
For Ubuntu:
sudo apt-get -y install libapr1 openssl
For Alpine Linux:
apk add --update apr openssl
Example Maven dependencies (for Linux):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>${netty.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative</artifactId>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</dependency>
</dependencies>
Configuring Hazelcast for OpenSSL
Configuring OpenSSL in Hazelcast is straight forward. On the client and/or member side, the following snippet enables TLS using OpenSSL:
<hazelcast>
...
<network>
<ssl enabled="true">
<factory-class-name>com.hazelcast.nio.ssl.OpenSSLEngineFactory</factory-class-name>
<properties>
<property name="protocol">TLSv1.2</property>
<property name="trustCertCollectionFile">trusted-certs.pem</property>
<!-- If the TLS mutual authentication is not used,
then the key configuration is not needed on the client side. -->
<property name="keyFile">privkey.pem</property>
<property name="keyCertChainFile">chain.pem</property>
</properties>
</ssl>
</network>
...
</hazelcast>
hazelcast:
network:
ssl:
enabled: true
factory-class-name: com.hazelcast.nio.ssl.OpenSSLEngineFactory
properties:
protocol: TLSv1.2
trustCertCollectionFile: trusted-certs.pem
# If the TLS mutual authentication is not used, following lines (key configuration) are not needed on the client side.
keyFile: privkey.pem
keyCertChainFile: chain.pem
The configuration is similar to a regular TLS integration. The main differences
are the OpenSSLEngineFactory
factory class and the following properties:
-
keyFile
: Path of your PKCS#8 key file in PEM format. -
keyPassword
: Password to access the key file when it’s encrypted. -
keyCertChainFile
: Path to an X.509 certificate chain file in PEM format. -
trustCertCollectionFile
: Path to an X.509 certificate collection file in PEM format. -
fipsMode
: Boolean flag to switch OpenSSL into the FIPS mode. See the FIPS 140-2 section.
The key and certificate related properties take precedence over keyStore and trustStore configurations. Using keyStores and trustStores together with OpenSSL causes problems on some Java versions, therefore we recommend to use the OpenSSL native way.
The following are the other supported properties:
-
keyStore
: Path of your keystore file.-
Using the
keyStore
property is not recommended, usekeyFile
andkeyCertChainFile
instead
-
-
keyStorePassword
: Password to access the key from your keystore file. -
keyStoreType
: Type of the keystore. Its default value isJKS
. Another commonly used type is thePKCS12
. Available keystore/truststore types depend on your Operating system and the Java runtime. -
keyManagerAlgorithm
: Name of the algorithm based on which the authentication keys are provided. -
trustManagerAlgorithm
: Name of the algorithm based on which the trust managers are provided. -
trustStore
: Path of your truststore file. The file truststore is a keystore file that contains a collection of certificates trusted by your application. Its type should beJKS
.-
Using the
trustStore
property is not recommended, usetrustCertCollectionFile
instead
-
-
trustStorePassword
: Password to unlock the truststore file. -
trustStoreType
: Type of the truststore. Its default value isJKS
. Another commonly used type is thePKCS12
. Available keystore/truststore types depend on your operating system and the Java runtime. -
mutualAuthentication
: Mutual authentication configuration. It’s empty by default which means the client side of connection is not authenticated. Available values are:-
REQUIRED
- server forces usage of a trusted client certificate -
OPTIONAL
- server asks for a client certificate, but it doesn’t require it
-
-
ciphersuites
: Comma-separated list of cipher suite names allowed to be used. -
protocol
: Name of the algorithm which is used in your TLS. Its default value is empty, meaning the protocol version to use is not specified. Available values depend on the engine implementation but usually support:-
TLS
(equivalent to the empty value) -
TLSv1.2
-
TLSv1.3
For the
protocol
property, we recommend you to provide TLS with its version information, e.g.,TLSv1.3
. It ensures the engine won’t allow a fallback to an old, insecure version.
-
-
validateIdentity
: Flag which allows enabling endpoint identity validation. It means, during the TLS handshake client verifies if the server’s hostname (or IP address) matches the information in X.509 certificate (Subject Alternative Name extension). Possible values are"true"
and"false"
(default).