---
title: "Managing mTLS with the Python client"
description: "Configure mutual TLS (mTLS) for Aerospike Database Enterprise Edition using the Python client."
---

# Managing mTLS with the Python client

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

Aerospike Database Enterprise Edition supports standard TLS and mutual authentication TLS (mTLS). This page describes how to configure a Python 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 Python 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:

Command

Terminal window

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

Example output

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

Command

Terminal window

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

Example output

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

::: bypass cn and san verification
Setting `tls-authenticate-client` to `any` bypasses Common Name (CN)/Subject Alternative Names (SAN) verification. The example above uses a named client CN (`example.client`) and does require CN verification.
:::

## Python client TLS configuration

During the TLS handshake, the client sends its certificate to the server. Configure TLS in the client configuration dictionary using the `tls` key.

Load the CA certificate, client certificate, and client private key from PEM files:

```python
import aerospike

config = {

    # The TLS name (third element) must match the server certificate CN or SAN

    'hosts': [('127.0.0.1', 4000, 'example.server')],

    'tls': {

        'enable': True,

        'cafile': '/etc/aerospike/ssl/example.ca.crt',

        'certfile': '/etc/aerospike/ssl/example.client.crt',

        'keyfile': '/etc/aerospike/ssl/example.client.key',

    },

}
```

For transport-only mTLS with password-based users, omit `auth_mode` or leave it at the default `aerospike.AUTH_INTERNAL`. If your cluster uses PKI-based user authentication (the client certificate’s CN is the Aerospike username), set `auth_mode` to `aerospike.AUTH_PKI`:

```python
config = {

    'hosts': [('127.0.0.1', 4000, 'example.server')],

    'policies': {'auth_mode': aerospike.AUTH_PKI},

    'tls': {

        'enable': True,

        'cafile': '/etc/aerospike/ssl/example.ca.crt',

        'certfile': '/etc/aerospike/ssl/example.client.crt',

        'keyfile': '/etc/aerospike/ssl/example.client.key',

    },

}
```

The `cipher_suite` property is optional, but Aerospike recommends providing a list of valid cipher suites to exclude less secure or poor-performing algorithms. Cipher suites can be specified in the client `tls` configuration, in the Aerospike server `cipher-suite` directive, or both:

```python
'tls': {

    'enable': True,

    'cafile': '/etc/aerospike/ssl/example.ca.crt',

    'certfile': '/etc/aerospike/ssl/example.client.crt',

    'keyfile': '/etc/aerospike/ssl/example.client.key',

    'cipher_suite': (

        'ECDHE-RSA-AES256-GCM-SHA384:'

        'ECDHE-ECDSA-AES256-GCM-SHA384:'

        'ECDHE-RSA-AES128-GCM-SHA256:'

        'ECDHE-ECDSA-AES128-GCM-SHA256:'

        'AES256-GCM-SHA384:'

        'AES128-GCM-SHA256'

    ),

}
```

## Python application

A Python application that connects to an Aerospike cluster using mTLS:

-   Must enable TLS in the client configuration (`tls.enable`).
-   Must specify the host’s TLS name as the third element of each host tuple.
-   Must provide the client certificate and key in `tls.certfile` and `tls.keyfile` when the server requires mutual authentication.
-   Enable client debug logging when troubleshooting.

The following example uses `aerospike.AUTH_PKI`. For transport-only mTLS with password-based users, omit `auth_mode` or set it to `aerospike.AUTH_INTERNAL`.

The following example connects to a cluster using mTLS:

```python
import aerospike

def log_callback(level, func, path, line, msg):

    print(f"[{func}] {msg}")

aerospike.set_log_level(aerospike.LOG_LEVEL_DEBUG)

aerospike.set_log_handler(log_callback)

config = {

    'hosts': [('127.0.0.1', 4000, 'example.server')],

    'policies': {'auth_mode': aerospike.AUTH_PKI},

    'tls': {

        'enable': True,

        'cafile': '/etc/aerospike/ssl/example.ca.crt',

        'certfile': '/etc/aerospike/ssl/example.client.crt',

        'keyfile': '/etc/aerospike/ssl/example.client.key',

    },

}

client = aerospike.client(config).connect()
```

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.

To log Aerospike debug messages, see the Python client [logging usage](https://aerospike.com/docs/develop/client/python/logging/).

For standard TLS without mutual authentication, see [Connecting](https://aerospike.com/docs/develop/client/python/connect/#tls-secured-connection).

See the [client configuration](https://aerospike-python-client.readthedocs.io/en/latest/aerospike.html#client-configuration) reference for additional TLS options.