Subject: Re: bandwidth limiting Cassandra's replication and access control
On Tue, 10 Nov 2009 17:09:44 -0600 Jonathan Ellis <firstname.lastname@example.org
JE> 2009/11/10 Ted Zlatanov <email@example.com
>> I see all the methods implementing the server interface in
>> org.apache.cassandra.service.CassandraServer. Is that where the
>> authentication should happen? Should I use JAAS (LDAP+PAM+other
>> backends) or is there something else preferred?
JE> Right, CassandraServer is the first non-generated stop for Thrift connections.
JE> JAAS looks like the standard java way to do this sort of thing, which
JE> makes me a little suspicious. :)
I looked for other solutions, but nothing was as convenient. The docs
for the NIS auth backend show incorrect sample data (the LDAP sample is
copied) which makes me a lot suspicious. It's not too enterprisey, though.
JE> But if you're already familiar with that, let's run with it.
I will learn it, I don't know it well yet. Bear with me; discussion
follows. Should we move this to the devel list, BTW?
>> Does libThrift allow persistent state per client somehow or do I have to
>> implement my own security tokens? I don't see a way to track the client
>> in any of the Cassandra services currently so I suspect libThrift is
>> stateless on its own.
JE> Yes. Since we're using the thrift threaded server, setting up a
JE> threadlocal from a login method and leaving the other methods alone
JE> would be my preferred approach.
Is it OK to keep the local auth info as a field in the CassandraServer
instance or is another place better?
JE> Ultimately what I'd like is to have a client authenticate to a
JE> specific keyspace. Then we'd drop the keyspace argument from the
JE> other methods.
It looks like JAAS lets us use a jaas.conf file to specify the
authentication backend. The application just needs to specify the
java.security.auth.login.config property as the full name of the
The JNDI login module (LDAP and NIS) supports these properties,
according to the docs at http://java.sun.com/javase/6/docs/jre/api/security/jaas/spec/index.html
before login() is called. The other JAAS modules don't support that
(AFAICT they only work on the current user) so we'd only be able to
authenticate based on NIS or LDAP, or other JNDI providers. This should
support at least Active Directory and most Unix shops.
As far as authorization after authentication, JAAS supports config files
like this (from the tutorial):
grant codebase "file:./SampleAction.jar",
permission java.util.PropertyPermission "java.home", "read";
permission java.util.PropertyPermission "user.home", "read";
permission java.io.FilePermission "foo.txt", "read";
The Principal is the user ID.
We should be able to use anything that extends java.security.Permission
here; I think you're suggesting a KeyspacePermission but we should also
have a ClusterPermission. I think we should allow wildcards in the
This seems like a reasonable way to configure things and it does not
require any changes to the existing configuration files. I like that;
separating security policies from the other configuration is always a
See the tutorials for the details, starting at:http://java.sun.com/javase/technologies/security/index.jsp
The actual auth method is pretty simple then. Passing the password in a
non-Kerberos environment is risky but I am not sure of the right way to
encrypt the channel just for the password. Encrypting just the login
info requires some thought as well. Maybe someone has done this before?
For now the auth can just be
public void authenticateUser(Map<String, String> credentials, String cluster, String keyspace) throws ???
where the credentials are just the 'user' and 'password' keys in that map.
If there are no objections I'll put together a patch.