Author: eevans
Date: Wed Oct 6 15:19:13 2010
New Revision: 1005080
URL: http://svn.apache.org/viewvc?rev=1005080&view=rev
Log:
refactor ClientState and RPC for CF authorizations
Patch by eevans; reviewed by Stu Hood for CASSANDRA-1554
Modified:
cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java
cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java
cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
Modified:
cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java?rev=1005080&r1=1005079&r2=1005080&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/avro/CassandraServer.java Wed
Oct 6 15:19:13 2010
@@ -823,7 +823,7 @@ public class CassandraServer implements
{
try
{
- state().hasKeyspaceAccess(perm);
+ state().hasColumnFamilyListAccess(perm);
}
catch (org.apache.cassandra.thrift.InvalidRequestException e)
{
@@ -1040,7 +1040,7 @@ public class CassandraServer implements
try
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyAccess((String)columnFamily,
Permission.WRITE);
schedule();
StorageProxy.truncateBlocking(state().getKeyspace(),
columnFamily.toString());
}
@@ -1073,7 +1073,7 @@ public class CassandraServer implements
String keyspace = state().getKeyspace();
try
{
- state().hasKeyspaceAccess(Permission.READ);
+
state().hasColumnFamilyAccess(column_parent.column_family.toString(),
Permission.READ);
}
catch (org.apache.cassandra.thrift.InvalidRequestException thriftE)
{
@@ -1139,7 +1139,7 @@ public class CassandraServer implements
try
{
- state().hasKeyspaceAccess(Permission.READ);
+
state().hasColumnFamilyAccess(column_parent.column_family.toString(),
Permission.READ);
}
catch (org.apache.cassandra.thrift.InvalidRequestException thriftE)
{
Modified: cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java?rev=1005080&r1=1005079&r2=1005080&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/service/ClientState.java Wed
Oct 6 15:19:13 2010
@@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.auth.AuthenticatedUser;
import org.apache.cassandra.auth.Permission;
import org.apache.cassandra.auth.Resources;
-import org.apache.cassandra.config.Config.RequestSchedulerId;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.thrift.AuthenticationException;
import org.apache.cassandra.thrift.InvalidRequestException;
@@ -42,8 +41,6 @@ public class ClientState
// Current user for the session
private AuthenticatedUser user;
private String keyspace;
- private Set<Permission> keyspaceAccess;
- private List<Object> resource = new ArrayList<Object>();
/**
* Construct a new, empty ClientState: can be reused after logout() or
reset().
@@ -52,26 +49,7 @@ public class ClientState
{
reset();
}
-
- /**
- * Called when the keyspace or user have changed.
- */
- private void updateKeyspaceAccess()
- {
- if (user == null || keyspace == null)
- // user is not logged in or keyspace is not set
- keyspaceAccess = null;
- else
- {
- // authorize the user for the current keyspace
- resource.clear();
- resource.add(Resources.ROOT);
- resource.add(Resources.KEYSPACES);
- resource.add(keyspace);
- keyspaceAccess = DatabaseDescriptor.getAuthority().authorize(user,
resource);
- }
- }
-
+
public String getKeyspace()
{
return keyspace;
@@ -80,7 +58,6 @@ public class ClientState
public void setKeyspace(String ks)
{
keyspace = ks;
- updateKeyspaceAccess();
}
public String getSchedulingValue()
@@ -101,7 +78,6 @@ public class ClientState
if (logger.isDebugEnabled())
logger.debug("logged in: {}", user);
this.user = user;
- updateKeyspaceAccess();
}
public void logout()
@@ -115,8 +91,6 @@ public class ClientState
{
user = DatabaseDescriptor.getAuthenticator().defaultUser();
keyspace = null;
- keyspaceAccess = null;
- resource.clear();
}
/**
@@ -124,25 +98,54 @@ public class ClientState
*/
public void hasKeyspaceListAccess(Permission perm) throws
InvalidRequestException
{
- if (user == null)
- throw new InvalidRequestException("You have not logged in");
+ validateLogin();
+
List<Object> resource = Arrays.<Object>asList(Resources.ROOT,
Resources.KEYSPACES);
Set<Permission> perms =
DatabaseDescriptor.getAuthority().authorize(user, resource);
hasAccess(user, perms, perm, resource);
}
-
+
/**
- * Confirms that the client thread has the given Permission in the context
of the current Keyspace.
+ * Confirms that the client thread has the given Permission for the
ColumnFamily list of
+ * the current keyspace.
*/
- public void hasKeyspaceAccess(Permission perm) throws
InvalidRequestException
+ public void hasColumnFamilyListAccess(Permission perm) throws
InvalidRequestException
+ {
+ validateLogin();
+ validateKeyspace();
+
+ List<Object> resource = Arrays.<Object>asList(Resources.ROOT,
Resources.KEYSPACES, keyspace);
+ Set<Permission> perms =
DatabaseDescriptor.getAuthority().authorize(user, resource);
+
+ hasAccess(user, perms, perm, resource);
+ }
+
+ /**
+ * Confirms that the client thread has the given Permission in the context
of the given
+ * ColumnFamily and the current keyspace.
+ */
+ public void hasColumnFamilyAccess(String columnFamily, Permission perm)
throws InvalidRequestException
+ {
+ validateLogin();
+ validateKeyspace();
+
+ List<Object> resource = Arrays.<Object>asList(Resources.ROOT,
Resources.KEYSPACES, keyspace, columnFamily);
+ Set<Permission> perms =
DatabaseDescriptor.getAuthority().authorize(user, resource);
+
+ hasAccess(user, perms, perm, resource);
+ }
+
+ private void validateLogin() throws InvalidRequestException
{
if (user == null)
throw new InvalidRequestException("You have not logged in");
- if (keyspaceAccess == null)
+ }
+
+ private void validateKeyspace() throws InvalidRequestException
+ {
+ if (keyspace == null)
throw new InvalidRequestException("You have not set a keyspace for
this session");
-
- hasAccess(user, keyspaceAccess, perm, resource);
}
private static void hasAccess(AuthenticatedUser user, Set<Permission>
perms, Permission perm, List<Object> resource) throws InvalidRequestException
Modified:
cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
URL:
http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java?rev=1005080&r1=1005079&r2=1005080&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
(original)
+++ cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
Wed Oct 6 15:19:13 2010
@@ -257,7 +257,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("get_slice");
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.READ);
return multigetSliceInternal(state().getKeyspace(),
Collections.singletonList(key), column_parent, predicate,
consistency_level).get(key);
}
@@ -267,7 +267,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("multiget_slice");
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.READ);
return multigetSliceInternal(state().getKeyspace(), keys,
column_parent, predicate, consistency_level);
}
@@ -306,7 +306,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("get");
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_path.column_family,
Permission.READ);
String keyspace = state().getKeyspace();
ThriftValidation.validateColumnPath(keyspace, column_path);
@@ -334,7 +334,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("get_count");
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.READ);
return get_slice(key, column_parent, predicate,
consistency_level).size();
}
@@ -345,7 +345,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("multiget_count");
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.READ);
String keyspace = state().getKeyspace();
Map<byte[], Integer> counts = new HashMap<byte[], Integer>();
@@ -363,7 +363,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("insert");
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.WRITE);
ThriftValidation.validateKey(key);
ThriftValidation.validateColumnParent(state().getKeyspace(),
column_parent);
@@ -386,8 +386,8 @@ public class CassandraServer implements
{
if (logger.isDebugEnabled())
logger.debug("batch_mutate");
-
- state().hasKeyspaceAccess(Permission.WRITE);
+
+ List<String> cfamsSeen = new ArrayList<String>();
List<RowMutation> rowMutations = new ArrayList<RowMutation>();
for (Map.Entry<byte[], Map<String, List<Mutation>>> mutationEntry:
mutation_map.entrySet())
@@ -399,6 +399,13 @@ public class CassandraServer implements
for (Map.Entry<String, List<Mutation>> columnFamilyMutations :
columnFamilyToMutations.entrySet())
{
String cfName = columnFamilyMutations.getKey();
+
+ // Avoid unneeded authorizations
+ if (!(cfamsSeen.contains(cfName)))
+ {
+ state().hasColumnFamilyAccess(cfName, Permission.WRITE);
+ cfamsSeen.add(cfName);
+ }
for (Mutation mutation : columnFamilyMutations.getValue())
{
@@ -417,7 +424,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("remove");
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyAccess(column_path.column_family,
Permission.WRITE);
ThriftValidation.validateKey(key);
ThriftValidation.validateColumnPathOrParent(state().getKeyspace(),
column_path);
@@ -472,7 +479,7 @@ public class CassandraServer implements
logger.debug("range_slice");
String keyspace = state().getKeyspace();
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.READ);
ThriftValidation.validateColumnParent(keyspace, column_parent);
ThriftValidation.validatePredicate(keyspace, column_parent, predicate);
@@ -535,7 +542,7 @@ public class CassandraServer implements
if (logger.isDebugEnabled())
logger.debug("scan");
- state().hasKeyspaceAccess(Permission.READ);
+ state().hasColumnFamilyAccess(column_parent.column_family,
Permission.READ);
String keyspace = state().getKeyspace();
ThriftValidation.validateColumnParent(keyspace, column_parent);
ThriftValidation.validatePredicate(keyspace, column_parent,
column_predicate);
@@ -689,7 +696,7 @@ public class CassandraServer implements
public String system_add_column_family(CfDef cf_def) throws
InvalidRequestException, TException
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyListAccess(Permission.WRITE);
try
{
applyMigrationOnStage(new
AddColumnFamily(convertToCFMetaData(cf_def)));
@@ -711,7 +718,7 @@ public class CassandraServer implements
public String system_drop_column_family(String column_family) throws
InvalidRequestException, TException
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyListAccess(Permission.WRITE);
try
{
@@ -734,7 +741,7 @@ public class CassandraServer implements
public String system_rename_column_family(String old_name, String
new_name) throws InvalidRequestException, TException
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyListAccess(Permission.WRITE);
try
{
@@ -834,7 +841,7 @@ public class CassandraServer implements
public String system_rename_keyspace(String old_name, String new_name)
throws InvalidRequestException, TException
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyListAccess(Permission.WRITE);
try
{
@@ -858,7 +865,7 @@ public class CassandraServer implements
/** update an existing keyspace, but do not allow column family
modifications. */
public String system_update_keyspace(KsDef ks_def) throws
InvalidRequestException, TException
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyListAccess(Permission.WRITE);
if (ks_def.getCf_defs() != null && ks_def.getCf_defs().size() > 0)
throw new InvalidRequestException("Keyspace update must not
contain any column family definitions.");
@@ -896,7 +903,7 @@ public class CassandraServer implements
public String system_update_column_family(CfDef cf_def) throws
InvalidRequestException, TException
{
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyListAccess(Permission.WRITE);
if (cf_def.keyspace == null || cf_def.name == null)
throw new InvalidRequestException("Keyspace and CF name must be
set.");
@@ -956,7 +963,7 @@ public class CassandraServer implements
public void truncate(String cfname) throws InvalidRequestException,
UnavailableException, TException
{
logger.debug("truncating {} in {}", cfname, state().getKeyspace());
- state().hasKeyspaceAccess(Permission.WRITE);
+ state().hasColumnFamilyAccess(cfname, Permission.WRITE);
try
{
schedule();