Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Client TLS Configuration

This section covers TLS configuration for Cassandra clients including cqlsh, Java driver, Python driver, and other language drivers.

Terminal window
# Basic SSL connection
cqlsh --ssl hostname
# With explicit CA certificate
cqlsh --ssl --ssl-certfile=/path/to/ca-cert.pem hostname
# With client certificate (mutual TLS)
cqlsh --ssl \
--ssl-certfile=/path/to/ca-cert.pem \
--ssl-keyfile=/path/to/client-key.pem \
--ssl-usercert=/path/to/client-cert.pem \
hostname

Create ~/.cassandra/cqlshrc:

[connection]
hostname = cassandra-node-1.example.com
port = 9042
[ssl]
# Enable SSL
certfile = /path/to/ca-cert.pem
# Validate server certificate
validate = true
# Client certificate (for mutual TLS)
userkey = /path/to/client-key.pem
usercert = /path/to/client-cert.pem
# TLS version
version = TLSv1_2
[authentication]
username = app_user
password = app_password
[connection]
hostname = cassandra-node-1.example.com
port = 9042
[ssl]
certfile = /path/to/ca-cert.pem
validate = true
Terminal window
# Set SSL certificate path
export SSL_CERTFILE=/path/to/ca-cert.pem
# Use with cqlsh
cqlsh --ssl hostname

import com.datastax.oss.driver.api.core.CqlSession;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.security.KeyStore;
public class CassandraClient {
public static CqlSession createSecureSession() throws Exception {
// Load truststore
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(
new FileInputStream("/path/to/truststore.jks"),
"truststore_password".toCharArray()
);
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return CqlSession.builder()
.addContactPoint(new InetSocketAddress("cassandra-node-1.example.com", 9042))
.withLocalDatacenter("dc1")
.withSslContext(sslContext)
.withAuthCredentials("username", "password")
.build();
}
}
public static CqlSession createMtlsSession() throws Exception {
// Load keystore (client certificate)
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(
new FileInputStream("/path/to/client-keystore.p12"),
"keystore_password".toCharArray()
);
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "keystore_password".toCharArray());
// Load truststore
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(
new FileInputStream("/path/to/truststore.jks"),
"truststore_password".toCharArray()
);
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return CqlSession.builder()
.addContactPoint(new InetSocketAddress("cassandra-node-1.example.com", 9042))
.withLocalDatacenter("dc1")
.withSslContext(sslContext)
.build();
}

File-Based Configuration (application.conf)

Section titled “File-Based Configuration (application.conf)”
datastax-java-driver {
basic {
contact-points = ["cassandra-node-1.example.com:9042"]
load-balancing-policy.local-datacenter = dc1
}
advanced.ssl-engine-factory {
class = DefaultSslEngineFactory
# Truststore for server certificate validation
truststore-path = /path/to/truststore.jks
truststore-password = truststore_password
# Keystore for client certificate (mutual TLS)
keystore-path = /path/to/client-keystore.p12
keystore-password = keystore_password
# Hostname verification
hostname-validation = true
# Cipher suites
cipher-suites = [
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
]
}
advanced.auth-provider {
class = PlainTextAuthProvider
username = app_user
password = app_password
}
}
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.SSLOptions;
import com.datastax.driver.core.RemoteEndpointAwareJdkSSLOptions;
Cluster cluster = Cluster.builder()
.addContactPoint("cassandra-node-1.example.com")
.withSSL(RemoteEndpointAwareJdkSSLOptions.builder()
.withSSLContext(sslContext)
.build())
.withCredentials("username", "password")
.build();

from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
from ssl import SSLContext, PROTOCOL_TLS_CLIENT, CERT_REQUIRED
# Create SSL context
ssl_context = SSLContext(PROTOCOL_TLS_CLIENT)
ssl_context.verify_mode = CERT_REQUIRED
ssl_context.load_verify_locations('/path/to/ca-cert.pem')
# Create auth provider
auth_provider = PlainTextAuthProvider(
username='app_user',
password='app_password'
)
# Connect with SSL
cluster = Cluster(
['cassandra-node-1.example.com'],
port=9042,
ssl_context=ssl_context,
auth_provider=auth_provider
)
session = cluster.connect()
from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
from ssl import SSLContext, PROTOCOL_TLS_CLIENT, CERT_REQUIRED
# Create SSL context with client certificate
ssl_context = SSLContext(PROTOCOL_TLS_CLIENT)
ssl_context.verify_mode = CERT_REQUIRED
ssl_context.load_verify_locations('/path/to/ca-cert.pem')
ssl_context.load_cert_chain(
certfile='/path/to/client-cert.pem',
keyfile='/path/to/client-key.pem',
password='key_password' # If key is encrypted
)
cluster = Cluster(
['cassandra-node-1.example.com'],
ssl_context=ssl_context,
auth_provider=PlainTextAuthProvider('user', 'pass')
)
from ssl import SSLContext, PROTOCOL_TLS_CLIENT, CERT_REQUIRED
import ssl
ssl_context = SSLContext(PROTOCOL_TLS_CLIENT)
ssl_context.verify_mode = CERT_REQUIRED
ssl_context.check_hostname = True # Enable hostname verification
ssl_context.load_verify_locations('/path/to/ca-cert.pem')

const cassandra = require('cassandra-driver');
const fs = require('fs');
const client = new cassandra.Client({
contactPoints: ['cassandra-node-1.example.com'],
localDataCenter: 'dc1',
sslOptions: {
ca: [fs.readFileSync('/path/to/ca-cert.pem')],
rejectUnauthorized: true
},
credentials: {
username: 'app_user',
password: 'app_password'
}
});
client.connect()
.then(() => console.log('Connected'))
.catch(err => console.error('Connection error', err));
const cassandra = require('cassandra-driver');
const fs = require('fs');
const client = new cassandra.Client({
contactPoints: ['cassandra-node-1.example.com'],
localDataCenter: 'dc1',
sslOptions: {
ca: [fs.readFileSync('/path/to/ca-cert.pem')],
cert: fs.readFileSync('/path/to/client-cert.pem'),
key: fs.readFileSync('/path/to/client-key.pem'),
rejectUnauthorized: true
}
});

package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"github.com/gocql/gocql"
)
func main() {
// Load CA certificate
caCert, err := ioutil.ReadFile("/path/to/ca-cert.pem")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Configure TLS
tlsConfig := &tls.Config{
RootCAs: caCertPool,
MinVersion: tls.VersionTLS12,
}
// Create cluster config
cluster := gocql.NewCluster("cassandra-node-1.example.com")
cluster.SslOpts = &gocql.SslOptions{
Config: tlsConfig,
EnableHostVerification: true,
}
cluster.Authenticator = gocql.PasswordAuthenticator{
Username: "app_user",
Password: "app_password",
}
session, err := cluster.CreateSession()
if err != nil {
log.Fatal(err)
}
defer session.Close()
}
// Load client certificate and key
cert, err := tls.LoadX509KeyPair(
"/path/to/client-cert.pem",
"/path/to/client-key.pem",
)
if err != nil {
log.Fatal(err)
}
tlsConfig := &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
}

Terminal window
# Test TLS connection to Cassandra
openssl s_client -connect cassandra-node-1.example.com:9042 \
-CAfile /path/to/ca-cert.pem \
-servername cassandra-node-1.example.com
# Show certificate details
openssl s_client -connect cassandra-node-1.example.com:9042 \
-CAfile /path/to/ca-cert.pem \
2>/dev/null | openssl x509 -noout -text
Terminal window
# Verbose connection test
cqlsh --ssl --debug cassandra-node-1.example.com