Role name validation and generation

CEP-55 is logical continuation of CEP-24. CEP-24 covers generation and validation of passwords while CEP-55 deals with role name generation.

The configuration of role name policy in cassandra.yaml is as follows:

role_name_policy:
#  # Implementation class of a validator. When not in form of FQCN, the
#  # package name org.apache.cassandra.db.guardrails is prepended.
#  # By default, there is no validator.
#  #validator_class_name: YourValidatorOfRoleNames
#  # 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 is prepended.
#  # By default, there is no generator.
#  # There is currently only one generator possible to configure - UUIDRoleNameGenerator
  generator_class_name: UUIDRoleNameGenerator
#  # Minimum generated size of a name when name_size option is specified in CQL.
#  # This can not be less than 10 and more than 32.
#  #min_generated_name_size: 10

UUIDRoleNameGenerator is the only built-in implementation of a generator which generates role names. As its name suggests, generated role names will be UUIDs (without hyphens) and their first character will be always a letter.

Once enabled (together with CassandraRoleManager as role_manager), a user might execute these queries:

The most simple variation is:

CREATE GENERATED ROLE;

 generated_role_name
----------------------------------
 a40dcc81c5964a79a5be670d99b18159

Every generation command will return a result resembling a table which will return generated_role_name value to a user.

CREATE GENERATED ROLE WITH PASSWORD = 'U9~63o<7M}oM';

 generated_role_name
----------------------------------
 f7f1871a41d740b483ac561cbbf1e4a9

When CEP-24 / password generation is enabled, it is possible to combine the generation of a role name together with the generation of a password like this:

CREATE GENERATED ROLE WITH GENERATED PASSWORD;

 generated_password | generated_role_name
--------------------+----------------------------------
       0zdHJ,]dW[s6 | cbaeea62551d41dbb26a349428ccd741

If we want that role to be able to log in, we would execute:

CREATE GENERATED ROLE WITH GENERATED PASSWORD AND LOGIN = true;

Operational workflow

A common provisioning flow is:

  1. Enable role_name_policy.generator_class_name and CassandraRoleManager before you create the service account.

  2. Create the generated role and capture the returned role name and password in your secret store.

  3. Grant the permissions the service needs, then update the application configuration to use the generated credentials.

  4. Test the login path with the generated credentials before you route production traffic to the account.

It is also possible to specify custom prefix and suffix of a generated role name like this:

CREATE GENERATED ROLE WITH OPTIONS = {'name_suffix': '_read_only'};

  generated_role_name
--------------------------------------------
 b40cc1a568b142e1b5630a9083880aa8_read_only

or prefix version:

CREATE GENERATED ROLE WITH OPTIONS = {'name_prefix': 'department_a_'};

  generated_role_name
----------------------------------------------------
 department_a_d7cc48cac819456fa3eb38c59649ec60

Of course, it is also possible to specify both name_prefix and name_suffix at the same time.

It is also possible to specify length of generated role name via name_size parameter:

CREATE GENERATED ROLE WITH OPTIONS = {'name_suffix': '_read_only', 'name_prefix': 'department_a_', 'name_size': 15};

  generated_role_name
----------------------------------------------------
 department_a_ac7896b4994d40c_read_only

min_generated_name_size parameter in cassandra.yaml sets minimum size of name. If name_size is specified in CQL’s OPTIONS, it will be checked against this minimum size and fail if smaller than that. The value of name_size option can not be less than 10 and more than 32.

There is currently no implementation of validator_class_name you might use. However, if you happen to put your implementation on a class path of Cassandra and referenced it in validator_class_name in role_name_policy, if somebody creates a role by specifying a role name by hand (or generated), it will be validated against such validator and either a warning will be issued to a caller or it will fail the query altogether, depending based on what logic it implemented. When used together with generator, it will basically validate what it generated to comply with its self-imposed policy. That way it will fail if you generate a role name in such a way that it would fail role creation if a user happened to specify it manually.

The configuration of role_name_policy is configurable in runtime via JMX. You get the actual configuration by calling GuardrailsMBean#getRoleNamePolicy() which returns JSON representation of such a policy as a string. Similarly, you can use GuardrailsMBean#setRoleNamePolicy(String) to configure it in runtime.

If you do not want to be able to configure this in runtime, please set role_name_policy_reconfiguration_enabled in cassandra.yaml to false.

The fact that you see a "table" returned after generated role name / password is the result of CassandraRoleManager overriding createRoleWithResult and alterRoleWithResult methods and populating the response message with generated values. If you happen to have a completely custom implementation of IRoleManager, e.g. integrating with an external service, this is a way how to hook in your own "credentials" to be returned to a user. E.g. an IRoleManager integrating with some vault-like solution might return there custom credentials-like values for end-user to act on and similar.