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