Databases

Secure Apache Cassandra with cnspec

Scan Apache Cassandra clusters, roles, and keyspaces against security and compliance best practices with cnspec.

Scan your Apache Cassandra clusters to find security risks before they become incidents. cnspec evaluates the cluster's authentication, authorization, client and internode encryption, and audit logging, along with its roles and permission grants, nodes, and keyspace replication.

cnspec connects over CQL and inventories the cluster through read-only queries against the system and system_auth keyspaces and the system_views.settings virtual table. It never touches your data.

If you're new to cnspec, start with the Quickstart. For an overview of every database cnspec can scan, see the database scanning overview.

Prerequisites

To scan Cassandra with cnspec, you must have:

  • cnspec installed on your workstation
  • Network access to the cluster on its CQL port (9042 by default)
  • A role with SELECT on the system, system_schema, system_auth, and system_views keyspaces

Authenticate

cnspec authenticates with a Cassandra role and password through the PasswordAuthenticator:

cnspec shell cassandra db.contoso.com --user cassandra --ask-pass

For a TLS connection, add the TLS flags:

cnspec shell cassandra db.contoso.com --user auditor --ask-pass --tls --tls-ca ca.pem

Prefer a least-privileged role for auditing. Without the system_auth and system_views grants the cluster still resolves, while the security posture and roles come back null or empty rather than failing the scan.

When the cluster runs the default AllowAllAuthenticator, no credentials are needed at all and the roles table is empty. cassandra.cluster.security.authenticationEnabled reports that, and it's the first thing worth checking.

Connection options

OptionDescription
--hostCluster hostname or IP address (also accepted as the positional argument)
--portCQL native transport port (default 9042)
--user, -uRole to authenticate as
--password, -pPassword, or --ask-pass to be prompted
--tlsConnect over TLS
--tls-caPath to a CA certificate to verify the cluster
--tls-insecureSkip TLS certificate verification (testing only)

Verify with a quick Cassandra check

cnspec shell cassandra db.contoso.com --user cassandra --ask-pass
cnspec> cassandra.cluster { name version }
cassandra.cluster: {
  name: "Test Cluster"
  version: "5.0.8"
}

If cnspec connects and shows the version, you're ready to scan.

Scan Cassandra

cnspec scan cassandra db.contoso.com --user auditor --ask-pass

When a scan completes, cnspec prints a summary of all the checks it ran, grouped by policy, along with a risk score from 0 (no risk) to 100 (highest risk). Failed checks include remediation guidance to help you fix issues. To learn more about reading scan results, read Understand cnspec Results.

Mondoo doesn't yet ship an out-of-the-box Cassandra policy. The resources are shaped around the CIS Apache Cassandra Benchmark, so the checks below map closely to its recommendations. Use them as a starting point and create your own policies to meet your requirements.

Explore and test checks interactively

cnspec shell cassandra db.contoso.com --user auditor --ask-pass

Read the cluster's security posture

cnspec> cassandra.cluster.security { authenticationEnabled authorizationEnabled clientEncryptionEnabled internodeEncryption auditLoggingEnabled }
cassandra.cluster.security: {
  authenticationEnabled: true
  authorizationEnabled: true
  clientEncryptionEnabled: false
  internodeEncryption: "none"
  auditLoggingEnabled: false
}

List roles

cnspec> cassandra.cluster.roles { name canLogin isSuperuser hasPassword memberOf }

Inspect a role's permission grants

cnspec> cassandra.cluster.roles.where(name == "auditor").first.permissions { resource permissions }

List keyspaces and their replication

cnspec> cassandra.cluster.keyspaces.where(isSystem == false) { name replicationStrategy replicationFactors durableWrites }

List nodes

cnspec> cassandra.cluster.nodes { address datacenter rack releaseVersion }

Example security checks

Ensure authentication is enabled

The default AllowAllAuthenticator accepts any client that can reach the port:

cnspec> cassandra.cluster.security.authenticationEnabled == true
[ok] value: true

Ensure authorization is enforced

Authentication without authorization identifies the caller but grants everyone the same access:

cnspec> cassandra.cluster.security.authorizationEnabled == true
[ok] value: true

Ensure client traffic is encrypted

cnspec> cassandra.cluster.security.clientEncryptionEnabled == true
[ok] value: true

Ensure internode traffic is encrypted

dc and rack encrypt only across those boundaries, leaving traffic inside one unencrypted:

cnspec> cassandra.cluster.security.internodeEncryption == "all"
[ok] value: true

Ensure audit logging is enabled

cnspec> cassandra.cluster.security.auditLoggingEnabled == true
[ok] value: true

Ensure the default cassandra superuser is not still in use

The default account is the first credential anyone tries:

cnspec> cassandra.cluster.roles.where(name == "cassandra").none(canLogin == true)
[ok] value: true

Ensure superuser is not granted broadly

cnspec> cassandra.cluster.roles.where(isSuperuser && canLogin) { name }

Ensure every login role has a password

cnspec> cassandra.cluster.roles.where(canLogin).all(hasPassword == true)
[ok] value: true

Ensure no role holds AUTHORIZE on all data

A role with AUTHORIZE can grant its own access to anyone else, which makes every other permission grant provisional:

cnspec> cassandra.cluster.roles.all(permissions.where(resource == "data").none(permissions.contains("AUTHORIZE")))
[ok] value: true

Ensure application keyspaces use NetworkTopologyStrategy

SimpleStrategy ignores data center topology, so replicas can all land in one failure domain:

cnspec> cassandra.cluster.keyspaces.where(isSystem == false).all(replicationStrategy == "NetworkTopologyStrategy")
[ok] value: true

Ensure application keyspaces keep durable writes on

Turning durable writes off skips the commit log, so an unclean shutdown loses acknowledged writes:

cnspec> cassandra.cluster.keyspaces.where(isSystem == false).all(durableWrites == true)
[ok] value: true

Review roles granted to other roles

cnspec> cassandra.cluster.roles.where(memberOf.length > 0) { name memberOf }

Learn more

CIS recommendations that cover cassandra.yaml permissions, keystore permissions, and JMX configuration aren't reachable over CQL. Scan the cluster's hosts with the os provider to cover them.

On this page