Cassandra Security Guide
A fresh Cassandra install has no security. Anyone who can reach port 9042 can read and write any data. There is no authentication, no authorization, no encryption. This is convenient for development but dangerous for anything else.
Cassandra has the expected security features—password, role-based access control, TLS encryption for client and internode traffic, audit logging—but they must be enabled. Each feature requires configuration changes and, for some, a rolling restart.
This guide covers enabling authentication, setting up roles and permissions, configuring encryption, and turning on audit logging.
Security Overview
Section titled “Security Overview”Security Layers
Section titled “Security Layers”| Layer | Scope |
|---|---|
| Application | Input validation, credential management, audit logging |
| Cassandra | Authentication, authorization, encryption |
| Network | Firewalls, VPNs, network isolation |
| Infrastructure | OS hardening, access controls, patching |
Security Components
Section titled “Security Components”| Component | Purpose | Default State |
|---|---|---|
| Authentication | Verify identity | Disabled |
| Authorization | Control access | Disabled |
| Client Encryption | Encrypt client traffic | Disabled |
| Internode Encryption | Encrypt cluster traffic | Disabled |
| Audit Logging | Track operations | Disabled |
Authentication
Section titled “Authentication”Enabling Authentication
Section titled “Enabling Authentication”# Enable password authenticationauthenticator: PasswordAuthenticator
# Alternative authenticators:# authenticator: AllowAllAuthenticator # No authentication (default)# authenticator: com.example.LdapAuthenticator # Custom LDAPDefault Superuser
Section titled “Default Superuser”After enabling authentication, use the default superuser:
-- Default credentials (CHANGE IMMEDIATELY)-- Username: cassandra-- Password: cassandra
cqlsh -u cassandra -p cassandra
-- Create new superuserCREATE ROLE admin WITH PASSWORD = 'strong_password_here' AND SUPERUSER = true AND LOGIN = true;
-- Disable default superuserALTER ROLE cassandra WITH SUPERUSER = false AND LOGIN = false;Creating Users
Section titled “Creating Users”-- Create application userCREATE ROLE app_user WITH PASSWORD = 'app_password' AND LOGIN = true;
-- Create read-only userCREATE ROLE readonly_user WITH PASSWORD = 'readonly_pass' AND LOGIN = true;
-- Create user with role inheritanceCREATE ROLE analyst WITH LOGIN = true AND PASSWORD = 'analyst_pass';GRANT readonly_role TO analyst;
-- List all rolesLIST ROLES;Authentication Cache
Section titled “Authentication Cache”Setting Name Changes
| Setting | Pre-4.1 | 4.1+ |
|---|---|---|
| Credentials validity | credentials_validity_in_ms | credentials_validity |
| Credentials update interval | credentials_update_interval_in_ms | credentials_update_interval |
Cassandra 4.1+ uses duration literals (e.g., 2000ms, 2s) instead of milliseconds.
# cassandra.yaml (4.1+ syntax)credentials_validity: 2000mscredentials_update_interval: 2000mscredentials_cache_max_entries: 1000
# Pre-4.1 syntax (deprecated)# credentials_validity_in_ms: 2000# credentials_update_interval_in_ms: 2000Authorization
Section titled “Authorization”Enabling Authorization
Section titled “Enabling Authorization”# Enable role-based authorizationauthorizer: CassandraAuthorizer
# Role managementrole_manager: CassandraRoleManagerPermission Types
Section titled “Permission Types”| Permission | Applies To | Description |
|---|---|---|
ALL | All | All permissions |
ALTER | Keyspace, Table, Function | Modify schema |
AUTHORIZE | All | Grant/revoke permissions |
CREATE | Keyspace, Table, Function, Role | Create objects |
DESCRIBE | All | DESCRIBE operations |
DROP | Keyspace, Table, Function, Role | Delete objects |
EXECUTE | Function | Execute functions |
MODIFY | Keyspace, Table | INSERT, UPDATE, DELETE |
SELECT | Keyspace, Table, MBean | Read data |
SELECT_MASKED | Table | Read masked data (Dynamic Data Masking, Cassandra 5.0+) |
UNMASK | Table | Read unmasked data (Dynamic Data Masking, Cassandra 5.0+) |
Granting Permissions
Section titled “Granting Permissions”-- Grant full access to keyspaceGRANT ALL PERMISSIONS ON KEYSPACE my_keyspace TO app_user;
-- Grant read-only accessGRANT SELECT ON KEYSPACE my_keyspace TO readonly_user;
-- Grant access to specific tableGRANT SELECT, MODIFY ON TABLE my_keyspace.users TO app_user;
-- Grant permission to create keyspacesGRANT CREATE ON ALL KEYSPACES TO admin_user;
-- List permissionsLIST ALL PERMISSIONS OF app_user;LIST ALL PERMISSIONS ON KEYSPACE my_keyspace;Role Hierarchy
Section titled “Role Hierarchy”-- Create role hierarchyCREATE ROLE base_role;CREATE ROLE extended_role;
-- Grant permissions to base roleGRANT SELECT ON KEYSPACE analytics TO base_role;
-- Grant additional permissions to extended roleGRANT MODIFY ON KEYSPACE analytics TO extended_role;
-- Extended role inherits from baseGRANT base_role TO extended_role;
-- Users can be assigned rolesGRANT extended_role TO analyst_user;Resource Permissions
Section titled “Resource Permissions”-- All keyspacesGRANT CREATE ON ALL KEYSPACES TO developer;
-- Specific keyspaceGRANT ALL ON KEYSPACE production TO admin;
-- All tables in keyspaceGRANT SELECT ON ALL TABLES IN KEYSPACE analytics TO analyst;
-- Specific tableGRANT SELECT, MODIFY ON TABLE production.orders TO app_user;
-- FunctionsGRANT EXECUTE ON FUNCTION my_keyspace.my_function(int, text) TO app_user;GRANT EXECUTE ON ALL FUNCTIONS IN KEYSPACE my_keyspace TO app_user;
-- JMX MBeans (for management)GRANT SELECT ON MBEAN 'org.apache.cassandra.db:*' TO monitoring_user;Revoking Permissions
Section titled “Revoking Permissions”-- Revoke specific permissionREVOKE MODIFY ON KEYSPACE my_keyspace FROM app_user;
-- Revoke all permissionsREVOKE ALL PERMISSIONS ON KEYSPACE my_keyspace FROM app_user;
-- Remove role assignmentREVOKE admin_role FROM user;Client-to-Node Encryption
Section titled “Client-to-Node Encryption”Generate Certificates
Section titled “Generate Certificates”#!/bin/bash# Create CA key and certificateopenssl genrsa -out ca-key.pem 4096openssl req -x509 -new -nodes -key ca-key.pem -days 3650 \ -out ca-cert.pem -subj "/CN=CassandraCA"
# For each node, create key and certificatefor NODE in node1 node2 node3; do # Generate private key openssl genrsa -out ${NODE}-key.pem 4096
# Generate certificate signing request openssl req -new -key ${NODE}-key.pem -out ${NODE}.csr \ -subj "/CN=${NODE}"
# Sign certificate with CA openssl x509 -req -in ${NODE}.csr -CA ca-cert.pem \ -CAkey ca-key.pem -CAcreateserial -out ${NODE}-cert.pem -days 365
# Create keystore (PKCS12) openssl pkcs12 -export -in ${NODE}-cert.pem -inkey ${NODE}-key.pem \ -out ${NODE}-keystore.p12 -name ${NODE} -password pass:keystorepass
# Convert to JKS (if needed) keytool -importkeystore -srckeystore ${NODE}-keystore.p12 \ -srcstoretype PKCS12 -srcstorepass keystorepass \ -destkeystore ${NODE}-keystore.jks -deststorepass keystorepassdone
# Create truststore with CA certificatekeytool -import -file ca-cert.pem -keystore truststore.jks \ -storepass truststorepass -noprompt -alias caConfigure Client Encryption
Section titled “Configure Client Encryption”client_encryption_options: # Enable encryption enabled: true
# Optional: Allow unencrypted connections optional: false
# Keystore containing server certificate keystore: /etc/cassandra/certs/node1-keystore.jks keystore_password: keystorepass
# Truststore for client certificate validation # Required if require_client_auth is true truststore: /etc/cassandra/certs/truststore.jks truststore_password: truststorepass
# Require client certificates (mutual TLS) require_client_auth: false
# TLS protocol versions protocol: TLS accepted_protocols: - TLSv1.2 - TLSv1.3
# Cipher suites (strong ciphers only) 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_SHA256Client Connection with SSL
Section titled “Client Connection with SSL”# cqlsh with SSLcqlsh --ssl node1.example.com
# With explicit certificatecqlsh --ssl --ssl-certfile=/path/to/ca-cert.pem node1.example.com
# cqlshrc configuration# ~/.cassandra/cqlshrc[ssl]certfile = /path/to/ca-cert.pemvalidate = trueuserkey = /path/to/client-key.pemusercert = /path/to/client-cert.pem// Java driver with SSLSSLContext sslContext = SSLContext.getInstance("TLS");TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");KeyStore ts = KeyStore.getInstance("JKS");ts.load(new FileInputStream("/path/to/truststore.jks"), "truststorepass".toCharArray());tmf.init(ts);sslContext.init(null, tmf.getTrustManagers(), null);
CqlSession session = CqlSession.builder() .addContactPoint(new InetSocketAddress("node1.example.com", 9042)) .withSslContext(sslContext) .build();Internode Encryption
Section titled “Internode Encryption”Configure Node-to-Node Encryption
Section titled “Configure Node-to-Node Encryption”server_encryption_options: # Encryption mode: # none: No encryption # dc: Encrypt only cross-datacenter traffic # rack: Encrypt only cross-rack traffic # all: Encrypt all internode traffic internode_encryption: all
# Keystore with node certificate keystore: /etc/cassandra/certs/node1-keystore.jks keystore_password: keystorepass
# Truststore with CA certificate truststore: /etc/cassandra/certs/truststore.jks truststore_password: truststorepass
# Require peer certificates require_client_auth: true
# TLS settings protocol: TLS accepted_protocols: - TLSv1.2 - TLSv1.3
cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
# Enable for legacy SSL port (optional) legacy_ssl_storage_port_enabled: falseEncryption Modes
Section titled “Encryption Modes”| Mode | Same Rack | Cross-Rack | Cross-DC |
|---|---|---|---|
none | Plain | Plain | Plain |
dc | Plain | Plain | Encrypted |
rack | Plain | Encrypted | Encrypted |
all | Encrypted | Encrypted | Encrypted |
Network Security
Section titled “Network Security”Firewall Rules
Section titled “Firewall Rules”# Required ports for Cassandra
# Client CQL portiptables -A INPUT -p tcp --dport 9042 -s 10.0.0.0/8 -j ACCEPT
# Internode communicationiptables -A INPUT -p tcp --dport 7000 -s 10.0.0.0/8 -j ACCEPT
# SSL internode (if legacy enabled)iptables -A INPUT -p tcp --dport 7001 -s 10.0.0.0/8 -j ACCEPT
# JMX (restrict to management network)iptables -A INPUT -p tcp --dport 7199 -s 10.0.1.0/24 -j ACCEPT
# Drop all other Cassandra portsiptables -A INPUT -p tcp --dport 9042 -j DROPiptables -A INPUT -p tcp --dport 7000 -j DROPiptables -A INPUT -p tcp --dport 7001 -j DROPiptables -A INPUT -p tcp --dport 7199 -j DROPBinding Interfaces
Section titled “Binding Interfaces”# Listen only on specific interfacelisten_address: 10.0.0.1
# Or listen on all interfaces# listen_address: 0.0.0.0# listen_interface: eth0
# RPC (client) addressrpc_address: 10.0.0.1
# Broadcast addresses (for NAT/cloud)broadcast_address: 10.0.0.1broadcast_rpc_address: 10.0.0.1JMX Security
Section titled “JMX Security”# cassandra-env.sh
# Enable JMX authenticationJVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=true"
# JMX access fileJVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password"JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.access.file=/etc/cassandra/jmxremote.access"
# Enable JMX SSLJVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl=true"JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.registry.ssl=true"JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStore=/etc/cassandra/certs/node1-keystore.jks"JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStorePassword=keystorepass"admin readwritemonitor readonly
# /etc/cassandra/jmxremote.password (chmod 400)admin admin_passwordmonitor monitor_passwordAudit Logging (Cassandra 4.0+)
Section titled “Audit Logging (Cassandra 4.0+)”Enable Audit Logging
Section titled “Enable Audit Logging”audit_logging_options: enabled: true
# Logger implementation logger: - class_name: BinAuditLogger
# Audit categories included_categories: QUERY, DML, DDL, AUTH, ERROR
# Excluded categories # excluded_categories:
# Include specific keyspaces (empty = all) included_keyspaces: - production - sensitive_data
# Exclude system keyspaces excluded_keyspaces: - system - system_schema - system_auth - system_distributed
# Include specific users (empty = all) # included_users:
# Exclude service accounts excluded_users: - cassandra - monitoringAudit Categories
Section titled “Audit Categories”| Category | Description |
|---|---|
QUERY | SELECT statements |
DML | INSERT, UPDATE, DELETE |
DDL | CREATE, ALTER, DROP |
DCL | GRANT, REVOKE |
AUTH | Login attempts |
ADMIN | Administrative operations |
ERROR | Failed operations |
PREPARE | Prepared statements |
View Audit Logs
Section titled “View Audit Logs”# Binary logs require auditlogviewerauditlogviewer /var/log/cassandra/audit/
# Or configure file-based logger# class_name: FileAuditLogger# parameters:# log_dir: /var/log/cassandra/auditSecurity Best Practices
Section titled “Security Best Practices”Production Checklist
Section titled “Production Checklist”Authentication & Authorization:
- Enable PasswordAuthenticator
- Enable CassandraAuthorizer
- Create dedicated superuser
- Disable default cassandra user
- Create application-specific roles
- Apply least-privilege permissions
- Enable password complexity requirements
Encryption:
- Enable client-to-node encryption
- Enable internode encryption
- Use TLS 1.2 or higher
- Use strong cipher suites
- Implement certificate rotation plan
- Use mutual TLS where appropriate
Network:
- Restrict access with firewalls
- Bind to specific interfaces
- Secure JMX access
- Use VPN for cross-DC traffic
- Disable unused ports
Monitoring & Audit:
- Enable audit logging
- Monitor authentication failures
- Alert on permission changes
- Regular security reviews
Common Mistakes
Section titled “Common Mistakes”| Mistake | Risk | Solution |
|---|---|---|
| Default cassandra user | Full access for attackers | Disable after creating new superuser |
| No encryption | Data interception | Enable TLS for all connections |
| GRANT ALL to apps | Over-privileged access | Apply least-privilege |
| JMX open to network | Remote management access | Restrict with firewall + auth |
| Weak passwords | Credential attacks | Enforce complexity policies |
| No audit logging | No visibility into access | Enable audit logging |
Next Steps
Section titled “Next Steps”- Configuration Reference - Cassandra configuration