Out of the box, Apache Cassandra authenticates nobody, authorises everything and sends client and node traffic in clear text, and turning on passwords alone still leaves the internode and JMX ports open to anyone who can reach them. The project's own security documentation says a default installation presents a large attack surface: someone who can talk to the internode or JMX ports can insert users into the authentication schema, drop schema or capture write traffic. This guide explains how Cassandra's authenticator, authoriser and role manager fit together, how to treat the default cassandra superuser, how application roles, JMX and mutual TLS should be configured, what to audit, and a hardening baseline for 4.0, 4.1 and 5.0 clusters. It is for database, platform and identity teams. Settings are taken from the Apache Cassandra documentation and the 5.0 cassandra.yaml; confirm them against your release.
Key takeaways
- Security is opt in. The defaults are
AllowAllAuthenticator,AllowAllAuthorizer,internode_encryption: noneand client encryption disabled. If authentication is off, permissions are effectively off too. - Retire the default superuser. Enabling
PasswordAuthenticatorcreatescassandra/cassandra. Create a named superuser, then runALTER ROLE cassandra WITH SUPERUSER = false AND LOGIN = false. - Protect the side doors. Internode (7000) and JMX (7199) access can bypass CQL authentication. Encrypt and authenticate internode traffic, keep JMX local or authenticated, and firewall both.
- Grant narrowly.
MODIFY ON ALL KEYSPACESwas enough to become superuser on unpatched releases (CVE-2025-23015, fixed in 4.0.16, 4.1.8 and 5.0.3). Grant applications permissions on their own keyspace only. - Audit logging must be switched on.
audit_logging_optionsships withenabled: false; enable it on every node with the AUTH, DCL and DDL categories at minimum.
How identity and access work in Apache Cassandra
Cassandra's security model has four pluggable parts, all set in cassandra.yaml. The authenticator proves who a client is; the role manager stores roles and memberships (default CassandraRoleManager, in the system_auth keyspace); the authoriser checks permissions on resources; and two optional authorisers restrict where a role may connect from. A role can be a user (LOGIN = true) or a group granted to other roles.
| Setting | Default | Secure options | Notes |
|---|---|---|---|
authenticator | AllowAllAuthenticator | PasswordAuthenticator; MutualTlsAuthenticator (client certificates, with a validator such as SpiffeCertificateValidator); MutualTlsWithPasswordFallbackAuthenticator | Password hashes stored in system_auth.roles. Password authentication requires CassandraRoleManager. |
authorizer | AllowAllAuthorizer | CassandraAuthorizer | Permissions are a whitelist; once enabled, everything is denied until granted. |
network_authorizer | AllowAllNetworkAuthorizer | CassandraNetworkAuthorizer | Restricts roles to datacentres with ACCESS TO DATACENTERS. |
cidr_authorizer | AllowAllCIDRAuthorizer | CassandraCIDRAuthorizer in MONITOR then ENFORCE mode | Restricts roles by source CIDR group (ACCESS FROM CIDRS). Applies to non-superusers unless cidr_checks_for_superusers is true; not applied to JMX. |
internode_authenticator | Not set | MutualTlsInternodeAuthenticator | Makes nodes prove identity to each other with certificates. |
Permissions
Permissions apply down a hierarchy, ALL KEYSPACES to KEYSPACE to TABLE (plus functions, roles and MBeans). The permission set is CREATE, ALTER, DROP, SELECT, MODIFY, AUTHORIZE, DESCRIBE, EXECUTE, and in 5.0 with dynamic data masking UNMASK and SELECT_MASKED. MODIFY covers INSERT, UPDATE, DELETE and TRUNCATE; AUTHORIZE lets a role grant and revoke permissions, which makes it an administrative permission in practice.
Auth data availability
By default system_auth has a replication factor of 1. If the one node holding a role's row is down, that role cannot log in. The documentation recommends 3 to 5 replicas per datacentre with NetworkTopologyStrategy, set before you enable authentication. The default superuser is read at QUORUM consistency, other roles at LOCAL_ONE, which is another reason not to use cassandra day to day. Credentials, permissions and roles are cached (roles_validity defaults to 2,000 ms in 5.0), so revocations take effect after the cache period, not instantly.
Admin roles and privileged access
- Superuser roles: a role with
SUPERUSER = truebypasses permission checks. Keep two named superusers for break glass, held in a vault, and use them only for role administration. - Default role: after creating your own superuser, disable
cassandra. The development branch addsdefault_role_initializerso new clusters can start with a hashed password or a mutual TLS identity instead of the published default; until your release has it, disabling the role is the control. - Delegated administration: instead of more superusers, create an admin role with
CREATE,ALTER,DROPandAUTHORIZEon specific keyspaces, and a separate role administrator with permissions onALL ROLES. - Restrict where admins connect from: enable
CassandraCIDRAuthorizerand setcidr_checks_for_superusers: trueso superuser logins only succeed from bastion or admin networks. Run in MONITOR mode first and review the warnings before switching to ENFORCE. - JMX is privileged access:
nodetooland other JMX tools can change topology, flush, drain, snapshot and enable or disable logging. By default JMX listens on localhost only (LOCAL_JMX=yesincassandra-env.sh) and local connections are not authenticated. If you enable remote JMX, use Cassandra integrated JMX authentication so CQL roles control access, grant only the MBeans each role needs (for example read onlynodetool status), and configurejmx_encryption_optionsfor TLS. - Host access equals database access: anyone with shell access as the Cassandra user can read SSTables, keystores and the JMX password file. Treat node logins as privileged access.
Integrations, API tokens and service accounts
Most Cassandra logins are applications, Spark jobs, Kafka connectors, backup tools and monitoring agents. Each is a non-human identity and should have its own role. See the Database Credential and Access Security Guide.
| Consumer | Typical grant | Avoid |
|---|---|---|
| Application service | SELECT and MODIFY on its own keyspace | ALL KEYSPACES grants, superuser, shared roles across services |
| Read only analytics or Spark job | SELECT on named tables, SELECT_MASKED where data masking is used | UNMASK unless the job needs clear values |
| Schema migration tool | CREATE, ALTER on the application keyspace, used only in deployment | Leaving the migration role enabled between releases |
| Backup agent | Host level snapshot access plus JMX rights for snapshot MBeans | Full remote JMX readwrite with a shared password |
| Monitoring exporter | Read only MBean access through integrated JMX auth | Superuser credentials in exporter config |
- Prefer certificates for services:
MutualTlsAuthenticatormaps a client certificate identity (for example a SPIFFE ID) to a role, which removes stored passwords and works with short-lived workload certificates. See the SPIFFE and SPIRE Guide and the mTLS Guide. - Keep passwords out of drivers' config files: where passwords remain, inject them from a secrets manager and rotate with
ALTER ROLE ... WITH PASSWORD, remembering cached credentials persist until the cache period passes. - Keystore passwords: TLS keystore and truststore passwords sit in
cassandra.yamlunless you usekeystore_password_file; restrict file permissions and keep the YAML out of shared repositories. - Disable risky code paths:
user_defined_functions_enabledis false by default. CVE-2021-44521 allowed code execution when scripted UDFs were enabled with UDF threads disabled; do not enable scripted UDFs, and grant no application roleCREATEonALL FUNCTIONS.
Logging and detection
Cassandra audit logging (since 4.0) records each request with user, source, keyspace, operation and category. Enable it in audit_logging_options or per node with nodetool enableauditlog. The default BinAuditLogger writes compact binary Chronicle Queue files read with auditlogviewer; FileAuditLogger writes text to audit/audit.log through the standard logging configuration, which is easier to ship to a SIEM. Full query logging (nodetool enablefullquerylog) is a separate, heavier feature intended for replay and debugging.
| Audit category | Covers | Detect |
|---|---|---|
| AUTH | LOGIN_SUCCESS, LOGIN_ERROR, UNAUTHORIZED_ATTEMPT | Brute force, logins as cassandra, superuser logins from new sources (T1078.001) |
| DCL | CREATE, ALTER, DROP ROLE, GRANT, REVOKE | New superusers, grants on ALL KEYSPACES, permission changes outside change windows |
| DDL | Keyspace, table, function and index changes | Dropped tables, new functions, replication changes on system_auth (T1485) |
| DML and QUERY | Writes and reads | Bulk reads by a role far above baseline (T1213.006); TRUNCATE by application roles |
| ERROR and OTHER | Failed requests, USE and other statements | Enumeration and injection attempts |
Exclude only high volume keyspaces you have assessed; logging every QUERY on a busy cluster costs I/O, so many teams log AUTH, DCL, DDL and ERROR everywhere and DML for sensitive keyspaces. Also alert on JMX connections from non-admin hosts, port scans against 7000, 7199 and 9042 (T1046), and CIDR authoriser MONITOR warnings. See the Detection Engineering for Non-Human Identities Guide.
Metrics
- Nodes with auth enforced: percentage of nodes running a non AllowAll authenticator and authoriser (target 100%).
- Encrypted links: percentage of nodes with
internode_encryption: alland mandatory client TLS. - Superuser count: number of roles with SUPERUSER, and superuser logins per month.
- Broad grants: roles with any permission on
ALL KEYSPACES(target: admin roles only). - Audit coverage: nodes with audit logging enabled and forwarding, tested quarterly.
- Patch lag: days between a Cassandra security release and deployment across the cluster.
Hardening baseline
- Fix the network first: bind
listen_addressandrpc_addressto private interfaces; allow 9042 (native protocol) only from application subnets, 7000 (and 7001 if used) only between nodes, and 7199 only from admin hosts. Never expose any of them to the internet. - Encrypt internode traffic: set
server_encryption_options.internode_encryption: allwithrequire_client_auth: true, and addMutualTlsInternodeAuthenticatorwhere available. Roll out node by node; the optional setting lets nodes accept both during migration. - Encrypt client traffic: set
client_encryption_options.enabled: true, useoptional: trueonly during migration, then false. Certificates hot reload every 10 minutes or onnodetool reloadssl. - Prepare auth replication:
ALTER KEYSPACE system_authtoNetworkTopologyStrategywith 3 to 5 replicas per datacentre and run a repair. - Enable authentication on one isolated node: pre-configure clients with credentials, set
authenticator: PasswordAuthenticator(or mutual TLS), restart, create your superuser, disablecassandra, then repeat on each node. - Enable authorisation: set
authorizer: CassandraAuthorizeron a node not serving clients, grant permissions for every application role, then roll across the cluster. Rollback is reverting the setting and restarting the node. - Lock down JMX: keep
LOCAL_JMX=yeswhere possible; if remote, use integrated JMX auth, per role MBean grants and JMX TLS. Set the JMX password file to mode 400 if using standard JMX auth. - Turn on audit logging: enable
audit_logging_optionswith retention settings (max_log_size,archive_command) that match your log policy, and forward to the SIEM. - Protect data at rest:
transparent_data_encryption_optionscovers only commit logs and hints, not SSTables, so use volume or disk encryption for data directories, snapshots and backups. See the Database and Storage Encryption Guide. - Patch within the supported series: the project supports 5.0, 4.1 and 4.0 (latest releases 5.0.9, 4.1.12 and 4.0.21 at the time of writing). Clusters on 3.x are out of maintenance and need an upgrade plan.
Testing and rollback
Rehearse the whole sequence on a staging cluster that mirrors production topology, with real driver versions, because older drivers and tools sometimes fail on mandatory TLS or missing credentials. During production rollout, change one node at a time and watch client error rates and the AUTH audit category before moving on. Keep the previous cassandra.yaml under version control: reverting a node means restoring the file and restarting it, and a node that fails to start after an authenticator change (for example a mutual TLS authenticator with no valid truststore) is the signal to stop the rollout, not to disable security cluster wide.
Small and large clusters
A small single datacentre cluster can run password authentication with a handful of keyspace scoped roles, TLS everywhere and AUTH plus DCL auditing. Large, multi-region or regulated estates should add mutual TLS for services and nodes, network and CIDR authorisers to stop roles connecting from the wrong region or subnet, delegated admin roles instead of shared superusers, and automated checks of grants after every deployment.
Common misconfigurations
- AllowAll left in place: clusters reachable on 9042 with no authentication, often after a lift and shift from a lab.
- Default superuser still active:
cassandra/cassandraworking years after go-live, because nobody ran the disable step (T1078.001). - Passwords on, internode open: CQL authentication enabled but internode traffic unencrypted and unauthenticated, which the project documents as a way to write into
system_author truncate schema. - Remote JMX with shared credentials: one readwrite JMX user shared by operators, monitoring and backups, so actions cannot be attributed.
- Broad application grants:
GRANT ALL ON ALL KEYSPACESto an application role; on releases before the CVE-2025-23015 fixes evenMODIFYat that level allowed escalation to superuser. - system_auth at replication factor 1: a single node failure locks out roles and pushes teams to disable authentication under pressure.
Framework mapping
| Control area | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | CIS Controls v8.1 |
|---|---|---|---|
| Authentication and default account removal | IA-5, AC-2 | PR.AA-01 | 4.7, 5.2 |
| Role based permissions and least privilege | AC-3, AC-6 | PR.AA-05 | 3.3, 6.8 |
| Internode and client TLS, mutual TLS | SC-8, SC-23 | PR.DS-02 | 3.10 |
| Audit logging | AU-2, AU-12 | PR.PS-04 | 8.2, 8.5 |
| Secure configuration (JMX, UDFs, ports) | CM-6, CM-7 | PR.PS-01 | 4.1, 4.8 |
| Patching | SI-2 | PR.PS-02 | 7.4 |
Practitioner checklist
- Every node runs a real authenticator and
CassandraAuthorizer; none use AllowAll. - The
cassandrarole has LOGIN and SUPERUSER set to false, and named superusers are vaulted. system_authusesNetworkTopologyStrategywith 3 to 5 replicas per datacentre.- Internode encryption is
allwith client certificate checks; client TLS is mandatory. - JMX is local only, or remote with integrated auth, per role MBean grants and TLS.
- Each application has its own role scoped to its keyspace; no application role has permissions on
ALL KEYSPACES. - Audit logging captures at least AUTH, DCL, DDL and ERROR on every node and reaches the SIEM.
- Data directories, snapshots and backups are encrypted at the volume level.
- Clusters run a supported series with the CVE-2025-23015 fix (4.0.16, 4.1.8, 5.0.3 or later).
Standards and references
- Apache Cassandra: Security
- Apache Cassandra: Audit logging
- Apache Cassandra: CQL security (roles and permissions)
- Apache Cassandra: cassandra.yaml (5.0 branch)
- Apache Cassandra: Downloads and supported releases
- Apache Cassandra: CVE-2025-23015 security announcement
- NIST: SP 800-53 Rev. 5
- MITRE ATT&CK: Default Accounts
Related NHI Mgmt Group resources: Database Security Guide · Database Credential and Access Security Guide · mTLS Guide · Service Account Security Guide