working copy of registry
[sfa.git] / registry / registry.py
1 import tempfile
2 import os
3
4 from cert import *
5 from gid import *
6 from geniserver import *
7 from excep import *
8 from hierarchy import *
9 from misc import *
10
11 def get_pl_object_by_hrn(hrn):
12     # find the object in the planetlab database
13     pointer = None
14     if (type=="sa") or (type=="ma"):
15         authname = hrn_to_pl_authname(name):
16         pl_res = shell.GetSites(pl_auth, {'name': authname)
17         if pl_res:
18             site_info = pl_res[0]
19             pointer = auth_info['auth_id']
20             return (site_info, pointer)
21     elif (type=="slice"):
22         slicename = hrn_to_pl_slicename(name)
23         pl_res = shell.GetSlices(pl_auth, {'name': slicename)
24         if pl_res:
25             slice_info = pl_res[0]
26             pointer = slice_info['slice_id']
27             return (slice_info, pointer)
28     elif (type=="user"):
29         username = hrn_to_pl_username(name)
30         pl_res = shell.GetPersons(pl_auth, {'name': slicename)
31         if pl_res:
32             person_info = pl_res[0]
33             pointer = slice_info['person_id']
34             return (person_info, pointer)
35     elif (type=="component"):
36         node_name = hrn_to_pl_nodename(hrn)
37         pl_res = shell.GetNodes(pl_auth, {'name': nodename)
38         if pl_res:
39             node_info = pl_res[0]
40             pointer = node_info['node_id']
41             return (node_info, pointer)
42     else:
43         raise UnknownGeniType(type)
44
45     return (None, None)
46
47 class Registry(GeniServer):
48     def __init__(self, ip, port, key_file, cert_file):
49         GeniServer.__init__(self, ip, port, key_file, cert_file)
50
51     def register_functions(self):
52         GeniServer.register_functions(self)
53         self.server.register_function(self.get_self_credential)
54         self.server.register_function(self.get_credential)
55         self.server.register_function(self.get_gid)
56
57     def get_auth_info(name):
58         return Hierarchy.get_auth_info(name)
59
60     def get_auth_table(self, auth_name):
61         auth_info = get_auth_info(name, can_create=False)
62
63         table = GeniTable(hrn = auth_name,
64                           auth_info.get_cninfo()
65                           auth_info.get_privkey_object()
66                           auth_info.get_gid_object())
67
68         # if the table doesn't exist, then it means we haven't put any records
69         # into this authority yet.
70
71         if not table.exists():
72             table.create()
73
74         return table
75
76     def verify_auth_belongs_to_me(self, name):
77         # get_auth_info will throw an exception if the authority does not
78         # exist
79         self.get_auth_info(name)
80
81     def verify_object_belongs_to_me(self, name):
82         auth_name = get_authority(name)
83         self.verify_auth_belongs_to_me(auth_name)
84
85     def register(self, cred, name, record_dict):
86         self.decode_authentication(cred)
87
88         auth_name = get_authority(name)
89         auth_info = self.get_auth_info(auth_name)
90         table = self.get_auth_table(auth_name)
91
92         record = GeniRecord(dict = record_dict)
93         type = record.get_type()
94
95         pkey = None
96
97         # check if record already exists
98         existing_records = table.resolve(name, type)
99         if existing_records:
100             raise ExistingRecord(name)
101
102         if (type == "sa") or (type=="ma"):
103             # update the tree
104             if not Hierarchy.auth_exists(name):
105                 Hierarchy.create_auth(name)
106
107             # get the public key from the newly created authority
108             child_auth_info = self.get_auth_info(name)
109             pkey = child_auth_info.get_pkey_object()
110
111             site_fields = record.get_pl_info()
112             pointer = shell.AddSite(pl_auth, site_fields)
113             record.set_pointer(pointer)
114
115         elif (type == "slice"):
116             slice_fields = record.get_pl_info()
117             pointer = shell.AddSlice(pl_auth, slice_fields)
118             record.set_pointer(pointer)
119
120         elif (type == "user"):
121             # TODO: extract pkey from user_fields
122             user_fields = record.get_pl_info()
123             pointer = shell.AddPerson(pl_auth, user_fields)
124             record.set_pointer(pointer)
125
126         elif (type == "node"):
127             node_fields = record.get_pl_info()
128             pointer = shell.AddNode(pl_auth, login_base, node_fields)
129             record.set_pointer(pointer)
130
131         else:
132             raise UnknownGeniType(type)
133
134         gid = Hierarchy.create_gid(name, create_uuid(), pkey)
135         record.set_gid(gid.save_to_string())
136         table.insert(record)
137
138     def remove(self, cred, record_dict):
139         self.decode_authentication(cred)
140
141         record = GeniRecord(dict = record_dict)
142         type = record.get_type()
143
144         auth_name = get_authority(record.get_name())
145         table = self.get_auth_table(auth_name)
146
147         # let's not trust that the caller has a well-formed record (a forged
148         # pointer field could be a disaster), so look it up ourselves
149         record = table.resolve(type, record.get_name(), must_exist=True)[0]
150
151         # TODO: sa, ma
152         if type == "user":
153             shell.DeletePerson(pl_auth, record.get_pointer())
154         elif type == "slice":
155             shell.DeleteSlice(pl_auth, record.get_pointer())
156         elif type == "node":
157             shell.DeleteNode(pl_auth, record.get_pointer())
158         else:
159             raise UnknownGeniType(type)
160
161         table.remove(record_dict)
162
163     def update(self, cred, record_dict):
164         self.decode_authentication(cred)
165
166         record = GeniRecord(dict = record_dict)
167         type = record.get_type()
168
169         auth_name = get_authority(record.get_name())
170         table = self.get_auth_table(auth_name)
171
172         # make sure the record exists
173         existing_record = table.resolve(type, record.get_name(), must_exist=True)[0]
174         pointer = existing_record.get_pointer()
175
176         if (type == "sa") or (type == "ma"):
177             shell.UpdateSite(pl_auth, pointer, record.get_pl_info())
178
179         elif type == "slice":
180             shell.UpdateSlice(pl_auth, pointer, record.get_pl_info())
181
182         elif type == "user":
183             shell.UpdatePerson(pl_auth, pointer, record.get_pl_info())
184
185         elif type == "node":
186             shell.UpdateNode(pl_auth, pointer, record.get_pl_info())
187
188         else:
189             raise UnknownGeniType(type)
190
191     def list(self, cred):
192         self.decode_authentication(cred)
193
194         auth_name = self.object_gid.get_hrn()
195         table = self.get_auth_table(auth_name)
196
197         dict_list = table.list_dict()
198
199         return dict_list
200
201     def resolve_raw(self, type, name, must_exist=True):
202         auth_name = get_authority(name)
203
204         table = get_auth_table(auth_name)
205
206         records = table.resolve(type, name)
207
208         if (not records) and must_exist:
209             raise RecordNotFound(name)
210
211         return records
212
213     def resolve(self, name):
214         self.decode_authentication(cred)
215
216         records = self.resolve("*", name)
217         dicts = []
218         for record in records:
219             dicts.append(record.as_dict())
220
221         return dicts
222
223     def get_gid(self, name):
224         self.verify_object_belongs_to_me(name) # XXX Fixme
225         records = self.resolve_raw("*", name)
226         gid_string_list = []
227         for record in records:
228             gid = record.get_gid()
229             gid_string_list.append(gid.save_to_string())
230         return gid_string_list
231
232     def get_self_credential(self, type, name):
233         self.verify_object_belongs_to_me(name)
234
235         # find a record that matches
236         records = self.resolve_raw(type, name, must_exist=True)
237         record = records[0]
238
239         gid = record.get_gid()
240         peer_cert = self.server.peer_cert
241         if not peer_cert.is_pubkey(gid.get_pubkey()):
242            raise ConnectionKeyGIDMismatch(gid.get_subject())
243
244         # create the credential
245         gid = found_record.get_gid()
246         cred = Credential(subject = gid.get_subject())
247         cred.set_gid_caller(gid)
248         cred.set_gid_object(gid)
249         cred.set_issuer(key=self.key, subject=auth_hrn)
250         cred.set_pubkey(gid.get_pubkey())
251         cred.encode()
252         cred.sign()
253
254         return cred.save_to_string()
255
256     def get_credential(self, cred, type, name):
257         if not cred:
258             return get_self_credential(self, type, name)
259
260         self.decode_authentication(cred)
261
262         self.verify_object_belongs_to_me(name)
263
264         records = self.resolve(type, name, must_exist=True)
265         record = records[0]
266
267         object_gid = record.get_gid()
268         new_cred = Credential(subject = object_gid.get_subject())
269         new_cred.set_gid_caller(self.client_gid)
270         new_cred.set_gid_object(object_gid)
271         new_cred.set_issuer(key=self.key, cert=self.cert)
272         new_cred.set_pubkey(object_gid.get_pubkey())
273         new_cred.encode()
274         new_cred.sign()
275
276         return new_cred.save_to_string()
277
278 if __name__ == "__main__":
279     key_file = "server.key"
280     cert_file = "server.cert"
281
282     # if no key is specified, then make one up
283     if (not os.path.exists(key_file)) or (not os.path.exists(cert_file)):
284         key = Keypair(create=True)
285         key.save_to_file(key_file)
286
287         cert = Certificate(subject="registry")
288         cert.set_issuer(key=key, subject="registry")
289         cert.set_pubkey(key)
290         cert.sign()
291         cert.save_to_file(cert_file)
292
293     s = Registry("localhost", 12345, key_file, cert_file)
294     s.run()
295