Cassandra Encryption
Cassandra supports two types of encryption: encryption in transit (TLS/SSL for client-to-node and node-to-node communication) and encryption at rest (encrypting data files on disk). Together they protect sensitive data from interception and unauthorized disk access.
Encryption in Transit
Without encryption in transit, data travelling between your application and Cassandra — and between Cassandra nodes — travels in plain text over the network. Anyone with access to the network can read credentials, query results, and data. TLS encrypts all network communication.
Two TLS Scopes
Scope Description
──────────────────────────────────────────────────────────────
Client-to-Node TLS Encrypts traffic between your application
(or cqlsh) and the Cassandra node
Node-to-Node TLS Encrypts inter-node gossip and data
streaming traffic inside the cluster
Generating Certificates
TLS requires a certificate authority (CA), server certificates, and optionally client certificates for mutual TLS (mTLS). The example below uses a self-signed CA for a development setup. In production, use certificates from an internal CA or a trusted certificate authority.
# Generate a CA private key and certificate: openssl genrsa -out ca.key 4096 openssl req -new -x509 -key ca.key -out ca.crt -days 3650 \ -subj "/CN=Cassandra CA" # Generate a server key and certificate signing request: openssl genrsa -out server.key 2048 openssl req -new -key server.key -out server.csr \ -subj "/CN=cassandra-node1" # Sign the server certificate with the CA: openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 365 # Create a PKCS12 keystore for Cassandra (Java requires this): openssl pkcs12 -export -in server.crt -inkey server.key \ -out server.p12 -name cassandra -password pass:cassandra # Convert to JKS (Java KeyStore): keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 \ -destkeystore server.jks -deststoretype JKS \ -srcstorepass cassandra -deststorepass cassandra # Import CA into truststore: keytool -importcert -alias CARoot -file ca.crt \ -keystore truststore.jks -storepass cassandra -noprompt
Enabling Client-to-Node TLS
# cassandra.yaml client_encryption_options: enabled: true optional: false # set false to require TLS (no plain-text) keystore: /etc/cassandra/ssl/server.jks keystore_password: cassandra truststore: /etc/cassandra/ssl/truststore.jks truststore_password: cassandra require_client_auth: false # set true for mutual TLS
Enabling Node-to-Node TLS
# cassandra.yaml server_encryption_options: internode_encryption: all # options: none, dc, rack, all keystore: /etc/cassandra/ssl/server.jks keystore_password: cassandra truststore: /etc/cassandra/ssl/truststore.jks truststore_password: cassandra require_client_auth: true # nodes authenticate each other
internode_encryption Options
Value Encrypts ────────────────────────────────────────────────────────────── none Nothing (default, insecure) dc Only cross-datacenter traffic rack Cross-rack traffic within a DC all All internode traffic (most secure)
Connecting cqlsh with TLS
cqlsh --ssl \ --ssl-certfile /etc/cassandra/ssl/ca.crt \ --ssl-userkey /path/to/client.key \ --ssl-usercert /path/to/client.crt \ -u alice -p 'Al1ce$ecure!' \ 10.0.0.1 9042
Connecting Java Driver with TLS
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("truststore.jks"), "cassandra".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
sslContext.init(null, tmf.getTrustManagers(), null);
CqlSession session = CqlSession.builder()
.withSslContext(sslContext)
.addContactPoint(new InetSocketAddress("10.0.0.1", 9042))
.withAuthCredentials("alice", "Al1ce$ecure!")
.withLocalDatacenter("us-east")
.build();
Encryption at Rest
Encryption at rest protects SSTable files on disk from unauthorized physical access. Even if a disk is stolen or a snapshot is extracted, the data remains unreadable without the encryption key.
Transparent Data Encryption (TDE)
Cassandra supports transparent data encryption of SSTables using a configurable encryption provider. The configuration lives in cassandra.yaml.
# cassandra.yaml (encryption at rest example)
transparent_data_encryption_options:
enabled: true
chunk_length_kb: 64
cipher: AES/CBC/PKCS5Padding
key_alias: cassandra_key
key_provider:
- class_name: org.apache.cassandra.security.JKSKeyProvider
parameters:
- keystore: /etc/cassandra/ssl/keystore.jks
keystore_password: cassandra
store_type: JCEKS
key_password: cassandra
Audit Logging
Cassandra 4.0 introduced built-in audit logging. Audit logs record every CQL statement executed along with the user, source IP, timestamp, and keyspace. This helps detect unauthorized access and satisfy compliance requirements.
# cassandra.yaml
audit_logging_options:
enabled: true
logger:
- class_name: BinAuditLogger
included_categories: AUTH,DCL,DDL,DML,QUERY
audit_logs_dir: /var/log/cassandra/audit/
TLS Checklist for Production
✓ Generate certificates from a trusted CA (not self-signed) ✓ Enable client_encryption_options with optional: false ✓ Enable server_encryption_options with internode_encryption: all ✓ Rotate certificates before expiry (set calendar reminders) ✓ Store keystore passwords in a secrets manager, not plain text ✓ Enable audit logging for compliance workloads ✓ Enable encryption at rest for sensitive data columns/keyspaces
Summary
Cassandra encryption covers two surfaces: data in transit (TLS) and data at rest. Enable client-to-node TLS to protect application traffic and node-to-node TLS to protect inter-cluster communication. Use certificates signed by a trusted CA in production and store keystore passwords in a secrets manager. Enable transparent data encryption for SSTables when regulatory requirements demand it. Pair encryption with authentication and authorization to build a complete security posture for your Cassandra cluster.
