Configure Cassandra SSL encryption and authentication with security hardening

Advanced 45 min May 01, 2026 74 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

Need help?

Don't want to manage this yourself?

We handle high availability infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.