OLD | NEW |
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 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 """ | 436 """ |
437 token_info, error = self.CheckToken() | 437 token_info, error = self.CheckToken() |
438 if not token_info: | 438 if not token_info: |
439 return error | 439 return error |
440 | 440 |
441 key_update_request = msg.device_state_key_update_request | 441 key_update_request = msg.device_state_key_update_request |
442 if len(key_update_request.server_backed_state_key) > 0: | 442 if len(key_update_request.server_backed_state_key) > 0: |
443 self.server.UpdateStateKeys(token_info['device_token'], | 443 self.server.UpdateStateKeys(token_info['device_token'], |
444 key_update_request.server_backed_state_key) | 444 key_update_request.server_backed_state_key) |
445 | 445 |
446 # If this is a publicaccount request then get the username now and use it | |
447 # in every PolicyFetchResponse produced. This is required to validate | |
448 # policy for extensions in public accounts. | |
449 username = self.server.GetPolicies().get('policy_user', None) | |
450 for request in msg.policy_request.request: | |
451 if request.policy_type == 'google/chromeos/publicaccount': | |
452 username = request.settings_entity_id | |
453 | |
454 response = dm.DeviceManagementResponse() | 446 response = dm.DeviceManagementResponse() |
455 for request in msg.policy_request.request: | 447 for request in msg.policy_request.request: |
456 if (request.policy_type in | 448 if (request.policy_type in |
457 ('google/android/user', | 449 ('google/android/user', |
458 'google/chromeos/device', | 450 'google/chromeos/device', |
459 'google/chromeos/publicaccount', | 451 'google/chromeos/publicaccount', |
460 'google/chromeos/user', | 452 'google/chromeos/user', |
461 'google/chrome/user', | 453 'google/chrome/user', |
462 'google/ios/user')): | 454 'google/ios/user')): |
463 fetch_response = response.policy_response.response.add() | 455 fetch_response = response.policy_response.response.add() |
464 self.ProcessCloudPolicy(request, token_info, fetch_response) | 456 self.ProcessCloudPolicy(request, token_info, fetch_response) |
465 elif request.policy_type == 'google/chrome/extension': | 457 elif request.policy_type == 'google/chrome/extension': |
466 self.ProcessCloudPolicyForExtensions( | 458 self.ProcessCloudPolicyForExtensions( |
467 request, response.policy_response, token_info, username) | 459 request, response.policy_response, token_info) |
468 else: | 460 else: |
469 fetch_response.error_code = 400 | 461 fetch_response.error_code = 400 |
470 fetch_response.error_message = 'Invalid policy_type' | 462 fetch_response.error_message = 'Invalid policy_type' |
471 | 463 |
472 return (200, response) | 464 return (200, response) |
473 | 465 |
474 def ProcessAutoEnrollment(self, msg): | 466 def ProcessAutoEnrollment(self, msg): |
475 """Handles an auto-enrollment check request. | 467 """Handles an auto-enrollment check request. |
476 | 468 |
477 The reply depends on the value of the modulus: | 469 The reply depends on the value of the modulus: |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 else: | 621 else: |
630 continue | 622 continue |
631 | 623 |
632 # Create protobuf message for this policy. | 624 # Create protobuf message for this policy. |
633 policy_message = eval('cp.' + field.message_type.name + '()') | 625 policy_message = eval('cp.' + field.message_type.name + '()') |
634 policy_message.policy_options.mode = mode | 626 policy_message.policy_options.mode = mode |
635 field_descriptor = policy_message.DESCRIPTOR.fields_by_name['value'] | 627 field_descriptor = policy_message.DESCRIPTOR.fields_by_name['value'] |
636 self.SetProtobufMessageField(policy_message, field_descriptor, value) | 628 self.SetProtobufMessageField(policy_message, field_descriptor, value) |
637 settings.__getattribute__(field.name).CopyFrom(policy_message) | 629 settings.__getattribute__(field.name).CopyFrom(policy_message) |
638 | 630 |
639 def ProcessCloudPolicyForExtensions(self, request, response, token_info, | 631 def ProcessCloudPolicyForExtensions(self, request, response, token_info): |
640 username): | |
641 """Handles a request for policy for extensions. | 632 """Handles a request for policy for extensions. |
642 | 633 |
643 A request for policy for extensions is slightly different from the other | 634 A request for policy for extensions is slightly different from the other |
644 cloud policy requests, because it can trigger 0, one or many | 635 cloud policy requests, because it can trigger 0, one or many |
645 PolicyFetchResponse messages in the response. | 636 PolicyFetchResponse messages in the response. |
646 | 637 |
647 Args: | 638 Args: |
648 request: The PolicyFetchRequest that triggered this handler. | 639 request: The PolicyFetchRequest that triggered this handler. |
649 response: The DevicePolicyResponse message for the response. Multiple | 640 response: The DevicePolicyResponse message for the response. Multiple |
650 PolicyFetchResponses will be appended to this message. | 641 PolicyFetchResponses will be appended to this message. |
651 token_info: The token extracted from the request. | 642 token_info: The token extracted from the request. |
652 username: The username for the response. | |
653 """ | 643 """ |
654 # Send one PolicyFetchResponse for each extension that has | 644 # Send one PolicyFetchResponse for each extension that has |
655 # configuration data at the server. | 645 # configuration data at the server. |
656 ids = self.server.ListMatchingComponents('google/chrome/extension') | 646 ids = self.server.ListMatchingComponents('google/chrome/extension') |
657 for settings_entity_id in ids: | 647 for settings_entity_id in ids: |
658 # Reuse the extension policy request, to trigger the same signature | 648 # Reuse the extension policy request, to trigger the same signature |
659 # type in the response. | 649 # type in the response. |
660 request.settings_entity_id = settings_entity_id | 650 request.settings_entity_id = settings_entity_id |
661 fetch_response = response.response.add() | 651 fetch_response = response.response.add() |
662 self.ProcessCloudPolicy(request, token_info, fetch_response, username) | 652 self.ProcessCloudPolicy(request, token_info, fetch_response) |
663 # Don't do key rotations for these messages. | 653 # Don't do key rotations for these messages. |
664 fetch_response.ClearField('new_public_key') | 654 fetch_response.ClearField('new_public_key') |
665 fetch_response.ClearField('new_public_key_signature') | 655 fetch_response.ClearField('new_public_key_signature') |
666 fetch_response.ClearField('new_public_key_verification_signature') | 656 fetch_response.ClearField('new_public_key_verification_signature') |
667 | 657 |
668 def ProcessCloudPolicy(self, msg, token_info, response, username=None): | 658 def ProcessCloudPolicy(self, msg, token_info, response): |
669 """Handles a cloud policy request. (New protocol for policy requests.) | 659 """Handles a cloud policy request. (New protocol for policy requests.) |
670 | 660 |
671 Encodes the policy into protobuf representation, signs it and constructs | 661 Encodes the policy into protobuf representation, signs it and constructs |
672 the response. | 662 the response. |
673 | 663 |
674 Args: | 664 Args: |
675 msg: The CloudPolicyRequest message received from the client. | 665 msg: The CloudPolicyRequest message received from the client. |
676 token_info: The token extracted from the request. | 666 token_info: The token extracted from the request. |
677 response: A PolicyFetchResponse message that should be filled with the | 667 response: A PolicyFetchResponse message that should be filled with the |
678 response data. | 668 response data. |
679 username: The username for the response. May be None. | |
680 """ | 669 """ |
681 | 670 |
682 if msg.machine_id: | 671 if msg.machine_id: |
683 self.server.UpdateMachineId(token_info['device_token'], msg.machine_id) | 672 self.server.UpdateMachineId(token_info['device_token'], msg.machine_id) |
684 | 673 |
685 # Response is only given if the scope is specified in the config file. | 674 # Response is only given if the scope is specified in the config file. |
686 # Normally 'google/chromeos/device', 'google/chromeos/user' and | 675 # Normally 'google/chromeos/device', 'google/chromeos/user' and |
687 # 'google/chromeos/publicaccount' should be accepted. | 676 # 'google/chromeos/publicaccount' should be accepted. |
688 policy = self.server.GetPolicies() | 677 policy = self.server.GetPolicies() |
689 policy_value = '' | 678 policy_value = '' |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 if invalidation_source is not None: | 739 if invalidation_source is not None: |
751 policy_data.invalidation_source = invalidation_source | 740 policy_data.invalidation_source = invalidation_source |
752 # Since invalidation_name is type bytes in the proto, the Unicode name | 741 # Since invalidation_name is type bytes in the proto, the Unicode name |
753 # provided needs to be encoded as ASCII to set the correct byte pattern. | 742 # provided needs to be encoded as ASCII to set the correct byte pattern. |
754 invalidation_name = policy.get('invalidation_name') | 743 invalidation_name = policy.get('invalidation_name') |
755 if invalidation_name is not None: | 744 if invalidation_name is not None: |
756 policy_data.invalidation_name = invalidation_name.encode('ascii') | 745 policy_data.invalidation_name = invalidation_name.encode('ascii') |
757 | 746 |
758 if signing_key: | 747 if signing_key: |
759 policy_data.public_key_version = current_key_index + 1 | 748 policy_data.public_key_version = current_key_index + 1 |
760 | 749 if msg.policy_type == 'google/chromeos/publicaccount': |
761 if username: | |
762 policy_data.username = username | |
763 elif msg.policy_type == 'google/chromeos/publicaccount': | |
764 policy_data.username = msg.settings_entity_id | 750 policy_data.username = msg.settings_entity_id |
765 else: | 751 else: |
766 # For regular user/device policy, there is no way for the testserver to | 752 # For regular user/device policy, there is no way for the testserver to |
767 # know the user name belonging to the GAIA auth token we received (short | 753 # know the user name belonging to the GAIA auth token we received (short |
768 # of actually talking to GAIA). To address this, we read the username from | 754 # of actually talking to GAIA). To address this, we read the username from |
769 # the policy configuration dictionary, or use a default. | 755 # the policy configuration dictionary, or use a default. |
770 policy_data.username = policy.get('policy_user', 'user@example.com') | 756 policy_data.username = policy.get('policy_user', 'user@example.com') |
771 policy_data.device_id = token_info['device_id'] | 757 policy_data.device_id = token_info['device_id'] |
772 signed_data = policy_data.SerializeToString() | 758 signed_data = policy_data.SerializeToString() |
773 | 759 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 dm.DeviceRegisterRequest.BROWSER: [ | 953 dm.DeviceRegisterRequest.BROWSER: [ |
968 'google/chrome/user', | 954 'google/chrome/user', |
969 'google/chrome/extension' | 955 'google/chrome/extension' |
970 ], | 956 ], |
971 dm.DeviceRegisterRequest.USER: [ | 957 dm.DeviceRegisterRequest.USER: [ |
972 'google/chromeos/user', | 958 'google/chromeos/user', |
973 'google/chrome/extension' | 959 'google/chrome/extension' |
974 ], | 960 ], |
975 dm.DeviceRegisterRequest.DEVICE: [ | 961 dm.DeviceRegisterRequest.DEVICE: [ |
976 'google/chromeos/device', | 962 'google/chromeos/device', |
977 'google/chromeos/publicaccount', | 963 'google/chromeos/publicaccount' |
978 'google/chrome/extension' | |
979 ], | 964 ], |
980 dm.DeviceRegisterRequest.ANDROID_BROWSER: [ | 965 dm.DeviceRegisterRequest.ANDROID_BROWSER: [ |
981 'google/android/user' | 966 'google/android/user' |
982 ], | 967 ], |
983 dm.DeviceRegisterRequest.IOS_BROWSER: [ | 968 dm.DeviceRegisterRequest.IOS_BROWSER: [ |
984 'google/ios/user' | 969 'google/ios/user' |
985 ], | 970 ], |
986 dm.DeviceRegisterRequest.TT: ['google/chromeos/user', | 971 dm.DeviceRegisterRequest.TT: ['google/chromeos/user', |
987 'google/chrome/user'], | 972 'google/chrome/user'], |
988 } | 973 } |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1240 if (self.options.log_to_console): | 1225 if (self.options.log_to_console): |
1241 logger.addHandler(logging.StreamHandler()) | 1226 logger.addHandler(logging.StreamHandler()) |
1242 if (self.options.log_file): | 1227 if (self.options.log_file): |
1243 logger.addHandler(logging.FileHandler(self.options.log_file)) | 1228 logger.addHandler(logging.FileHandler(self.options.log_file)) |
1244 | 1229 |
1245 testserver_base.TestServerRunner.run_server(self) | 1230 testserver_base.TestServerRunner.run_server(self) |
1246 | 1231 |
1247 | 1232 |
1248 if __name__ == '__main__': | 1233 if __name__ == '__main__': |
1249 sys.exit(PolicyServerRunner().main()) | 1234 sys.exit(PolicyServerRunner().main()) |
OLD | NEW |