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 |