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 | self.globals=set() |
---|
17 | |
---|
18 | @staticmethod |
---|
19 | def auth_name(name): |
---|
20 | """ |
---|
21 | Helper to convert a non-unicode local name to a unicode string. Mixed |
---|
22 | representations can needlessly confuse the authorizer. |
---|
23 | """ |
---|
24 | if isinstance(name, basestring): |
---|
25 | if not isinstance(name, unicode): return unicode(name) |
---|
26 | else: return name |
---|
27 | else: return name |
---|
28 | |
---|
29 | def valid_name(self, name): |
---|
30 | """ |
---|
31 | Ensure that the given name is valid. A valid name can either be a |
---|
32 | triple of strings and fedids representing one of our generalized Emulab |
---|
33 | names or a single fedid. Compound names can include wildcards (None) |
---|
34 | and must anchor to a fedid at their highest level (unless they're all |
---|
35 | None) |
---|
36 | |
---|
37 | This either returns True or throws an exception. More an assertion |
---|
38 | than a function. |
---|
39 | """ |
---|
40 | if isinstance(name, tuple) and len(name) == 3: |
---|
41 | for n in name: |
---|
42 | if n: |
---|
43 | if not (isinstance(n, basestring) or isinstance(n, fedid)): |
---|
44 | raise self.bad_name("names must be either a " +\ |
---|
45 | "triple or a fedid") |
---|
46 | for n in name: |
---|
47 | if n: |
---|
48 | if isinstance(n, fedid): |
---|
49 | return True |
---|
50 | else: |
---|
51 | raise self.bad_name("Compound names must be " + \ |
---|
52 | "rooted in fedids: %s" % str(name)) |
---|
53 | |
---|
54 | return True |
---|
55 | elif isinstance(name, fedid): |
---|
56 | return True |
---|
57 | else: |
---|
58 | raise self.bad_name("Names must be a triple or a fedid (%s)" % name) |
---|
59 | |
---|
60 | def set_attribute(self, name, attr): |
---|
61 | """ |
---|
62 | Attach attr to name. Multiple attrs can be attached. |
---|
63 | """ |
---|
64 | self.valid_name(name) |
---|
65 | if isinstance(name, tuple): |
---|
66 | aname = tuple([ self.auth_name(n) for n in name]) |
---|
67 | else: |
---|
68 | aname = self.auth_name(name) |
---|
69 | |
---|
70 | if not self.attrs.has_key(aname): |
---|
71 | self.attrs[aname] = set() |
---|
72 | self.attrs[aname].add(attr) |
---|
73 | |
---|
74 | def unset_attribute(self, name, attr): |
---|
75 | """ |
---|
76 | Remove an attribute from name |
---|
77 | """ |
---|
78 | self.valid_name(name) |
---|
79 | if isinstance(name, tuple): |
---|
80 | aname = tuple([ self.auth_name(n) for n in name]) |
---|
81 | else: |
---|
82 | aname = self.auth_name(name) |
---|
83 | |
---|
84 | attrs = self.attrs.get(aname, None) |
---|
85 | if attrs: attrs.discard(attr) |
---|
86 | |
---|
87 | def check_attribute(self, name, attr): |
---|
88 | """ |
---|
89 | Return True if name has attr (or if attr is global). Tuple names match |
---|
90 | any tuple name that matches all names present and has None entries in |
---|
91 | other fileds. For tuple names True implies that there is a matching |
---|
92 | tuple name with the attribute. |
---|
93 | """ |
---|
94 | def tup(tup, i, p): |
---|
95 | mask = 1 << i |
---|
96 | if p & mask : return authorizer.auth_name(tup[i]) |
---|
97 | else: return None |
---|
98 | |
---|
99 | self.valid_name(name) |
---|
100 | if attr in self.globals: |
---|
101 | return True |
---|
102 | |
---|
103 | if isinstance(name, tuple): |
---|
104 | for p in range(0,8): |
---|
105 | lookup = ( tup(name, 0, p), tup(name,1, p), tup(name,2,p)) |
---|
106 | if self.attrs.has_key(lookup): |
---|
107 | if attr in self.attrs[lookup]: |
---|
108 | return True |
---|
109 | else: |
---|
110 | return attr in self.attrs.get(self.auth_name(name), set()) |
---|
111 | |
---|
112 | def set_global_attribute(self, attr): |
---|
113 | """ |
---|
114 | Set a global attribute. All names, even those otherwise unknown to the |
---|
115 | authorizer have this attribute. |
---|
116 | """ |
---|
117 | self.globals.add(attr) |
---|
118 | |
---|
119 | def unset_global_attribute(self, attr): |
---|
120 | """ |
---|
121 | Remove a global attribute |
---|
122 | """ |
---|
123 | |
---|
124 | self.globals.discard(attr) |
---|
125 | |
---|