Skip to main content
Loading

Managing mTLS with a Java client

Aerospike Database Enterprise Edition supports standard TLS and mutual authentication TLS (mTLS). This page describes how to configure a Java application to connect to an Aerospike cluster that uses mTLS.

You can find a fully-functional example project in the aerospike-tls-examples Github repository.

Keys and certificates

For mTLS, both the client and server must have their own private key and certificate. In the following example, they are both signed by the same Certificate Authority (CA).

Install the certificates and the key on the Aerospike Server nodes:

  • CA Certificate: example.ca.crt
  • Server Certificate: example.server.crt
  • Server Private Key: example.server.key

Install the certificates and the key on the Java client nodes:

  • CA Certificate: example.ca.crt
  • Client Certificate: example.client.crt
  • Client Private Key: example.client.key
Protect private keys

Protect your private keys, and never share them. Public keys are meant to be shared freely. Public keys encrypt; private keys decrypt. Anyone who acquires your private key can impersonate you.

Aerospike configuration

The following example aerospike.conf configuration shows only the stanzas and directives that are relevant for this TLS configuration:

network {
tls example.server {
ca-file /opt/aerospike/etc/certs/example.ca.crt
cert-file /opt/aerospike/etc/certs/example.server.crt
key-file /opt/aerospike/etc/private/example.server.key
}

service {
tls-address any
tls-port 4000
tls-name example.server
tls-authenticate-client example.client
}
}

The tls block in the network stanza defines the TLS configuration for the Aerospike Database certificate. This is used in both standard TLS as well as in mTLS.

The name example.server is known as the TLS name. This must match the value of the Common Name (CN) or Subject Alternative Name (SAN) of the server certificate example.server.crt. It must also be referenced in the application code to connect to the cluster. The following command verifies that the certificate has the expected CN value in the subject:

openssl x509 -in example.server.crt -text -noout | grep -E -- "Subject:"
Subject: CN = example.server, O = "Aerospike, Inc.", C = US

The tls-authenticate-client directive specifies example.client. This must match the value of the Common Name (CN) or Subject Alternative Name (SAN) of the client certificate example.client.crt. The following command verifies that the certificate has the expected CN value in the subject:

openssl x509 -in example.client.crt -text -noout | grep -E -- "Subject:"
Subject: CN = example.client, O = "Aerospike, Inc.", C = US
Bypass CN and SAN verification

The tls-authenticate-client directive includes a value of any, which bypasses the step in which the Common Name (CN)/Subject Alternative Names (SAN) are verified.

Java client TLS configuration

Add CA certificate to Java TrustStore on client nodes

The CA certificate is a public certificate which verifies that the certificate presented by the Aerospike Database is signed by a trusted authority.

  1. Use the Java keytool command-line utility to import example.ca.crt into a new Java TrustStore that will be used exclusively by the intended Java application:

    keytool -importcert -storetype jks -alias example.ca \
    -keystore example.ca.jks -file example.ca.crt \
    -storepass changeit
    Create a strong password

    The previous example follows the Java convention of using "changeit" as the password. Change this to a strong password governed by your organization's password policy.

    This command creates a new TrustStore named example.ca.jks.

  2. Verify the certificate is in the TrustStore with the keystore -list command:

    keytool -list -keystore example.ca.jks -storepass changeit
    Keystore type: jks
    Keystore provider: SUN

    Your keystore contains 1 entry

    example.ca, Apr 5, 2022, trustedCertEntry,
    Certificate fingerprint (SHA1): 85:99:36:F8:20:A7:42:AA:ED:E6:9B:7B

    The entry is listed as trustedCertEntry. This file can be stored on the filesystem with other public certificates.

Truststore Storage

Do not import the CA certificate into the default system-wide TrustStore of trusted CA certificates used by the Java runtime. Default system-wide trusted CA certificates present security issues, and are not allowed by many enterprise security requirements.

Add client certificate chain to Java KeyStore

During the TLS handshake, the client sends its certificate and a message encrypted with the client's private key to the server. Since the Java application needs access to both the client certificate and the client private key, these must be imported into a Java KeyStore.

  1. The client certificate, the CA certificate, and the client private key must be concatenated together. This creates a single chain certificate. The following command creates a single chain certificate file named example.client.chain.crt. The certificates and key must be named in the same order as the example:

    cat example.client.crt example.ca.crt example.client.key > example.client.chain.crt
  2. The chain certificate must be converted to PKCS #12 format. This is a standard format for storing cryptographic objects, and we recommend it over the proprietary Java KeyStore (jks) format. The following command creates a chain certificate file named example.client.chain.p12, which is the KeyStore file the Java application will use:

    openssl pkcs12 -export -in example.client.chain.crt \
    -out example.client.chain.p12 -password pass:"changeit" \
    -name example.client -noiter -nomaciter

    Change the password from changeit to a more secure password in compliance with your organization's security policy.

  3. Verify the certificate is in the KeyStore using the keystore -list command:

    keytool -list -keystore example.client.chain.p12 -storepass changeit
    Keystore type: PKCS12
    Keystore provider: SUN

    Your keystore contains 1 entry

    example.client, Apr 5, 2022, PrivateKeyEntry,
    Certificate fingerprint (SHA1): A3:63:D6:B0:3B:E9:7E:78:81:46:5F
    Private key access

    The entry is listed as PrivateKeyEntry. This file should be stored on the filesystem securely with limited permissions. The user invoking the JVM will need read access.

Java application

A Java application that connects to an Aerospike cluster using TLS:

  • Must enable TLS in the client policy.
  • Must specify the host's TLS name.
  • Must use the TrustStore with the CA certificate.
  • Must use the KeyStore with the client certificate chain (for mTLS only).
  • Should log Aerospike debug messages.
  • Should log debug messages during the TLS handshake when troubleshooting.

To enable TLS in the Aerospike Client, the ClientPolicy must have a TlsPolicy assigned to the tlsPolicy property:

ClientPolicy policy = new ClientPolicy();
policy.tlsPolicy = new TlsPolicy();

To specify the TLS name, instantiate Host objects with the constructor that accept tlsName as the second parameter:

Host[] hosts = new Host[] {
new Host("127.0.0.1", "example.server", 4000)
};

Remember that the TLS name must match the Common Name (CN) or Subject Alternative Name (SAN) in the server certificate, as well as the tls-name used in the Aerospike configuration file.

Use the -Djavax.net.ssl.trustStore argument to pass the TrustStore containing the CA certificate to the JVM:

java -Djavax.net.ssl.trustStore=example.ca.jks \
-jar aerospike-tls-example.jar

To pass the KeyStore and KeyStore password containing the client certificate chain to the JVM use the Djavax.net.ssl.keyStore and -Djavax.net.ssl.keyStorePassword arguments respectively:

java -Djavax.net.ssl.trustStore=example.ca.jks \
-Djavax.net.ssl.keyStore=example.client.p12 \
-Djavax.net.ssl.keyStorePassword=changeit \
-jar aerospike-tls-example.jar

To log Aerospike debug messages, see the Java Client logging usage.

To log debug messages during the TLS handshake pass the -Djavax.net.debug argument to the JVM:

java -Djavax.net.debug=all \
-Djavax.net.ssl.keyStore=example.client.p12 \
-Djavax.net.ssl.keyStorePassword=changeit \
-Djavax.net.ssl.trustStore=example.ca.jks \
-jar aerospike-tls-example.jar

See tls-example-java for a complete example.