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

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

Issue 11434053: Add support for public account policy to CloudPolicyClient. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix nit. Created 8 years 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
« no previous file with comments | « chrome/browser/policy/user_cloud_policy_store_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """A bare-bones test server for testing cloud policy support. 5 """A bare-bones test server for testing cloud policy support.
6 6
7 This implements a simple cloud policy test server that can be used to test 7 This implements a simple cloud policy test server that can be used to test
8 chrome's device management service client. The policy information is read from 8 chrome's device management service client. The policy information is read from
9 the file named device_management in the server's data directory. It contains 9 the file named device_management in the server's data directory. It contains
10 enforced and recommended policies for the device and user scope, and a list 10 enforced and recommended policies for the device and user scope, and a list
11 of managed users. 11 of managed users.
12 12
13 The format of the file is JSON. The root dictionary contains a list under the 13 The format of the file is JSON. The root dictionary contains a list under the
14 key "managed_users". It contains auth tokens for which the server will claim 14 key "managed_users". It contains auth tokens for which the server will claim
15 that the user is managed. The token string "*" indicates that all users are 15 that the user is managed. The token string "*" indicates that all users are
16 claimed to be managed. Other keys in the root dictionary identify request 16 claimed to be managed. Other keys in the root dictionary identify request
17 scopes. The user-request scope is described by a dictionary that holds two 17 scopes. The user-request scope is described by a dictionary that holds two
18 sub-dictionaries: "mandatory" and "recommended". Both these hold the policy 18 sub-dictionaries: "mandatory" and "recommended". Both these hold the policy
19 definitions as key/value stores, their format is identical to what the Linux 19 definitions as key/value stores, their format is identical to what the Linux
20 implementation reads from /etc. 20 implementation reads from /etc.
21 The device-scope holds the policy-definition directly as key/value stores in the 21 The device-scope holds the policy-definition directly as key/value stores in the
22 protobuf-format. 22 protobuf-format.
23 23
24 Example: 24 Example:
25 25
26 { 26 {
27 "google/chromeos/device" : { 27 "google/chromeos/device" : {
28 "guest_mode_enabled" : false 28 "guest_mode_enabled" : false
29 }, 29 },
30 "google/chromeos/user" : { 30 "google/chromeos/user" : {
31 "mandatory" : { 31 "mandatory" : {
32 "HomepageLocation" : "http://www.chromium.org", 32 "HomepageLocation" : "http://www.chromium.org",
33 "IncognitoEnabled" : false 33 "IncognitoEnabled" : false
34 }, 34 },
35 "recommended" : { 35 "recommended" : {
36 "JavascriptEnabled": false 36 "JavascriptEnabled": false
37 } 37 }
38 }, 38 },
39 "google/chromeos/publicaccount/user@example.com" : {
40 "mandatory" : {
41 "HomepageLocation" : "http://www.chromium.org"
42 },
43 "recommended" : {
44 }
45 },
39 "managed_users" : [ 46 "managed_users" : [
40 "secret123456" 47 "secret123456"
41 ] 48 ]
42 } 49 }
43 50
44 """ 51 """
45 52
46 import cgi 53 import cgi
47 import hashlib 54 import hashlib
48 import logging 55 import logging
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 and constructs the response. 261 and constructs the response.
255 262
256 Args: 263 Args:
257 msg: The DevicePolicyRequest message received from the client. 264 msg: The DevicePolicyRequest message received from the client.
258 265
259 Returns: 266 Returns:
260 A tuple of HTTP status code and response data to send to the client. 267 A tuple of HTTP status code and response data to send to the client.
261 """ 268 """
262 for request in msg.request: 269 for request in msg.request:
263 if (request.policy_type in 270 if (request.policy_type in
264 ('google/chromeos/user', 'google/chromeos/device')): 271 ('google/chromeos/user',
272 'google/chromeos/device',
273 'google/chromeos/publicaccount')):
265 if request_type != 'policy': 274 if request_type != 'policy':
266 return (400, 'Invalid request type') 275 return (400, 'Invalid request type')
267 else: 276 else:
268 return self.ProcessCloudPolicy(request) 277 return self.ProcessCloudPolicy(request)
269 else: 278 else:
270 return (400, 'Invalid policy_type') 279 return (400, 'Invalid policy_type')
271 280
272 def ProcessAutoEnrollment(self, msg): 281 def ProcessAutoEnrollment(self, msg):
273 """Handles an auto-enrollment check request. 282 """Handles an auto-enrollment check request.
274 283
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 Args: 393 Args:
385 settings: The destination: a CloudPolicySettings protobuf. 394 settings: The destination: a CloudPolicySettings protobuf.
386 policies: The source: a dictionary containing policies under keys 395 policies: The source: a dictionary containing policies under keys
387 'recommended' and 'mandatory'. 396 'recommended' and 'mandatory'.
388 ''' 397 '''
389 for field in settings.DESCRIPTOR.fields: 398 for field in settings.DESCRIPTOR.fields:
390 # |field| is the entry for a specific policy in the top-level 399 # |field| is the entry for a specific policy in the top-level
391 # CloudPolicySettings proto. 400 # CloudPolicySettings proto.
392 401
393 # Look for this policy's value in the mandatory or recommended dicts. 402 # Look for this policy's value in the mandatory or recommended dicts.
394 if field.name in policies['mandatory']: 403 if field.name in policies.get('mandatory', {}):
395 mode = cp.PolicyOptions.MANDATORY 404 mode = cp.PolicyOptions.MANDATORY
396 value = policies['mandatory'][field.name] 405 value = policies['mandatory'][field.name]
397 elif field.name in policies['recommended']: 406 elif field.name in policies.get('recommended', {}):
398 mode = cp.PolicyOptions.RECOMMENDED 407 mode = cp.PolicyOptions.RECOMMENDED
399 value = policies['recommended'][field.name] 408 value = policies['recommended'][field.name]
400 else: 409 else:
401 continue 410 continue
402 411
403 # Create protobuf message for this policy. 412 # Create protobuf message for this policy.
404 policy_message = eval('cp.' + field.message_type.name + '()') 413 policy_message = eval('cp.' + field.message_type.name + '()')
405 policy_message.policy_options.mode = mode 414 policy_message.policy_options.mode = mode
406 field_descriptor = policy_message.DESCRIPTOR.fields_by_name['value'] 415 field_descriptor = policy_message.DESCRIPTOR.fields_by_name['value']
407 self.SetProtobufMessageField(policy_message, field_descriptor, value) 416 self.SetProtobufMessageField(policy_message, field_descriptor, value)
(...skipping 13 matching lines...) Expand all
421 """ 430 """
422 431
423 token_info, error = self.CheckToken() 432 token_info, error = self.CheckToken()
424 if not token_info: 433 if not token_info:
425 return error 434 return error
426 435
427 if msg.machine_id: 436 if msg.machine_id:
428 self._server.UpdateMachineId(token_info['device_token'], msg.machine_id) 437 self._server.UpdateMachineId(token_info['device_token'], msg.machine_id)
429 438
430 # Response is only given if the scope is specified in the config file. 439 # Response is only given if the scope is specified in the config file.
431 # Normally 'google/chromeos/device' and 'google/chromeos/user' should be 440 # Normally 'google/chromeos/device', 'google/chromeos/user' and
432 # accepted. 441 # 'google/chromeos/publicaccount' should be accepted.
433 policy = self._server.GetPolicies() 442 policy = self._server.GetPolicies()
434 policy_value = '' 443 policy_value = ''
435 if (msg.policy_type in token_info['allowed_policy_types'] and 444 policy_key = msg.policy_type
436 msg.policy_type in policy): 445 if msg.settings_entity_id:
446 policy_key += '/' + msg.settings_entity_id
447 if msg.policy_type in token_info['allowed_policy_types']:
437 if msg.policy_type == 'google/chromeos/user': 448 if msg.policy_type == 'google/chromeos/user':
438 settings = cp.CloudPolicySettings() 449 settings = cp.CloudPolicySettings()
439 self.GatherUserPolicySettings(settings, 450 self.GatherUserPolicySettings(settings, policy.get(policy_key, {}))
440 policy[msg.policy_type])
441 policy_value = settings.SerializeToString()
442 elif msg.policy_type == 'google/chromeos/device': 451 elif msg.policy_type == 'google/chromeos/device':
443 settings = dp.ChromeDeviceSettingsProto() 452 settings = dp.ChromeDeviceSettingsProto()
444 self.GatherDevicePolicySettings(settings, 453 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {}))
445 policy[msg.policy_type]) 454 elif msg.policy_type == 'google/chromeos/publicaccount':
446 policy_value = settings.SerializeToString() 455 settings = cp.CloudPolicySettings()
456 self.GatherUserPolicySettings(settings, policy.get(policy_key, {}))
447 457
448 # Figure out the key we want to use. If multiple keys are configured, the 458 # Figure out the key we want to use. If multiple keys are configured, the
449 # server will rotate through them in a round-robin fashion. 459 # server will rotate through them in a round-robin fashion.
450 signing_key = None 460 signing_key = None
451 req_key = None 461 req_key = None
452 key_version = 1 462 key_version = 1
453 nkeys = len(self._server.keys) 463 nkeys = len(self._server.keys)
454 if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0: 464 if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0:
455 if msg.public_key_version in range(1, nkeys + 1): 465 if msg.public_key_version in range(1, nkeys + 1):
456 # requested key exists, use for signing and rotate. 466 # requested key exists, use for signing and rotate.
457 req_key = self._server.keys[msg.public_key_version - 1]['private_key'] 467 req_key = self._server.keys[msg.public_key_version - 1]['private_key']
458 key_version = (msg.public_key_version % nkeys) + 1 468 key_version = (msg.public_key_version % nkeys) + 1
459 signing_key = self._server.keys[key_version - 1] 469 signing_key = self._server.keys[key_version - 1]
460 470
461 # Fill the policy data protobuf. 471 # Fill the policy data protobuf.
462 policy_data = dm.PolicyData() 472 policy_data = dm.PolicyData()
463 policy_data.policy_type = msg.policy_type 473 policy_data.policy_type = msg.policy_type
464 policy_data.timestamp = int(time.time() * 1000) 474 policy_data.timestamp = int(time.time() * 1000)
465 policy_data.request_token = token_info['device_token'] 475 policy_data.request_token = token_info['device_token']
466 policy_data.policy_value = policy_value 476 policy_data.policy_value = settings.SerializeToString()
467 policy_data.machine_name = token_info['machine_name'] 477 policy_data.machine_name = token_info['machine_name']
468 policy_data.valid_serial_number_missing = ( 478 policy_data.valid_serial_number_missing = (
469 token_info['machine_id'] in BAD_MACHINE_IDS) 479 token_info['machine_id'] in BAD_MACHINE_IDS)
470 480
471 if signing_key: 481 if signing_key:
472 policy_data.public_key_version = key_version 482 policy_data.public_key_version = key_version
473 # There is no way for the testserver to know the user name belonging to 483 if msg.policy_type == 'google/chromeos/publicaccount':
474 # the GAIA auth token we received (short of actually talking to GAIA). To 484 policy_data.username = msg.settings_entity_id
475 # address this, we read the username from the policy configuration 485 else:
476 # dictionary, or use a default. 486 # For regular user/device policy, there is no way for the testserver to
477 policy_data.username = policy.get('policy_user', 'user@example.com') 487 # know the user name belonging to the GAIA auth token we received (short
488 # of actually talking to GAIA). To address this, we read the username from
489 # the policy configuration dictionary, or use a default.
490 policy_data.username = policy.get('policy_user', 'user@example.com')
478 policy_data.device_id = token_info['device_id'] 491 policy_data.device_id = token_info['device_id']
479 signed_data = policy_data.SerializeToString() 492 signed_data = policy_data.SerializeToString()
480 493
481 response = dm.DeviceManagementResponse() 494 response = dm.DeviceManagementResponse()
482 fetch_response = response.policy_response.response.add() 495 fetch_response = response.policy_response.response.add()
483 fetch_response.policy_data = signed_data 496 fetch_response.policy_data = signed_data
484 if signing_key: 497 if signing_key:
485 fetch_response.policy_data_signature = ( 498 fetch_response.policy_data_signature = (
486 signing_key['private_key'].hashAndSign(signed_data).tostring()) 499 signing_key['private_key'].hashAndSign(signed_data).tostring())
487 if msg.public_key_version != key_version: 500 if msg.public_key_version != key_version:
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 623
611 Returns: 624 Returns:
612 The newly generated device token for the device. 625 The newly generated device token for the device.
613 """ 626 """
614 dmtoken_chars = [] 627 dmtoken_chars = []
615 while len(dmtoken_chars) < 32: 628 while len(dmtoken_chars) < 32:
616 dmtoken_chars.append(random.choice('0123456789abcdef')) 629 dmtoken_chars.append(random.choice('0123456789abcdef'))
617 dmtoken = ''.join(dmtoken_chars) 630 dmtoken = ''.join(dmtoken_chars)
618 allowed_policy_types = { 631 allowed_policy_types = {
619 dm.DeviceRegisterRequest.USER: ['google/chromeos/user'], 632 dm.DeviceRegisterRequest.USER: ['google/chromeos/user'],
620 dm.DeviceRegisterRequest.DEVICE: ['google/chromeos/device'], 633 dm.DeviceRegisterRequest.DEVICE: [
634 'google/chromeos/device',
635 'google/chromeos/publicaccount'
636 ],
621 dm.DeviceRegisterRequest.TT: ['google/chromeos/user'], 637 dm.DeviceRegisterRequest.TT: ['google/chromeos/user'],
622 } 638 }
623 if machine_id in KIOSK_MACHINE_IDS: 639 if machine_id in KIOSK_MACHINE_IDS:
624 enrollment_mode = dm.DeviceRegisterResponse.RETAIL 640 enrollment_mode = dm.DeviceRegisterResponse.RETAIL
625 else: 641 else:
626 enrollment_mode = dm.DeviceRegisterResponse.ENTERPRISE 642 enrollment_mode = dm.DeviceRegisterResponse.ENTERPRISE
627 self._registered_tokens[dmtoken] = { 643 self._registered_tokens[dmtoken] = {
628 'device_id': device_id, 644 'device_id': device_id,
629 'device_token': dmtoken, 645 'device_token': dmtoken,
630 'allowed_policy_types': allowed_policy_types[type], 646 'allowed_policy_types': allowed_policy_types[type],
(...skipping 26 matching lines...) Expand all
657 return self._registered_tokens.get(dmtoken, None) 673 return self._registered_tokens.get(dmtoken, None)
658 674
659 def UnregisterDevice(self, dmtoken): 675 def UnregisterDevice(self, dmtoken):
660 """Unregisters a device identified by the given DM token. 676 """Unregisters a device identified by the given DM token.
661 677
662 Args: 678 Args:
663 dmtoken: The device management token provided by the client. 679 dmtoken: The device management token provided by the client.
664 """ 680 """
665 if dmtoken in self._registered_tokens.keys(): 681 if dmtoken in self._registered_tokens.keys():
666 del self._registered_tokens[dmtoken] 682 del self._registered_tokens[dmtoken]
OLDNEW
« no previous file with comments | « chrome/browser/policy/user_cloud_policy_store_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698