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

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: Saving a file, sherlock? ;) 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
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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 "recommended" : { 43 "recommended" : {
44 } 44 }
45 }, 45 },
46 "managed_users" : [ 46 "managed_users" : [
47 "secret123456" 47 "secret123456"
48 ] 48 ]
49 } 49 }
50 50
51 """ 51 """
52 52
53 import BaseHTTPServer
53 import cgi 54 import cgi
54 import hashlib 55 import hashlib
55 import logging 56 import logging
56 import os 57 import os
57 import random 58 import random
58 import re 59 import re
59 import sys 60 import sys
60 import time 61 import time
61 import tlslite 62 import tlslite
62 import tlslite.api 63 import tlslite.api
63 import tlslite.utils 64 import tlslite.utils
64 65
65 # The name and availability of the json module varies in python versions. 66 # The name and availability of the json module varies in python versions.
66 try: 67 try:
67 import simplejson as json 68 import simplejson as json
68 except ImportError: 69 except ImportError:
69 try: 70 try:
70 import json 71 import json
71 except ImportError: 72 except ImportError:
72 json = None 73 json = None
73 74
74 import asn1der 75 import asn1der
76 import testserver_base
77
75 import device_management_backend_pb2 as dm 78 import device_management_backend_pb2 as dm
76 import cloud_policy_pb2 as cp 79 import cloud_policy_pb2 as cp
77 import chrome_device_policy_pb2 as dp 80 import chrome_device_policy_pb2 as dp
78 81
79 # ASN.1 object identifier for PKCS#1/RSA. 82 # ASN.1 object identifier for PKCS#1/RSA.
80 PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01' 83 PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01'
81 84
82 # SHA256 sum of "0". 85 # SHA256 sum of "0".
83 SHA256_0 = hashlib.sha256('0').digest() 86 SHA256_0 = hashlib.sha256('0').digest()
84 87
85 # List of bad machine identifiers that trigger the |valid_serial_number_missing| 88 # List of bad machine identifiers that trigger the |valid_serial_number_missing|
86 # flag to be set set in the policy fetch response. 89 # flag to be set set in the policy fetch response.
87 BAD_MACHINE_IDS = [ '123490EN400015' ]; 90 BAD_MACHINE_IDS = [ '123490EN400015' ];
88 91
89 # List of machines that trigger the server to send kiosk enrollment response 92 # List of machines that trigger the server to send kiosk enrollment response
90 # for the register request. 93 # for the register request.
91 KIOSK_MACHINE_IDS = [ 'KIOSK' ]; 94 KIOSK_MACHINE_IDS = [ 'KIOSK' ];
92 95
93 class RequestHandler(object): 96
97 class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
94 """Decodes and handles device management requests from clients. 98 """Decodes and handles device management requests from clients.
95 99
96 The handler implements all the request parsing and protobuf message decoding 100 The handler implements all the request parsing and protobuf message decoding
97 and encoding. It calls back into the server to lookup, register, and 101 and encoding. It calls back into the server to lookup, register, and
98 unregister clients. 102 unregister clients.
99 """ 103 """
100 104
101 def __init__(self, server, path, headers, request): 105 def __init__(self, request, client_address, server):
102 """Initialize the handler. 106 """Initialize the handler.
103 107
104 Args: 108 Args:
109 request: The request data received from the client as a string.
110 client_address: The client address.
105 server: The TestServer object to use for (un)registering clients. 111 server: The TestServer object to use for (un)registering clients.
106 path: A string containing the request path and query parameters.
107 headers: A rfc822.Message-like object containing HTTP headers.
108 request: The request data received from the client as a string.
109 """ 112 """
110 self._server = server 113 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request,
Joao da Silva 2013/02/12 19:06:05 Does this work? super(PolicyRequestHandler, self)
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 BaseRequestHandler (which is the root class here)
111 self._path = path 114 client_address, server);
Joao da Silva 2013/02/12 19:06:05 remove ;
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Done.
112 self._headers = headers
113 self._request = request
114 self._params = None
115 115
116 def GetUniqueParam(self, name): 116 def GetUniqueParam(self, name):
117 """Extracts a unique query parameter from the request. 117 """Extracts a unique query parameter from the request.
118 118
119 Args: 119 Args:
120 name: Names the parameter to fetch. 120 name: Names the parameter to fetch.
121 Returns: 121 Returns:
122 The parameter value or None if the parameter doesn't exist or is not 122 The parameter value or None if the parameter doesn't exist or is not
123 unique. 123 unique.
124 """ 124 """
125 if not self._params: 125 if not hasattr(self, '_params'):
126 self._params = cgi.parse_qs(self._path[self._path.find('?') + 1:]) 126 self._params = cgi.parse_qs(self.path[self.path.find('?') + 1:])
127 127
128 param_list = self._params.get(name, []) 128 param_list = self._params.get(name, [])
129 if len(param_list) == 1: 129 if len(param_list) == 1:
130 return param_list[0] 130 return param_list[0]
131 return None; 131 return None;
132 132
133 def do_POST(self):
Joao da Silva 2013/02/12 19:06:05 OVERRIDE ... oh wait.
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 NOT Done.
134 http_response, raw_reply = self.HandleRequest();
135 self.send_response(http_response)
136 if (http_response == 200):
137 self.send_header('Content-Type', 'application/x-protobuffer')
Joao da Silva 2013/02/12 19:06:05 device_management_service.cc uses "application/pro
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 I think that's because DMServer sends the latter a
138 self.end_headers()
139 self.wfile.write(raw_reply)
140
133 def HandleRequest(self): 141 def HandleRequest(self):
134 """Handles a request. 142 """Handles a request.
135 143
136 Parses the data supplied at construction time and returns a pair indicating 144 Parses the data supplied at construction time and returns a pair indicating
137 http status code and response data to be sent back to the client. 145 http status code and response data to be sent back to the client.
138 146
139 Returns: 147 Returns:
140 A tuple of HTTP status code and response data to send to the client. 148 A tuple of HTTP status code and response data to send to the client.
141 """ 149 """
142 rmsg = dm.DeviceManagementRequest() 150 rmsg = dm.DeviceManagementRequest()
143 rmsg.ParseFromString(self._request) 151 length = int(self.headers.getheader('content-length'))
152 rmsg.ParseFromString(self.rfile.read(length))
144 153
145 logging.debug('gaia auth token -> ' + 154 logging.debug('gaia auth token -> ' +
146 self._headers.getheader('Authorization', '')) 155 self.headers.getheader('Authorization', ''))
147 logging.debug('oauth token -> ' + str(self.GetUniqueParam('oauth_token'))) 156 logging.debug('oauth token -> ' + str(self.GetUniqueParam('oauth_token')))
148 logging.debug('deviceid -> ' + str(self.GetUniqueParam('deviceid'))) 157 logging.debug('deviceid -> ' + str(self.GetUniqueParam('deviceid')))
149 self.DumpMessage('Request', rmsg) 158 self.DumpMessage('Request', rmsg)
150 159
151 request_type = self.GetUniqueParam('request') 160 request_type = self.GetUniqueParam('request')
152 # Check server side requirements, as defined in 161 # Check server side requirements, as defined in
153 # device_management_backend.proto. 162 # device_management_backend.proto.
154 if (self.GetUniqueParam('devicetype') != '2' or 163 if (self.GetUniqueParam('devicetype') != '2' or
155 self.GetUniqueParam('apptype') != 'Chrome' or 164 self.GetUniqueParam('apptype') != 'Chrome' or
156 (request_type != 'ping' and 165 (request_type != 'ping' and
(...skipping 15 matching lines...) Expand all
172 """Extracts the auth token from the request and returns it. The token may 181 """Extracts the auth token from the request and returns it. The token may
173 either be a GoogleLogin token from an Authorization header, or an OAuth V2 182 either be a GoogleLogin token from an Authorization header, or an OAuth V2
174 token from the oauth_token query parameter. Returns None if no token is 183 token from the oauth_token query parameter. Returns None if no token is
175 present. 184 present.
176 """ 185 """
177 oauth_token = self.GetUniqueParam('oauth_token') 186 oauth_token = self.GetUniqueParam('oauth_token')
178 if oauth_token: 187 if oauth_token:
179 return oauth_token 188 return oauth_token
180 189
181 match = re.match('GoogleLogin auth=(\\w+)', 190 match = re.match('GoogleLogin auth=(\\w+)',
182 self._headers.getheader('Authorization', '')) 191 self.headers.getheader('Authorization', ''))
183 if match: 192 if match:
184 return match.group(1) 193 return match.group(1)
185 194
186 return None 195 return None
187 196
188 def ProcessRegister(self, msg): 197 def ProcessRegister(self, msg):
189 """Handles a register request. 198 """Handles a register request.
190 199
191 Checks the query for authorization and device identifier, registers the 200 Checks the query for authorization and device identifier, registers the
192 device with the server and constructs a response. 201 device with the server and constructs a response.
193 202
194 Args: 203 Args:
195 msg: The DeviceRegisterRequest message received from the client. 204 msg: The DeviceRegisterRequest message received from the client.
196 205
197 Returns: 206 Returns:
198 A tuple of HTTP status code and response data to send to the client. 207 A tuple of HTTP status code and response data to send to the client.
199 """ 208 """
200 # Check the auth token and device ID. 209 # Check the auth token and device ID.
201 auth = self.CheckGoogleLogin() 210 auth = self.CheckGoogleLogin()
202 if not auth: 211 if not auth:
203 return (403, 'No authorization') 212 return (403, 'No authorization')
204 213
205 policy = self._server.GetPolicies() 214 policy = self.server.GetPolicies()
206 if ('*' not in policy['managed_users'] and 215 if ('*' not in policy['managed_users'] and
207 auth not in policy['managed_users']): 216 auth not in policy['managed_users']):
208 return (403, 'Unmanaged') 217 return (403, 'Unmanaged')
209 218
210 device_id = self.GetUniqueParam('deviceid') 219 device_id = self.GetUniqueParam('deviceid')
211 if not device_id: 220 if not device_id:
212 return (400, 'Missing device identifier') 221 return (400, 'Missing device identifier')
213 222
214 token_info = self._server.RegisterDevice(device_id, 223 token_info = self.server.RegisterDevice(device_id,
215 msg.machine_id, 224 msg.machine_id,
216 msg.type) 225 msg.type)
217 226
218 # Send back the reply. 227 # Send back the reply.
219 response = dm.DeviceManagementResponse() 228 response = dm.DeviceManagementResponse()
220 response.register_response.device_management_token = ( 229 response.register_response.device_management_token = (
221 token_info['device_token']) 230 token_info['device_token'])
222 response.register_response.machine_name = token_info['machine_name'] 231 response.register_response.machine_name = token_info['machine_name']
223 response.register_response.enrollment_type = token_info['enrollment_mode'] 232 response.register_response.enrollment_type = token_info['enrollment_mode']
224 233
(...skipping 12 matching lines...) Expand all
237 246
238 Returns: 247 Returns:
239 A tuple of HTTP status code and response data to send to the client. 248 A tuple of HTTP status code and response data to send to the client.
240 """ 249 """
241 # Check the management token. 250 # Check the management token.
242 token, response = self.CheckToken(); 251 token, response = self.CheckToken();
243 if not token: 252 if not token:
244 return response 253 return response
245 254
246 # Unregister the device. 255 # Unregister the device.
247 self._server.UnregisterDevice(token['device_token']); 256 self.server.UnregisterDevice(token['device_token']);
248 257
249 # Prepare and send the response. 258 # Prepare and send the response.
250 response = dm.DeviceManagementResponse() 259 response = dm.DeviceManagementResponse()
251 response.unregister_response.CopyFrom(dm.DeviceUnregisterResponse()) 260 response.unregister_response.CopyFrom(dm.DeviceUnregisterResponse())
252 261
253 self.DumpMessage('Response', response) 262 self.DumpMessage('Response', response)
254 263
255 return (200, response.SerializeToString()) 264 return (200, response.SerializeToString())
256 265
257 def ProcessPolicy(self, msg, request_type): 266 def ProcessPolicy(self, msg, request_type):
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 437
429 Returns: 438 Returns:
430 A tuple of HTTP status code and response data to send to the client. 439 A tuple of HTTP status code and response data to send to the client.
431 """ 440 """
432 441
433 token_info, error = self.CheckToken() 442 token_info, error = self.CheckToken()
434 if not token_info: 443 if not token_info:
435 return error 444 return error
436 445
437 if msg.machine_id: 446 if msg.machine_id:
438 self._server.UpdateMachineId(token_info['device_token'], msg.machine_id) 447 self.server.UpdateMachineId(token_info['device_token'], msg.machine_id)
439 448
440 # Response is only given if the scope is specified in the config file. 449 # Response is only given if the scope is specified in the config file.
441 # Normally 'google/chromeos/device', 'google/chromeos/user' and 450 # Normally 'google/chromeos/device', 'google/chromeos/user' and
442 # 'google/chromeos/publicaccount' should be accepted. 451 # 'google/chromeos/publicaccount' should be accepted.
443 policy = self._server.GetPolicies() 452 policy = self.server.GetPolicies()
444 policy_value = '' 453 policy_value = ''
445 policy_key = msg.policy_type 454 policy_key = msg.policy_type
446 if msg.settings_entity_id: 455 if msg.settings_entity_id:
447 policy_key += '/' + msg.settings_entity_id 456 policy_key += '/' + msg.settings_entity_id
448 if msg.policy_type in token_info['allowed_policy_types']: 457 if msg.policy_type in token_info['allowed_policy_types']:
449 if (msg.policy_type == 'google/chromeos/user' or 458 if (msg.policy_type == 'google/chromeos/user' or
450 msg.policy_type == 'google/chrome/user' or 459 msg.policy_type == 'google/chrome/user' or
451 msg.policy_type == 'google/chromeos/publicaccount'): 460 msg.policy_type == 'google/chromeos/publicaccount'):
452 settings = cp.CloudPolicySettings() 461 settings = cp.CloudPolicySettings()
453 self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) 462 self.GatherUserPolicySettings(settings, policy.get(policy_key, {}))
454 elif msg.policy_type == 'google/chromeos/device': 463 elif msg.policy_type == 'google/chromeos/device':
455 settings = dp.ChromeDeviceSettingsProto() 464 settings = dp.ChromeDeviceSettingsProto()
456 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) 465 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {}))
457 466
458 # Figure out the key we want to use. If multiple keys are configured, the 467 # Figure out the key we want to use. If multiple keys are configured, the
459 # server will rotate through them in a round-robin fashion. 468 # server will rotate through them in a round-robin fashion.
460 signing_key = None 469 signing_key = None
461 req_key = None 470 req_key = None
462 key_version = 1 471 key_version = 1
463 nkeys = len(self._server.keys) 472 nkeys = len(self.server.keys)
464 if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0: 473 if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0:
465 if msg.public_key_version in range(1, nkeys + 1): 474 if msg.public_key_version in range(1, nkeys + 1):
466 # requested key exists, use for signing and rotate. 475 # requested key exists, use for signing and rotate.
467 req_key = self._server.keys[msg.public_key_version - 1]['private_key'] 476 req_key = self.server.keys[msg.public_key_version - 1]['private_key']
468 key_version = (msg.public_key_version % nkeys) + 1 477 key_version = (msg.public_key_version % nkeys) + 1
469 signing_key = self._server.keys[key_version - 1] 478 signing_key = self.server.keys[key_version - 1]
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):
Joao da Silva 2013/02/12 19:06:05 indent
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Done.
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: Serer host and port.
Joao da Silva 2013/02/12 19:06:05 *Server
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Done.
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,
Joao da Silva 2013/02/12 19:06:05 Same re super()
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Doesn't work here due to multiple inheritance.
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 27 matching lines...) Expand all
596 policy = {} 611 policy = {}
597 if json is None: 612 if json is None:
598 print 'No JSON module, cannot parse policy information' 613 print 'No JSON module, cannot parse policy information'
599 else : 614 else :
600 try: 615 try:
601 policy = json.loads(open(self.policy_path).read()) 616 policy = json.loads(open(self.policy_path).read())
602 except IOError: 617 except IOError:
603 print 'Failed to load policy from %s' % self.policy_path 618 print 'Failed to load policy from %s' % self.policy_path
604 return policy 619 return policy
605 620
606 def HandleRequest(self, path, headers, request):
607 """Handles a request.
608
609 Args:
610 path: The request path and query parameters received from the client.
611 headers: A rfc822.Message-like object containing HTTP headers.
612 request: The request data received from the client as a string.
613 Returns:
614 A pair of HTTP status code and response data to send to the client.
615 """
616 handler = RequestHandler(self, path, headers, request)
617 return handler.HandleRequest()
618
619 def RegisterDevice(self, device_id, machine_id, type): 621 def RegisterDevice(self, device_id, machine_id, type):
620 """Registers a device or user and generates a DM token for it. 622 """Registers a device or user and generates a DM token for it.
621 623
622 Args: 624 Args:
623 device_id: The device identifier provided by the client. 625 device_id: The device identifier provided by the client.
624 626
625 Returns: 627 Returns:
626 The newly generated device token for the device. 628 The newly generated device token for the device.
627 """ 629 """
628 dmtoken_chars = [] 630 dmtoken_chars = []
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 return self._registered_tokens.get(dmtoken, None) 678 return self._registered_tokens.get(dmtoken, None)
677 679
678 def UnregisterDevice(self, dmtoken): 680 def UnregisterDevice(self, dmtoken):
679 """Unregisters a device identified by the given DM token. 681 """Unregisters a device identified by the given DM token.
680 682
681 Args: 683 Args:
682 dmtoken: The device management token provided by the client. 684 dmtoken: The device management token provided by the client.
683 """ 685 """
684 if dmtoken in self._registered_tokens.keys(): 686 if dmtoken in self._registered_tokens.keys():
685 del self._registered_tokens[dmtoken] 687 del self._registered_tokens[dmtoken]
688
689
690 class PolicyServerRunner(testserver_base.TestServerRunner):
691
692 def __init__(self):
693 testserver_base.TestServerRunner.__init__(self)
Joao da Silva 2013/02/12 19:06:05 Same re super()
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Done.
694
695 def create_server(self, server_data):
696 port = self.options.port
697 host = self.options.host
Joao da Silva 2013/02/12 19:06:05 These 2 aren't used
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Done.
698 config_file = (
699 self.options.config_file or
700 os.path.join(self.options.data_dir or '', 'device_management'))
701 server = PolicyTestServer((self.options.host, self.options.port),
702 config_file, self.options.policy_keys)
703 server_data['port'] = server.server_port
704 return server
705
706 def add_options(self):
707 testserver_base.TestServerRunner.add_options(self)
708 self.option_parser.add_option('--policy-key', action='append',
709 dest='policy_keys',
710 help='Specify a path to a PEM-encoded '
711 'private key to use for policy signing. May '
712 'be specified multiple times in order to '
713 'load multipe keys into the server. If the '
714 'server has multiple keys, it will rotate '
715 'through them in at each request a '
Joao da Silva 2013/02/12 19:06:05 through them at each request _in_ a ...
Mattias Nissler (ping if slow) 2013/02/13 11:54:10 Done.
716 'round-robin fashion. The server will '
717 'generate a random key if none is specified '
718 'on the command line.')
719 self.option_parser.add_option('--log-level', dest='log_level',
720 default='WARN',
721 help='Log level threshold to use.')
722 self.option_parser.add_option('--config-file', dest='config_file',
723 help='Specify a configuration file to use '
724 'instead of the default '
725 '<data_dir>/device_management')
726
727 def run_server(self):
728 logger = logging.getLogger()
729 logger.setLevel(getattr(logging, str(self.options.log_level).upper()))
730 if (self.options.log_to_console):
731 logger.addHandler(logging.StreamHandler())
732 if (self.options.log_file):
733 logger.addHandler(logging.FileHandler(self.options.log_file))
734
735 testserver_base.TestServerRunner.run_server(self);
736
737
738 if __name__ == '__main__':
739 sys.exit(PolicyServerRunner().main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698