X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fmethods%2Fupdate.py;h=4076e977de980fd8560567dc65b48e2c47f01199;hb=31acbe969d3fbfa97e069767c1787e770aa5943e;hp=03433f4894e77953d28b6c30017ddc9e6ecfa9fd;hpb=2d017e5431b49461821979dedae59cfce9df0c05;p=sfa.git diff --git a/sfa/methods/update.py b/sfa/methods/update.py index 03433f48..4076e977 100644 --- a/sfa/methods/update.py +++ b/sfa/methods/update.py @@ -1,14 +1,17 @@ ### $Id$ ### $URL$ +import time from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth from sfa.util.record import GeniRecord +from sfa.util.genitable import GeniTable from sfa.trust.certificate import Keypair, convert_public_key from sfa.trust.gid import * from sfa.util.debug import log +from sfa.trust.credential import Credential class update(Method): """ @@ -26,43 +29,55 @@ class update(Method): accepts = [ Parameter(str, "Credential string"), - Parameter(dict, "Record dictionary to be updated") + Parameter(dict, "Record dictionary to be updated"), + Mixed(Parameter(str, "Request hash"), + Parameter(None, "Request hash not specified")) ] returns = Parameter(int, "1 if successful") - def call(self, cred, record_dict): + def call(self, cred, record_dict, request_hash=None, caller_cred=None): + if caller_cred==None: + caller_cred=cred + + #log the call + self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, Credential(string=caller_cred).get_gid_caller().get_hrn(), None, self.name)) + # This cred might be an authority cred, not a user, so we cant use it to + # authenticate the caller's request_hash. Let just get the caller's gid + # from the cred and authenticate using that + client_gid = Credential(string=cred).get_gid_caller() + client_gid_str = client_gid.save_to_string(save_parents=True) + self.api.auth.authenticateGid(client_gid_str, [cred], request_hash) self.api.auth.check(cred, "update") - record = GeniRecord(dict = record_dict) - type = record.get_type() - self.api.auth.verify_object_permission(record.get_name()) - auth_name = self.api.auth.get_authority(record.get_name()) - if not auth_name: - auth_name = record.get_name() - table = self.api.auth.get_auth_table(auth_name) - + new_record = GeniRecord(dict = record_dict) + type = new_record['type'] + hrn = new_record['hrn'] + self.api.auth.verify_object_permission(hrn) + table = GeniTable() # make sure the record exists - existing_record_list = table.resolve(type, record.get_name()) - if not existing_record_list: - raise RecordNotFound(record.get_name()) - existing_record = existing_record_list[0] - + records = table.findObjects({'type': type, 'hrn': hrn}) + if not records: + raise RecordNotFound(hrn) + record = records[0] + record['last_updated'] = time.gmtime() + # Update_membership needs the membership lists in the existing record # filled in, so it can see if members were added or removed - self.api.fill_record_info(existing_record) + self.api.fill_record_info(record) # Use the pointer from the existing record, not the one that the user # gave us. This prevents the user from inserting a forged pointer - pointer = existing_record.get_pointer() + pointer = record['pointer'] # update the PLC information that was specified with the record if (type == "authority"): - self.api.plshell.UpdateSite(self.api.plauth, pointer, record) + self.api.plshell.UpdateSite(self.api.plauth, pointer, new_record) elif type == "slice": - hrn=record.get_name() - pl_record=self.api.geni_fields_to_pl_fields(type, hrn, record) + pl_record=self.api.geni_fields_to_pl_fields(type, hrn, new_record) + if 'name' in pl_record: + pl_record.pop('name') self.api.plshell.UpdateSlice(self.api.plauth, pointer, pl_record) elif type == "user": @@ -70,7 +85,7 @@ class update(Method): # updated. Ideally we should have a more generic way of doing # this. I copied the field names from UpdatePerson.py... update_fields = {} - all_fields = record + all_fields = new_record for key in all_fields.keys(): if key in ['first_name', 'last_name', 'title', 'email', 'password', 'phone', 'url', 'bio', 'accepted_aup', @@ -78,46 +93,43 @@ class update(Method): update_fields[key] = all_fields[key] self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields) - if 'key' in record and record['key']: + if 'key' in new_record and new_record['key']: # must check this key against the previous one if it exists persons = self.api.plshell.GetPersons(self.api.plauth, [pointer], ['key_ids']) person = persons[0] keys = person['key_ids'] keys = self.api.plshell.GetKeys(self.api.plauth, person['key_ids']) key_exists = False + if isinstance(new_record['key'], list): + new_key = new_record['key'][0] + else: + new_key = new_record['key'] + # Delete all stale keys for key in keys: - if record['key'] != key['key']: + if new_record['key'] != key['key']: self.api.plshell.DeleteKey(self.api.plauth, key['key_id']) else: key_exists = True if not key_exists: - self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': record['key']}) - - # find the existing geni record - hrn = record['hrn'] - auth_name = self.api.auth.get_authority(hrn) - auth_info = self.api.auth.get_auth_info(auth_name) - table = self.api.auth.get_auth_table(auth_name) - person_records = table.resolve('user', hrn) - person_record = person_records[0] - + self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': new_key}) + # update the openssl key and gid - pkey = convert_public_key(record['key']) + pkey = convert_public_key(new_key) uuid = create_uuid() gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey) gid = gid_object.save_to_string(save_parents=True) record['gid'] = gid - record.set_gid(gid) + record = GeniRecord(dict=record) table.update(record) elif type == "node": - self.api.plshell.UpdateNode(self.api.plauth, pointer, record) + self.api.plshell.UpdateNode(self.api.plauth, pointer, new_record) else: raise UnknownGeniType(type) # update membership for researchers, pis, owners, operators - self.api.update_membership(existing_record, record) + self.api.update_membership(record, new_record) return 1