Chromium Code Reviews| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 "robot_api_auth_code": "fake_auth_code", | 50 "robot_api_auth_code": "fake_auth_code", |
| 51 "invalidation_source": 1025, | 51 "invalidation_source": 1025, |
| 52 "invalidation_name": "UENUPOL" | 52 "invalidation_name": "UENUPOL" |
| 53 } | 53 } |
| 54 | 54 |
| 55 """ | 55 """ |
| 56 | 56 |
| 57 import base64 | 57 import base64 |
| 58 import BaseHTTPServer | 58 import BaseHTTPServer |
| 59 import cgi | 59 import cgi |
| 60 import glob | |
| 60 import google.protobuf.text_format | 61 import google.protobuf.text_format |
| 61 import hashlib | 62 import hashlib |
| 62 import logging | 63 import logging |
| 63 import os | 64 import os |
| 64 import random | 65 import random |
| 65 import re | 66 import re |
| 66 import sys | 67 import sys |
| 67 import time | 68 import time |
| 68 import tlslite | 69 import tlslite |
| 69 import tlslite.api | 70 import tlslite.api |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 439 return error | 440 return error |
| 440 | 441 |
| 441 key_update_request = msg.device_state_key_update_request | 442 key_update_request = msg.device_state_key_update_request |
| 442 if len(key_update_request.server_backed_state_key) > 0: | 443 if len(key_update_request.server_backed_state_key) > 0: |
| 443 self.server.UpdateStateKeys(token_info['device_token'], | 444 self.server.UpdateStateKeys(token_info['device_token'], |
| 444 key_update_request.server_backed_state_key) | 445 key_update_request.server_backed_state_key) |
| 445 | 446 |
| 446 response = dm.DeviceManagementResponse() | 447 response = dm.DeviceManagementResponse() |
| 447 for request in msg.policy_request.request: | 448 for request in msg.policy_request.request: |
| 448 fetch_response = response.policy_response.response.add() | 449 fetch_response = response.policy_response.response.add() |
| 449 if (request.policy_type in | 450 if (request.policy_type not in |
|
Mattias Nissler (ping if slow)
2014/04/25 11:51:46
The logic here is rather convoluted now. Can't we
Joao da Silva
2014/04/28 11:56:12
Done.
| |
| 450 ('google/android/user', | 451 ('google/android/user', |
| 451 'google/chrome/extension', | 452 'google/chrome/extension', |
| 452 'google/chromeos/device', | 453 'google/chromeos/device', |
| 453 'google/chromeos/publicaccount', | 454 'google/chromeos/publicaccount', |
| 454 'google/chromeos/user', | 455 'google/chromeos/user', |
| 455 'google/chrome/user', | 456 'google/chrome/user', |
| 456 'google/ios/user')): | 457 'google/ios/user')): |
| 457 if request_type != 'policy': | |
| 458 fetch_response.error_code = 400 | |
| 459 fetch_response.error_message = 'Invalid request type' | |
| 460 else: | |
| 461 self.ProcessCloudPolicy(request, token_info, fetch_response) | |
| 462 else: | |
| 463 fetch_response.error_code = 400 | 458 fetch_response.error_code = 400 |
| 464 fetch_response.error_message = 'Invalid policy_type' | 459 fetch_response.error_message = 'Invalid policy_type' |
| 460 elif request_type != 'policy': | |
| 461 fetch_response.error_code = 400 | |
| 462 fetch_response.error_message = 'Invalid request type' | |
| 463 elif request.policy_type == 'google/chrome/extension': | |
| 464 # Send one PolicyFetchResponse for each extension that has | |
| 465 # configuration data at the server. | |
| 466 del response.policy_response.response[-1] | |
| 467 ids = self.server.ListMatchingComponents('google/chrome/extension') | |
| 468 for settings_entity_id in ids: | |
| 469 fake_request = dm.PolicyFetchRequest() | |
| 470 # Copy the extension policy request, to trigger the same signature | |
| 471 # type in the response. | |
|
Mattias Nissler (ping if slow)
2014/04/25 11:51:46
Why not just use |request|?
Joao da Silva
2014/04/28 11:56:12
Done.
| |
| 472 fake_request.CopyFrom(request) | |
| 473 fake_request.settings_entity_id = settings_entity_id | |
| 474 fetch_response = response.policy_response.response.add() | |
| 475 self.ProcessCloudPolicy(fake_request, token_info, fetch_response) | |
| 476 # Don't do key rotations for these messages. | |
| 477 fetch_response.ClearField('new_public_key') | |
| 478 fetch_response.ClearField('new_public_key_signature') | |
| 479 fetch_response.ClearField('new_public_key_verification_signature') | |
| 480 else: | |
| 481 self.ProcessCloudPolicy(request, token_info, fetch_response) | |
| 465 | 482 |
| 466 return (200, response) | 483 return (200, response) |
| 467 | 484 |
| 468 def ProcessAutoEnrollment(self, msg): | 485 def ProcessAutoEnrollment(self, msg): |
| 469 """Handles an auto-enrollment check request. | 486 """Handles an auto-enrollment check request. |
| 470 | 487 |
| 471 The reply depends on the value of the modulus: | 488 The reply depends on the value of the modulus: |
| 472 1: replies with no new modulus and the sha256 hash of "0" | 489 1: replies with no new modulus and the sha256 hash of "0" |
| 473 2: replies with a new modulus, 4. | 490 2: replies with a new modulus, 4. |
| 474 4: replies with a new modulus, 2. | 491 4: replies with a new modulus, 2. |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1049 policy_selector: the policy type and settings entity id, joined by '/'. | 1066 policy_selector: the policy type and settings entity id, joined by '/'. |
| 1050 | 1067 |
| 1051 Returns: | 1068 Returns: |
| 1052 The filename corresponding to the policy_selector, without a file | 1069 The filename corresponding to the policy_selector, without a file |
| 1053 extension. | 1070 extension. |
| 1054 """ | 1071 """ |
| 1055 sanitized_policy_selector = re.sub('[^A-Za-z0-9.@-]', '_', policy_selector) | 1072 sanitized_policy_selector = re.sub('[^A-Za-z0-9.@-]', '_', policy_selector) |
| 1056 return os.path.join(self.data_dir or '', | 1073 return os.path.join(self.data_dir or '', |
| 1057 'policy_%s' % sanitized_policy_selector) | 1074 'policy_%s' % sanitized_policy_selector) |
| 1058 | 1075 |
| 1076 def ListMatchingComponents(self, policy_type): | |
| 1077 """Returns a list of settings entity IDs that have a configuration file. | |
| 1078 | |
| 1079 Args: | |
| 1080 policy_type: the policy type to look for. Only settings entity IDs for | |
| 1081 file selectors that match this policy_type will be returned. | |
| 1082 | |
| 1083 Returns: | |
| 1084 A list of settings entity IDs for the given |policy_type| that have a | |
| 1085 configuration file in this server (either as a .bin, .txt or .data file). | |
| 1086 """ | |
| 1087 base_name = self.GetBaseFilename(policy_type) | |
| 1088 files = glob.glob('%s_*.*' % base_name) | |
| 1089 len_base_name = len(base_name) + 1 | |
| 1090 return [ file[len_base_name:file.rfind('.')] for file in files ] | |
| 1091 | |
| 1059 def ReadPolicyFromDataDir(self, policy_selector, proto_message): | 1092 def ReadPolicyFromDataDir(self, policy_selector, proto_message): |
| 1060 """Tries to read policy payload from a file in the data directory. | 1093 """Tries to read policy payload from a file in the data directory. |
| 1061 | 1094 |
| 1062 First checks for a binary rendition of the policy protobuf in | 1095 First checks for a binary rendition of the policy protobuf in |
| 1063 <data_dir>/policy_<sanitized_policy_selector>.bin. If that exists, returns | 1096 <data_dir>/policy_<sanitized_policy_selector>.bin. If that exists, returns |
| 1064 it. If that file doesn't exist, tries | 1097 it. If that file doesn't exist, tries |
| 1065 <data_dir>/policy_<sanitized_policy_selector>.txt and decodes that as a | 1098 <data_dir>/policy_<sanitized_policy_selector>.txt and decodes that as a |
| 1066 protobuf using proto_message. If that fails as well, returns None. | 1099 protobuf using proto_message. If that fails as well, returns None. |
| 1067 | 1100 |
| 1068 Args: | 1101 Args: |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1184 if (self.options.log_to_console): | 1217 if (self.options.log_to_console): |
| 1185 logger.addHandler(logging.StreamHandler()) | 1218 logger.addHandler(logging.StreamHandler()) |
| 1186 if (self.options.log_file): | 1219 if (self.options.log_file): |
| 1187 logger.addHandler(logging.FileHandler(self.options.log_file)) | 1220 logger.addHandler(logging.FileHandler(self.options.log_file)) |
| 1188 | 1221 |
| 1189 testserver_base.TestServerRunner.run_server(self) | 1222 testserver_base.TestServerRunner.run_server(self) |
| 1190 | 1223 |
| 1191 | 1224 |
| 1192 if __name__ == '__main__': | 1225 if __name__ == '__main__': |
| 1193 sys.exit(PolicyServerRunner().main()) | 1226 sys.exit(PolicyServerRunner().main()) |
| OLD | NEW |