2 # Thierry Parmentelat - INRIA
4 from PLC.Faults import *
5 from PLC.Persons import Persons,Person
6 from PLC.Sites import Sites,Site
7 from PLC.Nodes import Nodes,Node
8 from PLC.Interfaces import Interfaces,Interface
9 from PLC.Slices import Slices,Slice
11 class AuthorizeHelpers:
14 def person_tag_type_common_roles (api, person, tag_type):
15 return list (set(person['roles']).intersection(set(tag_type['roles'])))
18 def caller_may_access_tag_type (api, caller, tag_type):
19 if isinstance(caller,Person):
20 return len(AuthorizeHelpers.person_tag_type_common_roles(api,caller,tag_type))!=0
21 elif isinstance(caller,Node):
22 return 'node' in tag_type['roles']
24 raise PLCInvalidArgument, "caller_may_access_tag_type - unexpected arg"
27 def person_may_access_person (api, caller_person, subject_person):
28 # keep it simple for now - could be a bit more advanced for PIs maybe
29 try: return caller_person['person_id'] == subject_person['person_id']
33 def person_in_site (api, person, site):
34 return site['site_id'] in person['site_ids']
37 def person_in_slice (api, caller_person, slice):
38 return caller_person['person_id'] in slice['person_ids']
41 def slice_in_site (api, slice, site):
42 return slice['site_id']==site['site_id']
45 def node_id_in_slice (api, node_id_or_hostname, slice):
46 if isinstance (node_id_or_hostname,int):
47 return node_id_or_hostname in slice['node_ids']
49 try: return Nodes(api,node_id_or_hostname)[0]['node_id'] in slice['node_ids']
53 def node_id_in_site (api, node_id_or_hostname, site):
54 if isinstance (node_id_or_hostname,int):
55 return node_id_or_hostname in site['node_ids']
57 try: return Nodes(api,node_id_or_hostname)[0]['node_id'] in site['node_ids']
62 def node_match_id (api, node, node_id_or_hostname):
63 if isinstance (node_id_or_hostname,int):
64 return node['node_id']==node_id_or_hostname
66 return node['hostname']==node_id_or_hostname
69 def interface_belongs_to_person (api,interface, person):
71 node=Nodes(api,[interface['node_id']])[0]
72 return AuthorizeHelpers.node_belongs_to_person (api, node, person)
77 def node_belongs_to_person (api, node, person):
79 site=Sites(api,[node['site_id']])[0]
80 return AuthorizeHelpers.person_in_site (api, person, site)
85 # does the slice belong to the site that the (pi) user is in ?
87 def slice_belongs_to_pi (api, slice, pi):
88 return slice['site_id'] in pi['site_ids']
91 def caller_is_node (api, caller, node):
92 return 'node_id' in caller and caller['node_id']==node['node_id']
95 # authorization methods - check if a given caller can set tag on this object
96 # called in {Add,Update,Delete}<Class>Tags methods, and in the accessors created in factory
97 # attach these as <Class>.caller_may_write_tag so accessors can find it
99 def caller_may_write_node_tag (node, api, caller, tag_type):
100 if 'roles' in caller and 'admin' in caller['roles']:
102 elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
103 raise PLCPermissionDenied, "Role mismatch for writing tag %s"%(tag_type['tagname'])
104 elif AuthorizeHelpers.node_belongs_to_person (api, node, caller):
106 elif AuthorizeHelpers.caller_is_node (api, caller, node):
109 raise PLCPermissionDenied, "Writing node tag: must belong in the same site as %s"%\
112 setattr(Node,'caller_may_write_tag',caller_may_write_node_tag)
115 def caller_may_write_interface_tag (interface, api, caller, tag_type):
116 if 'roles' in caller and 'admin' in caller['roles']:
118 elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
119 raise PLCPermissionDenied, "Role mismatch for writing tag %s"%(tag_type['tagname'])
120 elif AuthorizeHelpers.interface_belongs_to_person (api, interface, caller):
123 raise PLCPermissionDenied, "Writing interface tag: must belong in the same site as %s"%\
126 setattr(Interface,'caller_may_write_tag',caller_may_write_interface_tag)
129 def caller_may_write_site_tag (site, api, caller, tag_type):
130 if 'roles' in caller and 'admin' in caller['roles']:
132 elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
133 raise PLCPermissionDenied, "Role mismatch for writing tag %s"%(tag_type['tagname'])
134 elif AuthorizeHelpers.person_in_site (api, caller, site):
137 raise PLCPermissionDenied, "Writing site tag: must be part of site"%site['login_base']
139 setattr(Site,'caller_may_write_tag',caller_may_write_site_tag)
142 def caller_may_write_person_tag (person, api, caller, tag_type):
143 if 'roles' in caller and 'admin' in caller['roles']:
145 # user can change tags on self
146 elif AuthorizeHelpers.person_may_access_person (api, caller, person):
149 raise PLCPermissionDenied, "Writing person tag: you can only change your own tags"
151 setattr(Person,'caller_may_write_tag',caller_may_write_person_tag)
154 def caller_may_write_slice_tag (slice, api, caller, tag_type, node_id_or_hostname=None, nodegroup_id_or_name=None):
156 if 'roles' in caller and 'admin' in caller['roles']:
158 # does caller have right role(s) ? this knows how to deal with caller being a node
159 elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
161 # node callers: check the node is in the slice
162 elif isinstance(caller, Node):
163 # nodes can only set their own sliver tags
164 if node_id_or_hostname is None:
166 elif not AuthorizeHelpers.node_match_id (api, caller, node_id_or_hostname):
168 elif not AuthorizeHelpers.node_in_slice (api, caller, slice):
170 # caller is a non-admin person
172 # only admins can handle slice tags on a nodegroup
173 if nodegroup_id_or_name:
174 raise PLCPermissionDenied, "Cannot set slice tag %s on nodegroup - restricted to admins"%\
175 (tag_type['tagname'])
176 # if a node is specified it is expected to be in the slice
177 if node_id_or_hostname:
178 if not AuthorizeHelpers.node_id_in_slice (api, node_id_or_hostname, slice):
179 raise PLCPermissionDenied, "%s, node must be in slice when setting sliver tag"
180 # try all roles to find a match - tech are ignored b/c not in AddSliceTag.roles anyways
181 for role in AuthorizeHelpers.person_tag_type_common_roles(api,caller,tag_type):
182 # regular users need to be in the slice
184 if AuthorizeHelpers.person_in_slice(api, caller, slice):
186 # for convenience, pi's can tweak all the slices in their site
188 if AuthorizeHelpers.slice_belongs_to_pi (api, slice, caller):
191 raise PLCPermissionDenied, "Cannot write slice tag %s"%(tag_type['tagname'])
193 setattr(Slice,'caller_may_write_tag',caller_may_write_slice_tag)