From 0669db7a042b30276ee87046e8c748a071ee71dc Mon Sep 17 00:00:00 2001 From: Stefan Miklosovic Date: Mon, 5 May 2025 15:20:54 +0200 Subject: [PATCH] Write user docs for CEP-24 - Password validation / generation patch by Stefan Miklosovic for CASSANDRA-20619 --- doc/modules/cassandra/nav.adoc | 1 + .../pages/managing/operating/index.adoc | 1 + .../operating/password_validation.adoc | 325 ++++++++++++++++++ .../pages/managing/operating/security.adoc | 6 + 4 files changed, 333 insertions(+) create mode 100644 doc/modules/cassandra/pages/managing/operating/password_validation.adoc diff --git a/doc/modules/cassandra/nav.adoc b/doc/modules/cassandra/nav.adoc index 311bfb16c5..8c28d63155 100644 --- a/doc/modules/cassandra/nav.adoc +++ b/doc/modules/cassandra/nav.adoc @@ -106,6 +106,7 @@ **** xref:cassandra:managing/operating/topo_changes.adoc[Topology changes] **** xref:cassandra:managing/operating/transientreplication.adoc[Transient replication] **** xref:cassandra:managing/operating/virtualtables.adoc[Virtual tables] +**** xref:cassandra:managing/operating/password_validation.adoc[Password validation] *** xref:cassandra:managing/tools/index.adoc[Tools] **** xref:cassandra:managing/tools/cqlsh.adoc[cqlsh: the CQL shell] **** xref:cassandra:managing/tools/nodetool/nodetool.adoc[nodetool] diff --git a/doc/modules/cassandra/pages/managing/operating/index.adoc b/doc/modules/cassandra/pages/managing/operating/index.adoc index 492af4dfec..2fb9859431 100644 --- a/doc/modules/cassandra/pages/managing/operating/index.adoc +++ b/doc/modules/cassandra/pages/managing/operating/index.adoc @@ -19,3 +19,4 @@ * xref:cassandra:managing/operating/topo_changes.adoc[Topology changes] * xref:cassandra:managing/operating/transientreplication.adoc[Transient replication] * xref:cassandra:managing/operating/virtualtables.adoc[Virtual tables] +* xref:cassandra:managing/operating/password_validation.adoc[Password validation] diff --git a/doc/modules/cassandra/pages/managing/operating/password_validation.adoc b/doc/modules/cassandra/pages/managing/operating/password_validation.adoc new file mode 100644 index 0000000000..f6ad0fa812 --- /dev/null +++ b/doc/modules/cassandra/pages/managing/operating/password_validation.adoc @@ -0,0 +1,325 @@ += Password validation and generation +:navtitle: Password validation and generation +:description: Password validation and generation - How it works, how to configure it, and more. +:keywords: CEP-24, Password, Generation, Validation, Security + +Here’s the problem: while users have always had the ability to create whatever password they wanted in Cassandra - +from straightforward to incredibly complex and everything in between–this ultimately created a noticeable security vulnerability. + +While organizations might have internal processes for generating secure passwords that adhere to their own security policies, +Cassandra itself did not have the means to enforce these standards. To make the security vulnerability worse, +if a password initially met internal security guidelines, users could later downgrade their password to +a less secure option simply by using `ALTER ROLE` statements. + +When internal password requirements are enforced for an individual, users face the additional +burden of creating compliant passwords. This inevitably involved lots of trial-and-error in attempting +to create a compliant password that satisfied complex security roles. + +But what if there was a way to have Cassandra automatically create passwords that meet all +bespoke security requirements–but without requiring manual effort from users or system operators? + +That’s why we developed https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=228494146[CEP-24: Password validation/generation]. +We recognized that the complexity of secure password management could be significantly reduced (or eliminated entirely) +with the right approach –and improving both security and user experience at the same time. + +== The Goals of CEP-24 + +A Cassandra Enhancement Proposal (or CEP) is a structured process for proposing, creating, and ultimately implementing +new features for the Cassandra project. All CEPs are thoroughly vetted among the Cassandra community before +they are officially integrated into the project. + +These were the key goals we established for CEP-24: + +* Introduce a way to enforce password strength upon role creation or role alteration. +* Implement a reference implementation of a password validator which adheres to a recommended password strength policy, +to be used for Cassandra users out of the box. +* Emit a warning (and proceed) or just reject `CREATE ROLE` and `ALTER ROLE` statements when the provided +password does not meet a certain security level, based on user configuration of Cassandra. +* To be able to implement a custom password validator with its own policy, whatever it might be, +and provide a modular/pluggable mechanism to do so. +* Provide a way for Cassandra to generate a password which would pass the subsequent validation for use by the user. + +The Cassandra Password Validator and Generator builds upon an established framework in Cassandra called Guardrails, +which was originally implemented under CEP-3 (more details https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-3%3A+Guardrails[here]). + +== Implementation and configuration + +The password validator implements a custom guardrail introduced as part of CEP-24. A custom guardrail can validate and +generate values of arbitrary types when properly implemented. In the CEP-24 context, +the password guardrail provides `CassandraPasswordValidator` by extending `ValueValidator`, +while passwords are generated by `CassandraPasswordGenerator` by extending `ValueGenerator`. +Both components work with passwords as `String` type values. + +Password validation and generation are configured in `cassandra.yaml` file under the `password_validator` section. +Let’s explore the key configuration properties available. + +First, the `class_name` and `generator_class_name` parameters +specify which validator and generator classes will be used to validate and generate passwords respectively. + +Cassandra ships `CassandraPasswordValidator` and `CassandraPasswordGenerator` out of the box. +However, if a particular enterprise decides that they need something very custom, they are free to implement their own validators, +put it on Cassandra’s class path and reference it in the configuration behind `class_name` parameter. Same for the validator. + +CEP-24 provides implementations of the validator and generator that the Cassandra team believes will satisfy +the requirements of most users. These default implementations address common password security needs. +However, the framework is designed with flexibility in mind, allowing organizations to implement custom validation +and generation rules that align with their specific security policies and business requirements. + +---- +password_validator: +# Implementation class of a validator. When not in form of FQCN, the +# package name org.apache.cassandra.db.guardrails.validators is prepended. +# By default, there is no validator. + class_name: CassandraPasswordValidator +# Implementation class of related generator which generates values +# which are valid when tested against this validator. +# When not in form of FQCN, the package name +# org.apache.cassandra.db.guardrails.generators is prepended. +# By default, there is no generator. + generator_class_name: CassandraPasswordGenerator +---- + +Password quality might be looked at as the number of _characteristics_ a password satisfies. +There are two levels for any password to be evaluated – warning level and failure level. +Warning and failure levels nicely fit into how Guardrails act. Every guardrail has warning and failure thresholds. +Based on what value a specific guardrail evaluates, it will either emit a warning to a user that its usage +is discouraged (but ultimately allowed), or it will fail to be set altogether. + +This same principle applies to password evaluation – each password is assessed against both warning and failure thresholds. +These thresholds are determined by counting the characteristics present in the password. + +The system evaluates five key characteristics: + +* the password’s overall length +* the number of uppercase characters +* the number of lowercase characters +* the number of special characters +* and the number of digits. + +A comprehensive password security policy can be enforced by configuring minimum requirements for each of these characteristics. + +---- + # There are four characteristics (excluding password's length): + # upper-case, lower-case, special character and digit. + # If this value is set e.g. to 3, a password has to + # consist of 3 out of 4 characteristics. + # For example, it has to contain at least 2 upper-case characters, + # 2 lower-case, and 2 digits to pass, + # but it does not have to contain any special characters. + # If the number of characteristics found in the password is + # less than or equal to this number, it will emit a warning. + characteristic_warn: 3 + # If the number of characteristics found in the password is + #less than or equal to this number, it will emit a failure. + characteristic_fail: 2 +---- + +Next, there are configuration parameters for each characteristic which count towards warning or failure: +---- + +# If the password is shorter than this value, +# the validator will emit a warning. +length_warn: 12 +# If a password is shorter than this value, +# the validator will emit a failure. +length_fail: 8 +# If a password does not contain at least n +# upper-case characters, the validator will emit a warning. +upper_case_warn: 2 +# If a password does not contain at least +# n upper-case characters, the validator will emit a failure. +upper_case_fail: 1 +# If a password does not contain at least +# n lower-case characters, the validator will emit a warning. +lower_case_warn: 2 +# If a password does not contain at least +# n lower-case characters, the validator will emit a failure. +lower_case_fail: 1 +# If a password does not contain at least +# n digits, the validator will emit a warning. +digit_warn: 2 +# If a password does not contain at least +# n digits, the validator will emit a failure. +digit_fail: 1 +# If a password does not contain at least +# n special characters, the validator will emit a warning. +special_warn: 2 +# If a password does not contain at least +# n special characters, the validator will emit a failure. +special_fail: 1 +---- + +It is also possible to say that illegal sequences of certain length found in a password will be forbidden: + +---- +# If a password contains illegal sequences that are at least this long, it is invalid. +# Illegal sequences might be either alphabetical (form 'abcde'), +# numerical (form '34567'), or US qwerty (form 'asdfg') as well +# as sequences from supported character sets. +# The minimum value for this property is 3, +# by default it is set to 5. +illegal_sequence_length: 5 +---- + +Lastly, it is also possible to configure a dictionary of passwords to check against. +That way, we will be checking against password dictionary attacks. +It is up to the operator of a cluster to configure the password dictionary: + +---- +# Dictionary to check the passwords against. Defaults to no dictionary. +# Whole dictionary is cached into memory. Use with caution with relatively big dictionaries. +# Entries in a dictionary, one per line, have to be sorted per String's compareTo contract. +dictionary: /path/to/dictionary/file +---- + +Now that we have gone over all the configuration parameters, let’s take a look at an example of how password +validation and generation look in practice. + +=== Validation and generation of a password + +Consider a scenario where a Cassandra super-user (such as the default ‘cassandra’ role) attempts +to create a new role named ‘alice’. + +---- +cassandra@cqlsh> CREATE ROLE alice WITH PASSWORD = 'cassandraisadatabase' AND LOGIN = true; +InvalidRequest: Error from server: code=2200 [Invalid query] +message="Password was not set as it violated configured password +strength policy. To fix this error, the following has to be resolved: +Password contains the dictionary word 'cassandraisadatabase'. You may also use +'GENERATED PASSWORD' upon role creation or alteration." +---- + +The password is in the dictionary. When an operator sees this, +they will try to fix it by creating some random password not in dictionary: + +---- +cassandra@cqlsh> CREATE ROLE alice WITH PASSWORD = 'T8aum3?' AND LOGIN = true; +InvalidRequest: Error from server: code=2200 [Invalid query] +message="Password was not set as it violated configured password strength +policy. To fix this error, the following has to be resolved: Password +must be 8 or more characters in length. You may also use +'GENERATED PASSWORD' upon role creation or alteration." +---- + +Password is not in the dictionary, but it is not long enough. In the following example, +the password is finally set, but it is not considered to be secure enough. +It satisfies the minimum requirements but our validator identified that not all characteristics were met. + +---- +cassandra@cqlsh> CREATE ROLE alice WITH PASSWORD = 'mYAtt3mp' AND LOGIN = true; + +Warnings: + +Guardrail password violated: Password was set, however it might not be +strong enough according to the configured password strength policy. +To fix this warning, the following has to be resolved: Password must be 12 or more +characters in length. Passwords must contain 2 or more digit characters. Password +must contain 2 or more special characters. Password matches 2 of 4 character rules, +but 4 are required. You may also use 'GENERATED PASSWORD' upon role creation or alteration. +---- + +When an operator saw this, they noticed the note about the `GENERATED PASSWORD` clause which will +generate a password automatically without an operator needing to invent it on their own. +This is a lot of times, as shown, a cumbersome process better to be left on a machine. + +---- +cassandra@cqlsh> ALTER ROLE alice WITH GENERATED PASSWORD; + +generated_password +------------------ + R7tb33?.mcAX +---- + +The generated password shown above will satisfy all the rules we have configured in `cassandra.yaml` automatically. +Every generated password will satisfy all the rules. This is clearly an advantage over manual password generation. + +When the CQL statement is executed, it will be visible in the CQLSH history (`HISTORY` command or in `cqlsh_history` file) +but the password will not be logged, hence it cannot leak. It will also not appear in any auditing logs. +Previously, Cassandra had to obfuscate such statements. This is not necessary anymore. + +We can create a role with generated password like this: + +---- +cassandra@cqlsh> CREATE ROLE alice WITH GENERATED PASSWORD AND LOGIN = true; +---- + +or by `CREATE USER`: + +---- +cassandra@cqlsh> CREATE USER alice WITH GENERATED PASSWORD; +---- + +When a password is generated for `alice` she can log in: + +---- +$ cqlsh -u alice -p R7tb33?.mcAX +... +alice@cqlsh> +---- + +NOTE: It is recommended to save password to ~/.cassandra/credentials, for example: + +---- +[PlainTextAuthProvider] +username = cassandra +password = R7tb33?.mcAX +---- + +and by setting auth_provider in `~/.cassandra/cqlshrc` + +---- +[auth_provider] +module = cassandra.auth +classname = PlainTextAuthProvider +---- + +It is also possible to configure password validators in such a way that a user does not see why a password failed. +This is driven by configuration property for `password_validator` called `detailed_messages`. When set to `false`, +the violations will be very brief: + +---- +alice@cqlsh> ALTER ROLE alice WITH PASSWORD = 'myattempt'; + +InvalidRequest: Error from server: code=2200 [Invalid query] +message="Password was not set as it violated configured password strength policy. +You may also use 'GENERATED PASSWORD' upon role creation or alteration." +---- + +Several potential enhancements to password generation and validation could be implemented in future releases. +One promising extension would be validating new passwords against previous values. +This would prevent users from reusing passwords until after they’ve created a specified number of different passwords. +A related enhancement could include restricting how frequently users can change their passwords, +preventing rapid cycling through passwords to circumvent history-based restrictions. + +These features, while valuable for comprehensive password security, were considered beyond the scope of the initial +implementation and may be addressed in future updates. + +=== Runtime configuration + +Since this solution is based on guardrails which are configurable via JMX in runtime, same hold for +password validator, also configured via `GuardrailsMBean` as any other guardrails. There are two methods exposed: + +* `Map getPasswordValidatorConfig()` - gets password validator configuration +* `void reconfigurePasswordValidator(Map config)` - reconfigures the password validator by reading +and parsing the configuration from the provided map. Reconfiguration of password validator in runtime is considered +to be very sensitive operation. If an operator evaluates the reconfiguration in runtime is not allowed, they +might set `password_validator_reconfiguration_enabled` to `false` in `cassandra.yaml` to disable it. + +=== Diagnostic events + +If diagnostic event's framework is enabled and consumers are subscribed to them, diagnostic events about +warning and failures to generate a password will be published. + +=== Final thoughts and next steps + +The Cassandra Password Validator and Generator implemented under CEP-24 +represents a significant improvement in Cassandra’s security posture. + +By providing robust, configurable password policies with built-in enforcement mechanisms and +convenient password generation capabilities, organizations can now ensure compliance with their +security standards directly at the database level. This not only strengthens overall system security +but also improves the user experience by eliminating guesswork around password requirements. + +As Cassandra continues to evolve as an enterprise-ready database solution, +these security enhancements demonstrate a commitment to meeting the demanding +security requirements of modern applications while maintaining the flexibility that makes Cassandra so powerful. \ No newline at end of file diff --git a/doc/modules/cassandra/pages/managing/operating/security.adoc b/doc/modules/cassandra/pages/managing/operating/security.adoc index cdc76a625d..ee846cb13d 100644 --- a/doc/modules/cassandra/pages/managing/operating/security.adoc +++ b/doc/modules/cassandra/pages/managing/operating/security.adoc @@ -393,6 +393,12 @@ See also: xref:cassandra:developing/cql/security.adoc#grant-permission[`GRANT PE xref:cassandra:developing/cql/security.adoc#grant-all[`GRANT ALL`] and xref:cassandra:developing/cql/security.adoc#revoke-permission[`REVOKE PERMISSION`]. +== Password validation + +If you are interested into the application of a certain security policy for password strength for +user passwords, you are welcome to read about it more in xref:cassandra:managing/operating/password_validation.adoc[here] +which implements https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=228494146[CEP-24]. + [[auth-caching]] == Caching