Data In Transit Protection
SSL/TLS Encryption
Encrypt your data in transit - Prevent eavesdropping!
🔍 What is SSL/TLS Encryption?
SSL/TLS encrypts data in transit - like sending letters in locked boxes instead of postcards!
The Problem Without Encryption:
# WITHOUT SSL: Data sent in plain text
Client → Network → Cassandra
"SELECT * FROM credit_cards WHERE user_id='12345'"
# Attacker with Wireshark can see:
# - All queries being run
# - Data being returned
# - Credit card numbers, SSNs 😱
With SSL/TLS Enabled:
# WITH SSL: Data encrypted
Client → Encrypted Tunnel → Cassandra
�������������������������
# Attacker sees only gibberish ✅
# - Can't read queries
# - Can't read responses
# - Can't steal credentials
Compliance Requirements!
Many regulations REQUIRE encryption in transit:
- HIPAA: Healthcare data must be encrypted
- PCI DSS: Payment card data requires encryption
- GDPR: Personal data should be encrypted
🔐 Types of Encryption in Cassandra
Two independent encryption layers!
Client-to-Node
Application ↔ Cassandra
Protects:
- CQL queries from apps
- Query results
- cqlsh connections
Port: 9042
Node-to-Node
Cassandra ↔ Cassandra
Protects:
- Data streaming
- Gossip protocol
- Read/write coordination
Port: 7001
Independent Configuration
You can enable one or both:
- ✅ Client-to-Node only: Protects app traffic
- ✅ Node-to-Node only: Protects inter-node
- ✅ Both (recommended): Maximum security
📜 Understanding Certificates
Key Concepts
Keystore
Server's Private Key
Contains:
- Private key (secret!)
- Public certificate
Used by: Cassandra nodes
Truststore
Trusted CAs
Contains:
- CA certificates
- Trusted certs
Used by: Clients & nodes
Generating Certificates
Step 1: Create CA
# Generate CA private key
$ openssl genrsa -out ca-key.pem 4096
# Generate CA certificate
$ openssl req -new -x509 -key ca-key.pem \
-out ca-cert.pem -days 3650 \
-subj "/CN=CassandraCA/O=MyCompany/C=US"
# Result: CA valid for 10 years
Step 2: Generate Node Certificates
# For each node
$ openssl genrsa -out node1-key.pem 2048
$ openssl req -new -key node1-key.pem \
-out node1.csr \
-subj "/CN=node1.cassandra.local/O=MyCompany"
# Sign with CA
$ openssl x509 -req -in node1.csr \
-CA ca-cert.pem -CAkey ca-key.pem \
-out node1-cert.pem -days 365
Step 3: Create Java Keystores
# Convert to PKCS12
$ openssl pkcs12 -export \
-in node1-cert.pem \
-inkey node1-key.pem \
-out node1.p12 -name node1 \
-password pass:changeit
# Import to Java keystore
$ keytool -importkeystore \
-srckeystore node1.p12 \
-srcstoretype PKCS12 \
-destkeystore node1-keystore.jks \
-deststorepass changeit
# Create truststore
$ keytool -import -alias CARoot \
-file ca-cert.pem \
-keystore truststore.jks \
-storepass changeit -noprompt
Step 4: Distribute to Nodes
# Copy to nodes
$ sudo mkdir -p /etc/cassandra/certs
$ scp node1-keystore.jks node1:/etc/cassandra/certs/
$ scp truststore.jks node1:/etc/cassandra/certs/
# Set permissions
$ sudo chown cassandra:cassandra /etc/cassandra/certs/*
$ sudo chmod 400 /etc/cassandra/certs/*.jks
💻 Enabling Client-to-Node Encryption
1
Configure cassandra.yaml
# Edit /etc/cassandra/cassandra.yaml
client_encryption_options:
enabled: true
optional: false # true = allow non-SSL too
keystore: /etc/cassandra/certs/keystore.jks
keystore_password: changeit
require_client_auth: false
truststore: /etc/cassandra/certs/truststore.jks
truststore_password: changeit
protocol: TLS
store_type: JKS
2
Rolling Restart
# Restart each node one at a time
$ sudo systemctl restart cassandra
$ nodetool status # Wait for UN
# Check logs
$ grep -i "ssl\|encrypt" /var/log/cassandra/system.log
# Should see: "Enabling encrypted CQL connections"
3
Connect with SSL
# Create ~/.cassandra/cqlshrc
$ cat > ~/.cassandra/cqlshrc <<'EOF'
[connection]
hostname = 10.1.0.10
port = 9042
[ssl]
certfile = /path/to/ca-cert.pem
validate = true
[authentication]
username = cassandra
password = mypassword
EOF
# Connect
$ cqlsh --ssl
Connected! ✅
4
Update Application Drivers
# Python
from cassandra.cluster import Cluster
from ssl import SSLContext, PROTOCOL_TLSv1_2, CERT_REQUIRED
ssl_context = SSLContext(PROTOCOL_TLSv1_2)
ssl_context.load_verify_locations('/path/to/ca-cert.pem')
ssl_context.verify_mode = CERT_REQUIRED
cluster = Cluster(['10.1.0.10'], ssl_context=ssl_context)
session = cluster.connect()
# Java
Cluster cluster = Cluster.builder()
.addContactPoint("10.1.0.10")
.withSSL(sslOptions)
.build();
# Node.js
const sslOptions = {
ca: [fs.readFileSync('/path/to/ca-cert.pem')],
rejectUnauthorized: true
};
const client = new Client({ sslOptions });
🌐 Enabling Node-to-Node Encryption
Performance Impact
- ⚠️ CPU: 10-20% overhead
- ⚠️ Latency: Slight increase
- ✅ Worth it: Security benefits outweigh cost
Configuration
# Edit cassandra.yaml
server_encryption_options:
internode_encryption: all # none|dc|rack|all
keystore: /etc/cassandra/certs/keystore.jks
keystore_password: changeit
truststore: /etc/cassandra/certs/truststore.jks
truststore_password: changeit
require_client_auth: true
protocol: TLS
store_type: JKS
Verification
# Check logs
$ grep -i "internode\|encrypt" /var/log/cassandra/system.log
"Enabling encrypted internode communication"
# Test with tcpdump
$ sudo tcpdump -i eth0 -A port 7001
# Should see encrypted gibberish!
💼 Real-World Scenarios
Scenario 1: Zero-Downtime SSL Enablement
# Use 'optional' mode for transition
# PHASE 1: Generate certificates
$ openssl genrsa -out ca-key.pem 4096
$ openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 3650
# Create keystores for all nodes...
# PHASE 2: Enable optional SSL
client_encryption_options:
enabled: true
optional: true ← Allows both SSL and non-SSL!
# Rolling restart - cluster accepts both connections
# PHASE 3: Update applications with SSL
# Deploy updated configs
# PHASE 4: Enforce SSL
optional: false ← Now SSL required!
# Result: Zero downtime! ✅
Scenario 2: Certificate Renewal
# Check expiration
$ keytool -list -v -keystore keystore.jks | grep -i valid
Valid until: Tue Jan 01 2025 ← Expiring soon!
# Generate new certificate
$ openssl x509 -req -in wildcard.csr \
-CA ca-cert.pem -CAkey ca-key.pem \
-out wildcard-cert-new.pem -days 365
# Create new keystore
$ keytool -importkeystore \
-srckeystore wildcard-new.p12 \
-destkeystore keystore-new.jks
# Rolling update
$ for node in node{1..6}; do
ssh $node "sudo cp keystore-new.jks /etc/cassandra/certs/keystore.jks"
ssh $node "sudo systemctl restart cassandra"
sleep 300
done
Scenario 3: Multi-DC Encryption
# Encrypt between DCs only
server_encryption_options:
internode_encryption: dc ← DC only!
# Result:
# DC1 node ↔ DC1 node: Plain text (fast)
# DC1 node ↔ DC2 node: Encrypted (secure)
# Perfect for hybrid cloud!
🔧 Troubleshooting SSL/TLS Issues
❌ Connection Refused
# ERROR:
$ cqlsh 10.1.0.10
Unable to connect
# CAUSE: SSL enabled but client not using SSL
# FIX:
$ cqlsh 10.1.0.10 --ssl
Connected! ✅
❌ Certificate Verification Failed
# ERROR:
ssl.SSLError: CERTIFICATE_VERIFY_FAILED
# CHECK: Certificate validity
$ openssl x509 -in ca-cert.pem -noout -dates
notAfter=Jan 1 2025 ← Expired!
# FIX 1: Renew certificate
# FIX 2: For testing only, disable validation
[ssl]
validate = false ← NOT for production!
❌ Cassandra Won't Start
# ERROR in logs:
Failed to create SSL handler
# CHECK: Keystore permissions
$ ls -l /etc/cassandra/certs/
-rw-r--r-- keystore.jks ← Wrong! Too open
# FIX:
$ sudo chmod 400 /etc/cassandra/certs/*.jks
$ sudo chown cassandra:cassandra /etc/cassandra/certs/*.jks
❌ Nodes Showing as DOWN
# ERROR: Remote peer failed to authenticate
$ nodetool status
DN 10.1.0.11 ← Node down
# CHECK: All nodes have same truststore
$ for node in node{1..3}; do
ssh $node "md5sum /etc/cassandra/certs/truststore.jks"
done
← All should match!
# FIX: Distribute same truststore to all nodes
💡 Best Practices
DO
- Enable both client and node encryption
- Use strong cipher suites
- Use TLS 1.2 or higher
- Rotate certificates before expiry
- Use CA-signed certificates
- Secure keystore passwords
- Test in dev first
- Use 'optional' mode for transitions
- Monitor certificate expiration
- Keep private keys secure (400 permissions)
DON'T
- Run production without SSL
- Use self-signed certs in production
- Use weak cipher suites
- Hard-code passwords
- Share keystores between nodes
- Forget to renew certificates
- Skip testing after enabling
- Use same certs for prod/dev
- Disable certificate validation
- Leave keystores world-readable
Production SSL Checklist
- ✅ Client-to-Node SSL: Enabled with proper certificates
- ✅ Node-to-Node SSL: Enabled (internode_encryption: all)
- ✅ CA Certificates: Proper CA (not self-signed)
- ✅ Certificate Validity: Valid for 90+ days
- ✅ Strong Ciphers: TLS 1.2+ with strong cipher suites
- ✅ Password Security: Strong passwords, not plain text
- ✅ File Permissions: Keystores 400, cassandra user
- ✅ Application Updates: All clients using SSL
- ✅ Monitoring: Alert on cert expiration (30 days)
- ✅ Documentation: Cert renewal procedure
- ✅ Backup: Keystores backed up securely
- ✅ Testing: Verified in staging first
Certificate Lifecycle
Don't let certificates expire!
- 📅 90 days before: Order/generate new certificates
- 📅 60 days before: Test in staging
- 📅 30 days before: Schedule production rollout
- 📅 15 days before: Execute rolling update
- 📅 After expiry: Too late! Cluster breaks!
Set up alerts! Monitor expiration dates.
🎉 You're an Encryption Expert!
You now know how to encrypt Cassandra data in transit!
🎓 What You Learned:
- 🔍 SSL/TLS basics: Encrypt data in transit
- 🔐 Encryption types: Client-to-Node and Node-to-Node
- 📜 Certificates: CA, keystores, truststores
- 💻 Client-to-Node: Complete setup with drivers
- 🌐 Node-to-Node: Internode encryption
- 💼 Real scenarios: Zero-downtime, cert renewal, multi-DC
- 🔧 Troubleshooting: Fix SSL issues
- 💡 Best practices: Production checklist
💡 Key Takeaways:
- Enable both encryptions - Full protection
- Use 'optional' mode - Zero downtime transitions
- Proper CA certificates - Not self-signed in prod
- Strong cipher suites - TLS 1.2+ only
- Certificate lifecycle - Renew before expiry
- Secure keystores - 400 permissions
- Test thoroughly - Staging before production
- Monitor expiration - Set up alerts
📋 Quick Reference:
# Generate certificates
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -key ca-key.pem -out ca-cert.pem
# Enable client-to-node
client_encryption_options:
enabled: true
keystore: /etc/cassandra/certs/keystore.jks
# Enable node-to-node
server_encryption_options:
internode_encryption: all
# Connect with SSL
cqlsh --ssl
🔒 Encryption = Privacy + Security!
Complete security stack achieved! 🎯
Advertisement
📱 Responsive Ad 📱