Table of Contents

Cassandra has some great advantages over traditional RDBMSs in areas such as scaling, resilience and performance, but in other places has had to play catch-up. This is understandable, given its relative immaturity compared to products that have been developed over decades. One of those areas is authentication and authorization. But since Cassandra v2.2 the gap has narrowed significantly with the introduction of new functionality in this domain.

It has been said before, but it’s worth repeating: No matter what database you’re using, when you’re coming from a development environment there’s something that needs to be really clear in your mind:

developer friendly != production ready

So, with that in mind, there is a raft of measures that can be used to make your production environment more secure such as:

  • Cassandra authentication
  • Cassandra object authorization
  • Data encryption (at-rest & in-flight)
  • Audit logging
  • Encryption of sensitive configuration files

If you’re running Datastax Enterprise OpsCentre, there are other measures you can take:

  • OpsCenter authentication
  • OpsCenter role-based authorization
  • OpsCenter HTTPS
  • OpsCenter SSL

We’re going to look at the first two in this article, Cassandra authentication and authorization. We should consider these two as being ‘minimum best practice’.

Concepts and Terminology

First some concepts need to be explained.

Authentication is the process of verifying the identity of a database client. It answers the question “Who are you?” When access control is enabled, Cassandra requires all clients to identify themselves in order to determine whether they have access at all.

Although authentication and authorization are closely connected, authentication is distinct from authorization. Authorization determines the verified user’s access to resources and operations. It answers the question “OK, I know you, but what are you permitted to do here?”

Prior to Cassandra v2.2 there were no roles, just users. Permissions were granted at the individual user level, which can become somewhat unwieldy. Since v2.2, however, role-based permissions were added, and so was a ‘role’ having a password and the ability to log-in (connect) to the database (sounds like a traditional database user to me!)

Be that as it may, you can broadly look at it this way: prior to v2.2 things were user-based and since v2.2 they’re role-based. This article uses the latest version of Cassandra – which at the time of writing is v3.7 – so everything is going to be role-based, including log-in roles.

A Worked Example

Enable Authentication and Authorization

cassandra.yaml settings must be changed in order to use authentication and authorization. Add or change the following settings:

authenticator: PasswordAuthenticator
authorizer: CassandraAuthorizer

Once you have enabled authentication and authorization, you can log-in as the default Cassandra admin user like this:

cqlsh localhost -u cassandra -p cassandra

Once connected, immediately create another super-user account.

CREATE USER admin WITH PASSWORD 'sandwich' SUPERUSER;

Next, change the Cassandra super-user’s password to something long and incomprehensible. With your new super-user, you shouldn’t need the default Cassandra account again.

ALTER USER cassandra WITH PASSWORD 'FjIrWVTZOFcanrxR3ju3**99';

Exit from cqlsh and reconnect as your new super-user:

cqlsh localhost -u admin -p sandwich
Create Roles

We need to create roles that define the exact access a set of database users’ needs, following a principle of least privilege. In other words, only give away as much as you have to and no more.

Since roles can inherit the permissions from other roles, it is possible to construct a fine-grained hierarchy of permission without incurring a huge administrative overhead.

Finally we create login-roles and assign them only the roles they need to perform their operations. A login-role can be a real person or a client application.

Create a keyspace for a table:

CREATE KEYSPACE IF NOT EXISTS test WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
USE test;

We’re going to create just one table to give us an object to work with:

create table restaurants
(
id UUID PRIMARY KEY,
building    text,
street      text,
zipcode     text,
borough     text,
cuisine     text,
name        text
);

For this example we’re going to create a reader role, and a writer role:

CREATE ROLE reader;
CREATE ROLE writer;
GRANT reader to writer;

Note how writer inherits the reader role. We now grant object privileges to the roles:

GRANT SELECT ON test.restaurants TO reader;
GRANT MODIFY ON test.restaurants TO writer;

The end result is that the reader role can read the restaurants table, and the writer role has both read and write access to the table.

Create Login Roles

Using the above created roles, create the required login-roles. Here we have two data scientists who have read-only access to the table(s). Furthermore, using the custom data, we can identify these users directly back to their employee IDs:

CREATE ROLE dataScientist01 WITH PASSWORD = 'changeMe' AND LOGIN = true;
GRANT reader TO dataScientist01;
 
CREATE ROLE dataScientist02 WITH PASSWORD = 'changeMe' AND LOGIN = true;
GRANT reader TO dataScientist02;

Finally we create the user for our application:

CREATE ROLE appuser WITH PASSWORD = 'dontChangeMe' AND LOGIN = true;
GRANT writer TO appuser;

You can check that everything has been created correctly using the LIST ROLES command:

LIST ROLES;
 
role            | super | login | options
----------------+-------+-------+---------
          admin |  True |  True |        {}
        appuser | False |  True |        {}
      cassandra |  True |  True |        {}
datascientist01 | False |  True |        {}
datascientist02 | False |  True |        {}
         reader | False | False |        {}
         writer | False | False |        {}
 
(7 rows)
LIST ROLES of appuser;
 
 role    | super | login | options
---------+-------+-------+---------
 appuser | False |  True |        {}
  reader | False | False |        {}
  writer | False | False |        {}

This is a pretty simple example, but it shows what can be achieved wrapping privileges into roles. As new tables are added to the keyspace, only the roles need to be amended. All the users, in turn, inherit their privileges via the roles, keeping administration down to minimum.

Upcoming Webinars

© Copyright 2013 - 2020 Testclue, All Rights Reserved, Terms and Conditions of use Privacy Policy Could be found here. Refund Policy is available here. Disclaimer : F5, Cisco, VMware, pfsense, VyOS are trademarks and logos of respective companies  holding them, Testclue is not official partner or provider of vendor specific courses and material.