CASSANDRA-21146 Guardrail for client driver versions#4699
CASSANDRA-21146 Guardrail for client driver versions#4699smiklosovic wants to merge 2 commits intoapache:trunkfrom
Conversation
717609b to
4e3a9d4
Compare
There was a problem hiding this comment.
Pull request overview
Introduces a new guardrail to warn or reject native protocol connections based on configured minimum client driver versions.
Changes:
- Adds
ClientDriverVersionGuardrailand wires it into STARTUP processing to enforce driver version constraints. - Exposes warned/disallowed driver-version maps via Guardrails MBean + configuration plumbing.
- Adds unit and integration tests for version parsing/comparison and guardrail behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java |
Implements the guardrail logic for comparing driver versions against configured minimums. |
src/java/org/apache/cassandra/db/guardrails/Guardrails.java |
Registers the new guardrail and adds MBean getter/setter JSON serialization for the new config. |
src/java/org/apache/cassandra/transport/messages/StartupMessage.java |
Invokes the guardrail during client STARTUP when driver name/version are provided. |
src/java/org/apache/cassandra/db/guardrails/GuardrailsMBean.java |
Adds MBean methods for getting/setting minimum client driver versions (warn/fail). |
src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java |
Extends guardrails config interface with minimum driver version maps. |
src/java/org/apache/cassandra/config/GuardrailsOptions.java |
Implements the new config getters and adds setters with logging for runtime updates. |
src/java/org/apache/cassandra/config/Config.java |
Adds YAML-backed config fields for warned/disallowed minimum driver versions. |
src/java/org/apache/cassandra/tools/nodetool/GuardrailsConfigCommand.java |
Excludes the new map-based configs from nodetool guardrails config handling. |
conf/cassandra.yaml |
Documents new YAML options for minimum client driver versions (warn/disallow). |
conf/cassandra_latest.yaml |
Mirrors the new YAML documentation in the “latest” config template. |
test/unit/org/apache/cassandra/db/guardrails/GuardrailClientDriverVersionTest.java |
Adds unit/integration tests for version comparisons and guardrail outcomes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
eb26940 to
59d739e
Compare
59d739e to
254e4ec
Compare
|
|
||
| # Minimum client driver versions. Connections from drivers whose version is below | ||
| # the configured minimum will be warned or rejected. Connections that do not report | ||
| # a driver name or version are considered valid. The map key is the driver name |
There was a problem hiding this comment.
It might be really useful to have a way to warn or disallow on unknown Driver implementations, or ones that don't have anything set. Could we consider adding options for that (maybe using special keys like 'unknown' and 'unset'.
This doesn't necessarily need to be done in this change as could be done additively but would be nice if an operator wants to enforce specific driver implementations
There was a problem hiding this comment.
I am just thinking where this is going to be actually exercised? It is not like you are running drivers without any driver id every other day that this would be so common it would need to have a lot of attention. For 99.9% of cases your connections will always have identifiers in some fashion. At least everything under Apache Cassandra umbrella should have (not sure what the situation is with c++ or nodejs drivers etc but they should have the very same concept of driver ids).
There was a problem hiding this comment.
It is not like you are running drivers without any driver id every other day that this would be so common it would need to have a lot of attention
This does happen occasionally for us, we help partner teams by supporting specific drivers, but we don't currently mandate what gets used.
-
Clients not sending driver versions: We've had some occasions where a team is using a very old driver that doesn't send driver name/version and it would be nice to have some enforcement/visibility around that.
-
Clients using client libraries we don't know about: Using a language like rust that has a community maintained driver that does send this information (https://github.com/scylladb/scylla-rust-driver).
In either case having some visibility via the warning guardrail could be useful.
There was a problem hiding this comment.
"unknown"/"unset" implementation looks great to me, thank you!
2026/04/12 15:21:31 Host: 127.0.0.1
2026/04/12 15:21:31 Username: cassandra
2026/04/12 15:21:31 Driver name: Andys Custom Driver
2026/04/12 15:21:31 Driver version: 3.6.0
2026/04/12 15:21:31 gocql: received 1 warning(s) from server for frame op=ERROR stream=64
2026/04/12 15:21:31 gocql: warning - Guardrail minimum_client_driver_versions violated: Detected unknown driver id: Andys Custom Driver.
2026/04/12 15:21:31 Failed to connect to Cassandra: gocql: unable to create session: unable to discover protocol version: Guardrail minimum_client_driver_versions violated: Detected unknown driver id: Andys Custom Driver.
2026/04/12 15:59:04 Host: 127.0.0.1
2026/04/12 15:59:04 Username: cassandra
2026/04/12 15:59:04 gocql: received 1 warning(s) from server for frame op=ERROR stream=64
2026/04/12 15:59:04 gocql: warning - Guardrail minimum_client_driver_versions violated: Connections with unset driver id's are forbidden.
2026/04/12 15:59:04 Failed to connect to Cassandra: gocql: unable to create session: unable to discover protocol version: Guardrail minimum_client_driver_versions violated: Connections with unset driver id's are forbidden.
exit status 1
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
| String sanitizedDriverId = driverName == null ? null : driverName.trim(); | ||
| if (sanitizedDriverId == null || sanitizedDriverId.isBlank()) | ||
| { | ||
| logger.debug("minimum_client_driver_versions guardrail identified empty driver " + | ||
| "id to check the minimum version of, such connections will be allowed but " + | ||
| "an operator should check what kind of clients are connecting to the cluster."); | ||
| return; | ||
| } | ||
|
|
||
| String sanitizedDriverVersion = GuardrailsOptions.sanitizeVersion(driverVersion); | ||
| if (sanitizedDriverVersion == null) | ||
| { | ||
| logger.debug("minimum_client_driver_versions guardrail identified empty driver " + | ||
| "version to check the minimum version of, such connections will be allowed but " + | ||
| "an operator should check what kind of clients are connecting to the cluster."); | ||
| return; | ||
| } | ||
|
|
||
| if (!GuardrailsOptions.isValidVersion(sanitizedDriverVersion)) | ||
| { | ||
| logger.debug("minimum_client_driver_versions guardrail identified driver " + | ||
| "version which is not compliant semver version, such connections will be allowed but " + | ||
| "an operator should check what kind of clients are connecting to the cluster."); | ||
| return; | ||
| } |
There was a problem hiding this comment.
as alluded here i think it would be nice to guard on these scenarios too, but i don't think it needs to necessarily be handled in this PR
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
| if (minimumVersionWarn != null && isBelowMinimum(sanitizedDriverVersion, minimumVersionWarn)) | ||
| { | ||
| warn(String.format("Client driver %s is below recommended minimum version %s", | ||
| sanitizedDriverId, minimumVersionWarn)); |
There was a problem hiding this comment.
Another thing is that I suspect most drivers won't support logging warnings for something like a READY response, but this does work. I added it for gocql and I see the warnings being emitted for each connection:
2026/04/11 15:56:34 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 15:56:34 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver github.com/apache/cassandra-gocql-driver is below recommended minimum version 2.0.0
2026/04/11 15:56:34 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 15:56:34 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver github.com/apache/cassandra-gocql-driver is below recommended minimum version 2.0.0
2026/04/11 15:56:34 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 15:56:34 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver github.com/apache/cassandra-gocql-driver is below recommended minimum version 2.0.0
2026/04/11 15:56:34 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 15:56:34 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver github.com/apache/cassandra-gocql-driver is below recommended minimum version 2.0.0
src/java/org/apache/cassandra/db/guardrails/ClientDriverVersionGuardrail.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
This works great, thank you @smiklosovic ! I had a couple suggestions (e.g. including the client version in the messages), but I am +1 on the changes overall.
I tested this by updating gocql to log all warnings received on frames, and also to allow passing in arbitrary driver name and versions. Tried several permutations with multiple driver names/version combinations and everything works as expected:
go run main.go -n "DataStax Java Driver" -v 3.11.0
2026/04/11 16:46:16 Host: 127.0.0.1
2026/04/11 16:46:16 Username: cassandra
2026/04/11 16:46:16 Driver name: DataStax Java Driver
2026/04/11 16:46:16 Driver version: 3.11.0
2026/04/11 16:46:16 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 16:46:16 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver DataStax Java Driver is below recommended minimum version 4.0.0
2026/04/11 16:46:16 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 16:46:16 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver DataStax Java Driver is below recommended minimum version 4.0.0
2026/04/11 16:46:16 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 16:46:16 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver DataStax Java Driver is below recommended minimum version 4.0.0
2026/04/11 16:46:16 gocql: received 1 warning(s) from server for frame op=AUTHENTICATE stream=64
2026/04/11 16:46:16 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver DataStax Java Driver is below recommended minimum version 4.0.0
Connection successful!
Cluster Name: Test Cluster
Data Center: datacenter1
Rack: rack1
Host ID: 6d194555-f6eb-41d0-c000-000000000001
Peers in the cluster:
Active client connections:
Client: 127.0.0.1:51374
Driver: DataStax Java Driver/3.11.0
Protocol Version: 4
Username: cassandra
Client: 127.0.0.1:51375
Driver: DataStax Java Driver/3.11.0
Protocol Version: 4
Username: cassandra
Client: 127.0.0.1:51376
Driver: DataStax Java Driver/3.11.0
Protocol Version: 4
Username: cassandra
go run main.go -n "DataStax Java Driver" -v 3.6.0
2026/04/11 16:46:21 Host: 127.0.0.1
2026/04/11 16:46:21 Username: cassandra
2026/04/11 16:46:21 Driver name: DataStax Java Driver
2026/04/11 16:46:21 Driver version: 3.6.0
2026/04/11 16:46:21 gocql: received 1 warning(s) from server for frame op=ERROR stream=64
2026/04/11 16:46:21 gocql: warning - Guardrail minimum_client_driver_versions violated: Client driver DataStax Java Driver is below required minimum version 3.11.0, connection rejected
2026/04/11 16:46:21 Failed to connect to Cassandra: gocql: unable to create session: unable to discover protocol version: Guardrail minimum_client_driver_versions violated: Client driver DataStax Java Driver is below required minimum version 3.11.0, connection rejected6cbd771 to
0adc446
Compare
0adc446 to
54816b5
Compare
tolbertam
left a comment
There was a problem hiding this comment.
This is great, thank you! 🚀
Thanks for sending a pull request! Here are some tips if you're new here:
Commit messages should follow the following format:
The Cassandra Jira