Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: net/tools/testserver/device_management.py

Issue 6537020: Update policy backend and testserver for the newest policy protocol (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix unit tests and chromeos crashes Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python2.5 1 #!/usr/bin/python2.5
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """A bare-bones test server for testing cloud policy support. 6 """A bare-bones test server for testing cloud policy support.
7 7
8 This implements a simple cloud policy test server that can be used to test 8 This implements a simple cloud policy test server that can be used to test
9 chrome's device management service client. The policy information is read from 9 chrome's device management service client. The policy information is read from
10 the file named device_management in the server's data directory. It contains 10 the file named device_management in the server's data directory. It contains
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 import simplejson as json 54 import simplejson as json
55 except ImportError: 55 except ImportError:
56 try: 56 try:
57 import json 57 import json
58 except ImportError: 58 except ImportError:
59 json = None 59 json = None
60 60
61 import device_management_backend_pb2 as dm 61 import device_management_backend_pb2 as dm
62 import cloud_policy_pb2 as cp 62 import cloud_policy_pb2 as cp
63 63
64 # TODO(gfeher): Remove before commit.
65 LOG_FILENAME = '/dev/stdout'
66 logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
gfeher 2011/02/25 20:36:35 I didn't forget this!
64 67
65 class RequestHandler(object): 68 class RequestHandler(object):
66 """Decodes and handles device management requests from clients. 69 """Decodes and handles device management requests from clients.
67 70
68 The handler implements all the request parsing and protobuf message decoding 71 The handler implements all the request parsing and protobuf message decoding
69 and encoding. It calls back into the server to lookup, register, and 72 and encoding. It calls back into the server to lookup, register, and
70 unregister clients. 73 unregister clients.
71 """ 74 """
72 75
73 def __init__(self, server, path, headers, request): 76 def __init__(self, server, path, headers, request):
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 110
108 Parses the data supplied at construction time and returns a pair indicating 111 Parses the data supplied at construction time and returns a pair indicating
109 http status code and response data to be sent back to the client. 112 http status code and response data to be sent back to the client.
110 113
111 Returns: 114 Returns:
112 A tuple of HTTP status code and response data to send to the client. 115 A tuple of HTTP status code and response data to send to the client.
113 """ 116 """
114 rmsg = dm.DeviceManagementRequest() 117 rmsg = dm.DeviceManagementRequest()
115 rmsg.ParseFromString(self._request) 118 rmsg.ParseFromString(self._request)
116 119
120 logging.debug('auth -> ' + self._headers.getheader('Authorization', ''))
121 logging.debug('deviceid -> ' + self.GetUniqueParam('deviceid'))
117 self.DumpMessage('Request', rmsg) 122 self.DumpMessage('Request', rmsg)
118 123
119 request_type = self.GetUniqueParam('request') 124 request_type = self.GetUniqueParam('request')
125 # Check server side requirements, as defined in
126 # device_management_backend.proto.
127 if (self.GetUniqueParam('devicetype') != '2' or
128 self.GetUniqueParam('apptype') != 'Chrome' or
129 (request_type != 'ping' and
130 len(self.GetUniqueParam('deviceid')) >= 64) or
131 len(self.GetUniqueParam('agent')) >= 64):
132 return (400, 'Invalid request parameter')
120 if request_type == 'register': 133 if request_type == 'register':
121 return self.ProcessRegister(rmsg.register_request) 134 return self.ProcessRegister(rmsg.register_request)
122 elif request_type == 'unregister': 135 elif request_type == 'unregister':
123 return self.ProcessUnregister(rmsg.unregister_request) 136 return self.ProcessUnregister(rmsg.unregister_request)
124 elif request_type == 'policy': 137 elif request_type == 'policy' or request_type == 'ping':
125 return self.ProcessPolicy(rmsg.policy_request) 138 return self.ProcessPolicy(rmsg.policy_request, request_type)
126 elif request_type == 'cloud_policy':
127 return self.ProcessCloudPolicyRequest(rmsg.cloud_policy_request)
128 elif request_type == 'managed_check':
129 return self.ProcessManagedCheck(rmsg.managed_check_request)
130 else: 139 else:
131 return (400, 'Invalid request parameter') 140 return (400, 'Invalid request parameter')
132 141
133 def CheckGoogleLogin(self): 142 def CheckGoogleLogin(self):
134 """Extracts the GoogleLogin auth token from the HTTP request, and 143 """Extracts the GoogleLogin auth token from the HTTP request, and
135 returns it. Returns None if the token is not present. 144 returns it. Returns None if the token is not present.
136 """ 145 """
137 match = re.match('GoogleLogin auth=(\\w+)', 146 match = re.match('GoogleLogin auth=(\\w+)',
138 self._headers.getheader('Authorization', '')) 147 self._headers.getheader('Authorization', ''))
139 if not match: 148 if not match:
140 return None 149 return None
141 return match.group(1) 150 return match.group(1)
142 151
143 def GetDeviceName(self):
144 """Returns the name for the currently authenticated device based on its
145 device id.
146 """
147 return 'chromeos-' + self.GetUniqueParam('deviceid')
148
149 def ProcessRegister(self, msg): 152 def ProcessRegister(self, msg):
150 """Handles a register request. 153 """Handles a register request.
151 154
152 Checks the query for authorization and device identifier, registers the 155 Checks the query for authorization and device identifier, registers the
153 device with the server and constructs a response. 156 device with the server and constructs a response.
154 157
155 Args: 158 Args:
156 msg: The DeviceRegisterRequest message received from the client. 159 msg: The DeviceRegisterRequest message received from the client.
157 160
158 Returns: 161 Returns:
159 A tuple of HTTP status code and response data to send to the client. 162 A tuple of HTTP status code and response data to send to the client.
160 """ 163 """
161 # Check the auth token and device ID. 164 # Check the auth token and device ID.
162 if not self.CheckGoogleLogin(): 165 if not self.CheckGoogleLogin():
163 return (403, 'No authorization') 166 return (403, 'No authorization')
164 167
165 device_id = self.GetUniqueParam('deviceid') 168 device_id = self.GetUniqueParam('deviceid')
166 if not device_id: 169 if not device_id:
167 return (400, 'Missing device identifier') 170 return (400, 'Missing device identifier')
168 171
169 # Register the device and create a token. 172 token_info = self._server.RegisterDevice(device_id,
170 dmtoken = self._server.RegisterDevice(device_id) 173 msg.machine_id,
174 msg.type)
171 175
172 # Send back the reply. 176 # Send back the reply.
173 response = dm.DeviceManagementResponse() 177 response = dm.DeviceManagementResponse()
174 response.error = dm.DeviceManagementResponse.SUCCESS 178 response.error = dm.DeviceManagementResponse.SUCCESS
175 response.register_response.device_management_token = dmtoken 179 response.register_response.device_management_token = (
180 token_info['device_token'])
181 response.register_response.machine_name = token_info['machine_name']
176 182
177 self.DumpMessage('Response', response) 183 self.DumpMessage('Response', response)
178 184
179 return (200, response.SerializeToString()) 185 return (200, response.SerializeToString())
180 186
181 def ProcessUnregister(self, msg): 187 def ProcessUnregister(self, msg):
182 """Handles a register request. 188 """Handles a register request.
183 189
184 Checks for authorization, unregisters the device and constructs the 190 Checks for authorization, unregisters the device and constructs the
185 response. 191 response.
(...skipping 14 matching lines...) Expand all
200 206
201 # Prepare and send the response. 207 # Prepare and send the response.
202 response = dm.DeviceManagementResponse() 208 response = dm.DeviceManagementResponse()
203 response.error = dm.DeviceManagementResponse.SUCCESS 209 response.error = dm.DeviceManagementResponse.SUCCESS
204 response.unregister_response.CopyFrom(dm.DeviceUnregisterResponse()) 210 response.unregister_response.CopyFrom(dm.DeviceUnregisterResponse())
205 211
206 self.DumpMessage('Response', response) 212 self.DumpMessage('Response', response)
207 213
208 return (200, response.SerializeToString()) 214 return (200, response.SerializeToString())
209 215
210 def ProcessManagedCheck(self, msg): 216 def ProcessInitialPolicy(self, msg):
211 """Handles a 'managed check' request. 217 """Handles a 'preregister policy' request.
212 218
213 Queries the list of managed users and responds the client if their user 219 Queries the list of managed users and responds the client if their user
214 is managed or not. 220 is managed or not.
215 221
216 Args: 222 Args:
217 msg: The ManagedCheckRequest message received from the client. 223 msg: The PolicyFetchRequest message received from the client.
218 224
219 Returns: 225 Returns:
220 A tuple of HTTP status code and response data to send to the client. 226 A tuple of HTTP status code and response data to send to the client.
221 """ 227 """
222 # Check the management token. 228 # Check the GAIA token.
223 auth = self.CheckGoogleLogin() 229 auth = self.CheckGoogleLogin()
224 if not auth: 230 if not auth:
225 return (403, 'No authorization') 231 return (403, 'No authorization')
226 232
227 managed_check_response = dm.ManagedCheckResponse() 233 chrome_initial_settings = dm.ChromeInitialSettingsProto()
228 if ('*' in self._server.policy['managed_users'] or 234 if ('*' in self._server.policy['managed_users'] or
229 auth in self._server.policy['managed_users']): 235 auth in self._server.policy['managed_users']):
230 managed_check_response.mode = dm.ManagedCheckResponse.MANAGED; 236 chrome_initial_settings.enrollment_provision = (
237 dm.ChromeInitialSettingsProto.MANAGED);
231 else: 238 else:
232 managed_check_response.mode = dm.ManagedCheckResponse.UNMANAGED; 239 chrome_initial_settings.enrollment_provision = (
240 dm.ChromeInitialSettingsProto.UNMANAGED);
241
242 policy_data = dm.PolicyData()
243 policy_data.policy_type = msg.policy_type
244 policy_data.policy_value = chrome_initial_settings.SerializeToString()
233 245
234 # Prepare and send the response. 246 # Prepare and send the response.
235 response = dm.DeviceManagementResponse() 247 response = dm.DeviceManagementResponse()
236 response.error = dm.DeviceManagementResponse.SUCCESS 248 response.error = dm.DeviceManagementResponse.SUCCESS
237 response.managed_check_response.CopyFrom(managed_check_response) 249 fetch_response = response.policy_response.response.add()
250 fetch_response.policy_data = (
251 policy_data.SerializeToString())
238 252
239 self.DumpMessage('Response', response) 253 self.DumpMessage('Response', response)
240 254
241 return (200, response.SerializeToString()) 255 return (200, response.SerializeToString())
242 256
243 def ProcessPolicy(self, msg): 257 def ProcessDevicePolicy(self, msg):
244 """Handles a policy request.
245
246 Checks for authorization, encodes the policy into protobuf representation
247 and constructs the response.
248
249 Args:
250 msg: The DevicePolicyRequest message received from the client.
251
252 Returns:
253 A tuple of HTTP status code and response data to send to the client.
254 """
255 # Check the management token. 258 # Check the management token.
256 token, response = self.CheckToken() 259 token, response = self.CheckToken()
257 if not token: 260 if not token:
258 return response 261 return response
259 262
260 # Stuff the policy dictionary into a response message and send it back. 263 # Stuff the policy dictionary into a response message and send it back.
261 response = dm.DeviceManagementResponse() 264 response = dm.DeviceManagementResponse()
262 response.error = dm.DeviceManagementResponse.SUCCESS 265 response.error = dm.DeviceManagementResponse.SUCCESS
263 response.policy_response.CopyFrom(dm.DevicePolicyResponse()) 266 response.policy_response.CopyFrom(dm.DevicePolicyResponse())
264 267
265 # Respond only if the client requested policy for the cros/device scope, 268 # Respond only if the client requested policy for the cros/device scope,
266 # since that's where chrome policy is supposed to live in. 269 # since that's where chrome policy is supposed to live in.
267 if msg.policy_scope in self._server.policy: 270 if msg.policy_scope == 'chromeos/device':
268 policy = self._server.policy[msg.policy_scope]['mandatory'] 271 policy = self._server.policy['google/chromeos/user']['mandatory']
269 setting = response.policy_response.setting.add() 272 setting = response.policy_response.setting.add()
270 setting.policy_key = 'chrome-policy' 273 setting.policy_key = 'chrome-policy'
271 policy_value = dm.GenericSetting() 274 policy_value = dm.GenericSetting()
272 for (key, value) in policy.iteritems(): 275 for (key, value) in policy.iteritems():
273 entry = policy_value.named_value.add() 276 entry = policy_value.named_value.add()
274 entry.name = key 277 entry.name = key
275 entry_value = dm.GenericValue() 278 entry_value = dm.GenericValue()
276 if isinstance(value, bool): 279 if isinstance(value, bool):
277 entry_value.value_type = dm.GenericValue.VALUE_TYPE_BOOL 280 entry_value.value_type = dm.GenericValue.VALUE_TYPE_BOOL
278 entry_value.bool_value = value 281 entry_value.bool_value = value
279 elif isinstance(value, int): 282 elif isinstance(value, int):
280 entry_value.value_type = dm.GenericValue.VALUE_TYPE_INT64 283 entry_value.value_type = dm.GenericValue.VALUE_TYPE_INT64
281 entry_value.int64_value = value 284 entry_value.int64_value = value
282 elif isinstance(value, str) or isinstance(value, unicode): 285 elif isinstance(value, str) or isinstance(value, unicode):
283 entry_value.value_type = dm.GenericValue.VALUE_TYPE_STRING 286 entry_value.value_type = dm.GenericValue.VALUE_TYPE_STRING
284 entry_value.string_value = value 287 entry_value.string_value = value
285 elif isinstance(value, list): 288 elif isinstance(value, list):
286 entry_value.value_type = dm.GenericValue.VALUE_TYPE_STRING_ARRAY 289 entry_value.value_type = dm.GenericValue.VALUE_TYPE_STRING_ARRAY
287 for list_entry in value: 290 for list_entry in value:
288 entry_value.string_array.append(str(list_entry)) 291 entry_value.string_array.append(str(list_entry))
289 entry.value.CopyFrom(entry_value) 292 entry.value.CopyFrom(entry_value)
290 setting.policy_value.CopyFrom(policy_value) 293 setting.policy_value.CopyFrom(policy_value)
291 294
292 self.DumpMessage('Response', response) 295 self.DumpMessage('Response', response)
293 296
294 return (200, response.SerializeToString()) 297 return (200, response.SerializeToString())
295 298
299 def ProcessPolicy(self, msg, request_type):
300 """Handles a policy request.
301
302 Checks for authorization, encodes the policy into protobuf representation
303 and constructs the response.
304
305 Args:
306 msg: The DevicePolicyRequest message received from the client.
307
308 Returns:
309 A tuple of HTTP status code and response data to send to the client.
310 """
311
312 if msg.request:
313 for request in msg.request:
314 if request.policy_type == 'google/chromeos/unregistered_user':
315 if request_type != 'ping':
316 return (400, 'Invalid request type')
317 return self.ProcessInitialPolicy(request)
318 elif (request.policy_type in
319 ('google/chromeos/user', 'google/chromeos/device')):
320 if request_type != 'policy':
321 return (400, 'Invalid request type')
322 return self.ProcessCloudPolicy(request)
323 else:
324 return (400, 'Invalid policy_type')
325 else:
326 return self.ProcessDevicePolicy(msg)
327
296 def SetProtobufMessageField(self, group_message, field, field_value): 328 def SetProtobufMessageField(self, group_message, field, field_value):
297 '''Sets a field in a protobuf message. 329 '''Sets a field in a protobuf message.
298 330
299 Args: 331 Args:
300 group_message: The protobuf message. 332 group_message: The protobuf message.
301 field: The field of the message to set, it shuold be a member of 333 field: The field of the message to set, it shuold be a member of
302 group_message.DESCRIPTOR.fields. 334 group_message.DESCRIPTOR.fields.
303 field_value: The value to set. 335 field_value: The value to set.
304 ''' 336 '''
305 if field.label == field.LABEL_REPEATED: 337 if field.type == field.TYPE_BOOL:
338 assert type(field_value) == bool
339 elif field.type == field.TYPE_STRING:
340 assert type(field_value) == str
341 elif field.type == field.TYPE_INT64:
342 assert type(field_value) == int
343 elif (field.type == field.TYPE_MESSAGE and
344 field.message_type.name == 'StringList'):
306 assert type(field_value) == list 345 assert type(field_value) == list
307 assert field.type == field.TYPE_STRING 346 entries = group_message.__getattribute__(field.name).entries
308 list_field = group_message.__getattribute__(field.name)
309 for list_item in field_value: 347 for list_item in field_value:
310 list_field.append(list_item) 348 entries.append(list_item)
349 return
311 else: 350 else:
312 # Simple cases: 351 raise Exception('Unknown field type %s' % field.type)
313 if field.type == field.TYPE_BOOL: 352 group_message.__setattr__(field.name, field_value)
314 assert type(field_value) == bool
315 elif field.type == field.TYPE_STRING:
316 assert type(field_value) == str
317 elif field.type == field.TYPE_INT64:
318 assert type(field_value) == int
319 else:
320 raise Exception('Unknown field type %s' % field.type_name)
321 group_message.__setattr__(field.name, field_value)
322 353
323 def GatherPolicySettings(self, settings, policies): 354 def GatherPolicySettings(self, settings, policies):
324 '''Copies all the policies from a dictionary into a protobuf of type 355 '''Copies all the policies from a dictionary into a protobuf of type
325 CloudPolicySettings. 356 CloudPolicySettings.
326 357
327 Args: 358 Args:
328 settings: The destination: a CloudPolicySettings protobuf. 359 settings: The destination: a CloudPolicySettings protobuf.
329 policies: The source: a dictionary containing policies under keys 360 policies: The source: a dictionary containing policies under keys
330 'recommended' and 'mandatory'. 361 'recommended' and 'mandatory'.
331 ''' 362 '''
(...skipping 13 matching lines...) Expand all
345 group_message.policy_options.mode = cp.PolicyOptions.MANDATORY 376 group_message.policy_options.mode = cp.PolicyOptions.MANDATORY
346 field_value = policies['mandatory'][field.name] 377 field_value = policies['mandatory'][field.name]
347 elif field.name in policies['recommended']: 378 elif field.name in policies['recommended']:
348 field_value = policies['recommended'][field.name] 379 field_value = policies['recommended'][field.name]
349 if field_value != None: 380 if field_value != None:
350 got_fields = True 381 got_fields = True
351 self.SetProtobufMessageField(group_message, field, field_value) 382 self.SetProtobufMessageField(group_message, field, field_value)
352 if got_fields: 383 if got_fields:
353 settings.__getattribute__(group.name).CopyFrom(group_message) 384 settings.__getattribute__(group.name).CopyFrom(group_message)
354 385
355 def ProcessCloudPolicyRequest(self, msg): 386 def ProcessCloudPolicy(self, msg):
356 """Handles a cloud policy request. (New protocol for policy requests.) 387 """Handles a cloud policy request. (New protocol for policy requests.)
357 388
358 Checks for authorization, encodes the policy into protobuf representation, 389 Checks for authorization, encodes the policy into protobuf representation,
359 signs it and constructs the repsonse. 390 signs it and constructs the repsonse.
360 391
361 Args: 392 Args:
362 msg: The CloudPolicyRequest message received from the client. 393 msg: The CloudPolicyRequest message received from the client.
363 394
364 Returns: 395 Returns:
365 A tuple of HTTP status code and response data to send to the client. 396 A tuple of HTTP status code and response data to send to the client.
366 """ 397 """
367 token, response = self.CheckToken() 398
368 if not token: 399 token_info, error = self.CheckToken()
369 return response 400 if not token_info:
401 return error
370 402
371 settings = cp.CloudPolicySettings() 403 settings = cp.CloudPolicySettings()
372 404
373 if msg.policy_scope in self._server.policy: 405 if (msg.policy_type in token_info['allowed_policy_types'] and
374 # Respond is only given if the scope is specified in the config file. 406 msg.policy_type in self._server.policy):
407 # Response is only given if the scope is specified in the config file.
375 # Normally 'chromeos/device' and 'chromeos/user' should be accepted. 408 # Normally 'chromeos/device' and 'chromeos/user' should be accepted.
376 self.GatherPolicySettings(settings, 409 self.GatherPolicySettings(settings,
377 self._server.policy[msg.policy_scope]) 410 self._server.policy[msg.policy_type])
378 411
379 # Construct response 412 policy_data = dm.PolicyData()
380 signed_response = dm.SignedCloudPolicyResponse() 413 policy_data.policy_value = settings.SerializeToString()
381 signed_response.settings.CopyFrom(settings) 414 policy_data.policy_type = msg.policy_type
382 signed_response.timestamp = int(time.time()) 415 policy_data.timestamp = int(time.time() * 1000)
383 signed_response.request_token = token; 416 policy_data.request_token = token_info['device_token'];
384 signed_response.device_name = self.GetDeviceName() 417 policy_data.machine_name = token_info['machine_name']
385 418 signed_data = policy_data.SerializeToString()
386 cloud_response = dm.CloudPolicyResponse()
387 cloud_response.signed_response = signed_response.SerializeToString()
388 signed_data = cloud_response.signed_response
389 cloud_response.signature = (
390 self._server.private_key.hashAndSign(signed_data).tostring())
391 for certificate in self._server.cert_chain:
392 cloud_response.certificate_chain.append(
393 certificate.writeBytes().tostring())
394 419
395 response = dm.DeviceManagementResponse() 420 response = dm.DeviceManagementResponse()
396 response.error = dm.DeviceManagementResponse.SUCCESS 421 response.error = dm.DeviceManagementResponse.SUCCESS
397 response.cloud_policy_response.CopyFrom(cloud_response) 422 fetch_response = response.policy_response.response.add()
423 fetch_response.policy_data = signed_data
424 fetch_response.policy_data_signature = (
425 self._server.private_key.hashAndSign(signed_data).tostring())
426 for certificate in self._server.cert_chain:
427 fetch_response.certificate_chain.append(
428 certificate.writeBytes().tostring())
398 429
399 self.DumpMessage('Response', response) 430 self.DumpMessage('Response', response)
400 431
401 return (200, response.SerializeToString()) 432 return (200, response.SerializeToString())
402 433
403 def CheckToken(self): 434 def CheckToken(self):
404 """Helper for checking whether the client supplied a valid DM token. 435 """Helper for checking whether the client supplied a valid DM token.
405 436
406 Extracts the token from the request and passed to the server in order to 437 Extracts the token from the request and passed to the server in order to
407 look up the client. Returns a pair of token and error response. If the token 438 look up the client.
408 is None, the error response is a pair of status code and error message.
409 439
410 Returns: 440 Returns:
411 A pair of DM token and error response. If the token is None, the message 441 A pair of token information record and error response. If the first
412 will contain the error response to send back. 442 element is None, then the second contains an error code to send back to
443 the client. Otherwise the first element is the same structure that is
444 returned by LookupToken().
413 """ 445 """
414 error = None 446 error = None
415 dmtoken = None 447 dmtoken = None
416 request_device_id = self.GetUniqueParam('deviceid') 448 request_device_id = self.GetUniqueParam('deviceid')
417 match = re.match('GoogleDMToken token=(\\w+)', 449 match = re.match('GoogleDMToken token=(\\w+)',
418 self._headers.getheader('Authorization', '')) 450 self._headers.getheader('Authorization', ''))
419 if match: 451 if match:
420 dmtoken = match.group(1) 452 dmtoken = match.group(1)
421 if not dmtoken: 453 if not dmtoken:
422 error = dm.DeviceManagementResponse.DEVICE_MANAGEMENT_TOKEN_INVALID 454 error = dm.DeviceManagementResponse.DEVICE_MANAGEMENT_TOKEN_INVALID
423 elif (not request_device_id or
424 not self._server.LookupDevice(dmtoken) == request_device_id):
425 error = dm.DeviceManagementResponse.DEVICE_NOT_FOUND
426 else: 455 else:
427 return (dmtoken, None) 456 token_info = self._server.LookupToken(dmtoken)
457 if (not token_info or
458 not request_device_id or
459 token_info['device_id'] != request_device_id):
460 error = dm.DeviceManagementResponse.DEVICE_NOT_FOUND
461 else:
462 return (token_info, None)
428 463
429 response = dm.DeviceManagementResponse() 464 response = dm.DeviceManagementResponse()
430 response.error = error 465 response.error = error
431 466
432 self.DumpMessage('Response', response) 467 self.DumpMessage('Response', response)
433 468
434 return (None, (200, response.SerializeToString())) 469 return (None, (200, response.SerializeToString()))
435 470
436 def DumpMessage(self, label, msg): 471 def DumpMessage(self, label, msg):
437 """Helper for logging an ASCII dump of a protobuf message.""" 472 """Helper for logging an ASCII dump of a protobuf message."""
438 logging.debug('%s\n%s' % (label, str(msg))) 473 logging.debug('%s\n%s' % (label, str(msg)))
439 474
440 class TestServer(object): 475 class TestServer(object):
441 """Handles requests and keeps global service state.""" 476 """Handles requests and keeps global service state."""
442 477
443 def __init__(self, policy_path, policy_cert_chain): 478 def __init__(self, policy_path, policy_cert_chain):
444 """Initializes the server. 479 """Initializes the server.
445 480
446 Args: 481 Args:
447 policy_path: Names the file to read JSON-formatted policy from. 482 policy_path: Names the file to read JSON-formatted policy from.
448 policy_cert_chain: List of paths to X.509 certificate files of the 483 policy_cert_chain: List of paths to X.509 certificate files of the
449 certificate chain used for signing responses. 484 certificate chain used for signing responses.
450 """ 485 """
451 self._registered_devices = {} 486 self._registered_tokens = {}
452 self.policy = {} 487 self.policy = {}
453 if json is None: 488 if json is None:
454 print 'No JSON module, cannot parse policy information' 489 print 'No JSON module, cannot parse policy information'
455 else : 490 else :
456 try: 491 try:
457 self.policy = json.loads(open(policy_path).read()) 492 self.policy = json.loads(open(policy_path).read())
458 except IOError: 493 except IOError:
459 print 'Failed to load policy from %s' % policy_path 494 print 'Failed to load policy from %s' % policy_path
460 495
461 self.private_key = None 496 self.private_key = None
(...skipping 16 matching lines...) Expand all
478 Args: 513 Args:
479 path: The request path and query parameters received from the client. 514 path: The request path and query parameters received from the client.
480 headers: A rfc822.Message-like object containing HTTP headers. 515 headers: A rfc822.Message-like object containing HTTP headers.
481 request: The request data received from the client as a string. 516 request: The request data received from the client as a string.
482 Returns: 517 Returns:
483 A pair of HTTP status code and response data to send to the client. 518 A pair of HTTP status code and response data to send to the client.
484 """ 519 """
485 handler = RequestHandler(self, path, headers, request) 520 handler = RequestHandler(self, path, headers, request)
486 return handler.HandleRequest() 521 return handler.HandleRequest()
487 522
488 def RegisterDevice(self, device_id): 523 def RegisterDevice(self, device_id, machine_id, type=None):
489 """Registers a device and generate a DM token for it. 524 """Registers a device or user and generates a DM token for it.
490 525
491 Args: 526 Args:
492 device_id: The device identifier provided by the client. 527 device_id: The device identifier provided by the client.
493 528
494 Returns: 529 Returns:
495 The newly generated device token for the device. 530 The newly generated device token for the device.
496 """ 531 """
497 dmtoken_chars = [] 532 dmtoken_chars = []
498 while len(dmtoken_chars) < 32: 533 while len(dmtoken_chars) < 32:
499 dmtoken_chars.append(random.choice('0123456789abcdef')) 534 dmtoken_chars.append(random.choice('0123456789abcdef'))
500 dmtoken = ''.join(dmtoken_chars) 535 dmtoken = ''.join(dmtoken_chars)
501 self._registered_devices[dmtoken] = device_id
502 return dmtoken
503 536
504 def LookupDevice(self, dmtoken): 537 self._registered_tokens[dmtoken] = {
505 """Looks up a device by DMToken. 538 'device_id': device_id,
539 'device_token': dmtoken,
540 'allowed_policy_types': {
541 dm.DeviceRegisterRequest.USER: ['google/chromeos/user'],
542 dm.DeviceRegisterRequest.DEVICE: ['google/chromeos/device'],
543 dm.DeviceRegisterRequest.TT: ['google/chromeos/user'],
544 }[type],
Jakob Kummerow 2011/02/28 11:06:31 Not sure if I like this expression. It's concise,
gfeher 2011/02/28 12:21:32 How about it now?
545 'machine_name': 'chromeos-' + machine_id,
546 }
547 return self._registered_tokens[dmtoken]
548
549 def LookupToken(self, dmtoken):
550 """Looks up a device or a user by DM token.
506 551
507 Args: 552 Args:
508 dmtoken: The device management token provided by the client. 553 dmtoken: The device management token provided by the client.
509 554
510 Returns: 555 Returns:
511 The corresponding device identifier or None if not found. 556 A dictionary with information about a device or user that is registered by
557 dmtoken, or None if the token is not found.
512 """ 558 """
513 return self._registered_devices.get(dmtoken, None) 559 return self._registered_tokens.get(dmtoken, None)
514 560
515 def UnregisterDevice(self, dmtoken): 561 def UnregisterDevice(self, dmtoken):
516 """Unregisters a device identified by the given DM token. 562 """Unregisters a device identified by the given DM token.
517 563
518 Args: 564 Args:
519 dmtoken: The device management token provided by the client. 565 dmtoken: The device management token provided by the client.
520 """ 566 """
521 if dmtoken in self._registered_devices: 567 if dmtoken in self._registered_tokens.keys():
522 del self._registered_devices[dmtoken] 568 del self._registered_tokens[dmtoken]
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698