# 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](https://github.com/aerospike-examples/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:

Terminal window

```bash
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:

Terminal window

```bash
openssl x509 -in example.server.crt -text -noout | grep -E -- "Subject:"

        Subject: CN = example.server, O = "Aerospike, Inc.", C = US
```

The [tls-authenticate-client](https://aerospike.com/docs/database/reference/config#network__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:

Terminal window

```bash
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.

Replace all placeholder certificate filenames with the correct filenames for your system.

1.  The following command imports `example.ca.crt` into a new Java TrustStore named `example.ca.jks`. The new TrustStore will be used exclusively by the intended Java application.

Terminal window

```bash
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.

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

Terminal window

```bash
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:

Terminal window

```bash
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:

Terminal window

```bash
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:

Terminal window

```bash
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:

```java
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:

```java
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
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
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](https://aerospike.com/docs/develop/client/java/logging/).

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

```java
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](https://github.com/aerospike-examples/aerospike-tls-examples/tree/master/tls-example-java) for a complete example.