5 from sfa.util.faults import RecordNotFound, AccountNotEnabled, PermissionError, MissingAuthority, \
6 UnknownSfaType, ExistingRecord
7 from sfa.util.prefixTree import prefixTree
8 from sfa.util.record import SfaRecord
9 from sfa.senslab.table_slab import SfaTable
10 from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
11 from sfa.util.version import version_core
13 from sfa.trust.gid import GID
14 from sfa.trust.credential import Credential
15 from sfa.trust.certificate import Certificate, Keypair, convert_public_key
16 from sfa.trust.gid import create_uuid
18 # The GENI GetVersion call
20 peers =dict ([ (peername,v._ServerProxy__host) for (peername,v) in api.registries.iteritems()
21 if peername != api.hrn])
23 return version_core({'interface':'registry',
28 def get_credential(api, xrn, type, is_self=False):
31 hrn = urn_to_hrn(xrn)[0]
33 hrn, type = urn_to_hrn(xrn)
35 # Is this a root or sub authority
36 auth_hrn = api.auth.get_authority(hrn)
37 print>> sys.stderr , " \r\n REGISTRY get_credential auth_hrn:" , auth_hrn,"hrn : ", hrn, " Type : ", type, "is self : " , is_self,"<<"
38 if not auth_hrn or hrn == api.config.SFA_INTERFACE_HRN:
41 auth_info = api.auth.get_auth_info(auth_hrn)
43 print >> sys.stderr , " findObject ", type, hrn
44 records = table.findObjects({'type': type, 'hrn': hrn})
45 print>> sys.stderr , " \r\n ++ REGISTRY get_credential hrn %s records %s " %(hrn, records)
47 raise RecordNotFound(hrn)
50 # verify_cancreate_credential requires that the member lists
51 # (researchers, pis, etc) be filled in
52 api.driver.fill_record_info(record, api.aggregates)
53 record['enabled'] = True
54 print>> sys.stderr , " \r\n ++ REGISTRY get_credential hrn %s record['enabled'] %s is_self %s" %(hrn, record['enabled'], is_self)
55 if record['type']=='user':
56 if not record['enabled']:
57 print>> sys.stderr , " \r\n ++ REGISTRY get_credential hrn %s ACCOUNT Not enabled"
58 raise AccountNotEnabled(": PlanetLab account %s is not enabled. Please contact your site PI" %(record['email']))
61 # if this is a self cred the record's gid is the caller's gid
64 caller_gid = record.get_gid_object()
65 print>>sys.stderr, " \r\n REGISTRY IS SELF OK caller_hrn %s--- \r\n caller_gid %s---------" %(caller_hrn,caller_gid)
67 print>> sys.stderr , " \r\n ++ ELSE "
68 caller_gid = api.auth.client_cred.get_gid_caller()
69 print>> sys.stderr , " \r\n ++ ELSE caller_gid %s record %s" %(caller_gid, record)
70 caller_hrn = caller_gid.get_hrn()
71 print>> sys.stderr , " \r\n ++ ELSE caller_hrn %s " %(caller_hrn)
73 object_hrn = record.get_gid_object().get_hrn()
74 print>> sys.stderr , " \r\n ++ ELSE object_hrn %s " %(object_hrn)
76 rights = api.auth.determine_user_rights(caller_hrn, record)
77 print>> sys.stderr , " \r\n ++ After rights record: %s \r\n ====RIGHTS %s " %(record , rights)
79 # make sure caller has rights to this object
81 raise PermissionError(caller_hrn + " has no rights to " + record['name'])
83 object_gid = GID(string=record['gid'])
84 new_cred = Credential(subject = object_gid.get_subject())
85 new_cred.set_gid_caller(caller_gid)
86 new_cred.set_gid_object(object_gid)
87 new_cred.set_issuer_keys(auth_info.get_privkey_filename(), auth_info.get_gid_filename())
88 #new_cred.set_pubkey(object_gid.get_pubkey())
89 new_cred.set_privileges(rights)
90 new_cred.get_privileges().delegate_all_privileges(True)
91 if 'expires' in record:
92 new_cred.set_expiration(int(record['expires']))
93 auth_kind = "authority,ma,sa"
94 # Parent not necessary, verify with certs
95 #new_cred.set_parent(api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind))
99 return new_cred.save_to_string(save_parents=True)
102 def resolve(api, xrns, type=None, full=True):
104 # load all known registry names into a prefix tree and attempt to find
105 # the longest matching prefix
106 print >>sys.stderr , '\t\t REGISTRY MANAGER : resolve=========xrns ', xrns
107 if not isinstance(xrns, types.ListType):
109 type = Xrn(xrns).get_type()
111 hrns = [urn_to_hrn(xrn)[0] for xrn in xrns]
112 print >>sys.stderr , '\t\t =========hrns ', hrns
113 # create a dict where key is a registry hrn and its value is a
114 # hrns at that registry (determined by the known prefix tree).
116 print >>sys.stderr, '\r\n REGISTRY MANAGER : resolve xrns ' , xrns #api.__dict__.keys()
117 registries = api.registries
119 registry_hrns = registries.keys()
120 print >>sys.stderr, '\r\n \t\t REGISTRY MANAGER registry_hrns' , registry_hrns
121 tree.load(registry_hrns)
123 registry_hrn = tree.best_match(urn_to_hrn(xrn)[0])
124 print >>sys.stderr, '\t\tREGISTRY MANAGER *****tree.best_match ', registry_hrn
125 if registry_hrn not in xrn_dict:
126 xrn_dict[registry_hrn] = []
127 xrn_dict[registry_hrn].append(xrn)
128 print >>sys.stderr, '\t\tREGISTRY MANAGER *****xrn_dict[registry_hrn] ',xrn_dict[registry_hrn]
130 for registry_hrn in xrn_dict:
131 # skip the hrn without a registry hrn
132 # XX should we let the user know the authority is unknown?
133 print >>sys.stderr, '\t\t registry_hrn in xrn_dict ', registry_hrn
137 # if the best match (longest matching hrn) is not the local registry,
138 # forward the request
139 xrns = xrn_dict[registry_hrn]
140 if registry_hrn != api.hrn:
141 credential = api.getCredential()
142 interface = api.registries[registry_hrn]
143 server = api.server_proxy(interface, credential)
144 peer_records = server.Resolve(xrns, credential)
145 print >>sys.stderr , '\t\t peer_records ', peer_records
146 records.extend([SfaRecord(dict=record).as_dict() for record in peer_records])
148 print >>sys.stderr,'\t\t hrns ' , hrns
149 # try resolving the remaining unfound records at the local registry
150 remaining_hrns = set(hrns).difference([record['hrn'] for record in records])
151 # convert set to list
152 remaining_hrns = [hrn for hrn in remaining_hrns]
153 print >>sys.stderr, '\t\t remaining_hrns', remaining_hrns
155 local_records = table.findObjects({'hrn': remaining_hrns})
157 print >>sys.stderr, '\t\t LOCAL REC !', local_records
158 for rec in local_records:
159 print >>sys.stderr, '\t\t resolve regmanager : rec ', rec
162 print >>sys.stderr, '\r\n \r\n REGISTRY:_FULL', api
163 api.driver.fill_record_info(local_records)
165 # convert local record objects to dicts
166 records.extend([dict(record) for record in local_records])
167 print >>sys.stderr, "\r\n \t\t records extends %s" %(records)
169 raise RecordNotFound(str(hrns))
172 records = filter(lambda rec: rec['type'] in [type], records)
176 def list(api, xrn, origin_hrn=None):
177 hrn, type = urn_to_hrn(xrn)
178 # load all know registry names into a prefix tree and attempt to find
179 # the longest matching prefix
181 registries = api.registries
182 registry_hrns = registries.keys()
184 tree.load(registry_hrns)
185 registry_hrn = tree.best_match(hrn)
187 #if there was no match then this record belongs to an unknow registry
189 raise MissingAuthority(xrn)
190 # if the best match (longest matching hrn) is not the local registry,
191 # forward the request
193 if registry_hrn != api.hrn:
194 credential = api.getCredential()
195 print>>sys.stderr, "Registries : ", registries
196 interface = api.registries[registry_hrn]
197 server = api.server_proxy(interface, credential)
198 record_list = server.List(xrn, credential)
199 records = [SfaRecord(dict=record).as_dict() for record in record_list]
201 # if we still have not found the record yet, try the local registry
203 if not api.auth.hierarchy.auth_exists(hrn):
204 raise MissingAuthority(hrn)
207 records = table.find({'authority': hrn})
212 def register(api, record):
214 #hrn, type = record['hrn'], record['type']
215 hrn = str(record['hrn']).strip("['']")
216 type = str( record['type']).strip("['']")
217 urn = hrn_to_urn(hrn,type)
219 if type not in ['authority', 'slice', 'node', 'user']:
220 raise UnknownSfaType(type)
222 # check if record already exists
224 existing_records = table.find({'type': type, 'hrn': hrn})
226 raise ExistingRecord(hrn)
228 record = SfaRecord(dict = record)
230 print>>sys.stderr, " \r\n \r\n ----------- REGISTRY_MANAGER_SLAN.PY register SfaRecordrecord %s" %(record)
231 #record['authority'] = get_authority(record['hrn'])
232 record['authority'] = get_authority(hrn)
234 #type_of_rec = record['type']
237 #api.auth.verify_object_permission(hrn)
238 api.auth.verify_object_permission( record['hrn'])
239 auth_info = api.auth.get_auth_info(record['authority'])
241 # make sure record has a gid
242 if 'gid' not in record:
244 pkey = Keypair(create=True)
245 if 'key' in record and record['key']:
246 if isinstance(record['key'], types.ListType):
247 pub_key = record['key'][0]
249 pub_key = record['key']
250 pkey = convert_public_key(pub_key)
252 gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
253 gid = gid_object.save_to_string(save_parents=True)
256 print>>sys.stderr, " \r\n \r\n ----------- REGISTRY_MANAGER_SLAB.PY record['gid'] %s" %(record['gid'])
257 print>>sys.stderr, " \r\n \r\n ----------- REGISTRY_MANAGER_SLAB.PY register type %s"%(type)
259 if type in ["authority"]:
261 if not api.auth.hierarchy.auth_exists(hrn):
262 api.auth.hierarchy.create_auth(hrn_to_urn(hrn,'authority'))
264 # get the GID from the newly created authority
265 gid = auth_info.get_gid_object()
266 record.set_gid(gid.save_to_string(save_parents=True))
268 #pl_record = api.driver.sfa_fields_to_pl_fields(type, hrn, record)
269 print>>sys.stderr, " \r\n \r\n ----------- REGISTRY_MANAGER_SLAB.PY register : type in [authority ] sfa_fields_to_pl_fields FIELDS A CHANGER"
271 # thierry: ideally we'd like to be able to write api.driver.GetSites
272 # in which case the code would become mostly the same as for pl
273 sites = api.driver.GetSites([pl_record['login_base']])
276 # Error (E0601, register): Using variable 'pl_record' before assignment
277 pointer = api.driver.AddSite( pl_record)
279 pointer = sites[0]['site_id']
281 record.set_pointer(pointer)
282 record['pointer'] = pointer
284 elif (type == "slice"):
285 acceptable_fields=['url', 'instantiation', 'name', 'description']
286 pl_record = api.driver.sfa_fields_to_pl_fields(type, hrn, record)
287 print>>sys.stderr, " \r\n \r\n ----------- REGISTRY_MANAGER_SLAB.PY register slice pl_record %s"%(pl_record)
288 for key in pl_record.keys():
289 if key not in acceptable_fields:
291 slices = api.driver.GetSlices([pl_record['name']])
293 pointer = api.driver.AddSlice(pl_record)
295 pointer = slices[0]['slice_id']
296 record.set_pointer(pointer)
297 record['pointer'] = pointer
299 elif (type == "user"):
300 persons = api.driver.GetPersons([record['email']])
302 print>>sys.stderr, " \r\n \r\n ----------- registry_manager_slab register NO PERSON ADD TO LDAP?"
305 #pointer = api.driver.AddPerson( dict(record))
307 #pointer = persons[0]['person_id']
309 if 'enabled' in record and record['enabled']:
310 api.driver.UpdatePerson(pointer, {'enabled': record['enabled']})
311 # add this persons to the site only if he is being added for the first
312 # time by sfa and doesont already exist in plc
313 if not persons or not persons[0]['site_ids']:
314 login_base = get_leaf(record['authority'])
315 api.driver.AddPersonToSite(pointer, login_base)
317 # What roles should this user have?
318 api.driver.AddRoleToPerson('user', pointer)
321 api.driver.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
323 #elif (type == "node"):
324 #pl_record = api.driver.sfa_fields_to_pl_fields(type, hrn, record)
325 #login_base = hrn_to_pl_login_base(record['authority'])
326 #nodes = api.driver.GetNodes([pl_record['hostname']])
328 #pointer = api.driver.AddNode(login_base, pl_record)
330 #pointer = nodes[0]['node_id']
332 ##record['pointer'] = pointer
333 ##record.set_pointer(pointer)
334 #record_id = table.insert(record)
335 #record['record_id'] = record_id
337 # update membership for researchers, pis, owners, operators
338 api.driver.update_membership(None, record)
340 return record.get_gid_object().save_to_string(save_parents=True)
342 def update(api, record_dict):
343 new_record = SfaRecord(dict = record_dict)
344 type = new_record['type']
345 hrn = new_record['hrn']
346 urn = hrn_to_urn(hrn,type)
347 api.auth.verify_object_permission(hrn)
349 # make sure the record exists
350 records = table.findObjects({'type': type, 'hrn': hrn})
352 raise RecordNotFound(hrn)
354 record['last_updated'] = time.gmtime()
356 # Update_membership needs the membership lists in the existing record
357 # filled in, so it can see if members were added or removed
358 api.driver.fill_record_info(record)
360 # Use the pointer from the existing record, not the one that the user
361 # gave us. This prevents the user from inserting a forged pointer
362 pointer = record['pointer']
363 # update the PLC information that was specified with the record
365 if (type == "authority"):
366 api.driver.UpdateSite(pointer, new_record)
368 elif type == "slice":
369 pl_record=api.driver.sfa_fields_to_pl_fields(type, hrn, new_record)
370 if 'name' in pl_record:
371 pl_record.pop('name')
372 api.driver.UpdateSlice(pointer, pl_record)
375 # SMBAKER: UpdatePerson only allows a limited set of fields to be
376 # updated. Ideally we should have a more generic way of doing
377 # this. I copied the field names from UpdatePerson.py...
379 all_fields = new_record
380 for key in all_fields.keys():
381 if key in ['first_name', 'last_name', 'title', 'email',
382 'password', 'phone', 'url', 'bio', 'accepted_aup',
384 update_fields[key] = all_fields[key]
385 api.driver.UpdatePerson(pointer, update_fields)
387 if 'key' in new_record and new_record['key']:
388 # must check this key against the previous one if it exists
389 persons = api.driver.GetPersons([pointer], ['key_ids'])
391 keys = person['key_ids']
392 keys = api.driver.GetKeys(person['key_ids'])
394 if isinstance(new_record['key'], types.ListType):
395 new_key = new_record['key'][0]
397 new_key = new_record['key']
399 # Delete all stale keys
401 if new_record['key'] != key['key']:
402 api.driver.DeleteKey(key['key_id'])
406 api.driver.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
408 # update the openssl key and gid
409 pkey = convert_public_key(new_key)
411 gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
412 gid = gid_object.save_to_string(save_parents=True)
414 record = SfaRecord(dict=record)
418 api.driver.UpdateNode(pointer, new_record)
421 raise UnknownSfaType(type)
423 # update membership for researchers, pis, owners, operators
424 api.driver.update_membership(record, new_record)
428 # expecting an Xrn instance
429 def remove(api, xrn, origin_hrn=None):
432 filter = {'hrn': xrn.get_hrn()}
435 if type and type not in ['all', '*']:
436 filter['type'] = type
438 records = table.find(filter)
439 if not records: raise RecordNotFound(hrn)
441 type = record['type']
443 credential = api.getCredential()
444 registries = api.registries
446 # Try to remove the object from the PLCDB of federated agg.
447 # This is attempted before removing the object from the local agg's PLCDB and sfa table
448 if hrn.startswith(api.hrn) and type in ['user', 'slice', 'authority']:
449 for registry in registries:
450 if registry not in [api.hrn]:
452 result=registries[registry].remove_peer_object(credential, record, origin_hrn)
456 persons = api.driver.GetPersons(record['pointer'])
457 # only delete this person if he has site ids. if he doesnt, it probably means
458 # he was just removed from a site, not actually deleted
459 if persons and persons[0]['site_ids']:
460 api.driver.DeletePerson(record['pointer'])
461 elif type == "slice":
462 if api.driver.GetSlices(record['pointer']):
463 api.driver.DeleteSlice(record['pointer'])
465 if api.driver.GetNodes(record['pointer']):
466 api.driver.DeleteNode(record['pointer'])
467 elif type == "authority":
468 if api.driver.GetSites(record['pointer']):
469 api.driver.DeleteSite(record['pointer'])
471 raise UnknownSfaType(type)
477 def remove_peer_object(api, record, origin_hrn=None):
480 def register_peer_object(api, record, origin_hrn=None):