Make SimpleAuthority work with Cassandra 1.1.6 permissions

A few days ago I was about to upgrade Cassandra cluster from 1.1.0 (+ Authentication patch I wrote) to 1.1.6, but – a bit surprisingly – I realized that something is wrong with new Cassandra. I had no problems with creating keyspaces before, as I set proper modify-keyspaces property in access.properties, but after the upgrade it stopped to work. After a short investigation I found out that there were some significant changes in Cassandra’s Permission system which broke SimpleAuthenticator. This article is about how to make it work again.

As I mentioned, the problem occured because some significant changes to Cassandra’s Permissions system were introduced some time ago. Except new permission types, also resource hierarchy has changed – previously creating a keyspace was requesting for for WRITE permission for /cassandra/keyspaces. Now it requests for CREATE permission for /cassandra/keyspaces/. This change brakes the SimpleAuthority code that relies on the length of the resource list which differs now – we cannot distinguish operations that modify keyspaces (perviously: resource list of length 2; currently: 3) from these ones that read it or so (resource list of length 3). See my previous article on SimpleAuthority permissions for reference. Anyway, the problem is that having a user with modify-keyspaces permission will not make him able to… modify keyspaces. Too bad – I had to fix this.

This is how it looked like before and how it looks now:

# cassandra_1.1.0
[x@unknown] create keyspace xxx;
#<User x groups=[]> does not have permission WRITE for /cassandra/keyspaces
 
# cassandra_1.1.6
[x@unknown] create keyspace xxx;
#<User x groups=[]> does not have permission CREATE for /cassandra/keyspaces/xxx

So, how to get rid of this problem? Well, “use the source, Luke” – I wrote a patch. Here’s the diff so you could verify it:

diff --git a/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java b/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java
index 6127370..2fc93c6 100644
--- a/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java
+++ b/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java
@@ -29,32 +29,36 @@ import java.util.EnumSet;
 import java.util.List;
 import java.util.Properties;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.cassandra.config.ConfigurationException;
 import org.apache.cassandra.io.util.FileUtils;
 
 public class SimpleAuthority implements IAuthority
 {
+    private static Logger logger = LoggerFactory.getLogger(SimpleAuthority.class);
+
     public final static String ACCESS_FILENAME_PROPERTY = "access.properties";
     // magical property for WRITE permissions to the keyspaces list
     public final static String KEYSPACES_WRITE_PROPERTY = "<modify-keyspaces>";
 
     public EnumSet<Permission> authorize(AuthenticatedUser user, List<Object> resource)
     {
-        if (resource.size() < 2 || !Resources.ROOT.equals(resource.get(0)) || !Resources.KEYSPACES.equals(resource.get(1)))
+        logger.debug("Checking permissions for user {} for resource {}", user, resource);
+
+        if (resource.size() < 3 || !Resources.ROOT.equals(resource.get(0)) || !Resources.KEYSPACES.equals(resource.get(1)))
             return Permission.NONE;
 
+        boolean checkKeyspaceWriteProperty = false;
         String keyspace, columnFamily = null;
         EnumSet<Permission> authorized = Permission.NONE;
-        
-        // /cassandra/keyspaces
-        if (resource.size() == 2)
-        {
-            keyspace = KEYSPACES_WRITE_PROPERTY;
-            authorized = EnumSet.of(Permission.READ);
-        }
+
         // /cassandra/keyspaces/<keyspace name>
-        else if (resource.size() == 3)
+        if (resource.size() == 3)
         {
+            // it is possible that it's a CREATE keyspace request
+            checkKeyspaceWriteProperty = true;
             keyspace = (String)resource.get(2);
         }
         // /cassandra/keyspaces/<keyspace name>/<cf name>
@@ -77,15 +81,17 @@ public class SimpleAuthority implements IAuthority
             Properties accessProperties = new Properties();
             accessProperties.load(in);
 
-            // Special case access to the keyspace list
-            if (keyspace == KEYSPACES_WRITE_PROPERTY)
+            if (checkKeyspaceWriteProperty)
             {
                 String kspAdmins = accessProperties.getProperty(KEYSPACES_WRITE_PROPERTY);
                 for (String admin : kspAdmins.split(","))
                     if (admin.equals(user.username))
+                    {
+                        logger.debug("User {} can do everything!", user);
                         return Permission.ALL;
+                    }
             }
-            
+
             boolean canRead = false, canWrite = false;
             String readers = null, writers = null;
 
@@ -141,6 +147,8 @@ public class SimpleAuthority implements IAuthority
             FileUtils.closeQuietly(in);
         }
 
+        logger.debug("User's permissions: {}", authorized);
+
         return authorized;
     }

You can download it here: cassandra-1.1.6-issue-4933.txt

I’ve tested it on working application + run its systemtests, so it looks valid. How to make Cassandra use this changes? See my previous blog post on Cassandra Authentication to see how to enable it and apply this patch before creating a JAR file.

If you don’t want to play with all this stuff and all you need is a working JAR file – here it is: cassandra-authentication.jar

This patch does NOT require any changes in your permission configuration or so.

If you’re interested in new permission types – see org.apache.cassandra.auth.Permission package for details.

One important information – IAuthority2-related changes that caused SimpleAuthority to break will be reverted in 1.1.7 (CASSANDRA-4875), so 1.1.6 likely will be the ONLY release affected by this problem. If you don’t have to upgrade now – better wait for 1.1.7 or 1.2 (which will base on new IAuthority).

Comments are closed.