From: Thierry Parmentelat Date: Mon, 22 Nov 2010 22:17:57 +0000 (+0100) Subject: add/update/delete slice tags should be fine X-Git-Tag: plcapi-5.0-19~45 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=e807caf3a73d84951a2fbfb09bae0b6a1eb4a942;p=plcapi.git add/update/delete slice tags should be fine --- diff --git a/PLC/AuthorizeHelpers.py b/PLC/AuthorizeHelpers.py index 8c09cc3..7cbc5ab 100644 --- a/PLC/AuthorizeHelpers.py +++ b/PLC/AuthorizeHelpers.py @@ -9,54 +9,78 @@ from PLC.Nodes import Nodes,Node class AuthorizeHelpers: @staticmethod - def interface_belongs_to_person (api,interface, person): - try: - node=Nodes(api,[interface['node_id']])[0] - return AuthorizeHelpers.node_belong_to_person (api, node, person) - except: - return False - - @staticmethod - def node_belongs_to_person (api, node, person): - try: - site=Sites(api,[node['site_id']])[0] - return AuthorizeHelpers.person_belongs_to_site (api, person, site) - except: - return False - - @staticmethod - def person_belongs_to_site (api, person, site): - return site['site_id'] in person['site_ids'] + def person_tag_type_common_roles (api, person, tag_type): + return list (set(person['roles']).intersection(set(tag_type['roles']))) @staticmethod def caller_may_access_tag_type (api, caller, tag_type): if isinstance(caller,Person): - return len(set(caller['roles']).intersection(set(tag_type['roles'])))!=0 + return len(AuthorizeHelpers.person_tag_type_common_roles(api,caller,tag_type))!=0 elif isinstance(caller,Node): return 'node' in tag_type['roles'] else: raise PLCInvalidArgument, "caller_may_access_tag_type - unexpected arg" @staticmethod - def person_access_person (api, caller_person, subject_person): + def person_may_access_person (api, caller_person, subject_person): # keep it simple for now - could be a bit more advanced for PIs maybe try: return caller_person['person_id'] == subject_person['person_id'] except: return False + @staticmethod + def person_in_site (api, person, site): + return site['site_id'] in person['site_ids'] + @staticmethod def person_in_slice (api, caller_person, slice): return caller_person['person_id'] in slice['person_ids'] @staticmethod - def node_in_slice (api, caller_node, slice): - return caller_node['node_id'] in slice['node_ids'] + def slice_in_site (api, slice, slice): + return caller_person['person_id'] in slice['person_ids'] @staticmethod - def node_id_or_hostname_in_slice (api, node_id_or_hostname, slice): + def node_id_in_slice (api, node_id_or_hostname, slice): if isinstance (node_id_or_hostname,int): return node_id_or_hostname in slice['node_ids'] else: - try: return Nodes(api,node_id_or_hostname_in_slice)[0]['node_id'] in slice['node_ids'] + try: return Nodes(api,node_id_or_hostname)[0]['node_id'] in slice['node_ids'] + except:return False + + @staticmethod + def node_id_in_site (api, node_id_or_hostname, site): + if isinstance (node_id_or_hostname,int): + return node_id_or_hostname in site['node_ids'] + else: + try: return Nodes(api,node_id_or_hostname)[0]['node_id'] in site['node_ids'] except:return False + @staticmethod + def node_match_id (api, node, node_id_or_hostname): + if isinstance (node_id_or_hostname,int): + return node['node_id']==node_id_or_hostname + else: + return node['hostname']==node_id_or_hostname + + @staticmethod + def interface_belongs_to_person (api,interface, person): + try: + node=Nodes(api,[interface['node_id']])[0] + return AuthorizeHelpers.node_belongs_to_person (api, node, person) + except: + return False + + @staticmethod + def node_belongs_to_person (api, node, person): + try: + site=Sites(api,[node['site_id']])[0] + return AuthorizeHelpers.person_in_site (api, person, site) + except: + return False + + # does the slice belong to the site that the (pi) user is in ? + @staticmethod + def slice_belongs_to_pi (api, slice, pi): + return slice['site_id'] in pi['site_ids'] + diff --git a/PLC/Methods/AddPersonTag.py b/PLC/Methods/AddPersonTag.py index 6bba377..edd3970 100644 --- a/PLC/Methods/AddPersonTag.py +++ b/PLC/Methods/AddPersonTag.py @@ -59,7 +59,7 @@ class AddPersonTag(Method): if 'admin' in self.caller['roles']: pass # user can change tags on self - elif AuthorizeHelpers.person_access_person (self.api, self.caller, person): + elif AuthorizeHelpers.person_may_access_person (self.api, self.caller, person): pass else: raise PLCPermissionDenied, "%s: you can only change your own tags"%self.name diff --git a/PLC/Methods/AddSiteTag.py b/PLC/Methods/AddSiteTag.py index 3c59f0b..2069698 100644 --- a/PLC/Methods/AddSiteTag.py +++ b/PLC/Methods/AddSiteTag.py @@ -64,7 +64,7 @@ class AddSiteTag(Method): pass elif not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) - elif AuthorizeHelpers.person_belongs_to_site (self.api, self.caller, site): + elif AuthorizeHelpers.person_in_site (self.api, self.caller, site): pass else: raise PLCPermissionDenied, "%s: you must be part of the subject site"%self.name diff --git a/PLC/Methods/AddSliceTag.py b/PLC/Methods/AddSliceTag.py index 4638116..0d7fe68 100644 --- a/PLC/Methods/AddSliceTag.py +++ b/PLC/Methods/AddSliceTag.py @@ -26,9 +26,8 @@ class AddSliceTag(Method): Non-admins need to have at least one of the roles attached to the tagtype. In addition: (*) Users may only set tags of slices or slivers of which they are members. - (*) PIs may only set tags of slices or slivers at their sites, or of which they - are members. - (*) techs may only set tags of slivers at their sites. + (*) PIs may only set tags of slices in their site + (*) techs cannot use this method Returns the new slice_tag_id (> 0) if successful, faults otherwise. @@ -65,34 +64,43 @@ class AddSliceTag(Method): tag_type = tag_types[0] # check authorizations - if 'admin' not in self.caller['roles']: - # this knows how to deal with self.caller being a node - if not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): - raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) - # node callers: check the node is in the slice - if isinstance(self.caller, Node): - granted=AuthorizeHelpers.node_in_slice (self.api, self.caller, slice) - else: - if nodegroup_id_or_name: - raise PLCPermissionDenied, "%s, cannot set slice tag on nodegroup"%self.name - # try all roles to find a match + granted=False + if 'admin' in self.caller['roles']: + granted=True + # does caller have right role(s) ? this knows how to deal with self.caller being a node + elif not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): + granted=False + # node callers: check the node is in the slice + elif isinstance(self.caller, Node): + # nodes can only set their own sliver tags + if node_id_or_hostname is None: granted=False - for role in self.caller['roles']: - if role=='pi': - if AuthorizeHelpers.person_in_slice(self.api, self.caller, slice): - granted=True ; break - if node_id_or_hostname is not None and \ - AuthorizeHelpers.node_id_or_hostname_in_slice(self.api, node_id_or_hostname_in_slice, slice): - granted=True ; break - elif role=='user': - if AuthorizeHelpers.person_in_slice(self.api, self.caller, slice): - granted=True ; break - elif role=='tech': - if node_id_or_hostname is not None and \ - AuthorizeHelpers.node_id_or_hostname_in_slice(self.api, node_id_or_hostname_in_slice, slice): - granted=True ; break - if not granted: - raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) + elif not AuthorizeHelpers.node_match_id (self.api, self.caller, node_id_or_hostname): + granted=False + elif not AuthorizeHelpers.node_in_slice (self.api, self.caller, slice): + granted=False + # caller is a non-admin person + else: + # only admins can handle slice tags on a nodegroup + if nodegroup_id_or_name: + raise PLCPermissionDenied, "%s, cannot set slice tag %s on nodegroup - restricted to admins"%\ + (self.name,tag_type['tagname']) + # if a node is specified it is expected to be in the slice + if node_id_or_hostname: + if not AuthorizeHelpers.node_id_in_slice (self.api, node_id_or_hostname, slice): + raise PLCPermissionDenied, "%s, node must be in slice when setting sliver tag" + # try all roles to find a match - tech are ignored b/c not in AddSliceTag.roles anyways + for role in AuthorizeHelpers.person_tag_type_common_roles(self.api,self.caller,tag_type): + # regular users need to be in the slice + if role=='user': + if AuthorizeHelpers.person_in_slice(self.api, self.caller, slice): + granted=True ; break + # for convenience, pi's can tweak all the slices in their site + elif role=='pi': + if AuthorizeHelpers.slice_belongs_to_pi (self.api, slice, self.caller): + granted=True ; break + if not granted: + raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) # if initscript is specified, validate value if tag_type['tagname'] in ['initscript']: diff --git a/PLC/Methods/DeletePersonTag.py b/PLC/Methods/DeletePersonTag.py index 19ab5fe..ee4f6b3 100644 --- a/PLC/Methods/DeletePersonTag.py +++ b/PLC/Methods/DeletePersonTag.py @@ -41,7 +41,7 @@ class DeletePersonTag(Method): if 'admin' in self.caller['roles']: pass # user can change tags on self - elif AuthorizeHelpers.person_access_person (self.api, self.caller, person): + elif AuthorizeHelpers.person_may_access_person (self.api, self.caller, person): pass else: raise PLCPermissionDenied, "%s: you can only change your own tags"%self.name diff --git a/PLC/Methods/DeleteSiteTag.py b/PLC/Methods/DeleteSiteTag.py index 3aa8d83..6c31c1d 100644 --- a/PLC/Methods/DeleteSiteTag.py +++ b/PLC/Methods/DeleteSiteTag.py @@ -48,7 +48,7 @@ class DeleteSiteTag(Method): pass elif not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) - elif AuthorizeHelpers.person_belongs_to_site (self.api, self.caller, site): + elif AuthorizeHelpers.person_in_site (self.api, self.caller, site): pass else: raise PLCPermissionDenied, "%s: you must be part of the subject site"%self.name diff --git a/PLC/Methods/DeleteSliceTag.py b/PLC/Methods/DeleteSliceTag.py index e63393e..d433e02 100644 --- a/PLC/Methods/DeleteSliceTag.py +++ b/PLC/Methods/DeleteSliceTag.py @@ -47,17 +47,46 @@ class DeleteSliceTag(Method): assert slice_tag['slice_tag_id'] in slice['slice_tag_ids'] - if 'admin' not in self.caller['roles']: - if self.caller['person_id'] in slice['person_ids']: - pass - elif 'pi' not in self.caller['roles']: - raise PLCPermissionDenied, "Not a member of the specified slice" - elif slice['site_id'] not in self.caller['site_ids']: - raise PLCPermissionDenied, "Specified slice not associated with any of your sites" - - if slice_tag['min_role_id'] is not None and \ - min(self.caller['role_ids']) > slice_tag['min_role_id']: - raise PLCPermissioinDenied, "Not allowed to delete the specified attribute" + # check authorizations + node_id_or_hostname=slice_tag['node_id'] + nodegroup_id_or_name=slice_tag['nodegroup_id'] + granted=False + if 'admin' in self.caller['roles']: + granted=True + # does caller have right role(s) ? this knows how to deal with self.caller being a node + elif not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): + granted=False + # node callers: check the node is in the slice + elif isinstance(self.caller, Node): + # nodes can only set their own sliver tags + if node_id_or_hostname is None: + granted=False + elif not AuthorizeHelpers.node_match_id (self.api, self.caller, node_id_or_hostname): + granted=False + elif not AuthorizeHelpers.node_in_slice (self.api, self.caller, slice): + granted=False + # caller is a non-admin person + else: + # only admins can handle slice tags on a nodegroup + if nodegroup_id_or_name: + raise PLCPermissionDenied, "%s, cannot set slice tag %s on nodegroup - restricted to admins"%\ + (self.name,tag_type['tagname']) + # if a node is specified it is expected to be in the slice + if node_id_or_hostname: + if not AuthorizeHelpers.node_id_in_slice (self.api, node_id_or_hostname, slice): + raise PLCPermissionDenied, "%s, node must be in slice when setting sliver tag" + # try all roles to find a match - tech are ignored b/c not in AddSliceTag.roles anyways + for role in AuthorizeHelpers.person_tag_type_common_roles(self.api,self.caller,tag_type): + # regular users need to be in the slice + if role=='user': + if AuthorizeHelpers.person_in_slice(self.api, self.caller, slice): + granted=True ; break + # for convenience, pi's can tweak all the slices in their site + elif role=='pi': + if AuthorizeHelpers.slice_belongs_to_pi (self.api, slice, self.caller): + granted=True ; break + if not granted: + raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) slice_tag.delete() self.event_objects = {'SliceTag': [slice_tag['slice_tag_id']]} diff --git a/PLC/Methods/UpdatePersonTag.py b/PLC/Methods/UpdatePersonTag.py index 97862ef..2a88179 100644 --- a/PLC/Methods/UpdatePersonTag.py +++ b/PLC/Methods/UpdatePersonTag.py @@ -42,7 +42,7 @@ class UpdatePersonTag(Method): if 'admin' in self.caller['roles']: pass # user can change tags on self - elif AuthorizeHelpers.person_access_person (self.api, self.caller, person): + elif AuthorizeHelpers.person_may_access_person (self.api, self.caller, person): pass else: raise PLCPermissionDenied, "%s: you can only change your own tags"%self.name diff --git a/PLC/Methods/UpdateSiteTag.py b/PLC/Methods/UpdateSiteTag.py index fadd953..733cb12 100644 --- a/PLC/Methods/UpdateSiteTag.py +++ b/PLC/Methods/UpdateSiteTag.py @@ -49,7 +49,7 @@ class UpdateSiteTag(Method): pass elif not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) - elif AuthorizeHelpers.person_belongs_to_site (self.api, self.caller, site): + elif AuthorizeHelpers.person_in_site (self.api, self.caller, site): pass else: raise PLCPermissionDenied, "%s: you must be part of the subject site"%self.name diff --git a/PLC/Methods/UpdateSliceTag.py b/PLC/Methods/UpdateSliceTag.py index e8b8b33..5e1123a 100644 --- a/PLC/Methods/UpdateSliceTag.py +++ b/PLC/Methods/UpdateSliceTag.py @@ -49,23 +49,46 @@ class UpdateSliceTag(Method): assert slice_tag['slice_tag_id'] in slice['slice_tag_ids'] - if not isinstance(self.caller, Node): - if 'admin' not in self.caller['roles']: - if self.caller['person_id'] in slice['person_ids']: - pass - elif 'pi' not in self.caller['roles']: - raise PLCPermissionDenied, "Not a member of the specified slice" - elif slice['site_id'] not in self.caller['site_ids']: - raise PLCPermissionDenied, "Specified slice not associated with any of your sites" - - if slice_tag['min_role_id'] is not None and \ - min(self.caller['role_ids']) > slice_tag['min_role_id']: - raise PLCPermissionDenied, "Not allowed to update the specified attribute" + # check authorizations + node_id_or_hostname=slice_tag['node_id'] + nodegroup_id_or_name=slice_tag['nodegroup_id'] + granted=False + if 'admin' in self.caller['roles']: + granted=True + # does caller have right role(s) ? this knows how to deal with self.caller being a node + elif not AuthorizeHelpers.caller_may_access_tag_type (self.api, self.caller, tag_type): + granted=False + # node callers: check the node is in the slice + elif isinstance(self.caller, Node): + # nodes can only set their own sliver tags + if node_id_or_hostname is None: + granted=False + elif not AuthorizeHelpers.node_match_id (self.api, self.caller, node_id_or_hostname): + granted=False + elif not AuthorizeHelpers.node_in_slice (self.api, self.caller, slice): + granted=False + # caller is a non-admin person else: - ### make node's min_role_id == PI min_role_id - node_role_id = 20 - if slice_tag['min_role_id'] is not None and node_role_id > slice_tag['min_role_id']: - raise PLCPermissionDenied, "Not allowed to update the specified slice attribute" + # only admins can handle slice tags on a nodegroup + if nodegroup_id_or_name: + raise PLCPermissionDenied, "%s, cannot set slice tag %s on nodegroup - restricted to admins"%\ + (self.name,tag_type['tagname']) + # if a node is specified it is expected to be in the slice + if node_id_or_hostname: + if not AuthorizeHelpers.node_id_in_slice (self.api, node_id_or_hostname, slice): + raise PLCPermissionDenied, "%s, node must be in slice when setting sliver tag" + # try all roles to find a match - tech are ignored b/c not in AddSliceTag.roles anyways + for role in AuthorizeHelpers.person_tag_type_common_roles(self.api,self.caller,tag_type): + # regular users need to be in the slice + if role=='user': + if AuthorizeHelpers.person_in_slice(self.api, self.caller, slice): + granted=True ; break + # for convenience, pi's can tweak all the slices in their site + elif role=='pi': + if AuthorizeHelpers.slice_belongs_to_pi (self.api, slice, self.caller): + granted=True ; break + if not granted: + raise PLCPermissionDenied, "%s, forbidden tag %s"%(self.name,tag_type['tagname']) if slice_tag['tagname'] in ['initscript']: initscripts = InitScripts(self.api, {'enabled': True, 'name': value}) diff --git a/PLC/PersonTags.py b/PLC/PersonTags.py index 30869af..9327abf 100644 --- a/PLC/PersonTags.py +++ b/PLC/PersonTags.py @@ -1,5 +1,3 @@ -# $Id$ -# $URL$ # # Thierry Parmentelat - INRIA # diff --git a/PLC/SiteTags.py b/PLC/SiteTags.py index 45cbfd9..d04b947 100644 --- a/PLC/SiteTags.py +++ b/PLC/SiteTags.py @@ -1,5 +1,3 @@ -# $Id$ -# $URL$ # # Thierry Parmentelat - INRIA #