mirror of https://github.com/apache/cassandra
Write user docs for CEP-24 - Password validation / generation
patch by Stefan Miklosovic for CASSANDRA-20619
This commit is contained in:
parent
f6eb4a6b31
commit
0669db7a04
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<String, Object> getPasswordValidatorConfig()` - gets password validator configuration
|
||||
* `void reconfigurePasswordValidator(Map<String, Object> 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.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue