Cluster Security: Auth & Encryption
Security in Cassandra is often overlooked until it’s too late. A production cluster must be secured on three fronts:
- Authentication: Verifying who the user is.
- Authorization: Verifying what the user can do (RBAC).
- Encryption: Securing data in flight (mTLS) and at rest.
1. Authorization (RBAC)
Cassandra uses RBAC. Instead of assigning permissions to users, you assign permissions to Roles, and users assume those Roles.
Interactive RBAC Policy Simulator
Define a Role’s permissions and test access against specific resources.
1. Configure Role Permissions
2. Test Access
2. Authentication
Cassandra supports pluggable authentication. The default AllowAllAuthenticator is insecure and should never be used in production.
First Principles: Performance Impact
Enabling authentication adds a small overhead (network roundtrip for login). However, Cassandra drivers use connection pooling. Authentication happens only when a connection is established, not on every query.
- Connection Open: Auth Handshake (Slow)
- Query: Auth Token/Session ID (Fast)
Enabling Password Auth
- Update
cassandra.yaml:authenticator: PasswordAuthenticator authorizer: CassandraAuthorizer - Restart the node.
- Login with default credentials (
cassandra/cassandra). - IMMEDIATELY change the default password and create new superusers.
3. Encryption (mTLS)
Encryption is critical for preventing man-in-the-middle attacks.
- Client-to-Node: Encrypts traffic between your application and Cassandra.
- Node-to-Node (Internode): Encrypts gossip and streaming traffic. Critical because data streaming (bootstrap/repair) moves raw SSTables across the wire.
mTLS (Mutual TLS)
In standard TLS, the client verifies the server. In mTLS, both parties verify each other using certificates signed by a trusted Certificate Authority (CA).
4. Secure Drivers (Code Examples)
Connecting to a secure cluster requires configuring SSL in your driver.
import com.datastax.oss.driver.api.core.CqlSession;
import javax.net.ssl.SSLContext;
import java.net.InetSocketAddress;
import java.nio.file.Paths;
public class SecureConnect {
public static void main(String[] args) {
// Option 1: Using a Cloud Secure Connect Bundle (simplest for cloud)
// try (CqlSession session = CqlSession.builder()
// .withCloudSecureConnectBundle(Paths.get("/path/to/bundle.zip"))
// .withAuthCredentials("user", "pass")
// .build()) { ... }
// Option 2: Programmatic SSL Context (for self-managed)
try {
// Assuming you have a helper to load your KeyStore/TrustStore
SSLContext sslContext = SSLContext.getDefault();
try (CqlSession session = CqlSession.builder()
.addContactPoint(new InetSocketAddress("10.0.0.1", 9042))
.withAuthCredentials("admin", "super_secret_password")
.withLocalDatacenter("dc1")
.withSslContext(sslContext) // Enable SSL
.build()) {
System.out.println("Connected to: " + session.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"github.com/gocql/gocql"
)
func main() {
cluster := gocql.NewCluster("10.0.0.1", "10.0.0.2")
cluster.Keyspace = "my_keyspace"
cluster.Consistency = gocql.Quorum
// 1. Authentication
cluster.Authenticator = gocql.PasswordAuthenticator{
Username: "admin",
Password: "super_secret_password",
}
// 2. Load CA Certificate (to verify the server)
caCert, err := ioutil.ReadFile("/path/to/ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 3. Load Client Certificate (for mTLS - so server verifies us)
cert, err := tls.LoadX509KeyPair("/path/to/client.crt", "/path/to/client.key")
if err != nil {
log.Fatal(err)
}
// 4. Configure TLS
cluster.SslOpts = &gocql.SslOptions{
Config: &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{cert},
// In production, InsecureSkipVerify MUST be false
InsecureSkipVerify: false,
ServerName: "cassandra.prod.local", // Must match Cert CN/SAN
},
EnableHostVerification: true,
}
session, err := cluster.CreateSession()
if err != nil {
log.Fatal(err)
}
defer session.Close()
log.Println("Secure mTLS connection established.")
}
5. Diagram: Mutual TLS (mTLS) Handshake
Figure 3: Mutual TLS requires both parties to prove their identity before data is exchanged.