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