* privilege is converted into the list of privileges determined by determine_rights...
[sfa.git] / sfa / trust / rights.py
1 ##
2 # This Module implements rights and lists of rights for the SFA. Rights
3 # are implemented by two classes:
4 #
5 # Right - represents a single right
6 #
7 # RightList - represents a list of rights
8 #
9 # A right may allow several different operations. For example, the "info" right
10 # allows "listslices", "listcomponentresources", etc.
11 ##
12
13
14
15 ##
16 # privilege_table is a list of priviliges and what operations are allowed
17 # per privilege.
18
19 privilege_table = {"authority": ["register", "remove", "update", "resolve", "list", "getcredential", "*"],
20                    "refresh": ["remove", "update"],
21                    "resolve": ["resolve", "list", "getcredential", "listresources", "getversion"],
22                    "sa": ["getticket", "redeemslice", "redeemticket", "createslice", "deleteslice", "updateslice", 
23                           "getsliceresources", "getticket", "loanresources", "stopslice", "startslice", 
24                           "deleteslice", "resetslice", "listslices", "listnodes", "getpolicy", "createsliver"],
25                    "embed": ["getticket", "redeemslice", "redeemticket", "createslice", "createsliver",  "deleteslice", "updateslice", "getsliceresources"],
26                    "bind": ["getticket", "loanresources", "redeemticket"],
27                    "control": ["updateslice", "createslice", "createsliver", "stopslice", "startslice", "deleteslice", "resetslice", "getsliceresources", "getgids"],
28                    "info": ["listslices", "listnodes", "getpolicy"],
29                    "ma": ["setbootstate", "getbootstate", "reboot", "getgids", "gettrustedcerts"],
30                    "operator": ["gettrustedcerts", "getgids"]}
31
32
33
34 ##
35 # Determine tje rights that an object should have. The rights are entirely
36 # dependent on the type of the object. For example, users automatically
37 # get "refresh", "resolve", and "info".
38 #
39 # @param type the type of the object (user | sa | ma | slice | node)
40 # @param name human readable name of the object (not used at this time)
41 #
42 # @return RightList object containing rights
43
44 def determine_rights(type, name):
45     rl = RightList()
46
47     # rights seem to be somewhat redundant with the type of the credential.
48     # For example, a "sa" credential implies the authority right, because
49     # a sa credential cannot be issued to a user who is not an owner of
50     # the authority
51     if type == "user":
52         rl.add("refresh")
53         rl.add("resolve")
54         rl.add("info")
55     elif type == "sa":
56         rl.add("authority")
57         rl.add("sa")
58     elif type == "ma":
59         rl.add("authority")
60         rl.add("ma")
61     elif type == "authority":
62         rl.add("authority")
63         rl.add("sa")
64         rl.add("ma")
65     elif type == "slice":
66         rl.add("refresh")
67         rl.add("embed")
68         rl.add("bind")
69         rl.add("control")
70         rl.add("info")
71     elif type == "component":
72         rl.add("operator")
73     return rl
74
75
76 ##
77 # The Right class represents a single privilege.
78
79
80
81 class Right:
82    ##
83    # Create a new right.
84    #
85    # @param kind is a string naming the right. For example "control"
86
87    def __init__(self, kind, delegate=False):
88       self.kind = kind
89       self.delegate = delegate
90       
91    ##
92    # Test to see if this right object is allowed to perform an operation.
93    # Returns True if the operation is allowed, False otherwise.
94    #
95    # @param op_name is a string naming the operation. For example "listslices".
96
97    def can_perform(self, op_name):
98       allowed_ops = privilege_table.get(self.kind.lower(), None)
99       if not allowed_ops:
100          return False
101
102       # if "*" is specified, then all ops are permitted
103       if "*" in allowed_ops:
104          return True
105
106       return (op_name.lower() in allowed_ops)
107
108    ##
109    # Test to see if this right is a superset of a child right. A right is a
110    # superset if every operating that is allowed by the child is also allowed
111    # by this object.
112    #
113    # @param child is a Right object describing the child right
114
115    def is_superset(self, child):
116       my_allowed_ops = privilege_table.get(self.kind.lower(), None)
117       child_allowed_ops = privilege_table.get(child.kind.lower(), None)
118
119       if not self.delegate:
120           return False
121
122       if "*" in my_allowed_ops:
123           return True
124
125       for right in child_allowed_ops:
126           if not right in my_allowed_ops:
127               return False
128
129       return True
130
131 ##
132 # A RightList object represents a list of privileges.
133
134 class RightList:
135     ##
136     # Create a new rightlist object, containing no rights.
137     #
138     # @param string if string!=None, load the rightlist from the string
139
140     def __init__(self, string=None):
141         self.rights = []
142         if string:
143             self.load_from_string(string)
144
145     def is_empty(self):
146         return self.rights == []
147
148     ##
149     # Add a right to this list
150     #
151     # @param right is either a Right object or a string describing the right
152
153     def add(self, right, delegate=False):
154         if isinstance(right, str):
155             right = Right(right, delegate)
156         self.rights.append(right)
157
158     ##
159     # Load the rightlist object from a string
160
161     def load_from_string(self, string):
162         self.rights = []
163
164         # none == no rights, so leave the list empty
165         if not string:
166             return
167
168         parts = string.split(",")
169         for part in parts:
170             if ':' in part:
171                 spl = part.split(':')
172                 kind = spl[0].strip()
173                 delegate = bool(int(spl[1]))
174             else:
175                 kind = part.strip()
176                 delegate = 0
177             self.rights.append(Right(kind, bool(delegate)))
178
179     ##
180     # Save the rightlist object to a string. It is saved in the format of a
181     # comma-separated list.
182
183     def save_to_string(self):        
184         right_names = []
185         for right in self.rights:
186             right_names.append('%s:%d' % (right.kind.strip(), right.delegate))
187
188         return ",".join(right_names)
189
190     ##
191     # Check to see if some right in this list allows an operation. This is
192     # done by evaluating the can_perform function of each operation in the
193     # list.
194     #
195     # @param op_name is an operation to check, for example "listslices"
196
197     def can_perform(self, op_name):
198         for right in self.rights:
199             if right.can_perform(op_name):
200                 return True
201         return False
202
203     ##
204     # Check to see if all of the rights in this rightlist are a superset
205     # of all the rights in a child rightlist. A rightlist is a superset
206     # if there is no operation in the child rightlist that cannot be
207     # performed in the parent rightlist.
208     #
209     # @param child is a rightlist object describing the child
210
211     def is_superset(self, child):
212         for child_right in child.rights:
213             allowed = False
214             for my_right in self.rights:
215                 if my_right.is_superset(child_right):
216                     allowed = True
217             if not allowed:
218                 return False
219         return True
220
221
222     ##
223     # set the delegate bit to 'delegate' on
224     # all privileges
225     #
226     # @param delegate boolean (True or False)
227
228     def delegate_all_privileges(self, delegate):
229         for right in self.rights:
230             right.delegate = delegate
231
232     ##
233     # true if all privileges have delegate bit set true
234     # false otherwise
235
236     def get_all_delegate(self):
237         for right in self.rights:
238             if not right.delegate:
239                 return False
240         return True
241
242
243
244     ##
245     # Determine the rights that an object should have. The rights are entirely
246     # dependent on the type of the object. For example, users automatically
247     # get "refresh", "resolve", and "info".
248     #
249     # @param type the type of the object (user | sa | ma | slice | node)
250     # @param name human readable name of the object (not used at this time)
251     #
252     # @return RightList object containing rights
253
254     def determine_rights(self, type, name):
255         rl = RightList()
256
257         # rights seem to be somewhat redundant with the type of the credential.
258         # For example, a "sa" credential implies the authority right, because
259         # a sa credential cannot be issued to a user who is not an owner of
260         # the authority
261
262         if type == "user":
263             rl.add("refresh")
264             rl.add("resolve")
265             rl.add("info")
266         elif type == "sa":
267             rl.add("authority")
268             rl.add("sa")
269         elif type == "ma":
270             rl.add("authority")
271             rl.add("ma")
272         elif type == "authority":
273             rl.add("authority")
274             rl.add("sa")
275             rl.add("ma")
276         elif type == "slice":
277             rl.add("refresh")
278             rl.add("embed")
279             rl.add("bind")
280             rl.add("control")
281             rl.add("info")
282         elif type == "component":
283             rl.add("operator")
284
285         return rl