cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alek...@apache.org
Subject [1/2] git commit: Replace IAuthority with new IAuthorizer; patch by Aleksey Yeschenko, reviewed by Jonathan Ellis for CASSANDRA-4874
Date Tue, 27 Nov 2012 17:32:01 GMT
Updated Branches:
  refs/heads/cassandra-1.2.0 7b4639ab2 -> 5a3eb1a6c


Replace IAuthority with new IAuthorizer; patch by Aleksey Yeschenko,
reviewed by Jonathan Ellis for CASSANDRA-4874


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5a3eb1a6
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5a3eb1a6
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5a3eb1a6

Branch: refs/heads/cassandra-1.2.0
Commit: 5a3eb1a6c3e61bd217e23e5d1e7c27f03fab4f08
Parents: 7b4639a
Author: Aleksey Yeschenko <aleksey@apache.org>
Authored: Tue Nov 27 20:04:22 2012 +0300
Committer: Aleksey Yeschenko <aleksey@apache.org>
Committed: Tue Nov 27 20:30:24 2012 +0300

----------------------------------------------------------------------
 CHANGES.txt                                        |    1 +
 NEWS.txt                                           |   14 +
 conf/cassandra.yaml                                |    4 +-
 examples/client_only/conf/cassandra.yaml           |    4 +-
 examples/simple_authentication/README.txt          |    4 +-
 .../simple_authentication/conf/access.properties   |    2 +-
 .../org/apache/cassandra/auth/SimpleAuthority.java |  157 ---------
 .../apache/cassandra/auth/SimpleAuthorizer.java    |  157 +++++++++
 pylib/cqlshlib/cql3handling.py                     |   61 ++--
 .../cassandra/auth/AllowAllAuthenticator.java      |   10 +-
 .../apache/cassandra/auth/AllowAllAuthority.java   |   36 --
 .../apache/cassandra/auth/AllowAllAuthorizer.java  |   70 ++++
 .../apache/cassandra/auth/AuthenticatedUser.java   |   22 +-
 .../org/apache/cassandra/auth/DataResource.java    |  248 +++++++++++++++
 src/java/org/apache/cassandra/auth/IAuthority.java |   63 ----
 .../org/apache/cassandra/auth/IAuthority2.java     |   70 ----
 .../apache/cassandra/auth/IAuthorityContainer.java |   83 -----
 .../org/apache/cassandra/auth/IAuthorizer.java     |  122 +++++++
 src/java/org/apache/cassandra/auth/IResource.java  |   53 +++
 .../apache/cassandra/auth/LegacyAuthorizer.java    |  111 +++++++
 .../apache/cassandra/auth/MigrationListener.java   |   53 +++
 src/java/org/apache/cassandra/auth/Permission.java |   57 ++--
 .../apache/cassandra/auth/PermissionDenied.java    |   34 --
 .../apache/cassandra/auth/PermissionDetails.java   |   70 ++++
 src/java/org/apache/cassandra/auth/Resources.java  |   28 ++-
 src/java/org/apache/cassandra/config/Config.java   |    3 +-
 .../cassandra/config/DatabaseDescriptor.java       |   37 +--
 .../org/apache/cassandra/cql/DeleteStatement.java  |    2 +-
 .../apache/cassandra/cql/DropIndexStatement.java   |   65 +++--
 .../org/apache/cassandra/cql/QueryProcessor.java   |   77 ++---
 .../org/apache/cassandra/cql/UpdateStatement.java  |   10 +-
 src/java/org/apache/cassandra/cql3/Cql.g           |  116 ++++---
 .../org/apache/cassandra/cql3/QueryProcessor.java  |    2 +-
 .../cql3/statements/AuthorizationStatement.java    |   66 ++++
 .../cassandra/cql3/statements/BatchStatement.java  |    2 +-
 .../statements/CreateColumnFamilyStatement.java    |    2 +-
 .../cql3/statements/CreateKeyspaceStatement.java   |    2 +-
 .../cql3/statements/DropIndexStatement.java        |   57 ++--
 .../cassandra/cql3/statements/GrantStatement.java  |   17 +-
 .../cql3/statements/ListGrantsStatement.java       |   42 ---
 .../cql3/statements/ListPermissionsStatement.java  |  106 ++++++
 .../cql3/statements/ModificationStatement.java     |    5 +-
 .../statements/PermissionAlteringStatement.java    |   54 ++--
 .../cassandra/cql3/statements/RevokeStatement.java |   15 +-
 .../cql3/statements/TruncateStatement.java         |    2 +-
 .../apache/cassandra/service/CassandraDaemon.java  |    6 +
 .../org/apache/cassandra/service/ClientState.java  |  175 ++++-------
 .../apache/cassandra/thrift/CassandraServer.java   |  119 +++----
 test/conf/access.properties                        |    2 +-
 49 files changed, 1520 insertions(+), 998 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9c80e87..8bfcc06 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -25,6 +25,7 @@
  * Fix adding column when the table has collections (CASSANDRA-4982)
  * Fix allowing collections with compact storage (CASSANDRA-4990)
  * Refuse ttl/writetime function on collections (CASSANDRA-4992)
+ * Replace IAuthority with new IAuthorizer (CASSANDRA-4874)
 Merged from 1.1:
  * cqlsh: improve COPY FROM performance (CASSANDRA-4921)
  * Fall back to old describe_splits if d_s_ex is not available (CASSANDRA-4803)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index 639e3c9..bc361c5 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -14,6 +14,15 @@ by version X, but the inverse is not necessarily the case.)
 
 Upgrading
 ---------
+    - IAuthority interface has been deprecated in favor of IAuthorizer.
+      AllowAllAuthority and SimpleAuthority have been renamed to
+      AllowAllAuthorizer and SimpleAuthorizer, respectively. In order to
+      simplify the upgrade to the new interface, a new abstract
+      LegacyAuthorizer has been added - you should subclass it in your
+      old IAuthority implementation and everything should just work
+      (this only affects users who implemented custom authorities).
+      'authority' setting in cassandra.yaml has been renamed to 'authorizer',
+      'authority' is no longer recognized. This affects all upgrading users.
     - 1.2 is NOT network-compatible with versions older than 1.0. That
       means if you want to do a rolling, zero-downtime upgrade, you'll need
       to upgrade first to 1.0.x or 1.1.x, and then to 1.2.  1.2 retains
@@ -93,6 +102,11 @@ Features
       guarantee that (at the price of pre-writing the batch to another node
       first), all mutations in the batch will be applied, even if the
       coordinator fails mid-batch.
+    - new IAuthorizer interface has replaced the old IAuthority. IAuthorizer
+      allows dynamic permission management via new CQL3 statements:
+      GRANT, REVOKE, LIST PERMISSIONS. A native implementation storing
+      the permissions in Cassandra is being worked on and we expect to
+      include it in 1.2.1 or 1.2.2.
 
 
 1.1.5

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/conf/cassandra.yaml
----------------------------------------------------------------------
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index 8aaeb38..2861c43 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -56,8 +56,8 @@ max_hints_delivery_threads: 2
 # authentication backend, implementing IAuthenticator; used to identify users
 authenticator: org.apache.cassandra.auth.AllowAllAuthenticator
 
-# authorization backend, implementing IAuthority; used to limit access/provide permissions
-authority: org.apache.cassandra.auth.AllowAllAuthority
+# authorization backend, implementing IAuthorizer; used to limit access/provide permissions
+authorizer: org.apache.cassandra.auth.AllowAllAuthorizer
 
 # The partitioner is responsible for distributing rows (by key) across
 # nodes in the cluster.  Any IPartitioner may be used, including your

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/examples/client_only/conf/cassandra.yaml
----------------------------------------------------------------------
diff --git a/examples/client_only/conf/cassandra.yaml b/examples/client_only/conf/cassandra.yaml
index 701d191..0edc473 100644
--- a/examples/client_only/conf/cassandra.yaml
+++ b/examples/client_only/conf/cassandra.yaml
@@ -40,8 +40,8 @@ hinted_handoff_throttle_delay_in_ms: 50
 # authentication backend, implementing IAuthenticator; used to identify users
 authenticator: org.apache.cassandra.auth.AllowAllAuthenticator
 
-# authorization backend, implementing IAuthority; used to limit access/provide permissions
-authority: org.apache.cassandra.auth.AllowAllAuthority
+# authorization backend, implementing IAuthorizer; used to limit access/provide permissions
+authorizer: org.apache.cassandra.auth.AllowAllAuthorizer
 
 # The partitioner is responsible for distributing rows (by key) across
 # nodes in the cluster.  Any IPartitioner may be used, including your

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/examples/simple_authentication/README.txt
----------------------------------------------------------------------
diff --git a/examples/simple_authentication/README.txt b/examples/simple_authentication/README.txt
index dcf9553..f81f5e7 100644
--- a/examples/simple_authentication/README.txt
+++ b/examples/simple_authentication/README.txt
@@ -1,12 +1,12 @@
 The files in this directory provide a (simplistic) example of how to add
 authentication and resource permissions to Cassandra by implementing the
-org.apache.cassandra.auth.{IAuthenticator, IAuthority} interfaces.
+org.apache.cassandra.auth.{IAuthenticator, IAuthorizer} interfaces.
 
 To try those examples, copy the two JAVA sources (in src/) into the main
 cassandra sources directory and the two configuration files (in conf/) in the
 main cassandra configuration directory.
 
-You can then set the authenticator and authority properties in cassandra.yaml
+You can then set the authenticator and authorizer properties in cassandra.yaml
 to use those classes. See the two configuration files access.properties and
 passwd.properties to configure the authorized users and permissions.
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/examples/simple_authentication/conf/access.properties
----------------------------------------------------------------------
diff --git a/examples/simple_authentication/conf/access.properties b/examples/simple_authentication/conf/access.properties
index 9cce0dc..f403c2f 100644
--- a/examples/simple_authentication/conf/access.properties
+++ b/examples/simple_authentication/conf/access.properties
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This is a sample access file for SimpleAuthority. The format of this file
+# This is a sample access file for SimpleAuthorizer. The format of this file
 # is KEYSPACE[.COLUMNFAMILY].PERMISSION=USERS, where:
 #
 # * KEYSPACE is the keyspace name.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java
----------------------------------------------------------------------
diff --git a/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java b/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java
deleted file mode 100644
index 88814ec..0000000
--- a/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthority.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.apache.cassandra.auth;
-/*
- * 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * 
- */
-
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.cassandra.exceptions.ConfigurationException;
-import org.apache.cassandra.io.util.FileUtils;
-
-public class SimpleAuthority implements IAuthority
-{
-    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)))
-            return Permission.NONE;
-        
-        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)
-        {
-            keyspace = (String)resource.get(2);
-        }
-        // /cassandra/keyspaces/<keyspace name>/<cf name>
-        else if (resource.size() == 4)
-        {
-            keyspace = (String)resource.get(2);
-            columnFamily = (String)resource.get(3);
-        }
-        else
-        {
-            // We don't currently descend any lower in the hierarchy.
-            throw new UnsupportedOperationException();
-        }
-        
-        String accessFilename = System.getProperty(ACCESS_FILENAME_PROPERTY);
-        InputStream in=null;
-        try
-        {
-            in = new BufferedInputStream(new FileInputStream(accessFilename));
-            Properties accessProperties = new Properties();
-            accessProperties.load(in);
-
-            // Special case access to the keyspace list
-            if (keyspace == KEYSPACES_WRITE_PROPERTY)
-            {
-                String kspAdmins = accessProperties.getProperty(KEYSPACES_WRITE_PROPERTY);
-                for (String admin : kspAdmins.split(","))
-                    if (admin.equals(user.username))
-                        return Permission.ALL;
-            }
-            
-            boolean canRead = false, canWrite = false;
-            String readers = null, writers = null;
-            
-            if (columnFamily == null)
-            {    
-                readers = accessProperties.getProperty(keyspace + ".<ro>");
-                writers = accessProperties.getProperty(keyspace + ".<rw>");
-            }
-            else
-            {
-                readers = accessProperties.getProperty(keyspace + "." + columnFamily + ".<ro>");
-                writers = accessProperties.getProperty(keyspace + "." + columnFamily + ".<rw>");
-            }
-            
-            if (readers != null)
-            {
-                for (String reader : readers.split(","))
-                {
-                    if (reader.equals(user.username))
-                    {
-                        canRead = true;
-                        break;
-                    }
-                }
-            }
-            
-            if (writers != null)
-            {
-                for (String writer : writers.split(","))
-                {
-                    if (writer.equals(user.username))
-                    {
-                        canWrite = true;
-                        break;
-                    }
-                }
-            }
-            
-            if (canWrite)
-                authorized = Permission.ALL;
-            else if (canRead)
-                authorized = EnumSet.of(Permission.READ);
-                
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException(String.format("Authorization table file '%s' could not be opened: %s",
-                                                     accessFilename,
-                                                     e.getMessage()));
-        }
-        finally
-        {
-            FileUtils.closeQuietly(in);
-        }
-
-        return authorized;
-    }
-
-    public void validateConfiguration() throws ConfigurationException
-    {
-        String afilename = System.getProperty(ACCESS_FILENAME_PROPERTY);
-        if (afilename == null)
-        {
-            throw new ConfigurationException(String.format("When using %s, '%s' property must be defined.",
-                                                           this.getClass().getCanonicalName(),
-                                                           ACCESS_FILENAME_PROPERTY));	
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthorizer.java
----------------------------------------------------------------------
diff --git a/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthorizer.java b/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthorizer.java
new file mode 100644
index 0000000..2d7b644
--- /dev/null
+++ b/examples/simple_authentication/src/org/apache/cassandra/auth/SimpleAuthorizer.java
@@ -0,0 +1,157 @@
+package org.apache.cassandra.auth;
+/*
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ */
+
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.io.util.FileUtils;
+
+public class SimpleAuthorizer extends LegacyAuthorizer
+{
+    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)))
+            return EnumSet.copyOf(Permission.NONE);
+        
+        String keyspace, columnFamily = null;
+        EnumSet<Permission> authorized = EnumSet.copyOf(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)
+        {
+            keyspace = (String)resource.get(2);
+        }
+        // /cassandra/keyspaces/<keyspace name>/<cf name>
+        else if (resource.size() == 4)
+        {
+            keyspace = (String)resource.get(2);
+            columnFamily = (String)resource.get(3);
+        }
+        else
+        {
+            // We don't currently descend any lower in the hierarchy.
+            throw new UnsupportedOperationException();
+        }
+        
+        String accessFilename = System.getProperty(ACCESS_FILENAME_PROPERTY);
+        InputStream in=null;
+        try
+        {
+            in = new BufferedInputStream(new FileInputStream(accessFilename));
+            Properties accessProperties = new Properties();
+            accessProperties.load(in);
+
+            // Special case access to the keyspace list
+            if (keyspace == KEYSPACES_WRITE_PROPERTY)
+            {
+                String kspAdmins = accessProperties.getProperty(KEYSPACES_WRITE_PROPERTY);
+                for (String admin : kspAdmins.split(","))
+                    if (admin.equals(user.username))
+                        return EnumSet.copyOf(Permission.ALL);
+            }
+            
+            boolean canRead = false, canWrite = false;
+            String readers = null, writers = null;
+            
+            if (columnFamily == null)
+            {    
+                readers = accessProperties.getProperty(keyspace + ".<ro>");
+                writers = accessProperties.getProperty(keyspace + ".<rw>");
+            }
+            else
+            {
+                readers = accessProperties.getProperty(keyspace + "." + columnFamily + ".<ro>");
+                writers = accessProperties.getProperty(keyspace + "." + columnFamily + ".<rw>");
+            }
+            
+            if (readers != null)
+            {
+                for (String reader : readers.split(","))
+                {
+                    if (reader.equals(user.username))
+                    {
+                        canRead = true;
+                        break;
+                    }
+                }
+            }
+            
+            if (writers != null)
+            {
+                for (String writer : writers.split(","))
+                {
+                    if (writer.equals(user.username))
+                    {
+                        canWrite = true;
+                        break;
+                    }
+                }
+            }
+            
+            if (canWrite)
+                authorized = EnumSet.copyOf(Permission.ALL);
+            else if (canRead)
+                authorized = EnumSet.of(Permission.READ);
+                
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(String.format("Authorization table file '%s' could not be opened: %s",
+                                                     accessFilename,
+                                                     e.getMessage()));
+        }
+        finally
+        {
+            FileUtils.closeQuietly(in);
+        }
+
+        return authorized;
+    }
+
+    public void validateConfiguration() throws ConfigurationException
+    {
+        String afilename = System.getProperty(ACCESS_FILENAME_PROPERTY);
+        if (afilename == null)
+        {
+            throw new ConfigurationException(String.format("When using %s, '%s' property must be defined.",
+                                                           this.getClass().getCanonicalName(),
+                                                           ACCESS_FILENAME_PROPERTY));	
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index a775245..1ef9dcb 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -43,14 +43,12 @@ SYSTEM_KEYSPACES = ('system', 'system_traces')
 class Cql3ParsingRuleSet(CqlParsingRuleSet):
     keywords = set((
         'select', 'from', 'where', 'and', 'key', 'insert', 'update', 'with',
-        'limit', 'using', 'consistency', 'one', 'quorum', 'all', 'any',
-        'local_quorum', 'each_quorum', 'two', 'three', 'use', 'count', 'set',
+        'limit', 'using', 'use', 'count', 'set',
         'begin', 'apply', 'batch', 'truncate', 'delete', 'in', 'create',
         'keyspace', 'schema', 'columnfamily', 'table', 'index', 'on', 'drop',
         'primary', 'into', 'values', 'timestamp', 'ttl', 'alter', 'add', 'type',
         'compact', 'storage', 'order', 'by', 'asc', 'desc', 'clustering',
-        'token', 'writetime', 'map', 'list', 'to', 'grant', 'grants', 'revoke',
-        'option', 'describe', 'for', 'full_access', 'no_access'
+        'token', 'writetime', 'map', 'list', 'to'
     ))
 
     columnfamily_options = (
@@ -275,16 +273,6 @@ JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ;
                           | <alterKeyspaceStatement>
                           ;
 
-<consistencylevel> ::= cl=( <K_ONE>
-                          | <K_QUORUM>
-                          | <K_ALL>
-                          | <K_ANY>
-                          | <K_LOCAL_QUORUM>
-                          | <K_EACH_QUORUM>
-                          | <K_TWO>
-                          | <K_THREE> )
-                          ;
-
 # timestamp is included here, since it's also a keyword
 <simpleStorageType> ::= typename=( <identifier> | <stringLiteral> | <K_TIMESTAMP> ) ;
 
@@ -307,15 +295,13 @@ JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ;
 
 <unreservedKeyword> ::= nocomplete=
                         ( <K_KEY>
-                        | <K_CONSISTENCY>
                         | <K_CLUSTERING>
                         # | <K_COUNT>  -- to get count(*) completion, treat count as reserved
                         | <K_TTL>
                         | <K_COMPACT>
                         | <K_STORAGE>
                         | <K_TYPE>
-                        | <K_VALUES>
-                        | <consistencylevel> )
+                        | <K_VALUES> )
                       ;
 
 # <property> will be defined once cqlsh determines whether we're using
@@ -666,10 +652,6 @@ def cf_old_prop_suboption_completer(ctxt, cass):
             return subopts
     return ()
 
-@completer_for('consistencylevel', 'cl')
-def consistencylevel_cl_completer(ctxt, cass):
-    return CqlRuleSet.consistency_levels
-
 @completer_for('tokenDefinition', 'token')
 def token_word_completer(ctxt, cass):
     return ['TOKEN(']
@@ -1246,39 +1228,48 @@ syntax_rules += r'''
 <alterKeyspaceStatement> ::= "ALTER" ( "KEYSPACE" | "SCHEMA" ) ks=<nonSystemKeyspaceName>
                                  "WITH" <newPropSpec> ( "AND" <newPropSpec> )*
                            ;
+'''
 
-<grantStatement> ::= "GRANT" <permission> "ON" cf=<columnFamilyName>
-                       "TO" <username>
-                       ( "WITH" "GRANT" "OPTION" )?
+syntax_rules += r'''
+<grantStatement> ::= "GRANT" <permissionExpr> "ON" <resource> "TO" <username>
                    ;
 
-<revokeStatement> ::= "REVOKE" <permission> "ON" cf=<columnFamilyName>
-                        "FROM" <username>
+<revokeStatement> ::= "REVOKE" <permissionExpr> "ON" <resource> "FROM" <username>
                     ;
 
-<listGrantsStatement> ::= "LIST" "GRANTS" "FOR" <username>;
+<listGrantsStatement> ::= "LIST" <permissionExpr>
+                              ( "ON" <resource> )? ( "OF" <username> )? "NORECURSIVE"?
+                        ;
 
-<permission> ::= "DESCRIBE"
-               | "USE"
+<permission> ::= "AUTHORIZE"
                | "CREATE"
                | "ALTER"
                | "DROP"
                | "SELECT"
-               | "INSERT"
-               | "UPDATE"
-               | "DELETE"
-               | "FULL_ACCESS"
-               | "NO_ACCESS"
+               | "MODIFY"
                ;
 
+<permissionExpr> ::= ( <permission> "PERMISSION"? )
+                   | ( "ALL" "PERMISSIONS"? )
+                   ;
+
+<resource> ::= <dataResource>
+             ;
+
+<dataResource> ::= ( "ALL" "KEYSPACES" )
+                 | ( "KEYSPACE" <nonSystemKeyspaceName> )
+                 | ( "TABLE"? <columnFamilyName> )
+                 ;
+
 <username> ::= user=( <identifier> | <stringLiteral> )
              ;
 '''
 
 @completer_for('username', 'user')
 def username_user_completer(ctxt, cass):
+    # TODO: implement user autocompletion
     # with I could see a way to do this usefully, but I don't. I don't know
-    # how any Authorities other than AllowAllAuthority work :/
+    # how any Authorities other than AllowAllAuthorizer work :/
     return [Hint('<username>')]
 
 # END SYNTAX/COMPLETION RULE DEFINITIONS

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/AllowAllAuthenticator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/AllowAllAuthenticator.java b/src/java/org/apache/cassandra/auth/AllowAllAuthenticator.java
index af88372..cd93dd0 100644
--- a/src/java/org/apache/cassandra/auth/AllowAllAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/AllowAllAuthenticator.java
@@ -24,16 +24,20 @@ import org.apache.cassandra.thrift.AuthenticationException;
 
 public class AllowAllAuthenticator implements IAuthenticator
 {
-    private final static AuthenticatedUser USER = new AuthenticatedUser("allow_all");
+    private final static AuthenticatedUser DEFAULT_USER = new AuthenticatedUser("nobody");
 
     public AuthenticatedUser defaultUser()
     {
-        return USER;
+        return DEFAULT_USER;
     }
 
     public AuthenticatedUser authenticate(Map<? extends CharSequence,? extends CharSequence> credentials) throws AuthenticationException
     {
-        return USER;
+
+        CharSequence username = credentials.get(IAuthenticator.USERNAME_KEY);
+        if (username == null)
+            return DEFAULT_USER;
+        return new AuthenticatedUser((String)username);
     }
 
     public void validateConfiguration() throws ConfigurationException

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/AllowAllAuthority.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/AllowAllAuthority.java b/src/java/org/apache/cassandra/auth/AllowAllAuthority.java
deleted file mode 100644
index 5a6f86d..0000000
--- a/src/java/org/apache/cassandra/auth/AllowAllAuthority.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.auth;
-
-import java.util.EnumSet;
-import java.util.List;
-
-import org.apache.cassandra.exceptions.ConfigurationException;
-
-public class AllowAllAuthority implements IAuthority
-{
-    public EnumSet<Permission> authorize(AuthenticatedUser user, List<Object> resource)
-    {
-        return Permission.ALL;
-    }
-
-    public void validateConfiguration() throws ConfigurationException
-    {
-        // pass
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/AllowAllAuthorizer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/AllowAllAuthorizer.java b/src/java/org/apache/cassandra/auth/AllowAllAuthorizer.java
new file mode 100644
index 0000000..8b839ea
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/AllowAllAuthorizer.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.cassandra.exceptions.InvalidRequestException;
+
+public class AllowAllAuthorizer implements IAuthorizer
+{
+    public Set<Permission> authorize(AuthenticatedUser user, IResource resource)
+    {
+        return Permission.ALL;
+    }
+
+    public void validateConfiguration()
+    {
+    }
+
+    public void setup()
+    {
+    }
+
+    public void grant(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String to)
+    throws InvalidRequestException
+    {
+        throw new InvalidRequestException("GRANT operation is not supported by AllowAllAuthorizer");
+    }
+
+    public void revoke(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String from)
+    throws InvalidRequestException
+    {
+        throw new InvalidRequestException("REVOKE operation is not supported by AllowAllAuthorizer");
+    }
+
+    public void revokeAll(String droppedUser)
+    {
+    }
+
+    public void revokeAll(IResource droppedResource)
+    {
+    }
+
+    public Set<PermissionDetails> listPermissions(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String of)
+    throws InvalidRequestException
+    {
+        throw new InvalidRequestException("LIST PERMISSIONS operation is not supported by AllowAllAuthorizer");
+    }
+
+    public Set<IResource> protectedResources()
+    {
+        return Collections.emptySet();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/AuthenticatedUser.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/AuthenticatedUser.java b/src/java/org/apache/cassandra/auth/AuthenticatedUser.java
index 091bdc5..e65446d 100644
--- a/src/java/org/apache/cassandra/auth/AuthenticatedUser.java
+++ b/src/java/org/apache/cassandra/auth/AuthenticatedUser.java
@@ -17,32 +17,30 @@
  */
 package org.apache.cassandra.auth;
 
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * An authenticated user and her groups.
- */
 public class AuthenticatedUser
 {
     public final String username;
-    public final Set<String> groups;
+    private final boolean isSuperUser;
 
     public AuthenticatedUser(String username)
     {
-        this.username = username;
-        this.groups = Collections.emptySet();
+        this(username, false);
     }
 
-    public AuthenticatedUser(String username, Set<String> groups)
+    public AuthenticatedUser(String username, boolean isSuperUser)
     {
         this.username = username;
-        this.groups = Collections.unmodifiableSet(groups);
+        this.isSuperUser = isSuperUser;
+    }
+
+    public boolean isSuperUser()
+    {
+        return isSuperUser;
     }
 
     @Override
     public String toString()
     {
-        return String.format("#<User %s groups=%s>", username, groups);
+        return String.format("#<User %s super=%s>", username, isSuperUser);
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/DataResource.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/DataResource.java b/src/java/org/apache/cassandra/auth/DataResource.java
new file mode 100644
index 0000000..3ee40a7
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/DataResource.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+import com.google.common.base.Objects;
+import org.apache.commons.lang.StringUtils;
+
+import org.apache.cassandra.config.Schema;
+
+/**
+ * The primary type of resource in Cassandra.
+ *
+ * Used to represent a column family or a keyspace or the root level "data" resource.
+ * "data"                                 - the root level data resource.
+ * "data/keyspace_name"                   - keyspace-level data resource.
+ * "data/keyspace_name/column_family_name" - cf-level data resource.
+ */
+public class DataResource implements IResource
+{
+    enum Level
+    {
+        ROOT, KEYSPACE, COLUMN_FAMILY
+    }
+
+    private static final String ROOT_NAME = "data";
+    private static final DataResource ROOT_RESOURCE = new DataResource();
+
+    private final Level level;
+    private final String keyspace;
+    private final String columnFamily;
+
+    private DataResource()
+    {
+        level = Level.ROOT;
+        keyspace = null;
+        columnFamily = null;
+    }
+
+    private DataResource(String keyspace)
+    {
+        level = Level.KEYSPACE;
+        this.keyspace = keyspace;
+        columnFamily = null;
+    }
+
+    private DataResource(String keyspace, String columnFamily)
+    {
+        level = Level.COLUMN_FAMILY;
+        this.keyspace = keyspace;
+        this.columnFamily = columnFamily;
+    }
+
+    /**
+     * @return the root-level resource.
+     */
+    public static DataResource root()
+    {
+        return ROOT_RESOURCE;
+    }
+
+    /**
+     * Creates a DataResource representing a keyspace.
+     *
+     * @param keyspace Name of the keyspace.
+     * @return DataResource instance representing the keyspace.
+     */
+    public static DataResource keyspace(String keyspace)
+    {
+        return new DataResource(keyspace);
+    }
+
+    /**
+     * Creates a DataResource instance representing a column family.
+     *
+     * @param keyspace Name of the keyspace.
+     * @param columnFamily Name of the column family.
+     * @return DataResource instance representing the column family.
+     */
+    public static DataResource columnFamily(String keyspace, String columnFamily)
+    {
+        return new DataResource(keyspace, columnFamily);
+    }
+
+    /**
+     * Parses a data resource name into a DataResource instance.
+     *
+     * @param name Name of the data resource.
+     * @return DataResource instance matching the name.
+     */
+    public static DataResource fromName(String name)
+    {
+        String[] parts = StringUtils.split(name, '/');
+
+        if (!parts[0].equals(ROOT_NAME) || parts.length > 3)
+            throw new IllegalArgumentException(String.format("%s is not a valid data resource name", name));
+
+        if (parts.length == 1)
+            return root();
+
+        if (parts.length == 2)
+            return keyspace(parts[1]);
+
+        return columnFamily(parts[1], parts[2]);
+    }
+
+    /**
+     * @return Printable name of the resource.
+     */
+    public String getName()
+    {
+        switch (level)
+        {
+            case ROOT:
+                return ROOT_NAME;
+            case KEYSPACE:
+                return String.format("%s/%s", ROOT_NAME, keyspace);
+            case COLUMN_FAMILY:
+                return String.format("%s/%s/%s", ROOT_NAME, keyspace, columnFamily);
+        }
+        throw new AssertionError();
+    }
+
+    /**
+     * @return Parent of the resource, if any. Throws IllegalStateException if it's the root-level resource.
+     */
+    public IResource getParent()
+    {
+        switch (level)
+        {
+            case KEYSPACE:
+                return root();
+            case COLUMN_FAMILY:
+                return keyspace(keyspace);
+        }
+        throw new IllegalStateException("Root-level resource can't have a parent");
+    }
+
+    public boolean isRootLevel()
+    {
+        return level.equals(Level.ROOT);
+    }
+
+    public boolean isKeyspaceLevel()
+    {
+        return level.equals(Level.KEYSPACE);
+    }
+
+    public boolean isColumnFamilyLevel()
+    {
+        return level.equals(Level.COLUMN_FAMILY);
+    }
+    /**
+     * @return keyspace of the resource. Throws IllegalStateException if it's the root-level resource.
+     */
+    public String getKeyspace()
+    {
+        if (isRootLevel())
+            throw new IllegalStateException("ROOT data resource has no keyspace");
+        return keyspace;
+    }
+
+    /**
+     * @return column family of the resource. Throws IllegalStateException if it's not a cf-level resource.
+     */
+    public String getColumnFamily()
+    {
+        if (!isColumnFamilyLevel())
+            throw new IllegalStateException(String.format("%s data resource has no column family", level));
+        return columnFamily;
+    }
+
+    /**
+     * @return Whether or not the resource has a parent in the hierarchy.
+     */
+    public boolean hasParent()
+    {
+        return !level.equals(Level.ROOT);
+    }
+
+    /**
+     * @return Whether or not the resource exists in Cassandra.
+     */
+    public boolean exists()
+    {
+        switch (level)
+        {
+            case ROOT:
+                return true;
+            case KEYSPACE:
+                return Schema.instance.getTables().contains(keyspace);
+            case COLUMN_FAMILY:
+                return Schema.instance.getCFMetaData(keyspace, columnFamily) != null;
+        }
+        throw new AssertionError();
+    }
+
+    @Override
+    public String toString()
+    {
+        switch (level)
+        {
+            case ROOT:
+                return "<all keyspaces>";
+            case KEYSPACE:
+                return String.format("<keyspace %s>", keyspace);
+            case COLUMN_FAMILY:
+                return String.format("<table %s.%s>", keyspace, columnFamily);
+        }
+        throw new AssertionError();
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+            return true;
+
+        if (!(o instanceof DataResource))
+            return false;
+
+        DataResource ds = (DataResource) o;
+
+        return Objects.equal(this.level, ds.level)
+            && Objects.equal(this.keyspace, ds.keyspace)
+            && Objects.equal(this.columnFamily, ds.columnFamily);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hashCode(level, keyspace, columnFamily);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/IAuthority.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/IAuthority.java b/src/java/org/apache/cassandra/auth/IAuthority.java
deleted file mode 100644
index 8b37470..0000000
--- a/src/java/org/apache/cassandra/auth/IAuthority.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.auth;
-
-import java.util.EnumSet;
-import java.util.List;
-
-import org.apache.cassandra.exceptions.ConfigurationException;
-
-/**
- *
- * Cassandra's resource hierarchy looks something like:
- * {{/cassandra/keyspaces/$ks_name/...}}
- *
- * In table form:
- *  /cassandra/
- *    - no checked permissions
- *    - String
- *    * Separates Cassandra-internal resources from resources that might be provided by plugins.
- *  keyspaces/
- *    - READ, WRITE
- *    - String
- *    * The list of keyspaces: READ/WRITE for this resource mean the ability to view/modify the list of keyspaces.
- *  $ks_name/
- *    - READ, WRITE
- *    - String
- *    * An individual keyspace: READ/WRITE permissions apply to the entire namespace and control the ability to both
- *      view and manipulate column families, and to read and write the data contained within.
- *
- * Over time Cassandra _may_ add additional authorize calls for resources higher or lower in the hierarchy and
- * IAuthority implementations should be able to handle these calls (although many will choose to ignore them
- * completely).
- *
- * NB: {{/cassandra/}} will not be checked for permissions via a call to IAuthority.authorize, so IAuthority
- * implementations can only deny access when a user attempts to access an ancestor resource.
- */
-public interface IAuthority
-{
-    /**
-     * @param user An authenticated user from a previous call to IAuthenticator.authenticate.
-     * @param resource A List of Objects containing Strings and byte[]s: represents a resource in the hierarchy
-     * described in the Javadocs.
-     * @return An AccessLevel representing the permissions for the user and resource: should never return null.
-     */
-    public EnumSet<Permission> authorize(AuthenticatedUser user, List<Object> resource);
-
-    public void validateConfiguration() throws ConfigurationException;
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/IAuthority2.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/IAuthority2.java b/src/java/org/apache/cassandra/auth/IAuthority2.java
deleted file mode 100644
index 2933f32..0000000
--- a/src/java/org/apache/cassandra/auth/IAuthority2.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.cassandra.auth;
-
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.transport.messages.ResultMessage;
-
-public interface IAuthority2 extends IAuthority
-{
-    /**
-     * Setup is called each time upon system startup
-     */
-    public void setup();
-
-    /**
-     * GRANT <permission> ON <resource> TO <user> [WITH GRANT OPTION];
-     *
-     * @param granter The user who grants the permission
-     * @param permission The specific permission
-     * @param to Grantee of the permission
-     * @param resource The resource which is affect by permission change
-     * @param grantOption Does grantee has a permission to grant the same kind of permission on this particular resource?
-     *
-     * @throws InvalidRequestException upon parameter misconfiguration or internal error.
-     */
-    public void grant(AuthenticatedUser granter, Permission permission, String to, CFName resource, boolean grantOption) throws UnauthorizedException, InvalidRequestException;
-
-    /**
-     * REVOKE <permission> ON <resource> FROM <user_name>;
-     *
-     * @param revoker The user know requests permission revoke
-     * @param permission The permission to revoke
-     * @param from The user to revoke permission from.
-     * @param resource The resource affected by permission change.
-     *
-     * @throws InvalidRequestException upon parameter misconfiguration or internal error.
-     */
-    public void revoke(AuthenticatedUser revoker, Permission permission, String from, CFName resource) throws UnauthorizedException, InvalidRequestException;
-
-    /**
-     * LIST GRANTS FOR <user>;
-     * Not 'SHOW' because it's reserved for CQLsh for commands like 'show cluster'
-     *
-     * @param username The username to look for permissions.
-     *
-     * @return All of the permission of this particular user.
-     *
-     * @throws InvalidRequestException upon parameter misconfiguration or internal error.
-     */
-    public ResultMessage listPermissions(String username) throws UnauthorizedException, InvalidRequestException;
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/IAuthorityContainer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/IAuthorityContainer.java b/src/java/org/apache/cassandra/auth/IAuthorityContainer.java
deleted file mode 100644
index 4aeb315..0000000
--- a/src/java/org/apache/cassandra/auth/IAuthorityContainer.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.cassandra.auth;
-
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.transport.messages.ResultMessage;
-
-/**
- * 1.1.x : Temporary measure to unable dynamic operations without changing IAuthority interface.
- */
-public class IAuthorityContainer
-{
-    private final IAuthority authority;
-    private final IAuthority2 dynamicAuthority;
-
-    public IAuthorityContainer(IAuthority authority)
-    {
-        this.authority = authority;
-        dynamicAuthority = (authority instanceof IAuthority2) ? ((IAuthority2) authority) : null;
-    }
-
-    public void setup()
-    {
-        if (dynamicAuthority != null)
-            dynamicAuthority.setup();
-    }
-
-    public boolean isDynamic()
-    {
-        return dynamicAuthority != null;
-    }
-
-    public IAuthority getAuthority()
-    {
-        return authority;
-    }
-
-    public void grant(AuthenticatedUser granter, Permission permission, String to, CFName resource, boolean grantOption) throws UnauthorizedException, InvalidRequestException
-    {
-        if (dynamicAuthority == null)
-            throw new InvalidRequestException("GRANT operation is not supported by your authority: " + authority);
-
-        if (permission.equals(Permission.READ) || permission.equals(Permission.WRITE))
-            throw new InvalidRequestException(String.format("Error setting permission to: %s, available permissions are %s", permission, Permission.GRANULAR_PERMISSIONS));
-
-        dynamicAuthority.grant(granter, permission, to, resource, grantOption);
-    }
-
-    public void revoke(AuthenticatedUser revoker, Permission permission, String from, CFName resource) throws UnauthorizedException, InvalidRequestException
-    {
-        if (dynamicAuthority == null)
-            throw new InvalidRequestException("REVOKE operation is not supported by your authority: " + authority);
-
-        dynamicAuthority.revoke(revoker, permission, from, resource);
-    }
-
-    public ResultMessage listPermissions(String username) throws UnauthorizedException, InvalidRequestException
-    {
-        if (dynamicAuthority == null)
-            throw new InvalidRequestException("LIST GRANTS operation is not supported by your authority: " + authority);
-
-        return dynamicAuthority.listPermissions(username);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/IAuthorizer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/IAuthorizer.java b/src/java/org/apache/cassandra/auth/IAuthorizer.java
new file mode 100644
index 0000000..916878b
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/IAuthorizer.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+import java.util.Set;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.UnauthorizedException;
+
+/**
+ * Primary Cassandra authorization interface.
+ */
+public interface IAuthorizer
+{
+    /**
+     * The primary IAuthorizer method. Returns a set of permissions of a user on a resource.
+     *
+     * @param user Authenticated user requesting authorization.
+     * @param resource Resource for which the authorization is being requested. @see DataResource.
+     * @return Set of permissions of the user on the resource. Should never return null. Use Permission.NONE instead.
+     */
+    public Set<Permission> authorize(AuthenticatedUser user, IResource resource);
+
+    /**
+     * Grants a set of permissions on a resource to a user.
+     * The opposite of revoke().
+     *
+     * @param performer User who grants the permissions.
+     * @param permissions Set of permissions to grant.
+     * @param to Grantee of the permissions.
+     * @param resource Resource on which to grant the permissions.
+     *
+     * @throws UnauthorizedException if the granting user isn't allowed to grant (and revoke) the permissions on the resource.
+     * @throws InvalidRequestException upon parameter misconfiguration or internal error.
+     */
+    public void grant(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String to)
+    throws UnauthorizedException, InvalidRequestException;
+
+    /**
+     * Revokes a set of permissions on a resource from a user.
+     * The opposite of grant().
+     *
+     * @param performer User who revokes the permissions.
+     * @param permissions Set of permissions to revoke.
+     * @param from Revokee of the permissions.
+     * @param resource Resource on which to revoke the permissions.
+     *
+     * @throws UnauthorizedException if the revoking user isn't allowed to revoke the permissions on the resource.
+     * @throws InvalidRequestException upon parameter misconfiguration or internal error.
+     */
+    public void revoke(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String from)
+    throws UnauthorizedException, InvalidRequestException;
+
+    /**
+     * Returns a list of permissions on a resource of a user.
+     *
+     * @param performer User who wants to see the permissions.
+     * @param permissions Set of Permission values the user is interested in. The result should only include the matching ones.
+     * @param resource The resource on which permissions are requested. Can be null, in which case permissions on all resources
+     *                 should be returned.
+     * @param of The user whose permissions are requested. Can be null, in which case permissions of every user should be returned.
+     *
+     * @return All of the matching permission that the requesting user is authorized to know about.
+     *
+     * @throws UnauthorizedException if the user isn't allowed to view the requested permissions.
+     * @throws InvalidRequestException upon parameter misconfiguration or internal error.
+     */
+    public Set<PermissionDetails> listPermissions(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String of)
+    throws UnauthorizedException, InvalidRequestException;
+
+    /**
+     * This method is called before deleting a user with DROP USER query so that a new user with the same
+     * name wouldn't inherit permissions of the deleted user in the future.
+     *
+     * @param droppedUser The user to revoke all permissions from.
+     */
+    public void revokeAll(String droppedUser);
+
+    /**
+     * This method is called after a resource is removed (i.e. keyspace or a table is dropped).
+     *
+     * @param droppedResource The resource to revoke all permissions on.
+     */
+    public void revokeAll(IResource droppedResource);
+
+    /**
+     * Set of resources that should be made inaccessible to users and only accessible internally.
+     *
+     * @return Keyspaces, column families that will be unreadable and unmodifiable by users; other resources.
+     */
+    public Set<? extends IResource> protectedResources();
+
+    /**
+     * Validates configuration of IAuthorizer implementation (if configurable).
+     *
+     * @throws ConfigurationException when there is a configuration error.
+     */
+    public void validateConfiguration() throws ConfigurationException;
+
+    /**
+     * Setup is called once upon system startup to initialize the IAuthorizer.
+     *
+     * For example, use this method to create any required keyspaces/column families.
+     */
+    public void setup();
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/IResource.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/IResource.java b/src/java/org/apache/cassandra/auth/IResource.java
new file mode 100644
index 0000000..635b0a6
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/IResource.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+/**
+ * The interface at the core of Cassandra authorization.
+ *
+ * Represents a resource in the hierarchy.
+ * Currently just one resource type is supported by Cassandra
+ * @see DataResource
+ */
+public interface IResource
+{
+    /**
+     * @return printable name of the resource.
+     */
+    public String getName();
+
+    /**
+     * Gets next resource in the hierarchy. Call hasParent first to make sure there is one.
+     *
+     * @return Resource parent (or IllegalStateException if there is none). Never a null.
+     */
+    public IResource getParent();
+
+    /**
+     * Indicates whether or not this resource has a parent in the hierarchy.
+     *
+     * Please perform this check before calling getParent() method.
+     * @return Whether or not the resource has a parent.
+     */
+    public boolean hasParent();
+
+    /**
+     * @return Whether or not this resource exists in Cassandra.
+     */
+    public boolean exists();
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/LegacyAuthorizer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/LegacyAuthorizer.java b/src/java/org/apache/cassandra/auth/LegacyAuthorizer.java
new file mode 100644
index 0000000..99e2ba8
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/LegacyAuthorizer.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+import java.util.*;
+
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.UnauthorizedException;
+
+/**
+ * Provides a transitional IAuthorizer implementation for old-style (pre-1.2) authorizers.
+ *
+ * Translates old-style authorze() calls to the new-style, expands Permission.READ and Permission.WRITE
+ * into the new Permission values, translates the new resource hierarchy into the old hierarchy.
+ * Stubs the rest of the new methods.
+ * Subclass LegacyAuthorizer instead of implementing the old IAuthority and your old IAuthority implementation should
+ * continue to work.
+ */
+public abstract class LegacyAuthorizer implements IAuthorizer
+{
+    /**
+     * @param user Authenticated user requesting authorization.
+     * @param resource List of Objects containing Strings and byte[]s: represents a resource in the old hierarchy.
+     * @return Set of permissions of the user on the resource. Should never return null. Use Permission.NONE instead.
+     */
+    public abstract EnumSet<Permission> authorize(AuthenticatedUser user, List<Object> resource);
+
+    @Override
+    public void setup()
+    {
+    }
+
+    /**
+     * Translates new-style authorize() method call to the old-style (including permissions and the hierarchy).
+     */
+    @Override
+    public Set<Permission> authorize(AuthenticatedUser user, IResource resource)
+    {
+        if (!(resource instanceof DataResource))
+            throw new IllegalArgumentException(String.format("%s resource is not supported by LegacyAuthorizer", resource.getName()));
+        DataResource dr = (DataResource) resource;
+
+        List<Object> legacyResource = new ArrayList<Object>();
+        legacyResource.add(Resources.ROOT);
+        legacyResource.add(Resources.KEYSPACES);
+        if (!dr.isRootLevel())
+            legacyResource.add(dr.getKeyspace());
+        if (dr.isColumnFamilyLevel())
+            legacyResource.add(dr.getColumnFamily());
+
+        Set<Permission> permissions = authorize(user, legacyResource);
+        if (permissions.contains(Permission.READ))
+            permissions.add(Permission.SELECT);
+        if (permissions.contains(Permission.WRITE))
+            permissions.addAll(EnumSet.of(Permission.CREATE, Permission.ALTER, Permission.DROP, Permission.MODIFY));
+
+        return permissions;
+    }
+
+    @Override
+    public void grant(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String to)
+    throws InvalidRequestException, UnauthorizedException
+    {
+        throw new InvalidRequestException("GRANT operation is not supported by LegacyAuthorizer");
+    }
+
+    @Override
+    public void revoke(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String from)
+    throws InvalidRequestException, UnauthorizedException
+    {
+        throw new InvalidRequestException("REVOKE operation is not supported by LegacyAuthorizer");
+    }
+
+    @Override
+    public void revokeAll(String droppedUser)
+    {
+    }
+
+    @Override
+    public void revokeAll(IResource droppedResource)
+    {
+    }
+
+    @Override
+    public Set<PermissionDetails> listPermissions(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String of)
+    throws InvalidRequestException, UnauthorizedException
+    {
+        throw new InvalidRequestException("LIST PERMISSIONS operation is not supported by LegacyAuthorizer");
+    }
+
+    @Override
+    public Set<IResource> protectedResources()
+    {
+        return Collections.emptySet();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/MigrationListener.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/MigrationListener.java b/src/java/org/apache/cassandra/auth/MigrationListener.java
new file mode 100644
index 0000000..66ac4b0
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/MigrationListener.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.service.IMigrationListener;
+
+/**
+ * IMigrationListener implementation that cleans up permissions on dropped resources.
+ */
+public class MigrationListener implements IMigrationListener
+{
+    public void onDropKeyspace(String ksName)
+    {
+        DatabaseDescriptor.getAuthorizer().revokeAll(DataResource.keyspace(ksName));
+    }
+
+    public void onDropColumnFamly(String ksName, String cfName)
+    {
+        DatabaseDescriptor.getAuthorizer().revokeAll(DataResource.columnFamily(ksName, cfName));
+    }
+
+    public void onCreateKeyspace(String ksName)
+    {
+    }
+
+    public void onCreateColumnFamly(String ksName, String cfName)
+    {
+    }
+
+    public void onUpdateKeyspace(String ksName)
+    {
+    }
+
+    public void onUpdateColumnFamly(String ksName, String cfName)
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/Permission.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/Permission.java b/src/java/org/apache/cassandra/auth/Permission.java
index 69e2d90..a982c85 100644
--- a/src/java/org/apache/cassandra/auth/Permission.java
+++ b/src/java/org/apache/cassandra/auth/Permission.java
@@ -18,45 +18,40 @@
 package org.apache.cassandra.auth;
 
 import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
 
 /**
- * An enum encapsulating the set of possible permissions that an authenticated user can have for a resource.
+ * An enum encapsulating the set of possible permissions that an authenticated user can have on a resource.
  *
- * IAuthority implementations may encode permissions using ordinals, so the Enum order must never change.
+ * IAuthorizer implementations may encode permissions using ordinals, so the Enum order must never change order.
+ * Adding new values is ok.
  */
 public enum Permission
 {
-    READ,  // for backward compatibility
-    WRITE, // for backward compatibility
-
-    FULL_ACCESS,
-    NO_ACCESS,
+    @Deprecated
+    READ,
+    @Deprecated
+    WRITE,
 
     // schema management
-    DESCRIBE,
-    CREATE,
-    ALTER,
-    DROP,
+    CREATE, // required for CREATE KEYSPACE and CREATE TABLE.
+    ALTER,  // required for ALTER KEYSPACE, ALTER TABLE, CREATE INDEX, DROP INDEX.
+    DROP,   // required for DROP KEYSPACE and DROP TABLE.
 
     // data access
-    UPDATE,
-    DELETE,
-    SELECT;
-
-    public static final EnumSet<Permission> ALL = EnumSet.allOf(Permission.class);
-    public static final EnumSet<Permission> NONE = EnumSet.noneOf(Permission.class);
-    public static final EnumSet<Permission> GRANULAR_PERMISSIONS = EnumSet.range(FULL_ACCESS, SELECT);
-    public static final EnumSet<Permission> ALLOWED_SYSTEM_ACTIONS = EnumSet.of(DESCRIBE, UPDATE, DELETE, SELECT);
-
-    /**
-     * Maps old permissions to the new ones as we want to support old client IAuthority implementations
-     * and new style of granular permission checking at the same time.
-     */
-    public static final Map<Permission, EnumSet<Permission>> oldToNew = new HashMap<Permission, EnumSet<Permission>>(2)
-    {{
-        put(READ,  EnumSet.of(DESCRIBE, SELECT));
-        put(WRITE, EnumSet.range(DESCRIBE, DELETE));
-    }};
+    SELECT, // required for SELECT.
+    MODIFY, // required for INSERT, UPDATE, DELETE, TRUNCATE.
+
+    // permission management
+    AUTHORIZE; // required for GRANT and REVOKE.
+
+
+    public static final Set<Permission> ALL_DATA =
+            ImmutableSet.copyOf(EnumSet.range(Permission.CREATE, Permission.AUTHORIZE));
+
+    public static final Set<Permission> ALL =
+            ImmutableSet.copyOf(EnumSet.range(Permission.CREATE, Permission.AUTHORIZE));
+    public static final Set<Permission> NONE = ImmutableSet.of();
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/PermissionDenied.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/PermissionDenied.java b/src/java/org/apache/cassandra/auth/PermissionDenied.java
deleted file mode 100644
index 22bf35a..0000000
--- a/src/java/org/apache/cassandra/auth/PermissionDenied.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cassandra.auth;
-
-import org.apache.cassandra.thrift.InvalidRequestException;
-
-public class PermissionDenied extends InvalidRequestException
-{
-    public PermissionDenied(String reason)
-    {
-        super(reason);
-    }
-
-    public String getMessage()
-    {
-        return why;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/PermissionDetails.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/PermissionDetails.java b/src/java/org/apache/cassandra/auth/PermissionDetails.java
new file mode 100644
index 0000000..52a8712
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/PermissionDetails.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ComparisonChain;
+
+/**
+ *  Sets of instances of this class are returned by IAuthorizer.listPermissions() method for LIST PERMISSIONS query.
+ *  None of the fields are nullable.
+ */
+public class PermissionDetails implements Comparable<PermissionDetails>
+{
+    public final String username;
+    public final IResource resource;
+    public final Permission permission;
+
+    public PermissionDetails(String username, IResource resource, Permission permission)
+    {
+        this.username = username;
+        this.resource = resource;
+        this.permission = permission;
+    }
+
+    @Override
+    public int compareTo(PermissionDetails other)
+    {
+        return ComparisonChain.start()
+                              .compare(username, other.username)
+                              .compare(resource.getName(), other.resource.getName())
+                              .compare(permission, other.permission)
+                              .result();
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("<PermissionDetails username:%s resource:%s permission:%s>",
+                             username,
+                             resource.getName(),
+                             permission);
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        return Objects.equal(this, o);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hashCode(username, resource, permission);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/auth/Resources.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/Resources.java b/src/java/org/apache/cassandra/auth/Resources.java
index 26d2abf..86900f9 100644
--- a/src/java/org/apache/cassandra/auth/Resources.java
+++ b/src/java/org/apache/cassandra/auth/Resources.java
@@ -17,20 +17,38 @@
  */
 package org.apache.cassandra.auth;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.cassandra.utils.Hex;
 
-/**
- * Constants related to Cassandra's resource hierarchy.
- *
- * A resource in Cassandra is a List containing both Strings and byte[]s.
- */
 public final class Resources
 {
+    /**
+     * Construct a chain of resource parents starting with the resource and ending with the root.
+     *
+     * @param resource The staring point.
+     * @return list of resource in the chain form start to the root.
+     */
+    public static List<? extends IResource> chain(IResource resource)
+    {
+        List<IResource> chain = new ArrayList<IResource>();
+        while (true)
+        {
+           chain.add(resource);
+           if (!resource.hasParent())
+               break;
+           resource = resource.getParent();
+        }
+        return chain;
+    }
+
+    @Deprecated
     public final static String ROOT = "cassandra";
+    @Deprecated
     public final static String KEYSPACES = "keyspaces";
 
+    @Deprecated
     public static String toString(List<Object> resource)
     {
         StringBuilder buff = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/config/Config.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index 6395690..24edf08 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -30,7 +30,8 @@ public class Config
 {
     public String cluster_name = "Test Cluster";
     public String authenticator;
-    public String authority;
+    public String authority; // for backwards compatibility - will log a warning.
+    public String authorizer;
 
     /* Hashing strategy Random or OPHF */
     public String partitioner;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index bb3e7c1..41eb437 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -51,7 +51,6 @@ import org.apache.cassandra.scheduler.IRequestScheduler;
 import org.apache.cassandra.scheduler.NoScheduler;
 import org.apache.cassandra.service.CacheService;
 import org.apache.cassandra.service.MigrationManager;
-import org.apache.cassandra.thrift.ThriftServer;
 import org.apache.cassandra.utils.FBUtilities;
 import org.yaml.snakeyaml.Loader;
 import org.yaml.snakeyaml.TypeDescription;
@@ -77,8 +76,7 @@ public class DatabaseDescriptor
     private static Config conf;
 
     private static IAuthenticator authenticator = new AllowAllAuthenticator();
-    private static IAuthority authority = new AllowAllAuthority();
-    private static IAuthorityContainer authorityContainer;
+    private static IAuthorizer authorizer = new AllowAllAuthorizer();
 
     private final static String DEFAULT_CONFIGURATION = "cassandra.yaml";
 
@@ -206,15 +204,23 @@ public class DatabaseDescriptor
 
 	        logger.debug("page_cache_hinting is " + conf.populate_io_cache_on_flush);
 
-            /* Authentication and authorization backend, implementing IAuthenticator and IAuthority */
+            /* Authentication and authorization backend, implementing IAuthenticator and IAuthorizer */
             if (conf.authenticator != null)
                 authenticator = FBUtilities.<IAuthenticator>construct(conf.authenticator, "authenticator");
+
             if (conf.authority != null)
-                authority = FBUtilities.<IAuthority>construct(conf.authority, "authority");
-            authenticator.validateConfiguration();
-            authority.validateConfiguration();
+            {
+                logger.warn("Please rename 'authority' to 'authorizer' in cassandra.yaml");
+                if (!conf.authority.equals("org.apache.cassandra.auth.AllowAllAuthority"))
+                    throw new ConfigurationException("IAuthority interface has been deprecated,"
+                                                     + " please implement IAuthorizer instead.");
+            }
+
+            if (conf.authorizer != null)
+                authorizer = FBUtilities.<IAuthorizer>construct(conf.authorizer, "authorizer");
 
-            authorityContainer = new IAuthorityContainer(authority);
+            authenticator.validateConfiguration();
+            authorizer.validateConfiguration();
 
             /* Hashing strategy */
             if (conf.partitioner == null)
@@ -462,12 +468,6 @@ public class DatabaseDescriptor
                 Schema.instance.setTableDefinition(ksmd);
             }
 
-            // setup schema required for authorization
-            authorityContainer.setup();
-
-            // setup schema required for authorization
-            authorityContainer.setup();
-
             /* Load the seeds for node contact points */
             if (conf.seed_provider == null)
             {
@@ -585,14 +585,9 @@ public class DatabaseDescriptor
         return authenticator;
     }
 
-    public static IAuthority getAuthority()
-    {
-        return authority;
-    }
-
-    public static IAuthorityContainer getAuthorityContainer()
+    public static IAuthorizer getAuthorizer()
     {
-        return authorityContainer;
+        return authorizer;
     }
 
     public static int getThriftMaxMessageLength()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/cql/DeleteStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/DeleteStatement.java b/src/java/org/apache/cassandra/cql/DeleteStatement.java
index 4190c80..87f48aa 100644
--- a/src/java/org/apache/cassandra/cql/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql/DeleteStatement.java
@@ -73,7 +73,7 @@ public class DeleteStatement extends AbstractModification
     {
         CFMetaData metadata = validateColumnFamily(keyspace, columnFamily);
 
-        clientState.hasColumnFamilyAccess(columnFamily, Permission.DELETE);
+        clientState.hasColumnFamilyAccess(keyspace, columnFamily, Permission.MODIFY);
         AbstractType<?> keyType = Schema.instance.getCFMetaData(keyspace, columnFamily).getKeyValidator();
 
         List<IMutation> rowMutations = new ArrayList<IMutation>(keys.size());

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a3eb1a6/src/java/org/apache/cassandra/cql/DropIndexStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/DropIndexStatement.java b/src/java/org/apache/cassandra/cql/DropIndexStatement.java
index 7df1f51..5114a41 100644
--- a/src/java/org/apache/cassandra/cql/DropIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql/DropIndexStatement.java
@@ -17,55 +17,64 @@
  */
 package org.apache.cassandra.cql;
 
-import java.io.IOException;
-
 import org.apache.cassandra.config.*;
-import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.thrift.CfDef;
-import org.apache.cassandra.thrift.ColumnDef;
 
 public class DropIndexStatement
 {
-    public final String index;
+    public final String indexName;
+    private String keyspace;
 
     public DropIndexStatement(String indexName)
     {
-        index = indexName;
+        this.indexName = indexName;
     }
 
-    public CFMetaData generateCFMetadataUpdate(String keyspace)
-    throws InvalidRequestException, ConfigurationException, IOException
+    public void setKeyspace(String keyspace)
     {
-        CfDef cfDef = null;
+        this.keyspace = keyspace;
+    }
 
-        KSMetaData ksm = Schema.instance.getTableDefinition(keyspace);
+    public String getColumnFamily() throws InvalidRequestException
+    {
+        return findIndexedCF().cfName;
+    }
+
+    public CFMetaData generateCFMetadataUpdate() throws InvalidRequestException
+    {
+        return updateCFMetadata(findIndexedCF());
+    }
 
+    private CFMetaData updateCFMetadata(CFMetaData cfm) throws InvalidRequestException
+    {
+        ColumnDefinition column = findIndexedColumn(cfm);
+        assert column != null;
+        CFMetaData cloned = cfm.clone();
+        ColumnDefinition toChange = cloned.getColumn_metadata().get(column.name);
+        assert toChange.getIndexName() != null && toChange.getIndexName().equals(indexName);
+        toChange.setIndexName(null);
+        toChange.setIndexType(null, null);
+        return cloned;
+    }
+
+    private CFMetaData findIndexedCF() throws InvalidRequestException
+    {
+        KSMetaData ksm = Schema.instance.getTableDefinition(keyspace);
         for (CFMetaData cfm : ksm.cfMetaData().values())
         {
-            cfDef = getUpdatedCFDef(cfm.toThrift());
-            if (cfDef != null)
-                break;
+            if (findIndexedColumn(cfm) != null)
+                return cfm;
         }
-
-        if (cfDef == null)
-            throw new InvalidRequestException("Index '" + index + "' could not be found in any of the ColumnFamilies of keyspace '" + keyspace + "'");
-
-        return CFMetaData.fromThrift(cfDef);
+        throw new InvalidRequestException("Index '" + indexName + "' could not be found in any of the column families of keyspace '" + keyspace + "'");
     }
 
-    private CfDef getUpdatedCFDef(CfDef cfDef) throws InvalidRequestException
+    private ColumnDefinition findIndexedColumn(CFMetaData cfm)
     {
-        for (ColumnDef column : cfDef.column_metadata)
+        for (ColumnDefinition column : cfm.getColumn_metadata().values())
         {
-            if (column.isSetIndex_type() && column.isSetIndex_name() && column.index_name.equals(index))
-            {
-                column.unsetIndex_name();
-                column.unsetIndex_type();
-                return cfDef;
-            }
+            if (column.getIndexType() != null && column.getIndexName() != null && column.getIndexName().equals(indexName))
+                return column;
         }
-
         return null;
     }
 }


Mime
View raw message