[3f6bc5f] | 1 | #/usr/local/bin/python |
---|
| 2 | |
---|
| 3 | from fedid import fedid |
---|
| 4 | |
---|
| 5 | class authorizer: |
---|
| 6 | """ |
---|
| 7 | This class keeps track of authorization attributes for the various modules |
---|
| 8 | running. When it gets smarter it will be the basis for a real |
---|
| 9 | attribute-based authentication system. |
---|
| 10 | """ |
---|
| 11 | # general error exception for badly formed names. |
---|
| 12 | class bad_name(RuntimeError): pass |
---|
| 13 | |
---|
| 14 | def __init__(self, def_attr="testbed"): |
---|
| 15 | self.attrs = { } |
---|
| 16 | |
---|
| 17 | @staticmethod |
---|
| 18 | def auth_name(name): |
---|
| 19 | """ |
---|
| 20 | Helper to convert a non-unicode local name to a unicode string. Mixed |
---|
| 21 | representations can needlessly confuse the authorizer. |
---|
| 22 | """ |
---|
| 23 | if isinstance(name, basestring): |
---|
| 24 | if not isinstance(name, unicode): return unicode(name) |
---|
| 25 | else: return name |
---|
| 26 | else: return name |
---|
| 27 | |
---|
| 28 | def valid_name(self, name): |
---|
| 29 | """ |
---|
| 30 | Ensure that the given name is valid. A valid name can either be a |
---|
| 31 | triple of strings and fedids representing one of our generalized Emulab |
---|
| 32 | names or a single fedid. Compound names can include wildcards (None) |
---|
| 33 | and must anchor to a fedid at their highest level (unless they're all |
---|
| 34 | None) |
---|
| 35 | |
---|
| 36 | This either returns True or throws an exception. More an assertion |
---|
| 37 | than a function. |
---|
| 38 | """ |
---|
| 39 | if isinstance(name, tuple) and len(name) == 3: |
---|
| 40 | for n in name: |
---|
| 41 | if n: |
---|
| 42 | if not (isinstance(n, basestring) or isinstance(n, fedid)): |
---|
| 43 | raise bad_name("names must be either a triple or " + \ |
---|
| 44 | "a fedid") |
---|
| 45 | for n in name: |
---|
| 46 | if n: |
---|
| 47 | if isinstance(n, fedid): |
---|
| 48 | return True |
---|
| 49 | else: |
---|
| 50 | raise self.bad_name("Compound names must be " + \ |
---|
| 51 | "rooted in fedids: %s" % str(name)) |
---|
| 52 | |
---|
| 53 | return True |
---|
| 54 | elif isinstance(name, fedid): |
---|
| 55 | return True |
---|
| 56 | else: |
---|
| 57 | raise bad_name("Names must be a triple or a fedid (%s)" % name) |
---|
| 58 | |
---|
| 59 | def set_attribute(self, name, attr): |
---|
| 60 | """ |
---|
| 61 | Attach attr to name. Multiple attrs can be attached. |
---|
| 62 | """ |
---|
| 63 | self.valid_name(name) |
---|
| 64 | if isinstance(name, tuple): |
---|
| 65 | aname = tuple([ self.auth_name(n) for n in name]) |
---|
| 66 | else: |
---|
| 67 | aname = self.auth_name(name) |
---|
| 68 | |
---|
| 69 | if not self.attrs.has_key(aname): |
---|
| 70 | self.attrs[aname] = set() |
---|
| 71 | self.attrs[aname].add(attr) |
---|
| 72 | |
---|
| 73 | def unset_attribute(self, name, attr): |
---|
| 74 | """ |
---|
| 75 | Remove an attribute from name |
---|
| 76 | """ |
---|
| 77 | self.valid_name(name) |
---|
| 78 | if isinstance(name, tuple): |
---|
| 79 | aname = tuple([ self.auth_name(n) for n in name]) |
---|
| 80 | else: |
---|
| 81 | aname = self.auth_name(name) |
---|
| 82 | |
---|
| 83 | attrs = self.attrs.get(aname, None) |
---|
| 84 | if attrs: attrs.discard(attr) |
---|
| 85 | |
---|
| 86 | def check_attribute(self, name, attr): |
---|
| 87 | """ |
---|
| 88 | Return True if name has attr. Tuple names match any tuple name that |
---|
| 89 | matches all names present and has None entries in other fileds. For |
---|
| 90 | tuple names True implies that there is a matching tuple name with the |
---|
| 91 | attribute. |
---|
| 92 | """ |
---|
| 93 | def tup(tup, i, p): |
---|
| 94 | mask = 1 << i |
---|
| 95 | if p & mask : return authorizer.auth_name(tup[i]) |
---|
| 96 | else: return None |
---|
| 97 | |
---|
| 98 | self.valid_name(name) |
---|
| 99 | |
---|
| 100 | if isinstance(name, tuple): |
---|
| 101 | for p in range(0,8): |
---|
| 102 | lookup = ( tup(name, 0, p), tup(name,1, p), tup(name,2,p)) |
---|
| 103 | if self.attrs.has_key(lookup): |
---|
| 104 | if attr in self.attrs[lookup]: |
---|
| 105 | return True |
---|
| 106 | else: |
---|
| 107 | return attr in self.attrs.get(self.auth_name(name), set()) |
---|
| 108 | |
---|
| 109 | |
---|