Awesome find, Michael. Checking into this now...hopefully it will save us lots of time.
(Good quality) Code we don't have to write is the best kind of code :) -jay On Mon, Aug 9, 2010 at 10:00 AM, Michael Gundlach <[email protected]> wrote: > Hooray for WSGI! There's an app for that: > > http://pypi.python.org/pypi/AuthKit/0.4.5 > May I propose that rather than reinventing the RBAC wheel, we just drop an > existing RBAC wsgi app in front of our system? And if it has any > shortcomings, we contribute back to AuthKit. > I've never used it -- I just searched for "wsgi rbac". The summary mentions > that it can work with LDAP, and that you can define your own roles. It > looks like AuthKit was written by the lead developer of the Pylons > framework. > Michael > > On Fri, Aug 6, 2010 at 2:58 PM, Jay Pipes <[email protected]> wrote: >> >> Hi all (especially Vish and Devin)! >> >> I've been going through the code in /nova/auth/* and have a few >> comments/suggestions on the implementation of authorization (not >> authentication) in Nova. Love to get some feedback from y'all. >> >> Currently, Nova's authorization is handled via role-based access >> control (RBAC). Nothing wrong with this at all; it's very common and >> well-understood. >> >> However, the current RBAC implementation, while quite elegant, isn't >> very flexible and is not configurable because: >> >> 1) All the roles are hard-coded strings (netadmin, projectmanager, etc..) >> 2) All the permissions are hard-coded using the decorators in >> /nova/rbac.py. >> >> As an example, here is the cloud controller's get_console_output() method: >> >> �[email protected]('projectmanager', 'sysadmin') >> def get_console_output(self, context, instance_id, **kwargs): >> # instance_id is passed in as a list of instances >> instance = self._get_instance(context, instance_id[0]) >> return rpc.call('%s.%s' % (FLAGS.compute_topic, >> instance['node_name']), >> {"method": "get_console_output", >> "args" : {"instance_id": instance_id[0]}}) >> >> The rbac.allow decorator establishes if the request context's user is >> in either the "projectmanager" or "sysadmin" roles. This decorator >> pattern is very elegant and declarative. >> >> Unfortunately, what this implementation means is that a user >> installing Nova has no say in: >> >> 1) The names and number of roles >> 2) The access permissions for the hard-coded roles >> >> without modifying the Nova source code, which of course isn't >> particularly friendly! :) >> >> I propose changing the authorization code to allow a flexible RBAC >> configuration file (possibly XML?) that would allow installing users >> to implement their own security groups and permissions. Of course, >> Nova would ship with a configuration file that matches the current >> hard-coded names and permissions... >> >> Consider this possible configuration file: >> >> ?xml version="1.0"?> >> <rbac> >> <roles> >> <role id="all" desc="Anyone" /> >> <role id="projectmanager" desc="Project Manager" /> >> <role id="sysadmin" desc="Sys Admin" /> >> <role id="netadmin" desc="Network Admin" /> >> .... >> </roles> >> <resourcegroups> >> <resourcegroup id="cloud"> >> <resource id="create_key_pair" allow="all" /> >> <resource id="delete_key_pair" allow="all" /> >> <resource id="describe_security_groups" allow="all" /> >> <resource id="create_security_group" allow="netadmin" /> >> <resource id="delete_security_group" allow="netadmin" /> >> ... >> </resourcegroup> >> </resources> >> </rbac> >> >> On controller initialization, the controller would call some interface >> that would parse this configuration file into an in-memory >> representation. Imagine something like this: >> >> // in /nova/auth/acl.py >> class ACL: >> def __init__(self): >> # Read config file and populate a dict of roles and resources... >> def allowed_roles(self, resource_id): >> # Takes a resource id and returns a set of allowed roles... >> >> The elegant decorator pattern could, of course, still be used, but in >> a slightly different manner. Something like this might work: >> >> class CloudController(object): >> ... >> �[email protected] >> def create_security_group(self, context, group_name, **kwargs): >> ... >> >> // in /nova/auth/rbac.py: >> from nova.auth import acl >> >> acl = acl.ACL() >> >> def check(): >> def wrap(f): >> def wrapped_f(self, context, *args, **kwargs): >> if context.user.is_superuser(): >> return f(self, context, *args, **kwargs) >> f_name = f.__name__ >> roles = acl.get_allowed_roles(f_name) >> for role in roles: >> if __matches_role(context, role): >> return f(self, context, *args, **kwargs) >> raise exception.NotAuthorized() >> return wrapped_f >> return wrap >> >> def __matches_role(context, role): >> if role == 'all': >> return True >> if role == 'none': >> return False >> return context.project.has_role(context.user.id, role) >> >> Thoughts? >> >> -jay >> >> _______________________________________________ >> Mailing list: https://launchpad.net/~nova >> Post to : [email protected] >> Unsubscribe : https://launchpad.net/~nova >> More help : https://help.launchpad.net/ListHelp > > Confidentiality Notice: This e-mail message (including any attached or > embedded documents) is intended for the exclusive and confidential use of > the > individual or entity to which this message is addressed, and unless > otherwise > expressly indicated, is confidential and privileged information of > Rackspace. > Any dissemination, distribution or copying of the enclosed material is > prohibited. > If you receive this transmission in error, please notify us immediately by > e-mail > at [email protected], and delete the original message. > Your cooperation is appreciated. > _______________________________________________ Mailing list: https://launchpad.net/~nova Post to : [email protected] Unsubscribe : https://launchpad.net/~nova More help : https://help.launchpad.net/ListHelp

