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

Side by Side Diff: chrome/browser/policy/test/policy_testserver.py

Issue 12235003: Split out policy code from net/tools/testserver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 80 chars. Created 7 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
« no previous file with comments | « chrome/browser/policy/test/local_policy_test_server.cc ('k') | chrome/browser_tests.isolate » ('j') | 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
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 } 44 }
45 }, 45 },
46 "managed_users" : [ 46 "managed_users" : [
47 "secret123456" 47 "secret123456"
48 ], 48 ],
49 "current_key_index": 0 49 "current_key_index": 0
50 } 50 }
51 51
52 """ 52 """
53 53
54 import BaseHTTPServer
54 import cgi 55 import cgi
55 import hashlib 56 import hashlib
56 import logging 57 import logging
57 import os 58 import os
58 import random 59 import random
59 import re 60 import re
60 import sys 61 import sys
61 import time 62 import time
62 import tlslite 63 import tlslite
63 import tlslite.api 64 import tlslite.api
64 import tlslite.utils 65 import tlslite.utils
65 66
66 # The name and availability of the json module varies in python versions. 67 # The name and availability of the json module varies in python versions.
67 try: 68 try:
68 import simplejson as json 69 import simplejson as json
69 except ImportError: 70 except ImportError:
70 try: 71 try:
71 import json 72 import json
72 except ImportError: 73 except ImportError:
73 json = None 74 json = None
74 75
75 import asn1der 76 import asn1der
77 import testserver_base
78
76 import device_management_backend_pb2 as dm 79 import device_management_backend_pb2 as dm
77 import cloud_policy_pb2 as cp 80 import cloud_policy_pb2 as cp
78 import chrome_device_policy_pb2 as dp 81 import chrome_device_policy_pb2 as dp
79 82
80 # ASN.1 object identifier for PKCS#1/RSA. 83 # ASN.1 object identifier for PKCS#1/RSA.
81 PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01' 84 PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01'
82 85
83 # SHA256 sum of "0". 86 # SHA256 sum of "0".
84 SHA256_0 = hashlib.sha256('0').digest() 87 SHA256_0 = hashlib.sha256('0').digest()
85 88
86 # List of bad machine identifiers that trigger the |valid_serial_number_missing| 89 # List of bad machine identifiers that trigger the |valid_serial_number_missing|
87 # flag to be set set in the policy fetch response. 90 # flag to be set set in the policy fetch response.
88 BAD_MACHINE_IDS = [ '123490EN400015' ]; 91 BAD_MACHINE_IDS = [ '123490EN400015' ];
89 92
90 # List of machines that trigger the server to send kiosk enrollment response 93 # List of machines that trigger the server to send kiosk enrollment response
91 # for the register request. 94 # for the register request.
92 KIOSK_MACHINE_IDS = [ 'KIOSK' ]; 95 KIOSK_MACHINE_IDS = [ 'KIOSK' ];
93 96
94 class RequestHandler(object): 97
98 class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
95 """Decodes and handles device management requests from clients. 99 """Decodes and handles device management requests from clients.
96 100
97 The handler implements all the request parsing and protobuf message decoding 101 The handler implements all the request parsing and protobuf message decoding
98 and encoding. It calls back into the server to lookup, register, and 102 and encoding. It calls back into the server to lookup, register, and
99 unregister clients. 103 unregister clients.
100 """ 104 """
101 105
102 def __init__(self, server, path, headers, request): 106 def __init__(self, request, client_address, server):
103 """Initialize the handler. 107 """Initialize the handler.
104 108
105 Args: 109 Args:
110 request: The request data received from the client as a string.
111 client_address: The client address.
106 server: The TestServer object to use for (un)registering clients. 112 server: The TestServer object to use for (un)registering clients.
107 path: A string containing the request path and query parameters.
108 headers: A rfc822.Message-like object containing HTTP headers.
109 request: The request data received from the client as a string.
110 """ 113 """
111 self._server = server 114 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request,
112 self._path = path 115 client_address, server)
113 self._headers = headers
114 self._request = request
115 self._params = None
116 116
117 def GetUniqueParam(self, name): 117 def GetUniqueParam(self, name):
118 """Extracts a unique query parameter from the request. 118 """Extracts a unique query parameter from the request.
119 119
120 Args: 120 Args:
121 name: Names the parameter to fetch. 121 name: Names the parameter to fetch.
122 Returns: 122 Returns:
123 The parameter value or None if the parameter doesn't exist or is not 123 The parameter value or None if the parameter doesn't exist or is not
124 unique. 124 unique.
125 """ 125 """
126 if not self._params: 126 if not hasattr(self, '_params'):
127 self._params = cgi.parse_qs(self._path[self._path.find('?') + 1:]) 127 self._params = cgi.parse_qs(self.path[self.path.find('?') + 1:])
128 128
129 param_list = self._params.get(name, []) 129 param_list = self._params.get(name, [])
130 if len(param_list) == 1: 130 if len(param_list) == 1:
131 return param_list[0] 131 return param_list[0]
132 return None; 132 return None;
133 133
134 def do_POST(self):
135 http_response, raw_reply = self.HandleRequest();
136 self.send_response(http_response)
137 if (http_response == 200):
138 self.send_header('Content-Type', 'application/x-protobuffer')
139 self.end_headers()
140 self.wfile.write(raw_reply)
141
134 def HandleRequest(self): 142 def HandleRequest(self):
135 """Handles a request. 143 """Handles a request.
136 144
137 Parses the data supplied at construction time and returns a pair indicating 145 Parses the data supplied at construction time and returns a pair indicating
138 http status code and response data to be sent back to the client. 146 http status code and response data to be sent back to the client.
139 147
140 Returns: 148 Returns:
141 A tuple of HTTP status code and response data to send to the client. 149 A tuple of HTTP status code and response data to send to the client.
142 """ 150 """
143 rmsg = dm.DeviceManagementRequest() 151 rmsg = dm.DeviceManagementRequest()
144 rmsg.ParseFromString(self._request) 152 length = int(self.headers.getheader('content-length'))
153 rmsg.ParseFromString(self.rfile.read(length))
145 154
146 logging.debug('gaia auth token -> ' + 155 logging.debug('gaia auth token -> ' +
147 self._headers.getheader('Authorization', '')) 156 self.headers.getheader('Authorization', ''))
148 logging.debug('oauth token -> ' + str(self.GetUniqueParam('oauth_token'))) 157 logging.debug('oauth token -> ' + str(self.GetUniqueParam('oauth_token')))
149 logging.debug('deviceid -> ' + str(self.GetUniqueParam('deviceid'))) 158 logging.debug('deviceid -> ' + str(self.GetUniqueParam('deviceid')))
150 self.DumpMessage('Request', rmsg) 159 self.DumpMessage('Request', rmsg)
151 160
152 request_type = self.GetUniqueParam('request') 161 request_type = self.GetUniqueParam('request')
153 # Check server side requirements, as defined in 162 # Check server side requirements, as defined in
154 # device_management_backend.proto. 163 # device_management_backend.proto.
155 if (self.GetUniqueParam('devicetype') != '2' or 164 if (self.GetUniqueParam('devicetype') != '2' or
156 self.GetUniqueParam('apptype') != 'Chrome' or 165 self.GetUniqueParam('apptype') != 'Chrome' or
157 (request_type != 'ping' and 166 (request_type != 'ping' and
(...skipping 15 matching lines...) Expand all
173 """Extracts the auth token from the request and returns it. The token may 182 """Extracts the auth token from the request and returns it. The token may
174 either be a GoogleLogin token from an Authorization header, or an OAuth V2 183 either be a GoogleLogin token from an Authorization header, or an OAuth V2
175 token from the oauth_token query parameter. Returns None if no token is 184 token from the oauth_token query parameter. Returns None if no token is
176 present. 185 present.
177 """ 186 """
178 oauth_token = self.GetUniqueParam('oauth_token') 187 oauth_token = self.GetUniqueParam('oauth_token')
179 if oauth_token: 188 if oauth_token:
180 return oauth_token 189 return oauth_token
181 190
182 match = re.match('GoogleLogin auth=(\\w+)', 191 match = re.match('GoogleLogin auth=(\\w+)',
183 self._headers.getheader('Authorization', '')) 192 self.headers.getheader('Authorization', ''))
184 if match: 193 if match:
185 return match.group(1) 194 return match.group(1)
186 195
187 return None 196 return None
188 197
189 def ProcessRegister(self, msg): 198 def ProcessRegister(self, msg):
190 """Handles a register request. 199 """Handles a register request.
191 200
192 Checks the query for authorization and device identifier, registers the 201 Checks the query for authorization and device identifier, registers the
193 device with the server and constructs a response. 202 device with the server and constructs a response.
194 203
195 Args: 204 Args:
196 msg: The DeviceRegisterRequest message received from the client. 205 msg: The DeviceRegisterRequest message received from the client.
197 206
198 Returns: 207 Returns:
199 A tuple of HTTP status code and response data to send to the client. 208 A tuple of HTTP status code and response data to send to the client.
200 """ 209 """
201 # Check the auth token and device ID. 210 # Check the auth token and device ID.
202 auth = self.CheckGoogleLogin() 211 auth = self.CheckGoogleLogin()
203 if not auth: 212 if not auth:
204 return (403, 'No authorization') 213 return (403, 'No authorization')
205 214
206 policy = self._server.GetPolicies() 215 policy = self.server.GetPolicies()
207 if ('*' not in policy['managed_users'] and 216 if ('*' not in policy['managed_users'] and
208 auth not in policy['managed_users']): 217 auth not in policy['managed_users']):
209 return (403, 'Unmanaged') 218 return (403, 'Unmanaged')
210 219
211 device_id = self.GetUniqueParam('deviceid') 220 device_id = self.GetUniqueParam('deviceid')
212 if not device_id: 221 if not device_id:
213 return (400, 'Missing device identifier') 222 return (400, 'Missing device identifier')
214 223
215 token_info = self._server.RegisterDevice(device_id, 224 token_info = self.server.RegisterDevice(device_id,
216 msg.machine_id, 225 msg.machine_id,
217 msg.type) 226 msg.type)
218 227
219 # Send back the reply. 228 # Send back the reply.
220 response = dm.DeviceManagementResponse() 229 response = dm.DeviceManagementResponse()
221 response.register_response.device_management_token = ( 230 response.register_response.device_management_token = (
222 token_info['device_token']) 231 token_info['device_token'])
223 response.register_response.machine_name = token_info['machine_name'] 232 response.register_response.machine_name = token_info['machine_name']
224 response.register_response.enrollment_type = token_info['enrollment_mode'] 233 response.register_response.enrollment_type = token_info['enrollment_mode']
225 234
(...skipping 12 matching lines...) Expand all
238 247
239 Returns: 248 Returns:
240 A tuple of HTTP status code and response data to send to the client. 249 A tuple of HTTP status code and response data to send to the client.
241 """ 250 """
242 # Check the management token. 251 # Check the management token.
243 token, response = self.CheckToken(); 252 token, response = self.CheckToken();
244 if not token: 253 if not token:
245 return response 254 return response
246 255
247 # Unregister the device. 256 # Unregister the device.
248 self._server.UnregisterDevice(token['device_token']); 257 self.server.UnregisterDevice(token['device_token']);
249 258
250 # Prepare and send the response. 259 # Prepare and send the response.
251 response = dm.DeviceManagementResponse() 260 response = dm.DeviceManagementResponse()
252 response.unregister_response.CopyFrom(dm.DeviceUnregisterResponse()) 261 response.unregister_response.CopyFrom(dm.DeviceUnregisterResponse())
253 262
254 self.DumpMessage('Response', response) 263 self.DumpMessage('Response', response)
255 264
256 return (200, response.SerializeToString()) 265 return (200, response.SerializeToString())
257 266
258 def ProcessPolicy(self, msg, request_type): 267 def ProcessPolicy(self, msg, request_type):
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 438
430 Returns: 439 Returns:
431 A tuple of HTTP status code and response data to send to the client. 440 A tuple of HTTP status code and response data to send to the client.
432 """ 441 """
433 442
434 token_info, error = self.CheckToken() 443 token_info, error = self.CheckToken()
435 if not token_info: 444 if not token_info:
436 return error 445 return error
437 446
438 if msg.machine_id: 447 if msg.machine_id:
439 self._server.UpdateMachineId(token_info['device_token'], msg.machine_id) 448 self.server.UpdateMachineId(token_info['device_token'], msg.machine_id)
440 449
441 # Response is only given if the scope is specified in the config file. 450 # Response is only given if the scope is specified in the config file.
442 # Normally 'google/chromeos/device', 'google/chromeos/user' and 451 # Normally 'google/chromeos/device', 'google/chromeos/user' and
443 # 'google/chromeos/publicaccount' should be accepted. 452 # 'google/chromeos/publicaccount' should be accepted.
444 policy = self._server.GetPolicies() 453 policy = self.server.GetPolicies()
445 policy_value = '' 454 policy_value = ''
446 policy_key = msg.policy_type 455 policy_key = msg.policy_type
447 if msg.settings_entity_id: 456 if msg.settings_entity_id:
448 policy_key += '/' + msg.settings_entity_id 457 policy_key += '/' + msg.settings_entity_id
449 if msg.policy_type in token_info['allowed_policy_types']: 458 if msg.policy_type in token_info['allowed_policy_types']:
450 if (msg.policy_type == 'google/chromeos/user' or 459 if (msg.policy_type == 'google/chromeos/user' or
451 msg.policy_type == 'google/chrome/user' or 460 msg.policy_type == 'google/chrome/user' or
452 msg.policy_type == 'google/chromeos/publicaccount'): 461 msg.policy_type == 'google/chromeos/publicaccount'):
453 settings = cp.CloudPolicySettings() 462 settings = cp.CloudPolicySettings()
454 self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) 463 self.GatherUserPolicySettings(settings, policy.get(policy_key, {}))
455 elif msg.policy_type == 'google/chromeos/device': 464 elif msg.policy_type == 'google/chromeos/device':
456 settings = dp.ChromeDeviceSettingsProto() 465 settings = dp.ChromeDeviceSettingsProto()
457 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) 466 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {}))
458 467
459 # Sign with 'current_key_index', defaulting to key 0. 468 # Sign with 'current_key_index', defaulting to key 0.
460 signing_key = None 469 signing_key = None
461 req_key = None 470 req_key = None
462 current_key_index = policy.get('current_key_index', 0) 471 current_key_index = policy.get('current_key_index', 0)
463 nkeys = len(self._server.keys) 472 nkeys = len(self.server.keys)
464 if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and 473 if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and
465 current_key_index in range(nkeys)): 474 current_key_index in range(nkeys)):
466 signing_key = self._server.keys[current_key_index] 475 signing_key = self.server.keys[current_key_index]
467 if msg.public_key_version in range(1, nkeys + 1): 476 if msg.public_key_version in range(1, nkeys + 1):
468 # requested key exists, use for signing and rotate. 477 # requested key exists, use for signing and rotate.
469 req_key = self._server.keys[msg.public_key_version - 1]['private_key'] 478 req_key = self.server.keys[msg.public_key_version - 1]['private_key']
470 479
471 # Fill the policy data protobuf. 480 # Fill the policy data protobuf.
472 policy_data = dm.PolicyData() 481 policy_data = dm.PolicyData()
473 policy_data.policy_type = msg.policy_type 482 policy_data.policy_type = msg.policy_type
474 policy_data.timestamp = int(time.time() * 1000) 483 policy_data.timestamp = int(time.time() * 1000)
475 policy_data.request_token = token_info['device_token'] 484 policy_data.request_token = token_info['device_token']
476 policy_data.policy_value = settings.SerializeToString() 485 policy_data.policy_value = settings.SerializeToString()
477 policy_data.machine_name = token_info['machine_name'] 486 policy_data.machine_name = token_info['machine_name']
478 policy_data.valid_serial_number_missing = ( 487 policy_data.valid_serial_number_missing = (
479 token_info['machine_id'] in BAD_MACHINE_IDS) 488 token_info['machine_id'] in BAD_MACHINE_IDS)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 Returns: 526 Returns:
518 A pair of token information record and error response. If the first 527 A pair of token information record and error response. If the first
519 element is None, then the second contains an error code to send back to 528 element is None, then the second contains an error code to send back to
520 the client. Otherwise the first element is the same structure that is 529 the client. Otherwise the first element is the same structure that is
521 returned by LookupToken(). 530 returned by LookupToken().
522 """ 531 """
523 error = 500 532 error = 500
524 dmtoken = None 533 dmtoken = None
525 request_device_id = self.GetUniqueParam('deviceid') 534 request_device_id = self.GetUniqueParam('deviceid')
526 match = re.match('GoogleDMToken token=(\\w+)', 535 match = re.match('GoogleDMToken token=(\\w+)',
527 self._headers.getheader('Authorization', '')) 536 self.headers.getheader('Authorization', ''))
528 if match: 537 if match:
529 dmtoken = match.group(1) 538 dmtoken = match.group(1)
530 if not dmtoken: 539 if not dmtoken:
531 error = 401 540 error = 401
532 else: 541 else:
533 token_info = self._server.LookupToken(dmtoken) 542 token_info = self.server.LookupToken(dmtoken)
534 if (not token_info or 543 if (not token_info or
535 not request_device_id or 544 not request_device_id or
536 token_info['device_id'] != request_device_id): 545 token_info['device_id'] != request_device_id):
537 error = 410 546 error = 410
538 else: 547 else:
539 return (token_info, None) 548 return (token_info, None)
540 549
541 logging.debug('Token check failed with error %d' % error) 550 logging.debug('Token check failed with error %d' % error)
542 551
543 return (None, (error, 'Server error %d' % error)) 552 return (None, (error, 'Server error %d' % error))
544 553
545 def DumpMessage(self, label, msg): 554 def DumpMessage(self, label, msg):
546 """Helper for logging an ASCII dump of a protobuf message.""" 555 """Helper for logging an ASCII dump of a protobuf message."""
547 logging.debug('%s\n%s' % (label, str(msg))) 556 logging.debug('%s\n%s' % (label, str(msg)))
548 557
549 class TestServer(object): 558
559 class PolicyTestServer(testserver_base.ClientRestrictingServerMixIn,
560 testserver_base.BrokenPipeHandlerMixIn,
561 testserver_base.StoppableHTTPServer):
550 """Handles requests and keeps global service state.""" 562 """Handles requests and keeps global service state."""
551 563
552 def __init__(self, policy_path, private_key_paths): 564 def __init__(self, server_address, policy_path, private_key_paths):
553 """Initializes the server. 565 """Initializes the server.
554 566
555 Args: 567 Args:
568 server_address: Server host and port.
556 policy_path: Names the file to read JSON-formatted policy from. 569 policy_path: Names the file to read JSON-formatted policy from.
557 private_key_paths: List of paths to read private keys from. 570 private_key_paths: List of paths to read private keys from.
558 """ 571 """
572 testserver_base.StoppableHTTPServer.__init__(self, server_address,
573 PolicyRequestHandler)
559 self._registered_tokens = {} 574 self._registered_tokens = {}
560 self.policy_path = policy_path 575 self.policy_path = policy_path
561 576
562 self.keys = [] 577 self.keys = []
563 if private_key_paths: 578 if private_key_paths:
564 # Load specified keys from the filesystem. 579 # Load specified keys from the filesystem.
565 for key_path in private_key_paths: 580 for key_path in private_key_paths:
566 try: 581 try:
567 key = tlslite.api.parsePEMKey(open(key_path).read(), private=True) 582 key = tlslite.api.parsePEMKey(open(key_path).read(), private=True)
568 except IOError: 583 except IOError:
(...skipping 28 matching lines...) Expand all
597 policy = {} 612 policy = {}
598 if json is None: 613 if json is None:
599 print 'No JSON module, cannot parse policy information' 614 print 'No JSON module, cannot parse policy information'
600 else : 615 else :
601 try: 616 try:
602 policy = json.loads(open(self.policy_path).read()) 617 policy = json.loads(open(self.policy_path).read())
603 except IOError: 618 except IOError:
604 print 'Failed to load policy from %s' % self.policy_path 619 print 'Failed to load policy from %s' % self.policy_path
605 return policy 620 return policy
606 621
607 def HandleRequest(self, path, headers, request):
608 """Handles a request.
609
610 Args:
611 path: The request path and query parameters received from the client.
612 headers: A rfc822.Message-like object containing HTTP headers.
613 request: The request data received from the client as a string.
614 Returns:
615 A pair of HTTP status code and response data to send to the client.
616 """
617 handler = RequestHandler(self, path, headers, request)
618 return handler.HandleRequest()
619
620 def RegisterDevice(self, device_id, machine_id, type): 622 def RegisterDevice(self, device_id, machine_id, type):
621 """Registers a device or user and generates a DM token for it. 623 """Registers a device or user and generates a DM token for it.
622 624
623 Args: 625 Args:
624 device_id: The device identifier provided by the client. 626 device_id: The device identifier provided by the client.
625 627
626 Returns: 628 Returns:
627 The newly generated device token for the device. 629 The newly generated device token for the device.
628 """ 630 """
629 dmtoken_chars = [] 631 dmtoken_chars = []
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 return self._registered_tokens.get(dmtoken, None) 679 return self._registered_tokens.get(dmtoken, None)
678 680
679 def UnregisterDevice(self, dmtoken): 681 def UnregisterDevice(self, dmtoken):
680 """Unregisters a device identified by the given DM token. 682 """Unregisters a device identified by the given DM token.
681 683
682 Args: 684 Args:
683 dmtoken: The device management token provided by the client. 685 dmtoken: The device management token provided by the client.
684 """ 686 """
685 if dmtoken in self._registered_tokens.keys(): 687 if dmtoken in self._registered_tokens.keys():
686 del self._registered_tokens[dmtoken] 688 del self._registered_tokens[dmtoken]
689
690
691 class PolicyServerRunner(testserver_base.TestServerRunner):
692
693 def __init__(self):
694 super(PolicyServerRunner, self).__init__()
695
696 def create_server(self, server_data):
697 config_file = (
698 self.options.config_file or
699 os.path.join(self.options.data_dir or '', 'device_management'))
700 server = PolicyTestServer((self.options.host, self.options.port),
701 config_file, self.options.policy_keys)
702 server_data['port'] = server.server_port
703 return server
704
705 def add_options(self):
706 testserver_base.TestServerRunner.add_options(self)
707 self.option_parser.add_option('--policy-key', action='append',
708 dest='policy_keys',
709 help='Specify a path to a PEM-encoded '
710 'private key to use for policy signing. May '
711 'be specified multiple times in order to '
712 'load multipe keys into the server. If the '
713 'server has multiple keys, it will rotate '
714 'through them in at each request in a '
715 'round-robin fashion. The server will '
716 'generate a random key if none is specified '
717 'on the command line.')
718 self.option_parser.add_option('--log-level', dest='log_level',
719 default='WARN',
720 help='Log level threshold to use.')
721 self.option_parser.add_option('--config-file', dest='config_file',
722 help='Specify a configuration file to use '
723 'instead of the default '
724 '<data_dir>/device_management')
725
726 def run_server(self):
727 logger = logging.getLogger()
728 logger.setLevel(getattr(logging, str(self.options.log_level).upper()))
729 if (self.options.log_to_console):
730 logger.addHandler(logging.StreamHandler())
731 if (self.options.log_file):
732 logger.addHandler(logging.FileHandler(self.options.log_file))
733
734 testserver_base.TestServerRunner.run_server(self);
735
736
737 if __name__ == '__main__':
738 sys.exit(PolicyServerRunner().main())
OLDNEW
« no previous file with comments | « chrome/browser/policy/test/local_policy_test_server.cc ('k') | chrome/browser_tests.isolate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698