From 0661854630204650b678ffe07846dcdcf5d48622 Mon Sep 17 00:00:00 2001 From: Evan Broder Date: Sun, 22 Nov 2009 23:14:51 -0500 Subject: [PATCH] Add a invirt.authz.locker module to invirt-base for XVM-style authorization. svn path=/trunk/packages/invirt-base/; revision=2559 --- debian/control | 2 +- python/invirt/authz/locker.py | 101 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 python/invirt/authz/__init__.py create mode 100644 python/invirt/authz/locker.py diff --git a/debian/control b/debian/control index bab7571..f300956 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Package: invirt-base Architecture: all Depends: ${python:Depends}, ${misc:Depends}, python-json (>= 3.4-2), python-yaml (>= 3.05), python-mako (>= - 0.2.2), remctl-client, invirt-config + 0.2.2), remctl-client, invirt-config, python-afs Provides: ${python:Provides} XB-Python-Version: ${python:Versions} Description: Base configuration required for all Invirt servers diff --git a/python/invirt/authz/__init__.py b/python/invirt/authz/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/invirt/authz/locker.py b/python/invirt/authz/locker.py new file mode 100644 index 0000000..4e22d2a --- /dev/null +++ b/python/invirt/authz/locker.py @@ -0,0 +1,101 @@ +import errno + +from afs import acl +from afs import fs +from afs import pts + +from invirt.config import structs as config + +# +# expandOwner and expandAdmin form the API that needs to be exported +# for all authz modules. +# + +# TODO: Make expandOwner and expandAdmin deal with acquiring tokens +# and encrypting the connection to the prdb as necessary/requested by +# the configuration. +def expandOwner(name): + """Expand an owner to a list of authorized users. + + For the locker authz module, an owner is an Athena locker. Those + users who have been given the administrator ('a') bit on the root + of a locker are given access to any VM owned by that locker, + unless they also have been given a negative administrator bit. + + If a locker doesn't exist, or we can't access the permissions, we + assume the ACL is empty. + """ + try: + path = _lockerPath(name) + cell = fs.whichcell(path) + a = acl.ACL.retrieve(path) + + allowed = set() + for ent in a.pos: + if a.pos[ent] & acl.ADMINISTER: + allowed.update(_expandGroup(ent, cell)) + for ent in a.neg: + if a.neg[ent] & acl.ADMINISTER: + allowed.difference_update(_expandGroup(ent, cell)) + + return allowed + except OSError, e: + if e.errno in (errno.ENOENT, errno.EACCES): + return [] + else: + raise + + +def expandAdmin(name, owner): + """Expand an administrator to a list of authorized users. + + Because the interpretation of an administrator might depend on the + owner, the owner is passed in as an argument. + + However, in the case of locker-based authentication, the + administrator is always interpreted as an AFS entry (either a user + or a group) in the home cell (athena.mit.edu for XVM). + """ + return _expandGroup(name) + + +# +# These are helper functions, and aren't part of the authz API +# + +def _expandGroup(name, cell=None): + """Expand an AFS group into a list of its members. + + Because groups are not global, but can vary from cell to cell, + this function accepts as an optional argument the cell in which + this group should be resolved. + + If no cell is specified, it is assumed that the default cell (or + ThisCell) should be used. + + If the name is a user, not a group, then a single-element set with + the same name is returned. + + As with expandOwner, if a group doesn't exist or if we're unable + to retrieve its membership, we assume it's empty. + """ + try: + ent = pts.PTS(cell).getEntry(name) + if ent.id > 0: + return set([ent.name]) + else: + return set([x.name for x in ent.members]) + except OSError, e: + if e.errno in (errno.ENOENT, errno.EACCESS): + return set() + else: + raise + + +def _lockerPath(owner): + """Given the name of a locker, return a path to that locker. + + This turns out to be pretty simple, thanks to the /mit + automounter. + """ + return '/mit/%s' % owner -- 1.7.9.5