Setting Up LDAP Authentication and Authorization, DSE 5.x, 6.x
Setting Up Authentication
1. Enable DSE Unified Authentication. Set the following in cassandra.yaml:
authenticator: com.datastax.bdp.cassandra.auth.DseAuthenticator
authorizer: com.datastax.bdp.cassandra.auth.DseAuthorizer
role_manager: com.datastax.bdp.cassandra.auth.DseRoleManager
2. In dse.yaml , enable authentication and configure it to use the desired authentication method(s). Note that, as part of the steps needed to get LDAP auth working with DSE, you'll need to log into cqlsh using the built-in cassandra superuser, so you should go ahead and configure dse.yaml to also use "internal" authentication along with LDAP authentication. The below example (settings in dse.yaml) allows both LDAP and Cassandra internal authentication to be used:
#########################
authentication_options:
## Turn authentication on/off
enabled: true
default_scheme: ldap
allow_digest_with_kerberos: true
plain_text_without_ssl: warn
transitional_mode: disabled
other_schemes:
- internal
## Set scheme_permissions to true if multiple schemes will
## be used for authenticating to DSE. Doing so prevents
## unintentional role assignment that might occur if user or
## group names overlap in the authentication service. When
## scheme_permissions is set to true, every role requires
## permissions to an authentication scheme
## (GRANT EXECUTE on <AUTHENTICATION_METHOD> SCHEME to <ROLE_NAME>)
## in order to be assigned to a login user.
scheme_permissions: true
role_management_options:
## You can set the role management mode to EITHER ldap OR internal here (more
## on this in the separate explanation for setting up Authorization for ldap in DSE)
## You cannot set the role management mode to both internal AND ldap
## For now, we set it to ldap
mode: ldap
authorization_options:
## Leave authorization disabled until you can get authentication working first
enabled: false
transitional_mode: disabled
allow_row_level_security: false
## example ldap_options for MS Active Directory
ldap_options:
server_host: 10.200.255.28
server_port: 389
search_dn: cn=thatran1a,dc=qawin2012,dc=datastax,dc=lan
search_password: datastax
use_ssl: false
use_tls: false
truststore_path:
truststore_password:
truststore_type: jks
user_search_base: cn=users,dc=qawin2012,dc=datastax,dc=lan
user_search_filter: (sAMAccountName={0})
user_memberof_attribute: memberOf
#group_search_type: directory_search
group_search_type: memberof_search
#group_search_base: cn=users,dc=qawin201,dc=lan
#group_search_filter: (member=cn={0},cn=users,dc=qawin2008,dc=datastax,dc=lan)
group_name_attribute: cn
credentials_validity_in_ms: 0
connection_pool:
max_active: 8
max_idle: 8
#########################
Restart dse for the dse.yaml changes to take effect.
3. When an ldap user logs in to dse/cassandra, dse will look up the ldap user's ldap group memberships and look for ROLES in dse/cassandra whose name matches any of the names of the ldap groups to which the ldap user belongs. Note that DSE does NOT require that an ldap user belong to just a single ldap group.
Log into cqlsh as the built-in cassandra superuser and then, for one or more of the ldap groups to which the ldap user belongs, create a ROLE in dse/cassandra whose name matches the name of the ldap group:
cassandra@cqlsh> create role usergroup1 with login=true;
NOTE that you do NOT have to create a dse/cassandra role for the ldap user itself (you just need to create a role for the ldap group) AND you do NOT have to do any role assignment (DSE will determine the user's dse/cassandra role based on the user's ldap group memberships).
4. Confirm that you can log in to cqlsh as an ldap user that belongs to an ldap group for which you've already created a corresponding dse/cassandra role:
$ cqlsh -u lduser1 -p lduser1password
Connected to TT_511_ldap at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.10.0.1695 | DSE 5.1.1 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
ldapuser1@cqlsh>
Setting Up Authorization / Role Management
Once you have authentication working, you can configure and test Authorization.
IMPORTANT NOTE:
Unlike DSE Authentication (which now (via DSE "Unified Authentication") allows different authentication methods to be used for a given DSE cluster), DSE Authorization is still limited/tied to using just a single mechanism. That's why the "role_management_options" "mode" setting in dse.yaml can only be set to EITHER internal OR ldap but NOT both at the same time. So, what does it really mean that only internal role management can be used or that only ldap role management can be used? Read on to find out.
Using "ldap" for role management:
If/when you set the role management mode to "ldap", (1) role management is expected to be done on the ldap server by the ldap administrator (by creating different ldap groups, where each ldap group is mapped to a dse/cassandra ROLE (you need to create the dse/cassandra ROLE in cqlsh) and then assigning the group membership accordingly for different ldap users), and (2) DSE will automatically determine a user's dse/cassandra role by checking the user's ldap group memberships (so, you don't have to, in dse/cassandra, assign any roles to any of your ldap users).
In fact, when the role management mode is set to ldap, you will actually get an error if you try to
cqlsh> GRANT <ROLE_A> to <ROLE_B>;
or
cqlsh> GRANT <ROLE_A> to <USER_ROLE_C>
where USER_ROLE_C is a Cassandra internal user since, starting with Cassandra , users are roles in Cassandra (so, roles in cassandra can be "roles" in the traditional sense or they can be users).
cassandra@cqlsh> grant DBADMIN to internaluser1;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Granting roles is not supported"
In short, you cannot assign any roles to any users in dse/cassandra if you use ldap role management, because the assignment is expected to be done on the ldap server.
However, you can still grant permissions to individual users/user roles, example:
cassandra@cqlsh> grant all on keyspace ks1 to internaluser1;
In summary, with ldap role management, you cannot assign roles to users in dse/cassandra (cqlsh), but you can still assign permissions to individual users/roles...which makes role management really only effective for "ldap roles" not for "internal roles".
For the exact steps needed to configure ldap role management, see Step 2 from the "Steps Needed to Configure and Enable Authorization" section below.
Using "internal" for role management:
If you set the role management mode to "internal", then you are expected to create roles in dse/cassandra and then assign those roles to other roles/user roles. In this case, in order to get Authorization to work for BOTH Cassandra internal users AND ldap users, you would have to:
- Create a dse/cassandra role for each ldap user (not just each internal user) :
(a) the dse/cassandra role name has to match the ldap username, where username=UID if you are using Open LDAP OR username=sAMAccountName if using Active Directory OR username=<something_else> in the uncommon case where customer is not using a typical ldap schema and
(b) the role should be created with login=true and without any password set for it - GRANT EXECUTE on LDAP SCHEME to the role you created in Step 1 above. See https://docs.datastax.com/en/dse/5.1/dse-admin/datastax_enterprise/security/secRolesInternal.html
- GRANT <INTERNAL_ROLE_NAME> to <ROLE_YOU_CREATED_FOR_LDAP_USER> where INTERNAL_ROLE_NAME is one of the dse/cassandra roles that you created in cqlsh to manage/organize the Cassandra internal users, and ROLE_YOU_CREATED_FOR_LDAP_USER is the role you created in Step 1 above.
- GRANT EXECUTE on INTERNAL SCHEME to <INTERNAL_ROLE_NAME>
- Finally, you can GRANT <PERMISSION> on <RESOURCE> to <INTERNAL_ROLE_NAME> to give access to specific resources
As can be seen from the steps above, when using "internal" for role management, you have to create a cassandra role for each ldap user VERSUS creating a cassandra role for just the ldap groups to which an ldap user belongs. This is because, when using "internal" role management, DSE will not do ldap group lookup to see what ldap groups an ldap user belongs to; it will only look up internal roles to see which internal role your user belongs to.
Steps Needed to Configure and Enable Authorization
1. Enable authorization in dse.yaml (and restart dse for it to take effect) :
#########################
authorization_options:
## Leave authorization disabled until you can get authentication working first
enabled: true
transitional_mode: disabled
allow_row_level_security: false
#########################
2. Create the necessary dse/cassandra roles and do the necessary GRANTs. The specific roles and GRANTs needed in this step depends on whether you are using ldap for role management or internal for role management.
For internal role management, see above (in the section "Using internal for role management").
For ldap role management:
(a) Create a dse/cassandra role whose name matches the ldap user's group name:
cassandra@cqlsh> create role testgrp1 with login = true;
(b) Grant EXECUTE on LDAP SCHEME to each of the dse/cassandra roles that you created for your ldap users in the step above:
cassandra@cqlsh> grant EXECUTE on LDAP SCHEME to testgrp1;
3. Grant permissions on different resources to the roles you created for your ldap groups:
cassandra@cqlsh:ks2> grant all on keyspace ks1 to 'testgrp1';
cassandra@cqlsh> list permissions of 'testgrp1';
role | username | resource | permission
----------+----------+----------------+------------
testgrp1 | testgrp1 | <scheme LDAP> | EXECUTE
testgrp1 | testgrp1 | <keyspace ks1> | CREATE
testgrp1 | testgrp1 | <keyspace ks1> | ALTER
testgrp1 | testgrp1 | <keyspace ks1> | DROP
testgrp1 | testgrp1 | <keyspace ks1> | SELECT
testgrp1 | testgrp1 | <keyspace ks1> | MODIFY
testgrp1 | testgrp1 | <keyspace ks1> | AUTHORIZE
(7 rows)
4. Log in as an ldap user and test authorization/permissions:
#########################
$ cqlsh -u cathytran -p datastax
Connected to TT_511_ldap at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.10.0.1695 | DSE 5.1.1 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
cathytran@cqlsh> select * from ks1.users1;
id | uname
----+--------
1 | thanht
(1 rows)
cathytran@cqlsh> select * from ks2.tab1;
Unauthorized: Error from server: code=2100 [Unauthorized] message="User cathytran has no SELECT permission on <table ks2.tab1> or any of its parents"
cathytran@cqlsh>
#########################
5. If you will also be using Cassandra internal authentication to authenticate Cassandra users, then you'll need to also:
(a) cassandra@cqlsh> grant execute on INTERNAL SCHEME to <your_user_role_for_username>;
and
(b) Grant permissions on different resources to your internal user(s) like what you did in step 3 above for your ldap groups.
6. If you have any trouble with any of the above, please doublecheck ALL steps to make sure no mistakes were made. In DSE versions that are pre-v5.1.6, there is little to no debugging facility for troubleshooting problematic dse ldap configurations. In DSE 5.1.6 and later (which have the enhancement from DSP-14418 (Add TRACE logging to LdapUtils to help in debugging LDAP issues)), you can debug your auth config by adding
<logger name="com.datastax.bdp.cassandra.auth" level="TRACE"/>
to your cassandra logback.xml, this will give you trace level logging in the cassandra debug.log that you can use to troubleshoot your auth config, see also https://academy.datastax.com/support-blog/troubleshooting-ldap-authentication-issues-dse-past-and-present.