8 from geniserver import *
10 from hierarchy import *
14 def geni_fields_to_pl_fields(type, hrn, geni_fields, pl_fields):
16 if not "email" in pl_fields:
17 if not "email" in geni_fields:
18 raise MissingGeniInfo("email")
19 pl_fields["email"] = geni_fields["email"]
21 if not "first_name" in pl_fields:
22 pl_fields["first_name"] = "geni"
24 if not "last_name" in pl_fields:
25 pl_fields["last_name"] = hrn
28 class Registry(GeniServer):
29 def __init__(self, ip, port, key_file, cert_file):
30 GeniServer.__init__(self, ip, port, key_file, cert_file)
32 # get PL account settings from config module
33 self.pl_auth = get_pl_auth()
35 # connect to planetlab
36 if "Url" in self.pl_auth:
37 self.connect_remote_shell()
39 self.connect_local_shell()
41 def connect_remote_shell(self):
43 self.shell = remoteshell.RemoteShell()
45 def connect_local_shell(self):
47 self.shell = PLC.Shell.Shell(globals = globals())
49 def register_functions(self):
50 GeniServer.register_functions(self)
51 self.server.register_function(self.create_gid)
52 self.server.register_function(self.get_self_credential)
53 self.server.register_function(self.get_credential)
54 self.server.register_function(self.get_gid)
55 self.server.register_function(self.register)
56 self.server.register_function(self.remove)
57 self.server.register_function(self.update)
58 self.server.register_function(self.list)
59 self.server.register_function(self.resolve)
61 def get_auth_info(self, name):
62 return AuthHierarchy.get_auth_info(name)
64 def get_auth_table(self, auth_name):
65 auth_info = self.get_auth_info(auth_name)
67 table = GeniTable(hrn=auth_name,
68 cninfo=auth_info.get_dbinfo())
70 # if the table doesn't exist, then it means we haven't put any records
71 # into this authority yet.
73 if not table.exists():
74 report.trace("Registry: creating table for authority " + auth_name)
79 def verify_auth_belongs_to_me(self, name):
80 # get_auth_info will throw an exception if the authority does not
82 self.get_auth_info(name)
84 def verify_object_belongs_to_me(self, name):
85 auth_name = get_authority(name)
87 # the root authority belongs to the registry by default?
90 self.verify_auth_belongs_to_me(auth_name)
92 def verify_object_permission(self, name):
93 object_hrn = self.object_gid.get_hrn()
94 if object_hrn == name:
96 if name.startswith(object_hrn + "."):
98 raise PermissionError(name)
100 def fill_record_pl_info(self, record):
101 type = record.get_type()
102 pointer = record.get_pointer()
104 if (type == "sa") or (type == "ma"):
105 pl_res = self.shell.GetSites(self.pl_auth, [pointer])
106 elif (type == "slice"):
107 pl_res = self.shell.GetSlices(self.pl_auth, [pointer])
108 elif (type == "user"):
109 pl_res = self.shell.GetPersons(self.pl_auth, [pointer])
110 elif (type == "node"):
111 pl_res = self.shell.GetNodes(self.pl_auth, [pointer])
113 raise UnknownGeniType(type)
116 # the planetlab record no longer exists
117 # TODO: delete the geni record ?
118 raise PlanetLabRecordDoesNotExist(record.get_name())
120 record.set_pl_info(pl_res[0])
122 def fill_record_geni_info(self, record):
125 def fill_record_info(self, record):
126 self.fill_record_pl_info(record)
127 self.fill_record_geni_info(record)
129 def register(self, cred, record_dict):
130 self.decode_authentication(cred, "register")
132 record = GeniRecord(dict = record_dict)
133 type = record.get_type()
134 name = record.get_name()
136 auth_name = get_authority(name)
137 self.verify_object_permission(auth_name)
138 auth_info = self.get_auth_info(auth_name)
139 table = self.get_auth_table(auth_name)
143 # check if record already exists
144 existing_records = table.resolve(name, type)
146 raise ExistingRecord(name)
148 if (type == "sa") or (type=="ma"):
150 if not AuthHierarchy.auth_exists(name):
151 AuthHierarchy.create_auth(name)
153 # authorities are special since they are managed by the registry
154 # rather than by the caller. We create our own GID for the
155 # authority rather than relying on the caller to supply one.
157 # get the public key from the newly created authority
158 child_auth_info = self.get_auth_info(name)
159 pkey = child_auth_info.get_pkey_object()
160 gid = AuthHierarchy.create_gid(name, create_uuid(), pkey)
161 record.set_gid(gid.save_to_string())
163 site_fields = record.get_pl_info()
164 pointer = self.shell.AddSite(self.pl_auth, site_fields)
165 record.set_pointer(pointer)
167 elif (type == "slice"):
168 slice_fields = record.get_pl_info()
169 pointer = self.shell.AddSlice(self.pl_auth, slice_fields)
170 record.set_pointer(pointer)
172 elif (type == "user"):
173 # TODO: extract pkey from user_fields?
174 geni_fields = record.get_geni_info()
175 user_fields = record.get_pl_info()
177 geni_fields_to_pl_fields(type, name, geni_fields, user_fields)
179 pointer = self.shell.AddPerson(self.pl_auth, user_fields)
180 record.set_pointer(pointer)
182 elif (type == "node"):
183 node_fields = record.get_pl_info()
184 pointer = self.shell.AddNode(self.pl_auth, login_base, node_fields)
185 record.set_pointer(pointer)
188 raise UnknownGeniType(type)
192 return record.get_gid_object().save_to_string()
194 def remove(self, cred, record_dict):
195 self.decode_authentication(cred, "remove")
197 record = GeniRecord(dict = record_dict)
198 type = record.get_type()
200 self.verify_object_permission(record.get_name())
202 auth_name = get_authority(record.get_name())
203 table = self.get_auth_table(auth_name)
205 # let's not trust that the caller has a well-formed record (a forged
206 # pointer field could be a disaster), so look it up ourselves
207 record_list = table.resolve(type, record.get_name())
209 raise RecordNotFound(name)
210 record = record_list[0]
214 self.shell.DeletePerson(self.pl_auth, record.get_pointer())
215 elif type == "slice":
216 self.shell.DeleteSlice(self.pl_auth, record.get_pointer())
218 self.shell.DeleteNode(self.pl_auth, record.get_pointer())
220 raise UnknownGeniType(type)
226 def update(self, cred, record_dict):
227 self.decode_authentication(cred, "update")
229 record = GeniRecord(dict = record_dict)
230 type = record.get_type()
232 self.verify_object_permission(record.get_name())
234 auth_name = get_authority(record.get_name())
235 table = self.get_auth_table(auth_name)
237 # make sure the record exists
238 existing_record = table.resolve(type, record.get_name(), must_exist=True)[0]
239 pointer = existing_record.get_pointer()
241 if (type == "sa") or (type == "ma"):
242 self.shell.UpdateSite(self.pl_auth, pointer, record.get_pl_info())
244 elif type == "slice":
245 self.shell.UpdateSlice(self.pl_auth, pointer, record.get_pl_info())
248 self.shell.UpdatePerson(self.pl_auth, pointer, record.get_pl_info())
251 self.shell.UpdateNode(self.pl_auth, pointer, record.get_pl_info())
254 raise UnknownGeniType(type)
256 # TODO: List doesn't take an hrn and uses the hrn contained in the
257 # objectGid of the credential. Does this mean the only way to list an
258 # authority is by having a credential for that authority?
259 def list(self, cred):
260 self.decode_authentication(cred, "list")
262 auth_name = self.object_gid.get_hrn()
263 table = self.get_auth_table(auth_name)
265 records = table.list()
268 for record in records:
270 self.fill_record_info(record)
271 good_records.append(record)
272 except PlanetLabRecordDoesNotExist:
273 # silently drop the ones that are missing in PL.
274 # is this the right thing to do?
275 report.error("ignoring geni record " + record.get_name() + " because pl record does not exist")
279 for record in good_records:
280 dicts.append(record.as_dict())
286 def resolve_raw(self, type, name, must_exist=True):
287 auth_name = get_authority(name)
289 table = self.get_auth_table(auth_name)
291 records = table.resolve(type, name)
293 if (not records) and must_exist:
294 raise RecordNotFound(name)
297 for record in records:
299 self.fill_record_info(record)
300 good_records.append(record)
301 except PlanetLabRecordDoesNotExist:
302 # silently drop the ones that are missing in PL.
303 # is this the right thing to do?
304 report.error("ignoring geni record " + record.get_hrn() + " because pl record does not exist")
309 def resolve(self, cred, name):
310 self.decode_authentication(cred, "resolve")
312 records = self.resolve_raw("*", name)
314 for record in records:
315 dicts.append(record.as_dict())
319 def get_gid(self, name):
320 self.verify_object_belongs_to_me(name) # XXX Fixme
321 records = self.resolve_raw("*", name)
323 for record in records:
324 gid = record.get_gid()
325 gid_string_list.append(gid.save_to_string())
326 return gid_string_list
328 def determine_rights(self, type, name):
331 # rights seem to be somewhat redundant with the type of the credential.
332 # For example, a "sa" credential implies the authority right, because
333 # a sa credential cannot be issued to a user who is not an owner of
343 elif type == "slice":
347 elif type == "component":
353 def get_self_credential(self, type, name):
354 self.verify_object_belongs_to_me(name)
356 auth_hrn = get_authority(name)
357 auth_info = self.get_auth_info(auth_hrn)
359 # find a record that matches
360 records = self.resolve_raw(type, name, must_exist=True)
363 gid = record.get_gid_object()
364 peer_cert = self.server.peer_cert
365 if not peer_cert.is_pubkey(gid.get_pubkey()):
366 raise ConnectionKeyGIDMismatch(gid.get_subject())
368 # create the credential
369 gid = record.get_gid_object()
370 cred = Credential(subject = gid.get_subject())
371 cred.set_gid_caller(gid)
372 cred.set_gid_object(gid)
373 cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn)
374 cred.set_pubkey(gid.get_pubkey())
376 rl = self.determine_rights(type, name)
377 cred.set_privileges(rl)
382 return cred.save_to_string()
384 def get_credential(self, cred, type, name):
386 return get_self_credential(self, type, name)
388 self.decode_authentication(cred, "getcredential")
390 self.verify_object_belongs_to_me(name)
392 auth_hrn = get_authority(name)
393 auth_info = self.get_auth_info(auth_hrn)
395 records = self.resolve_raw(type, name, must_exist=True)
398 # TODO: Check permission that self.client_cred can access the object
400 object_gid = record.get_gid_object()
401 new_cred = Credential(subject = object_gid.get_subject())
402 new_cred.set_gid_caller(self.client_gid)
403 new_cred.set_gid_object(object_gid)
404 new_cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn)
405 new_cred.set_pubkey(object_gid.get_pubkey())
407 rl = self.determine_rights(type, name)
408 new_cred.set_privileges(rl)
413 return new_cred.save_to_string()
415 def create_gid(self, cred, name, uuid, pubkey_str):
416 self.decode_authentication(cred, "getcredential")
418 self.verify_object_belongs_to_me(name)
420 self.verify_object_permission(name)
426 pkey.load_pubkey_from_string(pubkey_str)
427 gid = AuthHierarchy.create_gid(name, uuid, pkey)
429 return gid.save_to_string() ### save_parents=True)
432 if __name__ == "__main__":
435 key_file = "server.key"
436 cert_file = "server.cert"
438 # if no key is specified, then make one up
439 if (not os.path.exists(key_file)) or (not os.path.exists(cert_file)):
440 key = Keypair(create=True)
441 key.save_to_file(key_file)
443 cert = Certificate(subject="registry")
444 cert.set_issuer(key=key, subject="registry")
447 cert.save_to_file(cert_file)
449 AuthHierarchy = Hierarchy()
451 s = Registry("localhost", 12345, key_file, cert_file)