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

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

Powered by Google App Engine
This is Rietveld 408576698