Skip to content
Maintained by AxonOps — production-grade documentation from engineers who operate distributed databases at scale Get Cassandra Help Get Kafka Help

Cassandra Encryption Configuration

This section covers the complete encryption configuration options in cassandra.yaml for both internode and client-to-node encryption.

Configuration Overview

Cassandra provides two separate encryption configurations:

Section Purpose Port
server_encryption_options Node-to-node communication 7000 (7001 legacy SSL)
client_encryption_options Client-to-node communication 9042

Internode Encryption

Full Configuration Reference

# cassandra.yaml

server_encryption_options:
    # Encryption scope
    # Options: none, dc, rack, all
    internode_encryption: all

    # Enable legacy SSL storage port (7001)
    # Set to true during migration from unencrypted
    legacy_ssl_storage_port_enabled: false

    # Keystore containing node's private key and certificate
    keystore: /etc/cassandra/certs/node-keystore.jks
    keystore_password: changeit

    # Truststore containing CA certificates
    truststore: /etc/cassandra/certs/truststore.jks
    truststore_password: changeit

    # Require client certificate for internode connections
    require_client_auth: true

    # Hostname verification (Cassandra 4.0+)
    require_endpoint_verification: true

    # TLS protocol version
    protocol: TLS

    # Accepted protocol versions
    accepted_protocols:
        - TLSv1.2
        - TLSv1.3

    # Cipher suites (in preference order)
    cipher_suites:
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_AES_128_GCM_SHA256

    # Algorithm for secure random number generation
    # algorithm: SunX509

    # Keystore type (JKS, PKCS12, or PEM for Cassandra 4.0+)
    # store_type: JKS

    # SSL context factory (advanced)
    # ssl_context_factory:
    #     class_name: org.apache.cassandra.security.DefaultSslContextFactory

Encryption Modes

Mode Description Use Case
none No encryption Development only
dc Encrypt cross-datacenter only WAN traffic encryption
rack Encrypt cross-rack and cross-datacenter Physical rack isolation
all Encrypt all internode traffic Recommended for production

Migration to Encrypted Internode

Rolling migration from unencrypted to encrypted internode communication:

Phase 1: Enable Optional Encryption

# On all nodes
server_encryption_options:
    internode_encryption: all
    legacy_ssl_storage_port_enabled: true
    optional: true  # Accept both encrypted and unencrypted

Perform rolling restart.

Phase 2: Require Encryption

# On all nodes
server_encryption_options:
    internode_encryption: all
    legacy_ssl_storage_port_enabled: false
    optional: false

Perform rolling restart.

Internode Authentication with Mutual TLS (Cassandra 5.0+)

The MutualTlsInternodeAuthenticator provides certificate-based authentication for internode connections by extracting identities from certificates and verifying them against a list of authorized peers.

# cassandra.yaml
internode_authenticator:
  class_name: org.apache.cassandra.auth.MutualTlsInternodeAuthenticator
  parameters:
    validator_class_name: org.apache.cassandra.auth.SpiffeCertificateValidator
    # Optional: restrict to specific peer identities
    trusted_peer_identities: "spiffe://testdomain.com/cassandra/node1,spiffe://testdomain.com/cassandra/node2"
    # Optional: validate outbound keystore identity
    node_identity: "spiffe://testdomain.com/cassandra/this-node"
Parameter Required Description
validator_class_name Yes Certificate validator implementation class
trusted_peer_identities No Comma-separated list of authorized peer identities
node_identity No Expected identity from outbound keystore for validation

Prerequisites:

  • server_encryption_options.internode_encryption must be set to all
  • server_encryption_options.require_client_auth must be true

When trusted_peer_identities is configured, only nodes presenting certificates with matching identities can establish internode connections. When omitted, any certificate signed by a trusted CA is accepted.

The node_identity parameter validates the local node's keystore identity at startup, catching configuration errors early.


Client Encryption

Full Configuration Reference

# cassandra.yaml

client_encryption_options:
    # Enable client encryption
    enabled: true

    # Accept unencrypted connections alongside encrypted
    # Set to false in production
    optional: false

    # Keystore containing node's private key and certificate
    keystore: /etc/cassandra/certs/node-keystore.jks
    keystore_password: changeit

    # Truststore for validating client certificates
    # Required when require_client_auth is true
    truststore: /etc/cassandra/certs/truststore.jks
    truststore_password: changeit

    # Require client certificates (mutual TLS)
    require_client_auth: false

    # Hostname verification (Cassandra 4.0+)
    require_endpoint_verification: false

    # TLS protocol version
    protocol: TLS

    # Accepted protocol versions
    accepted_protocols:
        - TLSv1.2
        - TLSv1.3

    # Cipher suites
    cipher_suites:
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_AES_128_GCM_SHA256

Mutual TLS (mTLS)

Mutual TLS requires clients to present certificates, providing two-way authentication.

client_encryption_options:
    enabled: true
    require_client_auth: true
    truststore: /etc/cassandra/certs/client-truststore.jks
    truststore_password: changeit

With mTLS enabled: - Clients must present valid certificates - Certificates must be signed by a CA in the truststore - Connection fails if client certificate is invalid or missing


PEM File Configuration (Cassandra 4.0+)

Cassandra 4.0+ supports PEM files directly, eliminating JKS/PKCS12 conversion.

Server Encryption with PEM

server_encryption_options:
    internode_encryption: all
    keystore: /etc/cassandra/certs/node-key.pem
    keystore_password: ""
    truststore: /etc/cassandra/certs/ca-chain.pem
    truststore_password: ""

Client Encryption with PEM

client_encryption_options:
    enabled: true
    keystore: /etc/cassandra/certs/node-key.pem
    keystore_password: ""
    truststore: /etc/cassandra/certs/ca-cert.pem
    truststore_password: ""

PEM File Format

Keystore PEM should contain private key followed by certificate chain:

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
... (node certificate)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (intermediate CA, if applicable)
-----END CERTIFICATE-----

Truststore PEM should contain CA certificates:

-----BEGIN CERTIFICATE-----
... (root CA)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (intermediate CA, if applicable)
-----END CERTIFICATE-----

Hot Reloading (Cassandra 4.0+)

Cassandra 4.0+ can reload certificates without restart when files change.

Requirements

  • Keystore and truststore file paths remain the same
  • New certificates must be valid
  • File modification triggers reload

Monitoring Reload

Check logs for reload messages:

INFO  [main] SSLFactory.java:... - Loaded renewed keystore
INFO  [main] SSLFactory.java:... - Loaded renewed truststore

Forcing Reload via JMX

# Force SSL context reload
nodetool reloadssl

Configuration Validation

Verify Configuration Before Restart

# Check cassandra.yaml syntax
python3 -c "import yaml; yaml.safe_load(open('/etc/cassandra/cassandra.yaml'))"

# Verify keystore is readable
keytool -list -keystore /etc/cassandra/certs/node-keystore.jks -storepass changeit

# Verify truststore is readable
keytool -list -keystore /etc/cassandra/certs/truststore.jks -storepass changeit

# Verify certificate validity
openssl x509 -in /etc/cassandra/certs/node-cert.pem -noout -dates

Test TLS Connection

After restart, verify TLS is working:

# Test client port
openssl s_client -connect localhost:9042 -tls1_2

# Test internode port
openssl s_client -connect localhost:7000 -tls1_2

# Check negotiated cipher
openssl s_client -connect localhost:9042 2>/dev/null | grep "Cipher is"

Common Configurations

Development (Self-Signed)

server_encryption_options:
    internode_encryption: none

client_encryption_options:
    enabled: false

Production (Full Encryption)

server_encryption_options:
    internode_encryption: all
    keystore: /etc/cassandra/certs/node-keystore.p12
    keystore_password: ${KEYSTORE_PASSWORD}
    truststore: /etc/cassandra/certs/truststore.p12
    truststore_password: ${TRUSTSTORE_PASSWORD}
    require_client_auth: true
    require_endpoint_verification: true
    accepted_protocols:
        - TLSv1.2
        - TLSv1.3
    cipher_suites:
        - TLS_AES_256_GCM_SHA384
        - TLS_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

client_encryption_options:
    enabled: true
    optional: false
    keystore: /etc/cassandra/certs/node-keystore.p12
    keystore_password: ${KEYSTORE_PASSWORD}
    truststore: /etc/cassandra/certs/truststore.p12
    truststore_password: ${TRUSTSTORE_PASSWORD}
    require_client_auth: false
    accepted_protocols:
        - TLSv1.2
        - TLSv1.3
    cipher_suites:
        - TLS_AES_256_GCM_SHA384
        - TLS_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Mutual TLS (Zero Trust)

client_encryption_options:
    enabled: true
    optional: false
    require_client_auth: true
    keystore: /etc/cassandra/certs/node-keystore.p12
    keystore_password: ${KEYSTORE_PASSWORD}
    truststore: /etc/cassandra/certs/client-ca-truststore.p12
    truststore_password: ${TRUSTSTORE_PASSWORD}