#/usr/local/bin/python from fedid import fedid class authorizer: """ This class keeps track of authorization attributes for the various modules running. When it gets smarter it will be the basis for a real attribute-based authentication system. """ # general error exception for badly formed names. class bad_name(RuntimeError): pass def __init__(self, def_attr="testbed"): self.attrs = { } self.globals=set() @staticmethod def auth_name(name): """ Helper to convert a non-unicode local name to a unicode string. Mixed representations can needlessly confuse the authorizer. """ if isinstance(name, basestring): if not isinstance(name, unicode): return unicode(name) else: return name else: return name def valid_name(self, name): """ Ensure that the given name is valid. A valid name can either be a triple of strings and fedids representing one of our generalized Emulab names or a single fedid. Compound names can include wildcards (None) and must anchor to a fedid at their highest level (unless they're all None) This either returns True or throws an exception. More an assertion than a function. """ if isinstance(name, tuple) and len(name) == 3: for n in name: if n: if not (isinstance(n, basestring) or isinstance(n, fedid)): raise self.bad_name("names must be either a " +\ "triple or a fedid") for n in name: if n: if isinstance(n, fedid): return True else: raise self.bad_name("Compound names must be " + \ "rooted in fedids: %s" % str(name)) return True elif isinstance(name, fedid): return True else: raise self.bad_name("Names must be a triple or a fedid (%s)" % name) def set_attribute(self, name, attr): """ Attach attr to name. Multiple attrs can be attached. """ self.valid_name(name) if isinstance(name, tuple): aname = tuple([ self.auth_name(n) for n in name]) else: aname = self.auth_name(name) if not self.attrs.has_key(aname): self.attrs[aname] = set() self.attrs[aname].add(attr) def unset_attribute(self, name, attr): """ Remove an attribute from name """ self.valid_name(name) if isinstance(name, tuple): aname = tuple([ self.auth_name(n) for n in name]) else: aname = self.auth_name(name) attrs = self.attrs.get(aname, None) if attrs: attrs.discard(attr) def check_attribute(self, name, attr): """ Return True if name has attr (or if attr is global). Tuple names match any tuple name that matches all names present and has None entries in other fileds. For tuple names True implies that there is a matching tuple name with the attribute. """ def tup(tup, i, p): mask = 1 << i if p & mask : return authorizer.auth_name(tup[i]) else: return None self.valid_name(name) if attr in self.globals: return True if isinstance(name, tuple): for p in range(0,8): lookup = ( tup(name, 0, p), tup(name,1, p), tup(name,2,p)) if self.attrs.has_key(lookup): if attr in self.attrs[lookup]: return True else: return attr in self.attrs.get(self.auth_name(name), set()) def set_global_attribute(self, attr): """ Set a global attribute. All names, even those otherwise unknown to the authorizer have this attribute. """ self.globals.add(attr) def unset_global_attribute(self, attr): """ Remove a global attribute """ self.globals.discard(attr)