def ProcessCloudPolicy(self, msg): """Handles a cloud policy request. (New protocol for policy requests.) Checks for authorization, encodes the policy into protobuf representation, signs it and constructs the repsonse. Args: msg: The CloudPolicyRequest message received from the client. Returns: A tuple of HTTP status code and response data to send to the client. """ token_info, error = self.CheckToken() if not token_info: return error if msg.machine_id: self.server.UpdateMachineId(token_info['device_token'], msg.machine_id) # Response is only given if the scope is specified in the config file. # Normally 'google/chromeos/device', 'google/chromeos/user' and # 'google/chromeos/publicaccount' should be accepted. policy = self.server.GetPolicies() policy_value = '' policy_key = msg.policy_type if msg.settings_entity_id: policy_key += '/' + msg.settings_entity_id if msg.policy_type in token_info['allowed_policy_types']: if (msg.policy_type == 'google/chromeos/user' or msg.policy_type == 'google/chrome/user' or msg.policy_type == 'google/chromeos/publicaccount'): settings = cp.CloudPolicySettings() payload = self.server.ReadPolicyFromDataDir(policy_key, settings) if payload is None: self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) payload = settings.SerializeToString() elif msg.policy_type == 'google/chromeos/device': settings = dp.ChromeDeviceSettingsProto() payload = self.server.ReadPolicyFromDataDir(policy_key, settings) if payload is None: self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) payload = settings.SerializeToString() # Sign with 'current_key_index', defaulting to key 0. signing_key = None req_key = None current_key_index = policy.get('current_key_index', 0) nkeys = len(self.server.keys) if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and current_key_index in range(nkeys)): signing_key = self.server.keys[current_key_index] if msg.public_key_version in range(1, nkeys + 1): # requested key exists, use for signing and rotate. req_key = self.server.keys[msg.public_key_version - 1]['private_key'] # Fill the policy data protobuf. policy_data = dm.PolicyData() policy_data.policy_type = msg.policy_type policy_data.timestamp = int(time.time() * 1000) policy_data.request_token = token_info['device_token'] policy_data.policy_value = payload policy_data.machine_name = token_info['machine_name'] policy_data.valid_serial_number_missing = ( token_info['machine_id'] in BAD_MACHINE_IDS) policy_data.settings_entity_id = msg.settings_entity_id if signing_key: policy_data.public_key_version = current_key_index + 1 if msg.policy_type == 'google/chromeos/publicaccount': policy_data.username = msg.settings_entity_id else: # For regular user/device policy, there is no way for the testserver to # know the user name belonging to the GAIA auth token we received (short # of actually talking to GAIA). To address this, we read the username from # the policy configuration dictionary, or use a default. policy_data.username = policy.get('policy_user', '*****@*****.**') policy_data.device_id = token_info['device_id'] signed_data = policy_data.SerializeToString() response = dm.DeviceManagementResponse() fetch_response = response.policy_response.response.add() fetch_response.policy_data = signed_data if signing_key: fetch_response.policy_data_signature = ( signing_key['private_key'].hashAndSign(signed_data).tostring()) if msg.public_key_version != current_key_index + 1: fetch_response.new_public_key = signing_key['public_key'] if req_key: fetch_response.new_public_key_signature = ( req_key.hashAndSign(fetch_response.new_public_key).tostring()) self.DumpMessage('Response', response) return (200, response.SerializeToString())
def ProcessCloudPolicy(self, msg, token_info, response): """Handles a cloud policy request. (New protocol for policy requests.) Encodes the policy into protobuf representation, signs it and constructs the response. Args: msg: The CloudPolicyRequest message received from the client. token_info: the token extracted from the request. response: A PolicyFetchResponse message that should be filled with the response data. """ if msg.machine_id: self.server.UpdateMachineId(token_info['device_token'], msg.machine_id) # Response is only given if the scope is specified in the config file. # Normally 'google/chromeos/device', 'google/chromeos/user' and # 'google/chromeos/publicaccount' should be accepted. policy = self.server.GetPolicies() policy_value = '' policy_key = msg.policy_type if msg.settings_entity_id: policy_key += '/' + msg.settings_entity_id if msg.policy_type in token_info['allowed_policy_types']: if (msg.policy_type == 'google/chromeos/user' or msg.policy_type == 'google/chrome/user' or msg.policy_type == 'google/chromeos/publicaccount'): settings = cp.CloudPolicySettings() payload = self.server.ReadPolicyFromDataDir( policy_key, settings) if payload is None: self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) payload = settings.SerializeToString() elif dp is not None and msg.policy_type == 'google/chromeos/device': settings = dp.ChromeDeviceSettingsProto() payload = self.server.ReadPolicyFromDataDir( policy_key, settings) if payload is None: self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) payload = settings.SerializeToString() elif msg.policy_type == 'google/chrome/extension': settings = ep.ExternalPolicyData() payload = self.server.ReadPolicyFromDataDir( policy_key, settings) if payload is None: payload = self.CreatePolicyForExternalPolicyData( policy_key) else: response.error_code = 400 response.error_message = 'Invalid policy type' return else: response.error_code = 400 response.error_message = 'Request not allowed for the token used' return # Sign with 'current_key_index', defaulting to key 0. signing_key = None req_key = None current_key_index = policy.get('current_key_index', 0) nkeys = len(self.server.keys) if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and current_key_index in range(nkeys)): signing_key = self.server.keys[current_key_index] if msg.public_key_version in range(1, nkeys + 1): # requested key exists, use for signing and rotate. req_key = self.server.keys[msg.public_key_version - 1]['private_key'] # Fill the policy data protobuf. policy_data = dm.PolicyData() policy_data.policy_type = msg.policy_type policy_data.timestamp = int(time.time() * 1000) policy_data.request_token = token_info['device_token'] policy_data.policy_value = payload policy_data.machine_name = token_info['machine_name'] policy_data.valid_serial_number_missing = (token_info['machine_id'] in BAD_MACHINE_IDS) policy_data.settings_entity_id = msg.settings_entity_id policy_data.service_account_identity = policy.get( 'service_account_identity', 'policy_testserver.py-service_account_identity') invalidation_source = policy.get('invalidation_source') if invalidation_source is not None: policy_data.invalidation_source = invalidation_source # Since invalidation_name is type bytes in the proto, the Unicode name # provided needs to be encoded as ASCII to set the correct byte pattern. invalidation_name = policy.get('invalidation_name') if invalidation_name is not None: policy_data.invalidation_name = invalidation_name.encode('ascii') if signing_key: policy_data.public_key_version = current_key_index + 1 if msg.policy_type == 'google/chromeos/publicaccount': policy_data.username = msg.settings_entity_id else: # For regular user/device policy, there is no way for the testserver to # know the user name belonging to the GAIA auth token we received (short # of actually talking to GAIA). To address this, we read the username from # the policy configuration dictionary, or use a default. policy_data.username = policy.get('policy_user', '*****@*****.**') policy_data.device_id = token_info['device_id'] signed_data = policy_data.SerializeToString() response.policy_data = signed_data if signing_key: response.policy_data_signature = ( signing_key['private_key'].hashAndSign(signed_data).tostring()) if msg.public_key_version != current_key_index + 1: response.new_public_key = signing_key['public_key'] if req_key: response.new_public_key_signature = (req_key.hashAndSign( response.new_public_key).tostring()) self.DumpMessage('Response', response) return (200, response.SerializeToString())
def ProcessCloudPolicy(self, msg): """Handles a cloud policy request. (New protocol for policy requests.) Checks for authorization, encodes the policy into protobuf representation, signs it and constructs the repsonse. Args: msg: The CloudPolicyRequest message received from the client. Returns: A tuple of HTTP status code and response data to send to the client. """ token_info, error = self.CheckToken() if not token_info: return error if msg.machine_id: self._server.UpdateMachineId(token_info['device_token'], msg.machine_id) # Response is only given if the scope is specified in the config file. # Normally 'google/chromeos/device' and 'google/chromeos/user' should be # accepted. policy = self._server.GetPolicies() policy_value = '' if (msg.policy_type in token_info['allowed_policy_types'] and msg.policy_type in policy): if msg.policy_type == 'google/chromeos/user': settings = cp.CloudPolicySettings() self.GatherUserPolicySettings(settings, policy[msg.policy_type]) policy_value = settings.SerializeToString() elif msg.policy_type == 'google/chromeos/device': settings = dp.ChromeDeviceSettingsProto() self.GatherDevicePolicySettings(settings, policy[msg.policy_type]) policy_value = settings.SerializeToString() # Figure out the key we want to use. If multiple keys are configured, the # server will rotate through them in a round-robin fashion. signing_key = None req_key = None key_version = 1 nkeys = len(self._server.keys) if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0: if msg.public_key_version in range(1, nkeys + 1): # requested key exists, use for signing and rotate. req_key = self._server.keys[msg.public_key_version - 1]['private_key'] key_version = (msg.public_key_version % nkeys) + 1 signing_key = self._server.keys[key_version - 1] # Fill the policy data protobuf. policy_data = dm.PolicyData() policy_data.policy_type = msg.policy_type policy_data.timestamp = int(time.time() * 1000) policy_data.request_token = token_info['device_token'] policy_data.policy_value = policy_value policy_data.machine_name = token_info['machine_name'] policy_data.valid_serial_number_missing = ( token_info['machine_id'] in BAD_MACHINE_IDS) if signing_key: policy_data.public_key_version = key_version policy_data.username = self._server.username policy_data.device_id = token_info['device_id'] signed_data = policy_data.SerializeToString() response = dm.DeviceManagementResponse() fetch_response = response.policy_response.response.add() fetch_response.policy_data = signed_data if signing_key: fetch_response.policy_data_signature = ( signing_key['private_key'].hashAndSign(signed_data).tostring()) if msg.public_key_version != key_version: fetch_response.new_public_key = signing_key['public_key'] if req_key: fetch_response.new_public_key_signature = ( req_key.hashAndSign(fetch_response.new_public_key).tostring()) self.DumpMessage('Response', response) return (200, response.SerializeToString())