How to Keep Pirates “Hackers” Away From Your Booty “Data” with Cassandra RBAC
"Ye intruders beware.
Crushing death and grief,
Soaked with blood,
Of the trespassing thief."
-- Quote from Goonies, Pirate warning before the treasure vault.
There is absolutely no way that I can write a blog entry about database access control that is anywhere as good as a pirate treasure hunt, but that doesn't mean we can't borrow a little imagery to set the mood. Today, we call pirates "hackers" and the booty they're after is your data, which is sitting in a database somewhere. One of our main tools to ensure your data remains safe, is Cassandra Role-Based Access Control (RBAC).
With some really simple to implement strategies, we can all take basic steps to use Cassandra RBAC to make our data safer. Note, that here we are speaking strictly of authorization and not authentication. That's a related, but separate topic, and one that is a little more straightforward. You already know that you shouldn't go exposing databases without Authentication support to the internet, right? (Voiceover work by yours truly)
For the purposes of these suggestions, we'll assume that we're dealing with users that are internally managed by Cassandra, and not coming from an external source like LDAP, but the principles are very similar.
1. Cassandra has a confusing model that treats all roles as roles, and all users as roles. Don't play along.
Rather than treat users and roles as distinct types of database objects, Cassandra uses "role" objects to refer to roles as collections of permissions and also the entities that login to use those permissions. This is confusing at best. You will be better served long term by internally keeping two distinct buckets for those things. Your users will be humans, and software that performs a login to the database. Your roles will be collections of specific database permissions that then get assigned to users. Unless you have a very specific reason to do so, avoid granting database permissions directly to a user. To make that clear, here's an example:
CREATE ROLE alicethehuman with LOGIN=true;
CREATE ROLE READONLY;
GRANT SELECT, DESCRIBE ON mykeyspace.mytable TO READONLY;
GRANT SELECT, DESCRIBE on mykeyspace.myothertable TO READONLY;
GRANT ROLE READONLY TO alicethehuman;
So, note in the above example that our human is distinguished by the fact that LOGIN=true is assigned to her, then we create a clearly labeled role, and assign specific permissions to that, then we assign the role to alicetheuser
. What we should avoid are statements like this:
GRANT SELECT ON mykeyspace.mytable TO alicethehuman; #Don't do this
Following this general pattern will make your database permissions much more maintainable as the individuals that make up an organization come and go and have changes in their responsibilities.
2. Create basic roles for really common permissions like "read-only" and standardize on them.
This is relatively straightforward advice, but it can really help to add clarity to your authorization setup. Examples will vary depending on your organization's roles and responsibilities, but typical examples are READONLY, READWRITE, & CREATOR
. It can also be helpful to include prefixes or suffixes for common scopes. If a role is specific to a keyspace, prefix the role name with an abbreviation for the keyspace name. Similarly, if the role is specific to a table, suffix the role name with a table abbreviation. These are merely suggestions to get you started, use some creativity here, but document it and standardize it across your database team.
3. Don't go deep!
Finally, it helps to not nest your RBAC scheme too deeply. What I mean by that is, don't assign too many roles to roles. It can be hard to keep track of what specific permissions convey with too much hierarchy or nesting. Keep it simple. For the most part, your roles should consist solely of GRANTS for specific object permissions, and users should be granted a single or very small number of roles. Avoid assigning "roles of roles" to users, and for pity's sake please don't GRANT a user (remember, they're just special roles) to another user even though the system will let you.
It's easy to get wrapped around the axle with overly complex role structures. Don't let that happen. Keep it simple. If you'd like to explore these ideas more, but you don't have a Cassandra cluster with auth configured on it, just sign up for Astra and use the free tier to try these out.
To learn more about Astra architecture and security, download this whitepaper.