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 | |
---|