From: Thierry Parmentelat Date: Fri, 19 Nov 2010 14:38:11 +0000 (+0100) Subject: first draft of slice tags authorization in AddSliceTag X-Git-Tag: plcapi-5.0-19~51 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=abb42eea5e447613258cdcffcb6167155ee29cfe;hp=d7e6a0d352a7dee7d8fdff51f35142b9a739bdde;p=plcapi.git first draft of slice tags authorization in AddSliceTag --- diff --git a/PLC/AuthorizeHelpers.py b/PLC/AuthorizeHelpers.py index 9c3e666..1f3b8a9 100644 --- a/PLC/AuthorizeHelpers.py +++ b/PLC/AuthorizeHelpers.py @@ -2,6 +2,8 @@ # Thierry Parmentelat - INRIA # from PLC.Faults import * +from PLC.Persons import Person +from PLC.Nodes import Node class AuthorizeHelpers: @@ -26,13 +28,34 @@ class AuthorizeHelpers: return site['site_id'] in person['site_ids'] @staticmethod - def person_access_tag_type (api, person, tag_type): - return len(set(person['roles']).intersection(set(tag_type['roles'])))!=0 + 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 + 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): # keep it simple for now - could be a bit more advanced for PIs maybe - return caller_person['person_id'] == subject_person['person_id'] + try: return caller_person['person_id'] == subject_person['person_id'] + except: return False + @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'] + + @staticmethod + def node_id_or_hostname_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 GetNodes(node_id_or_hostname_in_slice)[0]['node_id'] in slice['node_ids'] + except:return False diff --git a/PLC/Methods/AddSliceTag.py b/PLC/Methods/AddSliceTag.py index a01bb12..34195f6 100644 --- a/PLC/Methods/AddSliceTag.py +++ b/PLC/Methods/AddSliceTag.py @@ -17,14 +17,18 @@ from PLC.AuthorizeHelpers import AuthorizeHelpers class AddSliceTag(Method): """ - Sets the specified attribute of the slice (or sliver, if - node_id_or_hostname is specified) to the specified value. + Sets the specified tag of the slice to the specified value. + If nodegroup is specified, this applies to all slivers of that group. + If node is specified, this only applies to a sliver. - Attributes may require the caller to have a particular role in - order to be set or changed. Users may only set attributes of - slices or slivers of which they are members. PIs may only set - attributes of slices or slivers at their sites, or of which they - are members. Admins may set attributes of any slice or sliver. + Admins have full access, including on nodegroups. + + 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. Returns the new slice_tag_id (> 0) if successful, faults otherwise. @@ -60,23 +64,35 @@ class AddSliceTag(Method): raise PLCInvalidArgument, "No such tag type %r"%tag_type_id_or_name tag_type = tag_types[0] - 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 tag_type['min_role_id'] is not None and \ - min(self.caller['role_ids']) > tag_type['min_role_id']: - raise PLCPermissionDenied, "Not allowed to set the specified slice attribute" - else: - ### make node's min_role_id == PI min_role_id - node_role_id = 20 - if tag_type['min_role_id'] is not None and node_role_id > tag_type['min_role_id']: - raise PLCPermissionDenied, "Not allowed to set the specified slice attribute" + # 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 + 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']) # if initscript is specified, validate value if tag_type['tagname'] in ['initscript']: @@ -109,7 +125,8 @@ class AddSliceTag(Method): system_slice_tags = SliceTags(self.api, {'tagname': 'system', 'value': '1'}).dict('slice_id') system_slice_ids = system_slice_tags.keys() if slice['slice_id'] not in system_slice_ids and node_id not in slice['node_ids']: - raise PLCInvalidArgument, "AddSliceTag: slice %s not on specified node %s nor is it a system slice (%r)"%(slice['name'],node['hostname'],system_slice_ids) + raise PLCInvalidArgument, "AddSliceTag: slice %s not on specified node %s nor is it a system slice (%r)"%\ + (slice['name'],node['hostname'],system_slice_ids) slice_tag['node_id'] = node['node_id'] # Sliver attribute shared accross nodes if nodegroup is sepcified @@ -124,7 +141,7 @@ class AddSliceTag(Method): slice_tag['nodegroup_id'] = nodegroup['nodegroup_id'] - # Check if slice attribute alreay exists + # Check if slice attribute already exists slice_tags_check = SliceTags(self.api, {'slice_id': slice['slice_id'], 'tagname': tag_type['tagname'], 'value': value}) diff --git a/migrations/104-down-noderole.sql b/migrations/104-down-noderole.sql index f7d7220..f3d5196 100644 --- a/migrations/104-down-noderole.sql +++ b/migrations/104-down-noderole.sql @@ -1,5 +1,5 @@ -- reverting.... --- DELETE from roles WHERE name='node'; +DELETE from roles WHERE name='node'; -- recreate the min_role_id column ALTER TABLE tag_types ADD COLUMN min_role_id integer REFERENCES roles; diff --git a/migrations/104-up-noderole.sql b/migrations/104-up-noderole.sql index c31af7a..95c0e93 100644 --- a/migrations/104-up-noderole.sql +++ b/migrations/104-up-noderole.sql @@ -117,6 +117,8 @@ CREATE OR REPLACE VIEW view_ilinks AS SELECT * FROM tag_types INNER JOIN ilink USING (tag_type_id); --- INSERT INTO roles (role_id, name) VALUES (50, 'node'); +-- use this to allow nodes to set slice tags +INSERT INTO roles (role_id, name) VALUES (50, 'node'); +-------------------- UPDATE plc_db_version SET subversion = 104;