Configure Cassandra SSL encryption and authentication with security hardening

Advanced 45 min May 01, 2026 614 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up comprehensive SSL/TLS encryption for Apache Cassandra with client-to-node and node-to-node security, certificate management, and production-grade authentication hardening.

Prerequisites

  • Root or sudo access
  • Apache Cassandra 4.0 or higher
  • Java 11 or higher
  • Basic understanding of SSL/TLS concepts

What this solves

Apache Cassandra clusters handle sensitive data that requires encryption in transit and strong authentication. This tutorial configures SSL/TLS encryption for both client-to-node and node-to-node communication, sets up certificate-based authentication, and implements security hardening measures for production environments.

Step-by-step configuration

Install Cassandra and Java

Install Apache Cassandra and Java Development Kit required for SSL operations.

wget -q -O - https://www.apache.org/dist/cassandra/KEYS | sudo apt-key add -
echo "deb https://debian.cassandra.apache.org 40x main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list
sudo apt update
sudo apt install -y cassandra openjdk-11-jdk-headless
sudo tee /etc/yum.repos.d/cassandra.repo > /dev/null <

Create SSL certificate directories

Set up directory structure for storing SSL certificates with proper permissions.

sudo mkdir -p /etc/cassandra/ssl/{keystore,truststore,certs}
sudo chown -R cassandra:cassandra /etc/cassandra/ssl
sudo chmod 750 /etc/cassandra/ssl
sudo chmod 750 /etc/cassandra/ssl/{keystore,truststore,certs}

Generate Certificate Authority

Create a private Certificate Authority for signing Cassandra node certificates.

cd /etc/cassandra/ssl/certs
sudo openssl genrsa -out ca-key.pem 4096
sudo openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 3650 -subj "/C=US/ST=State/L=City/O=Organization/OU=IT/CN=CassandraCA"

Generate node certificates

Create SSL certificates for each Cassandra node in your cluster.

# Generate private key for node
sudo openssl genrsa -out node1-key.pem 2048

# Create certificate signing request
sudo openssl req -new -key node1-key.pem -out node1.csr -subj "/C=US/ST=State/L=City/O=Organization/OU=IT/CN=cassandra-node1.example.com"

# Sign the certificate with CA
sudo openssl x509 -req -in node1.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out node1-cert.pem -days 365 -extensions v3_req -extfile <(echo "[v3_req]
subjectAltName=DNS:cassandra-node1.example.com,DNS:localhost,IP:127.0.0.1")

# Set proper permissions
sudo chown cassandra:cassandra /etc/cassandra/ssl/certs/*
sudo chmod 600 /etc/cassandra/ssl/certs/*-key.pem
sudo chmod 644 /etc/cassandra/ssl/certs/*-cert.pem /etc/cassandra/ssl/certs/ca-cert.pem

Create Java keystores

Convert PEM certificates to Java keystores required by Cassandra.

# Create PKCS12 keystore
sudo openssl pkcs12 -export -in /etc/cassandra/ssl/certs/node1-cert.pem -inkey /etc/cassandra/ssl/certs/node1-key.pem -out /etc/cassandra/ssl/keystore/node1.p12 -name node1 -CAfile /etc/cassandra/ssl/certs/ca-cert.pem -caname root -password pass:cassandra123

# Convert to JKS format
sudo keytool -importkeystore -deststorepass cassandra123 -destkeypass cassandra123 -destkeystore /etc/cassandra/ssl/keystore/node1.jks -srckeystore /etc/cassandra/ssl/keystore/node1.p12 -srcstoretype PKCS12 -srcstorepass cassandra123 -alias node1

# Create truststore with CA certificate
sudo keytool -import -alias ca -file /etc/cassandra/ssl/certs/ca-cert.pem -keystore /etc/cassandra/ssl/truststore/truststore.jks -storepass cassandra123 -noprompt

# Set keystore permissions
sudo chown cassandra:cassandra /etc/cassandra/ssl/keystore/* /etc/cassandra/ssl/truststore/*
sudo chmod 600 /etc/cassandra/ssl/keystore/* /etc/cassandra/ssl/truststore/*

Configure client-to-node SSL encryption

Enable SSL encryption for client connections by modifying the Cassandra configuration.

# Client encryption options
client_encryption_options:
    enabled: true
    optional: false
    keystore: /etc/cassandra/ssl/keystore/node1.jks
    keystore_password: cassandra123
    truststore: /etc/cassandra/ssl/truststore/truststore.jks
    truststore_password: cassandra123
    protocol: TLS
    algorithm: SunX509
    store_type: JKS
    cipher_suites: [TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA]
    require_client_auth: true

Configure node-to-node SSL encryption

Enable SSL encryption for inter-node communication within the cluster.

# Server encryption options
server_encryption_options:
    internode_encryption: all
    keystore: /etc/cassandra/ssl/keystore/node1.jks
    keystore_password: cassandra123
    truststore: /etc/cassandra/ssl/truststore/truststore.jks
    truststore_password: cassandra123
    protocol: TLS
    algorithm: SunX509
    store_type: JKS
    cipher_suites: [TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA]
    require_client_auth: true

Configure authentication and authorization

Enable password authentication and role-based access control.

# Authentication and authorization
authenticator: PasswordAuthenticator
authorizer: CassandraAuthorizer
role_manager: CassandraRoleManager

# Network topology strategy for system_auth
system_auth_replication:
    class: NetworkTopologyStrategy
    datacenter1: 3

Configure SSL native transport port

Set the SSL-enabled native transport port for client connections.

# Native transport configuration
native_transport_port: 9042
native_transport_port_ssl: 9142
start_native_transport: true

Configure JVM SSL options

Set JVM SSL parameters for proper certificate validation.

# SSL debugging (remove in production)
# -Djavax.net.debug=ssl

# SSL trust store location
-Djavax.net.ssl.trustStore=/etc/cassandra/ssl/truststore/truststore.jks
-Djavax.net.ssl.trustStorePassword=cassandra123

# SSL key store location
-Djavax.net.ssl.keyStore=/etc/cassandra/ssl/keystore/node1.jks
-Djavax.net.ssl.keyStorePassword=cassandra123

# Disable hostname verification for self-signed certificates
-Dcom.datastax.driver.FORCE_NIO=true

Create SSL-enabled cqlshrc configuration

Configure cqlsh client to use SSL connections with certificate validation.

[connection]
hostname = 127.0.0.1
port = 9142
factory = cqlshlib.ssl.ssl_transport_factory

[ssl]
certfile = /etc/cassandra/ssl/certs/ca-cert.pem
validate = true
userkey = /etc/cassandra/ssl/certs/node1-key.pem
usercert = /etc/cassandra/ssl/certs/node1-cert.pem
version = TLSv1_2
sudo mkdir -p /home/cassandra/.cassandra
sudo chown cassandra:cassandra /home/cassandra/.cassandra
sudo chmod 755 /home/cassandra/.cassandra

Implement security hardening

Apply additional security configurations for production deployments.

# Security hardening options
enable_user_defined_functions: false
enable_scripted_user_defined_functions: false
enable_materialized_views: false
transparent_data_encryption_options:
    enabled: false
    chunk_length_in_kb: 64
    cipher: AES/CBC/PKCS5Padding
    key_alias: testing:1
    key_provider:
      - class_name: org.apache.cassandra.security.JKSKeyProvider
        parameters:
          - keystore: /etc/cassandra/ssl/keystore/node1.jks
            keystore_password: cassandra123
            store_type: JKS
            key_password: cassandra123

Configure firewall rules

Set up firewall rules to restrict access to Cassandra SSL ports.

sudo ufw allow from 203.0.113.0/24 to any port 9142 comment 'Cassandra SSL client'
sudo ufw allow from 203.0.113.0/24 to any port 7001 comment 'Cassandra SSL inter-node'
sudo ufw allow from 203.0.113.0/24 to any port 7199 comment 'Cassandra JMX'
sudo ufw reload
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port protocol="tcp" port="9142" accept'
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port protocol="tcp" port="7001" accept'
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port protocol="tcp" port="7199" accept'
sudo firewall-cmd --reload

Start and enable Cassandra service

Start Cassandra with SSL configuration and enable automatic startup.

sudo systemctl enable cassandra
sudo systemctl restart cassandra
sudo systemctl status cassandra

Create secure database users

Set up authenticated users with specific permissions.

# Connect using default cassandra user
cqlsh -u cassandra -p cassandra --ssl

# Create application user with limited permissions
CREATE ROLE app_user WITH PASSWORD = 'SecurePass123!' AND LOGIN = true;
GRANT SELECT, INSERT, UPDATE, DELETE ON KEYSPACE myapp TO app_user;

# Create monitoring user
CREATE ROLE monitor_user WITH PASSWORD = 'MonitorPass123!' AND LOGIN = true;
GRANT SELECT ON SYSTEM.LOCAL TO monitor_user;
GRANT SELECT ON SYSTEM.PEERS TO monitor_user;

# Change default cassandra password
ALTER ROLE cassandra WITH PASSWORD = 'NewCassandraPass123!';

Configure certificate rotation

Set up automated certificate rotation using systemd timers.

#!/bin/bash
set -euo pipefail

CERT_DIR="/etc/cassandra/ssl/certs"
KEYSTORE_DIR="/etc/cassandra/ssl/keystore"
TRUSTSTORE_DIR="/etc/cassandra/ssl/truststore"
NODE_NAME="node1"
KEYSTORE_PASS="cassandra123"

cd "$CERT_DIR"

# Check if certificate expires in 30 days
if openssl x509 -checkend 2592000 -noout -in "${NODE_NAME}-cert.pem"; then
    echo "Certificate valid for 30+ days"
    exit 0
fi

echo "Certificate expires soon, rotating..."

# Generate new certificate
openssl genrsa -out "${NODE_NAME}-key-new.pem" 2048
openssl req -new -key "${NODE_NAME}-key-new.pem" -out "${NODE_NAME}-new.csr" -subj "/C=US/ST=State/L=City/O=Organization/OU=IT/CN=cassandra-${NODE_NAME}.example.com"
openssl x509 -req -in "${NODE_NAME}-new.csr" -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out "${NODE_NAME}-cert-new.pem" -days 365

# Update keystore
openssl pkcs12 -export -in "${NODE_NAME}-cert-new.pem" -inkey "${NODE_NAME}-key-new.pem" -out "${KEYSTORE_DIR}/${NODE_NAME}-new.p12" -name "$NODE_NAME" -CAfile ca-cert.pem -caname root -password "pass:$KEYSTORE_PASS"
keytool -importkeystore -deststorepass "$KEYSTORE_PASS" -destkeypass "$KEYSTORE_PASS" -destkeystore "${KEYSTORE_DIR}/${NODE_NAME}-new.jks" -srckeystore "${KEYSTORE_DIR}/${NODE_NAME}-new.p12" -srcstoretype PKCS12 -srcstorepass "$KEYSTORE_PASS" -alias "$NODE_NAME"

# Backup old certificates
cp "${NODE_NAME}-cert.pem" "${NODE_NAME}-cert.pem.bak"
cp "${NODE_NAME}-key.pem" "${NODE_NAME}-key.pem.bak"
cp "${KEYSTORE_DIR}/${NODE_NAME}.jks" "${KEYSTORE_DIR}/${NODE_NAME}.jks.bak"

# Replace certificates
mv "${NODE_NAME}-cert-new.pem" "${NODE_NAME}-cert.pem"
mv "${NODE_NAME}-key-new.pem" "${NODE_NAME}-key.pem"
mv "${KEYSTORE_DIR}/${NODE_NAME}-new.jks" "${KEYSTORE_DIR}/${NODE_NAME}.jks"

# Set permissions
chown cassandra:cassandra "${NODE_NAME}-cert.pem" "${NODE_NAME}-key.pem" "${KEYSTORE_DIR}/${NODE_NAME}.jks"
chmod 600 "${NODE_NAME}-key.pem" "${KEYSTORE_DIR}/${NODE_NAME}.jks"
chmod 644 "${NODE_NAME}-cert.pem"

# Restart Cassandra
systemctl restart cassandra

echo "Certificate rotation completed"
sudo chmod +x /usr/local/bin/cassandra-cert-rotate.sh

Create systemd timer for certificate rotation

Schedule automatic certificate rotation checks.

[Unit]
Description=Cassandra Certificate Rotation
After=network.target

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/cassandra-cert-rotate.sh
TimeoutStartSec=300
[Unit]
Description=Run Cassandra Certificate Rotation Weekly
Requires=cassandra-cert-rotate.service

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl enable cassandra-cert-rotate.timer
sudo systemctl start cassandra-cert-rotate.timer

Verify your setup

Test SSL connectivity and authentication to ensure proper configuration.

# Test SSL connection
cqlsh -u cassandra -p NewCassandraPass123! --ssl 127.0.0.1 9142

# Verify SSL settings
nodetool status
nodetool info

# Check certificate expiration
openssl x509 -in /etc/cassandra/ssl/certs/node1-cert.pem -noout -dates

# Test authentication
cqlsh -u app_user -p SecurePass123! --ssl 127.0.0.1 9142

# Verify encryption is working
netstat -tlnp | grep :9142
ss -tlnp | grep :7001
Note: You can monitor SSL connections and certificate health using Prometheus and Grafana monitoring for comprehensive cluster oversight.

Common issues

SymptomCauseFix
cqlsh SSL connection refusedWrong port or SSL not enabledCheck port 9142 is configured and client_encryption_options.enabled: true
Certificate verification failedHostname mismatchAdd proper SAN entries or use IP addresses in certificate
Keystore password errorIncorrect keystore passwordVerify password matches in cassandra.yaml and keystore creation
Inter-node SSL handshake failureCertificate not trustedEnsure all nodes have CA certificate in truststore
Authentication failed after SSLUser not created or wrong passwordCheck LIST ROLES; and recreate user with correct password
Performance degradationCPU overhead from encryptionMonitor CPU usage and consider hardware crypto acceleration

SSL certificate management best practices

Implement these practices for robust certificate lifecycle management.

  • Monitor certificate expiration dates with automated alerts
  • Use separate certificates for each environment (dev, staging, production)
  • Implement certificate revocation lists (CRL) for compromised certificates
  • Store private keys securely with restricted file permissions
  • Use certificate transparency logs for public-facing certificates
  • Test certificate rotation procedures in non-production environments
  • Document certificate authority chain and validation procedures

For advanced security configurations, consider implementing database-specific SSL hardening techniques and integrate with your existing security infrastructure.

Next steps

Running this in production?

Want this handled for you? Running this at scale adds a second layer of work: capacity planning, failover drills, cost control, and on-call. Our managed platform covers monitoring, backups and 24/7 response by default.

Automated install script

Run this to automate the entire setup

Sie möchten das nicht selbst verwalten?

Wir betreiben Infrastruktur für Unternehmen, die auf Verfügbarkeit angewiesen sind. Vollständig verwaltet, mit einem festen Ansprechpartner, der Ihre Umgebung kennt.

Sie erhalten einen festen Ansprechpartner, der Ihr Setup kennt

Am Schreibtisch in Rotterdam 10:03 · erreichbar per Nachricht, kein Ticketformular