Skip to content

Commit 035a220

Browse files
committed
Implementation of CEP-55 - Generation of role names
patch by Stefan Miklosovic; reviewed by Bernardo Botella for CASSANDRA-20897
1 parent ed12f31 commit 035a220

File tree

55 files changed

+2098
-405
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2098
-405
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
5.1
2+
* Implementation of CEP-55 - Generation of role names (CASSANDRA-20897)
23
* Add cqlsh autocompletion for the identity mapping feature (CASSANDRA-20021)
34
* Add DDL Guardrail enabling administrators to disallow creation/modification of keyspaces with durable_writes = false (CASSANDRA-20913)
45
* Optimize Counter, Meter and Histogram metrics using thread local counters (CASSANDRA-20250)

NEWS.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,13 @@ New features
102102
- Authentication mode is exposed in system_views.clients table, nodetool clientstats and ClientMetrics
103103
to help operators identify which authentication modes are being used. nodetool clientstats introduces --verbose flag
104104
behind which this information is visible.
105-
- CEP-24 - Password validation / generation. When built-in 'password_validator' guardrail is enabled, it will
105+
- CEP-24 - Password validation / generation. When built-in 'password_policy' guardrail is enabled, it will
106106
generate a password of configured password strength policy upon role creation or alteration
107107
when 'GENERATED PASSWORD' clause is used. Character sets supported are: English, Cyrillic, modern Cyrillic,
108108
German, Polish and Czech.
109+
- CEP-55 - Role name generation and validation. When built-in 'role_name_policy' guardrail is enabled, it will
110+
generate a role name automatically, without operators intervention. It is possible to configure
111+
this policy for both generation and as well as validation of role names.
109112
- There is new MBean of name org.apache.cassandra.service.snapshot:type=SnapshotManager which exposes user-facing
110113
snapshot operations. Snapshot-related methods on StorageServiceMBean are still present and functional
111114
but marked as deprecated.

conf/cassandra.yaml

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,20 +2507,41 @@ drop_compact_storage_enabled: false
25072507
# This would also apply to system keyspaces.
25082508
# maximum_replication_factor_warn_threshold: -1
25092509
# maximum_replication_factor_fail_threshold: -1
2510-
#
2510+
2511+
#role_name_policy:
2512+
# # Implementation class of a validator. When not in form of FQCN, the
2513+
# # package name org.apache.cassandra.db.guardrails is prepended.
2514+
# # By default, there is no validator.
2515+
# #validator_class_name: YourValidatorOfRoleNames
2516+
# # Implementation class of related generator which generates values which are valid when
2517+
# # tested against this validator. When not in form of FQCN, the
2518+
# # package name org.apache.cassandra.db.guardrails is prepended.
2519+
# # By default, there is no generator.
2520+
# # There is currently only one generator possible to configure - UUIDRoleNameGenerator
2521+
# generator_class_name: UUIDRoleNameGenerator
2522+
# # Minimum generated size of a name when name_size option is specified in CQL.
2523+
# # This can not be less than 10 and more than 32.
2524+
# #min_generated_name_size: 10
2525+
2526+
# If this is set to false, then it is not possible to call reconfiguration
2527+
# method in GuardrailsMBean. It will effectively forbid the reconfiguration of role_name_policy in runtime.
2528+
# You would need to stop the node, change the configuration in cassandra.yaml and start the node again.
2529+
# Defaults to true, which means that reconfiguration of role_name_policy via JMX is possible.
2530+
#role_name_policy_reconfiguration_enabled: true
2531+
25112532
# Guardrail to warn or fail when setting / altering a password.
25122533
# Supported character sets are (both upper and lower-case): English, Cyrillic and modern Cyrillic, Czech, German, Polish.
25132534
# Password is invalid if all characters are from non-supported character set. If a password is otherwise valid,
25142535
# but it contains characters from unsupported language, these characters contribute only to password length rule.
25152536
# All digits and all following special characters are supported too: !"#$%&()*+,-./:;<=>?@[\]^_`{|}~
2516-
#password_validator:
2537+
#password_policy:
25172538
# # Implementation class of a validator. When not in form of FQCN, the
2518-
# # package name org.apache.cassandra.db.guardrails.validators is prepended.
2539+
# # package name org.apache.cassandra.db.guardrails is prepended.
25192540
# # By default, there is no validator.
2520-
# class_name: CassandraPasswordValidator
2541+
# validator_class_name: CassandraPasswordValidator
25212542
# # Implementation class of related generator which generates values which are valid when
25222543
# # tested against this validator. When not in form of FQCN, the
2523-
# # package name org.apache.cassandra.db.guardrails.generators is prepended.
2544+
# # package name org.apache.cassandra.db.guardrails is prepended.
25242545
# # By default, there is no generator.
25252546
# generator_class_name: CassandraPasswordGenerator
25262547
# # There are four characteristics:
@@ -2571,7 +2592,7 @@ drop_compact_storage_enabled: false
25712592
# method in GuardrailsMBean. It will effectively forbid the reconfiguration of password validator in runtime.
25722593
# You would need to stop the node, change the configuration in cassandra.yaml and start the node again.
25732594
# Defaults to true, which means that reconfiguration of password validator via JMX is possible.
2574-
# password_validator_reconfiguration_enabled: true
2595+
#password_policy_reconfiguration_enabled: true
25752596

25762597
# Guardrail to enable a CREATE or ALTER TABLE statement when default_time_to_live is set to 0
25772598
# and the table is using TimeWindowCompactionStrategy compaction or a subclass of it.

conf/cassandra_latest.yaml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,6 +2290,98 @@ drop_compact_storage_enabled: false
22902290
# maximum_replication_factor_warn_threshold: -1
22912291
# maximum_replication_factor_fail_threshold: -1
22922292

2293+
#role_name_policy:
2294+
# # Implementation class of a validator. When not in form of FQCN, the
2295+
# # package name org.apache.cassandra.db.guardrails is prepended.
2296+
# # By default, there is no validator.
2297+
# #validator_class_name: YourValidatorOfRoleNames
2298+
# # Implementation class of related generator which generates values which are valid when
2299+
# # tested against this validator. When not in form of FQCN, the
2300+
# # package name org.apache.cassandra.db.guardrails is prepended.
2301+
# # By default, there is no generator.
2302+
# # There is currently only one generator possible to configure - UUIDRoleNameGenerator
2303+
# generator_class_name: UUIDRoleNameGenerator
2304+
# # Minimum generated size of a name when name_size option is specified in CQL.
2305+
# # This can not be less than 10 and more than 32.
2306+
# #min_generated_name_size: 10
2307+
2308+
# If this is set to false, then it is not possible to call reconfiguration
2309+
# method in GuardrailsMBean. It will effectively forbid the reconfiguration of role_name_policy in runtime.
2310+
# You would need to stop the node, change the configuration in cassandra.yaml and start the node again.
2311+
# Defaults to true, which means that reconfiguration of role_name_policy via JMX is possible.
2312+
#role_name_policy_reconfiguration_enabled: true
2313+
2314+
# If this is set to false, then it is not possible to call reconfiguration
2315+
# method in GuardrailsMBean. It will effectively forbid the reconfiguration of role_name_policy in runtime.
2316+
# You would need to stop the node, change the configuration in cassandra.yaml and start the node again.
2317+
# Defaults to true, which means that reconfiguration of role_name_policy via JMX is possible.
2318+
#rolename_validator_reconfiguration_enabled: true
2319+
2320+
# Guardrail to warn or fail when setting / altering a password.
2321+
# Supported character sets are (both upper and lower-case): English, Cyrillic and modern Cyrillic, Czech, German, Polish.
2322+
# Password is invalid if all characters are from non-supported character set. If a password is otherwise valid,
2323+
# but it contains characters from unsupported language, these characters contribute only to password length rule.
2324+
# All digits and all following special characters are supported too: !"#$%&()*+,-./:;<=>?@[\]^_`{|}~
2325+
#password_policy:
2326+
# # Implementation class of a validator. When not in form of FQCN, the
2327+
# # package name org.apache.cassandra.db.guardrails is prepended.
2328+
# # By default, there is no validator.
2329+
# validator_class_name: CassandraPasswordValidator
2330+
# # Implementation class of related generator which generates values which are valid when
2331+
# # tested against this validator. When not in form of FQCN, the
2332+
# # package name org.apache.cassandra.db.guardrails is prepended.
2333+
# # By default, there is no generator.
2334+
# generator_class_name: CassandraPasswordGenerator
2335+
# # There are four characteristics:
2336+
# # upper-case, lower-case, special character and digit.
2337+
# # If this value is set e.g. to 3, a password has to consist of 3 out of 4 characteristics.
2338+
# # For example, it has to contain at least 2 upper-case characters, 2 lower-case, and 2 digits to pass,
2339+
# # but it does not have to contain any special characters.
2340+
# # If number of characteristics found in the password is less than or equal to this number, it will emit warning.
2341+
# characteristic_warn: 3
2342+
# # If number of characteristics found in the password is less than or equal to this number, it will emit failure.
2343+
# characteristic_fail: 2
2344+
# # Maximum length of a password. Defaults to 1000.
2345+
# max_length: 1000
2346+
# # If password is shorter than this value, the validator will emit a warning.
2347+
# length_warn: 12
2348+
# # If a password is shorter than this value, the validator will emit a failure.
2349+
# length_fail: 8
2350+
# # If a password does not contain at least n upper-case characters, the validator will emit a warning.
2351+
# upper_case_warn: 2
2352+
# # If a password does not contain at least n upper-case characters, the validator will emit a failure.
2353+
# upper_case_fail: 1
2354+
# # If a password does not contain at least n lower-case characters, the validator will emit a warning.
2355+
# lower_case_warn: 2
2356+
# # If a password does not contain at least n lower-case characters, the validator will emit a failure.
2357+
# lower_case_fail: 1
2358+
# # If a password does not contain at least n digits, the validator will emit a warning.
2359+
# digit_warn: 2
2360+
# # If a password does not contain at least n digits, the validator will emit a failure.
2361+
# digit_fail: 1
2362+
# # If a password does not contain at least n special characters, the validator will emit a warning.
2363+
# special_warn: 2
2364+
# # If a password does not contain at least n special characters, the validator will emit a failure.
2365+
# special_fail: 1
2366+
# # If a password contain illegal sequences that at least this long, it is invalid.
2367+
# # Illegal sequences might be either alphabetical (form 'abcde'),
2368+
# # numerical (form '34567'), or US qwerty (form 'asdfg') as well as sequencies from supported character sets.
2369+
# # The minimum value for this property is 3, by default it is set to 5.
2370+
# illegal_sequence_length: 5
2371+
# # Dictionary to check the passwords against. Defaults to no dictionary.
2372+
# # Whole dictionary is cached into memory. Use with caution with relatively big dictionaries.
2373+
# # Entries in a dictionary, one per line, have to be sorted per String's compareTo contract.
2374+
# #dictionary: /path/to/dictionary/file
2375+
# # If set to true, a user will be informed what policies a suggested password is missing in order to be valid.
2376+
# # Defaults to true.
2377+
# detailed_messages: true
2378+
2379+
# If this is set to false, then it is not possible to call reconfiguration
2380+
# method in GuardrailsMBean. It will effectively forbid the reconfiguration of password validator in runtime.
2381+
# You would need to stop the node, change the configuration in cassandra.yaml and start the node again.
2382+
# Defaults to true, which means that reconfiguration of password validator via JMX is possible.
2383+
#password_policy_reconfiguration_enabled: true
2384+
22932385
# Guardrail to enable a CREATE or ALTER TABLE statement when default_time_to_live is set to 0
22942386
# and the table is using TimeWindowCompactionStrategy compaction or a subclass of it.
22952387
# It is suspicious to use default_time_to_live set to 0 with such compaction strategy.

doc/cql3/CQL.textile

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ h3(#createRoleStmt). CREATE ROLE
13291329
__Syntax:__
13301330

13311331
bc(syntax)..
1332-
<create-role-stmt> ::= CREATE ROLE ( IF NOT EXISTS )? <identifier> ( WITH <option> ( AND <option> )* )?
1332+
<create-role-stmt> ::= CREATE (GENERATED)? ROLE ( IF NOT EXISTS )? <identifier> ( WITH <option> ( AND <option> )* )?
13331333

13341334
<option> ::= ("HASHED")? PASSWORD = <string>
13351335
| GENERATED PASSWORD
@@ -1352,6 +1352,8 @@ CREATE ROLE carlos WITH OPTIONS = { 'custom_option1' : 'option1_value', 'custom_
13521352
CREATE ROLE rob WITH LOGIN = true and PASSWORD = 'password_c' AND ACCESS FROM ALL CIDRS;
13531353
CREATE ROLE hob WITH LOGIN = true and PASSWORD = 'password_d' AND ACCESS FROM CIDRS { 'region1' };
13541354
CREATE ROLE tom WITH LOGIN = true and GENERATED PASSWORD;
1355+
CREATE GENERATED ROLE WITH GENERATED PASSWORD;
1356+
CREATE GENERATED ROLE WITH PASSWORD = 'password_e';
13551357

13561358

13571359
By default roles do not possess @LOGIN@ privileges or @SUPERUSER@ status.
@@ -1370,9 +1372,13 @@ Use the @WITH PASSWORD@ clause to set a password for internal authentication, en
13701372
If internal authentication has not been set up or the role does not have @LOGIN@ privileges, the @WITH PASSWORD@ clause is not necessary.
13711373

13721374
When @WITH GENERATED PASSWORD@ is used, Cassandra provides out-of-the-box CassandraPasswordValidator and CassandraPasswordGenerator
1373-
under "password_validator" configuration property in cassandra.yaml. The usage of this clause will generate a password for a given password strength policy, as configured,
1375+
under "password_policy" configuration property in cassandra.yaml. The usage of this clause will generate a password for a given password strength policy, as configured,
13741376
and such password is returned to a client in CQL shell after query is executed. @GENERATED PASSWORD@ can not be used together with @HASHED PASSWORD@ nor with @PASSWORD@ alone.
13751377

1378+
When @GENERATED@ is used in front of @ROLE@, it is possible to generate a role name automatically. This is possible if `role_name_policy` is enabled in the configuration.
1379+
The usage of this clause will generate a role name based on given `generator_class_name` in `role_name_policy` section in cassandra.yaml. Generated role name (together with generated password) will
1380+
be returned in CQL response to a caller. Custom implementations of `IRoleManager` are able to specify custom response to return to a caller if default behaviour is not desired.
1381+
13761382
h4(#createRoleConditional). Creating a role conditionally
13771383

13781384
Attempting to create an existing role results in an invalid query condition unless the @IF NOT EXISTS@ option is used. If the option is used and the role exists, the statement is a no-op.
@@ -1522,7 +1528,6 @@ bc(syntax)..
15221528
<create-user-statement> ::= CREATE USER ( IF NOT EXISTS )? <identifier> ( WITH <option> ( AND <option> )* )?
15231529

15241530
<option> ::= ("HASHED")? PASSWORD = <string>
1525-
| GENERATED PASSWORD
15261531
| SUPERUSER
15271532
| NOSUPERUSER
15281533
p.
@@ -1532,7 +1537,6 @@ __Sample:__
15321537
bc(sample).
15331538
CREATE USER alice WITH PASSWORD 'password_a' SUPERUSER;
15341539
CREATE USER bob WITH PASSWORD 'password_b' NOSUPERUSER;
1535-
CREATE USER tom WITH GENERATED PASSWORD;
15361540

15371541
@CREATE USER@ is equivalent to @CREATE ROLE@ where the @LOGIN@ option is @true@. So, the following pairs of statements are equivalent:
15381542

@@ -1561,7 +1565,6 @@ bc(syntax)..
15611565
<alter-user-statement> ::= ALTER USER (IF EXISTS)? <identifier> ( WITH <option> ( AND <option> )* )?
15621566

15631567
<option> ::= ("HASHED")? PASSWORD = <string>
1564-
| GENERATED PASSWORD
15651568
| SUPERUSER
15661569
| NOSUPERUSER
15671570
p.
@@ -2729,6 +2732,7 @@ h3. 3.4.8
27292732

27302733
* Add support for the BETWEEN operator in WHERE clauses (see "CASSANDRA-19604":https://issues.apache.org/jira/browse/CASSANDRA-19604)
27312734
* Add support for GENERATED PASSWORD clause (see "CASSANDRA-17457":https://issues.apache.org/jira/browse/CASSANDRA-17457)
2735+
* Add support for GENERATED ROLE clause (see "CASSANDRA-17457":https://issues.apache.org/jira/browse/CASSANDRA-20902)
27322736

27332737
h3. 3.4.7
27342738

doc/modules/cassandra/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
**** xref:cassandra:managing/operating/transientreplication.adoc[Transient replication]
111111
**** xref:cassandra:managing/operating/virtualtables.adoc[Virtual tables]
112112
**** xref:cassandra:managing/operating/password_validation.adoc[Password validation]
113+
**** xref:cassandra:managing/operating/role_name_generation.adoc[Role name generation]
113114
**** xref:cassandra:managing/operating/onboarding-to-accord.adoc[]
114115
*** xref:cassandra:managing/tools/index.adoc[Tools]
115116
**** xref:cassandra:managing/tools/cqlsh.adoc[cqlsh: the CQL shell]

doc/modules/cassandra/pages/managing/operating/index.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@
2020
* xref:cassandra:managing/operating/transientreplication.adoc[Transient replication]
2121
* xref:cassandra:managing/operating/virtualtables.adoc[Virtual tables]
2222
* xref:cassandra:managing/operating/password_validation.adoc[Password validation]
23+
* xref:cassandra:managing/operating/role_name_generation.adoc[Role name generation]
2324
* xref:cassandra:managing/operating/onboarding-to-accord.adoc[]

doc/modules/cassandra/pages/managing/operating/password_validation.adoc

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ the password guardrail provides `CassandraPasswordValidator` by extending `Value
5050
while passwords are generated by `CassandraPasswordGenerator` by extending `ValueGenerator`.
5151
Both components work with passwords as `String` type values.
5252

53-
Password validation and generation are configured in `cassandra.yaml` file under the `password_validator` section.
53+
Password validation and generation are configured in `cassandra.yaml` file under the `password_policy` section.
5454
Let’s explore the key configuration properties available.
5555

5656
First, the `class_name` and `generator_class_name` parameters
@@ -66,7 +66,7 @@ However, the framework is designed with flexibility in mind, allowing organizati
6666
and generation rules that align with their specific security policies and business requirements.
6767

6868
----
69-
password_validator:
69+
password_policy:
7070
# Implementation class of a validator. When not in form of FQCN, the
7171
# package name org.apache.cassandra.db.guardrails.validators is prepended.
7272
# By default, there is no validator.
@@ -243,12 +243,6 @@ We can create a role with generated password like this:
243243
cassandra@cqlsh> CREATE ROLE alice WITH GENERATED PASSWORD AND LOGIN = true;
244244
----
245245
246-
or by `CREATE USER`:
247-
248-
----
249-
cassandra@cqlsh> CREATE USER alice WITH GENERATED PASSWORD;
250-
----
251-
252246
When a password is generated for `alice` she can log in:
253247
254248
----
@@ -274,7 +268,7 @@ classname = PlainTextAuthProvider
274268
----
275269
276270
It is also possible to configure password validators in such a way that a user does not see why a password failed.
277-
This is driven by configuration property for `password_validator` called `detailed_messages`. When set to `false`,
271+
This is driven by configuration property for `password_policy` called `detailed_messages`. When set to `false`,
278272
the violations will be very brief:
279273
280274
----
@@ -299,11 +293,12 @@ implementation and may be addressed in future updates.
299293
Since this solution is based on guardrails which are configurable via JMX in runtime, same hold for
300294
password validator, also configured via `GuardrailsMBean` as any other guardrails. There are two methods exposed:
301295
302-
* `Map<String, Object> getPasswordValidatorConfig()` - gets password validator configuration
303-
* `void reconfigurePasswordValidator(Map<String, Object> config)` - reconfigures the password validator by reading
304-
and parsing the configuration from the provided map. Reconfiguration of password validator in runtime is considered
296+
* `Map<String, Object> getPasswordPolicy()` - gets password validator configuration as JSON string,
297+
* `void setPasswordPolicy(String value)` - reconfigures the password validator by reading
298+
and parsing the configuration from the provided String, being JSON representation of configuration map.
299+
Reconfiguration of password validator in runtime is considered
305300
to be very sensitive operation. If an operator evaluates the reconfiguration in runtime is not allowed, they
306-
might set `password_validator_reconfiguration_enabled` to `false` in `cassandra.yaml` to disable it.
301+
might set `password_policy_reconfiguration_enabled` to `false` in `cassandra.yaml` to disable it.
307302
308303
=== Diagnostic events
309304

0 commit comments

Comments
 (0)