Security Essential

Authentication

Secure your Cassandra cluster - Control who can access your data!

🔍 What is Authentication?

Authentication verifies WHO you are - like checking your ID at the door!

The Problem Without Authentication:

# By default, Cassandra allows ANYONE to connect! $ cqlsh 10.1.0.10 Connected! ← No password needed! 😱 cqlsh> DROP KEYSPACE production_data; ← Anyone can delete everything!

With Authentication Enabled:

# Must provide valid credentials $ cqlsh 10.1.0.10 -u admin -p "password123" Connected! ← Verified! ✅ # Invalid credentials rejected $ cqlsh 10.1.0.10 -u hacker -p "guess" Authentication failed ← Blocked! 🚫

What Authentication Protects:

  • 🔒 CQL Access: Who can connect via cqlsh or drivers
  • 🔧 Nodetool Access: Who can run admin commands
  • 📊 JMX Access: Who can monitor cluster metrics
  • 🔐 Internal Communication: Node-to-node authentication

Default = Insecure!

Cassandra ships with authentication DISABLED by default!

This means anyone who can reach your cluster can connect and do ANYTHING. Always enable authentication in production!

⚖️ Authentication vs Authorization

Two different concepts - both essential!

🔐

Authentication

"WHO are you?"

Purpose:

  • Verify identity
  • Check username/password
  • Allow or deny connection

Example:

cqlsh -u alice -p pass123 ✅ Valid user → Connected
🛡️

Authorization

"WHAT can you do?"

Purpose:

  • Check permissions
  • Control access to data
  • Allow or deny operations

Example:

SELECT * FROM users; ❌ No SELECT permission

The Complete Security Flow

# Step 1: AUTHENTICATION - Who are you? $ cqlsh -u alice -p "password" → Check: Does user 'alice' exist? → Check: Is password correct? → YES → Allow connection ✅ # Step 2: AUTHORIZATION - What can you do? cqlsh> SELECT * FROM users; → Check: Does alice have SELECT permission on users? → YES → Execute query ✅ cqlsh> DROP TABLE users; → Check: Does alice have DROP permission? → NO → Deny operation ❌ Unauthorized: User alice has no DROP permission

🛠️ Cassandra Authenticators

Choose how to authenticate!

1

AllowAllAuthenticator (Default)

⚠️ INSECURE - Anyone can connect

# In cassandra.yaml (DEFAULT) authenticator: AllowAllAuthenticator # What it does: # - NO authentication required # - Anyone can connect without credentials # - Perfect for development, NEVER for production! # Connect without password: $ cqlsh 10.1.0.10 Connected! ← No credentials needed # When to use: # ✅ Local development # ✅ Testing on isolated networks # ❌ NEVER in production! # ❌ NEVER on internet-accessible servers!
2

PasswordAuthenticator

✅ RECOMMENDED - Built-in secure authentication

# In cassandra.yaml authenticator: PasswordAuthenticator # What it does: # - Requires username + password # - Credentials stored in system_auth.roles table # - Works out of the box # - Most common choice for production # Connect with credentials: $ cqlsh 10.1.0.10 -u admin -p "mypassword" Connected! ← Authenticated! ✅ # Default superuser created: # Username: cassandra # Password: cassandra # (CHANGE THIS IMMEDIATELY!) # When to use: # ✅ Production clusters # ✅ Any environment needing security # ✅ Standard deployment
3

Custom Authenticator (LDAP/Kerberos)

Enterprise authentication integration

# In cassandra.yaml (example) authenticator: com.company.LDAPAuthenticator # What it does: # - Integrates with existing auth systems # - LDAP, Active Directory, Kerberos # - Centralized user management # - Requires custom plugin or enterprise edition # Common enterprise authenticators: # - DataStax Enterprise: LDAP/Kerberos built-in # - Open-source plugins available # - Custom implementations possible # When to use: # ✅ Large enterprises with existing auth # ✅ Need SSO (Single Sign-On) # ✅ Compliance requirements (audit, MFA) # ✅ Centralized user management

⚡ Enabling Authentication - Complete Guide

Step-by-step with all commands!

Before You Start - Critical!

  • ⚠️ Take snapshot backup before enabling auth
  • ⚠️ Enable on ALL nodes in rolling fashion
  • ⚠️ Test in dev first - don't experiment in production
  • ⚠️ Update applications with credentials before enabling
  • ⚠️ Have console access in case you get locked out

Step-by-Step Enablement Process

Step 1: Configure system_auth Keyspace

# CRITICAL: Set RF for system_auth BEFORE enabling authentication! # Default RF=1 is dangerous - if that node dies, auth breaks! # Connect as default superuser $ cqlsh # Check current RF cqlsh> DESCRIBE KEYSPACE system_auth; CREATE KEYSPACE system_auth WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '1' ← DANGER! ⚠️ }; # Alter to proper RF (match your cluster) # For 3+ node cluster with RF=3: cqlsh> ALTER KEYSPACE system_auth WITH replication = { 'class': 'NetworkTopologyStrategy', 'datacenter1': '3' }; # For multi-DC cluster: cqlsh> ALTER KEYSPACE system_auth WITH replication = { 'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3' }; # IMPORTANT: Run repair on ALL nodes! $ nodetool repair -pr system_auth # Wait for completion, then repeat on each node

Step 2: Edit cassandra.yaml on First Node

# On node1, edit /etc/cassandra/cassandra.yaml # Find and change authenticator: authenticator: PasswordAuthenticator ← Change from AllowAllAuthenticator # Also enable authorization (covered in next lesson) authorizer: CassandraAuthorizer ← Change from AllowAllAuthorizer # Save file $ sudo vim /etc/cassandra/cassandra.yaml # Make changes above, save and exit

Step 3: Restart First Node

# Restart Cassandra on node1 $ sudo systemctl restart cassandra # Wait for node to come up $ nodetool status UN 10.1.0.10 500 GB 256 33.3% ← UP and NORMAL ✅ # Check logs for errors $ tail -50 /var/log/cassandra/system.log # Look for: "PasswordAuthenticator started" # Test connection with default credentials $ cqlsh 10.1.0.10 -u cassandra -p cassandra Connected! ← Authentication working! ✅

Step 4: Change Default Superuser Password

# CRITICAL: Change default password immediately! $ cqlsh 10.1.0.10 -u cassandra -p cassandra # Change password for cassandra user cqlsh> ALTER ROLE cassandra WITH PASSWORD = 'NewSecurePass123!'; # Test new password cqlsh> EXIT; $ cqlsh 10.1.0.10 -u cassandra -p 'NewSecurePass123!' Connected! ← New password works! ✅ # Old password no longer works $ cqlsh 10.1.0.10 -u cassandra -p cassandra Authentication failed ← Blocked! ✅

Step 5: Rolling Restart Other Nodes

# Repeat steps 2-3 on each remaining node # ONE NODE AT A TIME (rolling restart) # Node 2: $ ssh node2 $ sudo vim /etc/cassandra/cassandra.yaml # Enable PasswordAuthenticator $ sudo systemctl restart cassandra $ nodetool status # Wait for UN # Wait 2-5 minutes between nodes # Node 3: $ ssh node3 $ sudo vim /etc/cassandra/cassandra.yaml $ sudo systemctl restart cassandra $ nodetool status # Continue for all nodes... # Final check - all nodes UP with auth enabled $ nodetool status UN 10.1.0.10 500 GB 256 33.3% UN 10.1.0.11 500 GB 256 33.3% UN 10.1.0.12 500 GB 256 33.4% ← All UP! ✅

Step 6: Update Applications

# Update all application connection strings # Python driver example: from cassandra.cluster import Cluster from cassandra.auth import PlainTextAuthProvider auth_provider = PlainTextAuthProvider( username='app_user', password='app_password' ) cluster = Cluster( ['10.1.0.10', '10.1.0.11'], auth_provider=auth_provider ) session = cluster.connect() # Java driver example: Cluster cluster = Cluster.builder() .addContactPoints("10.1.0.10", "10.1.0.11") .withCredentials("app_user", "app_password") .build(); # Node.js driver example: const client = new cassandra.Client({ contactPoints: ['10.1.0.10', '10.1.0.11'], credentials: { username: 'app_user', password: 'app_password' } });

👥 User Management

Create and manage users!

Creating Users (Roles)

# In Cassandra, users are called "roles" # Create a regular user CREATE ROLE alice WITH PASSWORD = 'alice_pass_123' AND LOGIN = true; # Create superuser (full permissions) CREATE ROLE admin WITH PASSWORD = 'admin_pass_456' AND LOGIN = true AND SUPERUSER = true; # Create read-only user CREATE ROLE readonly WITH PASSWORD = 'readonly_789' AND LOGIN = true; # Create role for application CREATE ROLE app_user WITH PASSWORD = 'app_secret_key' AND LOGIN = true; # Key points: # - LOGIN = true → Can connect # - LOGIN = false → Group role (can't login directly) # - SUPERUSER = true → Bypass all permissions # - SUPERUSER = false (default) → Subject to permissions

Listing Users

# List all roles LIST ROLES; # Output: role | super | login | options -----------+-------+-------+--------- admin | True | True | {} alice | False | True | {} cassandra | True | True | {} readonly | False | True | {} app_user | False | True | {} # Check specific role LIST ROLES OF alice; # Check who has SUPERUSER SELECT * FROM system_auth.roles WHERE is_superuser = true;

Modifying Users

# Change password ALTER ROLE alice WITH PASSWORD = 'new_password_456'; # Make user a superuser ALTER ROLE alice WITH SUPERUSER = true; # Remove superuser privilege ALTER ROLE alice WITH SUPERUSER = false; # Disable login (keep role for permissions) ALTER ROLE alice WITH LOGIN = false; # Re-enable login ALTER ROLE alice WITH LOGIN = true;

Deleting Users

# Drop a role DROP ROLE alice; # Drop with safety check DROP ROLE IF EXISTS alice; # WARNING: Can't drop role if it has permissions granted! # Must revoke all permissions first (covered in authorization lesson) # NEVER drop the cassandra superuser! # Create another superuser first as backup

Password Policies

Strong Password Guidelines

  • ✅ Minimum 12 characters
  • ✅ Mix: Uppercase, lowercase, numbers, symbols
  • ✅ Unique per user - no shared passwords
  • ✅ Rotate regularly - change every 90 days
  • ❌ Avoid: Dictionary words, personal info, sequences
  • 🔐 Store securely: Use password manager or secrets management

💼 Real-World Scenarios

Complete authentication setups!

Scenario 1: Enabling Authentication on Production Cluster

# Context: 6-node production cluster, currently no auth # Goal: Enable PasswordAuthenticator with zero downtime # PHASE 1: Pre-work (Week before) # 1. Configure system_auth RF $ cqlsh node1 cqlsh> ALTER KEYSPACE system_auth WITH replication = { 'class': 'NetworkTopologyStrategy', 'datacenter1': '3' }; # 2. Repair system_auth on ALL nodes $ for node in node{1..6}; do ssh $node "nodetool repair -pr system_auth" sleep 600 # Wait 10 min between nodes done # 3. Update application configs (but don't deploy yet) # - Add username/password to connection strings # - Test in staging environment # - Prepare rollback plan # PHASE 2: Enablement (Maintenance window) # Time: Saturday 2 AM (low traffic) # Node 1: $ ssh node1 $ sudo vim /etc/cassandra/cassandra.yaml # Change: authenticator: PasswordAuthenticator $ sudo systemctl restart cassandra $ nodetool status # Wait for UN # Test: $ cqlsh node1 -u cassandra -p cassandra # ✅ Works! # Change default password: cqlsh> ALTER ROLE cassandra WITH PASSWORD = 'Prod$ecure2024!'; # Wait 5 minutes, check metrics normal # Nodes 2-6 (rolling restart): $ for node in node{2..6}; do echo "Enabling auth on $node..." ssh $node "sudo sed -i 's/AllowAllAuthenticator/PasswordAuthenticator/' /etc/cassandra/cassandra.yaml" ssh $node "sudo systemctl restart cassandra" sleep 300 # Wait 5 min between nodes ssh $node "nodetool status" done # PHASE 3: Application cutover # Deploy updated app configs with credentials # Monitor for authentication errors # If issues → rollback app config (auth still works without creds from apps temporarily) # RESULT: Authentication enabled, zero downtime! ✅

Scenario 2: Multi-Tenant Application Setup

# Context: SaaS platform with multiple customer databases # Goal: Isolate each customer with separate credentials # Setup 1: Create keyspace per customer cqlsh> CREATE KEYSPACE customer_acme WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'}; cqlsh> CREATE KEYSPACE customer_globex WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'}; # Setup 2: Create tables cqlsh> USE customer_acme; cqlsh> CREATE TABLE users (...); cqlsh> CREATE TABLE orders (...); # Setup 3: Create role per customer cqlsh> CREATE ROLE acme_app WITH PASSWORD = 'acme_secret_key_xyz' AND LOGIN = true; cqlsh> CREATE ROLE globex_app WITH PASSWORD = 'globex_secret_key_abc' AND LOGIN = true; # Setup 4: Grant permissions (authorization - next lesson) cqlsh> GRANT ALL PERMISSIONS ON KEYSPACE customer_acme TO acme_app; cqlsh> GRANT ALL PERMISSIONS ON KEYSPACE customer_globex TO globex_app; # Setup 5: Application connects with customer-specific credentials # ACME's app: cluster = Cluster( ['10.1.0.10'], auth_provider=PlainTextAuthProvider( username='acme_app', password='acme_secret_key_xyz' ) ) session = cluster.connect('customer_acme') # GLOBEX's app: cluster = Cluster( ['10.1.0.10'], auth_provider=PlainTextAuthProvider( username='globex_app', password='globex_secret_key_abc' ) ) session = cluster.connect('customer_globex') # RESULT: Perfect isolation! # - ACME can only access customer_acme # - GLOBEX can only access customer_globex # - No cross-customer data leaks ✅

Scenario 3: Emergency - Locked Out of Cluster

# PROBLEM: Forgot superuser password, can't connect! $ cqlsh -u cassandra -p "forgot_password" Authentication failed ← OH NO! 😱 # SOLUTION 1: Temporarily disable authentication # (Requires console/SSH access to server) $ ssh node1 # Edit cassandra.yaml $ sudo vim /etc/cassandra/cassandra.yaml # Change back to: authenticator: AllowAllAuthenticator ← Temporarily disable # Restart Cassandra $ sudo systemctl restart cassandra $ nodetool status # Wait for UN # Now can connect without password $ cqlsh node1 Connected! # Reset password cqlsh> ALTER ROLE cassandra WITH PASSWORD = 'NewPassword123!'; # Re-enable authentication $ sudo vim /etc/cassandra/cassandra.yaml authenticator: PasswordAuthenticator ← Re-enable $ sudo systemctl restart cassandra # Test new password $ cqlsh node1 -u cassandra -p 'NewPassword123!' Connected! ← Fixed! ✅ # Repeat on other nodes (rolling restart) # PREVENTION: Always maintain multiple superusers! cqlsh> CREATE ROLE backup_admin WITH PASSWORD = 'BackupAdminPass!' AND LOGIN = true AND SUPERUSER = true;

🔧 Troubleshooting Authentication Issues

Fix common problems!

❌ "Unable to connect: Authentication required"

# ERROR: $ cqlsh 10.1.0.10 Connection error: ('Unable to connect to any servers') # CAUSE: Authentication enabled but no credentials provided # FIX: Provide username and password $ cqlsh 10.1.0.10 -u cassandra -p "password" Connected! ← Fixed! ✅ # Or set in cqlshrc file: $ cat ~/.cassandra/cqlshrc [authentication] username = cassandra password = mypassword

❌ "Provided username/password are incorrect"

# ERROR: $ cqlsh -u alice -p "wrong_password" Provided username alice and/or password are incorrect # CAUSES: # 1. Wrong password # 2. User doesn't exist # 3. Typo in username # FIX 1: Check username exists (as superuser) $ cqlsh -u cassandra -p "admin_pass" cqlsh> LIST ROLES; # Check if alice is in list # FIX 2: Reset user password (as superuser) cqlsh> ALTER ROLE alice WITH PASSWORD = 'new_password'; # FIX 3: Check for typos $ cqlsh -u alice -p "correct_password" ← Note: Case-sensitive!

❌ system_auth Unavailable After Restart

# ERROR in logs: UnavailableException: Cannot achieve consistency level QUORUM # CAUSE: system_auth RF=1, that node is down # CHECK: $ cqlsh -u cassandra -p "password" cqlsh> DESCRIBE KEYSPACE system_auth; # If RF=1 → PROBLEM! # FIX 1: If can still connect, increase RF immediately cqlsh> ALTER KEYSPACE system_auth WITH replication = { 'class': 'NetworkTopologyStrategy', 'datacenter1': '3' }; # Repair on all nodes $ nodetool repair -pr system_auth # FIX 2: If locked out, temporarily disable auth # (See Scenario 3 above)

❌ Application Can't Connect After Enabling Auth

# ERROR in application logs: AuthenticationException: Authentication error # CAUSE: App not configured with credentials # FIX: Update application config # Python: from cassandra.auth import PlainTextAuthProvider auth_provider = PlainTextAuthProvider( username='app_user', password='app_password' ) cluster = Cluster( ['10.1.0.10'], auth_provider=auth_provider ← Add this! ) # Java: Cluster cluster = Cluster.builder() .addContactPoint("10.1.0.10") .withCredentials("app_user", "app_password") ← Add this! .build(); # Node.js: const client = new Client({ contactPoints: ['10.1.0.10'], credentials: { username: 'app_user', password: 'app_password' } ← Add this! });

💡 Best Practices

Security done right!

✅

DO

  • Enable auth in production
  • Set system_auth RF >= 3
  • Change default password immediately
  • Use strong passwords (12+ chars)
  • Create separate users per app/team
  • Maintain multiple superusers
  • Rotate passwords regularly (90 days)
  • Use least privilege principle
  • Test in dev before production
  • Store credentials securely
❌

DON'T

  • Leave AllowAll in production
  • Use default cassandra/cassandra
  • Share passwords between users
  • Use weak passwords
  • Hard-code credentials in code
  • Give everyone superuser
  • Skip system_auth RF setup
  • Enable auth without testing
  • Store passwords in plain text
  • Forget to update apps

Production Security Checklist

  1. ✅ Authentication: PasswordAuthenticator enabled
  2. ✅ system_auth RF: Set to 3+ (match cluster RF)
  3. ✅ Default password: Changed immediately
  4. ✅ Multiple superusers: Create backup admin accounts
  5. ✅ User per application: Separate credentials for each service
  6. ✅ Strong passwords: 12+ characters, mixed case, numbers, symbols
  7. ✅ Password rotation: Change every 90 days
  8. ✅ Least privilege: Grant minimal necessary permissions
  9. ✅ Secrets management: Use vault/secrets manager, not config files
  10. ✅ Encryption: Enable TLS/SSL (next lesson!)
  11. ✅ Audit logging: Track who does what
  12. ✅ Regular audits: Review users and permissions quarterly

Defense in Depth

Authentication is just one layer! Also implement:

  • 🔒 Network security: Firewall rules, VPC, security groups
  • 🔐 Encryption: TLS for client-to-node and node-to-node
  • 🛡️ Authorization: Role-based access control (RBAC)
  • 📋 Audit logging: Track all access and changes
  • 📊 Monitoring: Alert on failed logins, unusual access patterns
  • 🔄 Backups: Encrypted, offsite, tested recovery
  • 🚪 JMX security: Secure monitoring interfaces

🎉 You're an Authentication Expert!

Congratulations! You now know how to secure Cassandra with authentication!

🎓 What You Learned:

  • 🔍 Authentication basics: Verify WHO you are
  • ⚖️ Auth vs Authz: Authentication (who) vs Authorization (what)
  • 🛠️ Authenticators: AllowAll, Password, Custom (LDAP/Kerberos)
  • ⚡ Enabling auth: Complete step-by-step process
  • 👥 User management: Create, modify, delete users
  • 💼 Real scenarios: Production enablement, multi-tenant, emergency recovery
  • 🔧 Troubleshooting: Fix common authentication issues
  • 💡 Best practices: Security checklist, strong passwords, defense in depth

💡 Key Takeaways:

  1. Always enable auth in production - Default is insecure!
  2. Set system_auth RF to 3+ - Critical for auth availability
  3. Change default password - First thing after enabling
  4. One user per application - Never share credentials
  5. Strong passwords - 12+ characters, complex
  6. Multiple superusers - Backup admin accounts
  7. Test before production - Dev → staging → prod
  8. Update applications - Configure credentials before enabling

📋 Quick Reference:

# Enable authentication # 1. Set system_auth RF ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'}; nodetool repair -pr system_auth # 2. Edit cassandra.yaml authenticator: PasswordAuthenticator # 3. Rolling restart # 4. Change default password ALTER ROLE cassandra WITH PASSWORD = 'NewSecurePass!'; # Create users CREATE ROLE alice WITH PASSWORD = 'pass123' AND LOGIN = true; CREATE ROLE admin WITH PASSWORD = 'admin123' AND LOGIN = true AND SUPERUSER = true; # Manage users LIST ROLES; ALTER ROLE alice WITH PASSWORD = 'new_pass'; DROP ROLE alice;

🔐 Authentication = First line of defense!
Now add Authorization for complete security →