Adding simple authentication to Cassandra

Today I was asked to set up user authentication in Cassandra, so we could stop using the “default” user with unrestricted access only. I have to say that I was really surprised when I noticed that there’s NO out-of-the-box authentication and authorization framework in it. Luckily, it can be easily enabled in a few steps which I’m going to show you.

One important thing – SimpleAuthenticator we’re going to use is in the “examples” directory of Cassandra package. It’s because it is considered to be very simple and not very safe (it was even called a “toy” in one of Cassandra’s Jira tasks), so DO NOT rely on it as on a serious protection tool for your system. However it still fits many requirements (i.e. you don’t want user to make a mess in a Column Family he doesn’t need to work on) so you may find it useful. You have been warned.

First of all – you will need Ant 1.8 and Java SDK for building Cassandra’s jar file. Ant is available in Ubuntu’s apt repo by default. Sun’s (or actually Oracle’s) Java can be found in an ferramroberto’s alternative repository and installed this way:

sudo add-apt-repository ppa:ferramroberto/java
sudo apt-get update
sudo apt-get install sun-java6-bin sun-java6-jre sun-java6-jdk

Now we’re going to build Cassandra with the authentication classes we need. For this you need to download the source package of Cassandra which can be found here: http://cassandra.apache.org/download/ – I’ve picked the latest beta package, but this tutorial should not be version-dependent. Once you download it, unpack it end enter the directory:

tar -zxf apache-cassandra-1.1.0-beta2-src.tar.gz
cd apache-cassandra-1.1.0-beta2-src/

The two classes we need to be available for cassandra are: org.apache.cassandra.auth.SimpleAuthenticator and org.apache.cassandra.auth.SimpleAuthority. We have to copy them to the proper source code directory:

cp ./examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuth* \
./src/java/org/apache/cassandra/auth/

After doing this we can build Cassandra and – once it’s build – make a jar file. It may take a few minutes:

ant
ant jar

Having jar file we have to (OK, we don’t have to, but it’s a good idea) move it somewhere – i.e. to Cassandra’s jar directory – and substitute an existing symlink with a new one, refering to the freshly built jar:

sudo cp ./build/apache-cassandra-1.1.0-beta2-SNAPSHOT.jar /usr/share/cassandra/
cd /usr/share/cassandra/
sudo rm apache-cassandra.jar
sudo ln -s apache-cassandra-1.1.0-beta2-SNAPSHOT.jar apache-cassandra.jar

Now Cassandra is ready, time for configuration. First, create two files in conf directory of Cassandra’s settings directory – by default it’s /etc/cassandra

sudo mkdir /etc/cassandra/conf
touch /etc/cassandra/conf/passwd.properties
touch /etc/cassandra/conf/access.properties

First file contains user-password pairs like this:

myusername=mypassword
glados=youmonster
minsc=boo

The second one holds the access definitions in a format: keyspace.cfname. and a list of user having this privileges. Privileges can be which means read-only or which means read-write. I told you, that this permission system is very simple. Additionaly you can define users which have permission to modify keyspaces – it can be done with statement. Here’s an example of this file:

<modify-keyspaces>=myusername,glados
samplekeyspace.datacolumnfamily.<ro>=minsc,
samplekeyspace.datacolumnfamily.<rw>=myusername,glados

Then, tell Cassandra to use the proper Authenticator and Authority classes. You can do it by modifying /etc/cassandra/cassandra.yaml file – find authenticator and authority settings and change them to:

authenticator: org.apache.cassandra.auth.SimpleAuthenticator
authority: org.apache.cassandra.auth.SimpleAuthority

The last thing is to tell Cassandra to use the two config files described above when SimpleAuthenticator or SimpleAuthority ask for them. This can be done – for example – by modifying /etc/init.d/cassandra script directly, but it is a much better and cleaner solution to do it via JVM_OPTS in /etc/cassandra/cassandra-env.sh by adding:

# SimpleAuthenticator settings
JVM_OPTS="$JVM_OPTS -Dpasswd.properties=/etc/cassandra/conf/passwd.properties"
JVM_OPTS="$JVM_OPTS -Daccess.properties=/etc/cassandra/conf/access.properties"

just before this line:

JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS"

One more thing – if you want to, you can store your passwords as a MD5 hash (I didn’t do it in this example, but it works too and is, obviously, a nice idea) by adding one more variable in this (/etc/cassandra/cassandra-env.sh) file:

JVM_OPTS="$JVM_OPTS -Dpasswd.mode=MD5"

Now you are ready – you can restart Cassandra and try:

michal@aperture$ cassandra-cli
Login failure. Did you specify 'keyspace', 'username' and 'password'?
Welcome to Cassandra CLI version 1.1.0-11.449e037195c3c504d7aca5088e8
(...)

It will show the client prompt anyway, but you won’t be connected. Try some credentials then:

michal@aperture$ cassandra-cli -u myusername -pw mypassword -k samplekeyspace
Connected to: "Test Cluster" on 127.0.0.1/9160
Welcome to Cassandra CLI version 1.1.0-11.449e037195c3c504d7aca5088e8
(...)

That’s all, it works!

13 thoughts on “Adding simple authentication to Cassandra

  1. I’ve made a little update today – one information was wrong (MD5 password is not a cassandra.yaml setting but JVM one) and one thing (way of passing “-D” parameters) was done in a way which I didn’t like. Both things are fixed now.

  2. Hi,

    I followed your article.

    With authentication when you do
    cassandra-cli -u myusername -pw mypassword -k system
    the user can acess the system also.
    They can also show keyspaces;

    also create keyspace 1234 etc

    Though cassandra asks for user/pass, it does not actually work.

    Thanks,

  3. Thanks for comment!

    Yes, you’re mostly right, but I guess that’t the reason why SimpleAuthenticator was moved to “examples” directory. Of course I agree that it’s not good that you can access “system” keyspace as any (as I guess) user and list the keyspaces, but what was important for me is that even if you can do it, you are still unable to modify CFs. When I log in with:

    cassandra-cli -u myusername -pw mypassword -k system

    and try:

    [myusername@system] list IndexInfo ;
    (...)
    #<User myusername groups=[]> does not have permission READ for 
    /cassandra/keyspaces/system/IndexInfo 
    InvalidRequestException(why:#<User myusername groups=[]> does not 
    have permission READ for /cassandra/keyspaces/system/IndexInfo)

    And yes – he can create keyspaces because it has a “modify-keyspaces” permission. If you try to log in as a different user, who’s not on that list, you’ll get:

    [other@system] create keyspace new_keyspace;
    #<User other groups=[]> does not have permission WRITE for 
    /cassandra/keyspaces

    I’d say it’s satisfying solution for my case. I completely agree with you that it’s not something what we could call “good” or “safe” in general, but as I mentioned in the second paragraph: “(…) DO NOT rely on it as on a serious protection tool for your system. (…) You have been warned.” :)

    The other thing is that user having “modify-keyspaces” privilege is still UNABLE to create CF’s, which is a problem for me now and I don’t think it should work this way. I’ve asked a question about this setting on Cassandra’s mailing list today. When I get some more explainations on this – I’ll write something about it.

  4. Great article, and many thanks for this contribution.

    I also have another problem with Cassandra.
    I Want to perform wild searches on the database, but not lucky enough, came to know that Cassandra does not support wild search.(e.g.select KEY,username,password from Users Where username=’%hello%’)

    Can you please help with this issue?

    • Thanks for your good words!

      Unluckily, Cassandra wasn’t meant to work this way – as you already know there’s no way to do such queries.

      For many cases you can do some “tricks” that will mimic behavior you need with a little help of additional Column Families that will be a kind of “index” for – refering to your example – Users CF. You may take a look at this presentation for some ideas: Cassandra Basic Indexing, but – anyway – I think in your specific case it won’t work – creating a CFs with *all* possible string combinations that could match your usernames is just ridiculous ;) However, you may find it usefull for other cases (i.e. prefix search) you work on.

      In this particular case, at first, I’d reconsider if Cassandra is the best match for you. There are other solutions that offer such functionality and – simply – are just made to work in the way you expect. Take a look at MongoDB – it’s a really good solution. If you want to stay with Apache (“You will never get fired for choosing Apache stuff” ;) ), take a look at CouchDB – I don’t know it well, but it may fit your requirements as well.

      Secondly, if you need Cassandra because of other reasons – think about “caching” the data you need in one of the data stores I mentioned above. You’ll still be able to store your data in Cassandra, but the “cache frontend” will provide the “wildcard” functionality you need.

      I hope it helped you a bit.

  5. Pingback: Make SimpleAuthority work with Cassandra 1.1.6 Permissions | devblog.michalski.im

  6. The configuration normally do everything in accordance with the document.error
    ERROR 11:57:21,625 Fatal configuration error
    org.apache.cassandra.config.ConfigurationException: When using org.apache.cassan
    dra.auth.SimpleAuthenticator passwd.properties properties must be defined.
    at org.apache.cassandra.auth.SimpleAuthenticator.validateConfiguration (S
    impleAuthenticator.java: 141)
    Can not get System.getProperty (SimpleAuthenticator.PASSWD_FILENAME_PROPERTY);
    1.1.6 version crash

    • cassandra-env.sh
      # SimpleAuthenticator settings
      JVM_OPTS=”$JVM_OPTS -Dpasswd.properties=$CASSANDRA_HOME/conf/passwd.properties”
      JVM_OPTS=”$JVM_OPTS -Daccess.properties=$CASSANDRA_HOME/conf/access.properties”
      JVM_OPTS=”$JVM_OPTS $JVM_EXTRA_OPTS”

    • 似乎配置没有起到效果 cassandra-env.sh
      源码System.getProperty(“passwd.properties”)
      找不到系统参数

    • Have solved the original need
      cassandra. bat in
      set JAVA_OPTS =-ea ^
      After configuration
      -Dpasswd.properties = “% CASSANDRA_HOME% \ conf \ passwd.properties” ^
      -Daccess.properties = “% CASSANDRA_HOME% \ conf \ access.properties” ^

  7. Thanks for commenting and sharing your solution! As you can see, I’m a Linux user, so I completely forgot about customizing Windows’ Cassandra start-up script – thanks again.