330 lines
13 KiB
Python
330 lines
13 KiB
Python
import json
|
|
import logging
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.cros.enterprise import enterprise_policy_utils
|
|
from autotest_lib.client.cros.enterprise.policy_group import AllPolicies
|
|
|
|
|
|
CHROMEPOLICIES = 'chromePolicies'
|
|
DEVICELOCALACCOUNT = 'deviceLocalAccountPolicies'
|
|
EXTENSIONPOLICIES = 'extensionPolicies'
|
|
|
|
CHROMEOS_CLOUDDPC = {
|
|
'AudioCaptureAllowed': 'unmuteMicrophoneDisabled',
|
|
'DefaultGeolocationSetting': 'shareLocationDisabled',
|
|
'DeviceBlockDevmode': 'debuggingFeaturesDisabled',
|
|
'DisableScreenshots': 'screenCaptureDisabled',
|
|
'ExternalStorageDisabled': 'usbFileTransferDisabled',
|
|
'VideoCaptureAllowed': 'cameraDisabled',
|
|
}
|
|
|
|
|
|
class Policy_Manager(object):
|
|
|
|
def __init__(self, username=None, fake_dm_server=None):
|
|
"""
|
|
This class is to hanlde:
|
|
Setting policies to a Fake DM server
|
|
Obtaining policies from a DUT
|
|
Obtaining clouddpc policy settings.
|
|
Obtinaing both set/received policies in many different data formats
|
|
Verifying policies provided to the DUT are correct.
|
|
|
|
It has been designed so all the features are independent, meaning a
|
|
fake_dm_server is not required to obtain policies from the DUT, get
|
|
clouddpc values, etc.
|
|
|
|
@params username: username to be used when creating the fake DM policy.
|
|
@params fake_dm_server: The fake DM server object.
|
|
|
|
"""
|
|
self._configured = AllPolicies(True)
|
|
self._obtained = AllPolicies()
|
|
self.CHROME = 'chrome'
|
|
self.LOCAL = 'local'
|
|
self.EXT = 'ext'
|
|
self.username = username
|
|
self.fake_dm_server = fake_dm_server
|
|
self.autotest_ext = None
|
|
|
|
# If a fake_dm_sever is provided, enabled auto_update by default.
|
|
# Can be turned off if desired.
|
|
self._auto_updateDM = bool(fake_dm_server)
|
|
|
|
def configure_policies(self,
|
|
user={},
|
|
suggested_user={},
|
|
device={},
|
|
extension={},
|
|
new=True):
|
|
"""
|
|
Used to configure desired policies on the DUT. Will also save the
|
|
configured policies.
|
|
|
|
If a fake_dm_server was provided on class initialization, and
|
|
auto_updateDM is not False, this will also update the fake_dm_server.
|
|
|
|
@params user/suggested_user/device/extension: dict of the policies to
|
|
be set. extension must be provided with the extension id. e.g.
|
|
{'ExtensionID': {policy_dict}}
|
|
@param new: bool, if True clear all previously configured policies.
|
|
|
|
"""
|
|
if new:
|
|
self._configured = AllPolicies(True)
|
|
|
|
self._configured.set_policy('chrome', user, 'user')
|
|
self._configured.set_policy('chrome', suggested_user, 'suggested_user')
|
|
self._configured.set_policy('chrome', device, 'device')
|
|
|
|
self._configured.set_extension_policy(extension)
|
|
|
|
if self.auto_updateDM:
|
|
self.updateDMServer()
|
|
|
|
def configure_extension_visual_policy(self,
|
|
ext_policy={},
|
|
new=True):
|
|
"""
|
|
Extensions are... different. The policy set for them often is not the
|
|
actual policy, but a pointer to where the policy data is. This makes
|
|
verifying the extension policy tricky.
|
|
|
|
To help with, this function will allow you to set the 'real' policy.
|
|
Important things to note: This is only useful for verifying the policy,
|
|
and getting the policy as a dictionary (which has a flag for which
|
|
style of extension policies you want to see. The DM server will not be
|
|
set via this.
|
|
|
|
@param ext_policy: dict, Extension policy must be provided with the
|
|
extension id:
|
|
{'ExtensionID': {policy_dict}}.
|
|
@param new: bool, if True will erase any previously stored VISUAL
|
|
extension data.
|
|
|
|
"""
|
|
if new:
|
|
self._configured.ext_values = {}
|
|
|
|
self._configured.set_extension_policy(ext_policy, True)
|
|
|
|
def remove_policy(self,
|
|
policy_name,
|
|
policy_type,
|
|
extID=None):
|
|
"""
|
|
Removes the policy from the configured policies. Useful when you want
|
|
clear a specific policy, but leave the other policies untouched.
|
|
If auto_updateDM is True (thus a fake_dm_server has been provided), the
|
|
dm server will be updated.
|
|
|
|
@param policy_name: The policy name
|
|
@param policy_type: The type of policy it is. Valid types:
|
|
"user", "device", "extension", "suggested_user".
|
|
@param extID: The extension ID, if removing an extension policy.
|
|
|
|
"""
|
|
if policy_type != 'extension':
|
|
self._removeChromePolicy(policy_name)
|
|
else:
|
|
self._removeExtensionPolicy(policy_name, extID)
|
|
|
|
if self.auto_updateDM:
|
|
self.updateDMServer()
|
|
|
|
def _removeChromePolicy(self, policy_name):
|
|
"""
|
|
Attempts to remove the specified extension policy from specified
|
|
extension.
|
|
|
|
@rasies error.TestError: If the policy is not in the configured
|
|
policies.
|
|
|
|
"""
|
|
try:
|
|
del self._configured.chrome[policy_name]
|
|
except KeyError:
|
|
raise error.TestError('Policy {} missing from chrome policies.'
|
|
.format(policy_name))
|
|
|
|
def _removeExtensionPolicy(self, policy_name, extID):
|
|
"""
|
|
Attempts to remove the specified extension policy from specified
|
|
extension.
|
|
|
|
@raises error.TestError: if the policy_type is an 'extension', but the
|
|
extID is not provided, or the policy is not found in the extension.
|
|
|
|
"""
|
|
if not extID:
|
|
raise error.TestError(
|
|
'Cannot delete extension policy without extension ID')
|
|
try:
|
|
del self._configured.extension_configured_data[extID][policy_name]
|
|
except KeyError:
|
|
raise error.TestError(
|
|
'Policy {} missing from extension policies.'
|
|
.format(policy_name))
|
|
|
|
def obtain_policies_from_device(self, autotest_ext=None):
|
|
"""
|
|
Calls the autotest private getAllEnterprisePolicies() API, and saves
|
|
the response.
|
|
|
|
@param autotest_ext: The autotest browser extension.
|
|
|
|
"""
|
|
if autotest_ext:
|
|
self.autotest_ext = autotest_ext
|
|
if not self.autotest_ext:
|
|
raise error.TestError('Cannot obtain policies without autotest_ext')
|
|
self.raw_data = enterprise_policy_utils.get_all_policies(
|
|
self.autotest_ext)
|
|
self._obtained.set_policy(self.CHROME, self.raw_data[CHROMEPOLICIES])
|
|
self._obtained.set_policy(self.LOCAL, self.raw_data[DEVICELOCALACCOUNT])
|
|
self._obtained.set_extension_policy(self.raw_data[EXTENSIONPOLICIES])
|
|
|
|
def verify_policy(self, policyName, policy_value, extID=None):
|
|
"""Verifies the configured policies are == to the policies obtained."""
|
|
recieved_value = self.get_policy_value_from_DUT(policyName=policyName,
|
|
extID=extID,
|
|
refresh=True)
|
|
if not recieved_value == policy_value:
|
|
raise error.TestError(
|
|
'Policy {} value was not set correctly. \nExpected:\t {}'
|
|
'\nReceived: \t'.format(policyName,
|
|
policy_value,
|
|
recieved_value))
|
|
logging.info('Policy verification successful')
|
|
|
|
def verify_policies(self):
|
|
"""Verifies the configured policies are == to the policies obtained."""
|
|
if not self._configured == self._obtained:
|
|
raise error.TestError(
|
|
'Configured policies did not match policies received from DUT.')
|
|
logging.info('Policy verification successful')
|
|
|
|
def get_policy_value_from_DUT(self, policyName, extID=None, refresh=False):
|
|
"""
|
|
Get the value of a specified policy from the DUT. If the policy is from
|
|
an extension, an extension ID (extID) must be provided.
|
|
|
|
@param policyName: str, the name of the policy.
|
|
@param extID: The ID of the extension.
|
|
@param refresh: bool, if you want to get the policies from the DUT again
|
|
Note: This does NOT force the DUT to re-obtain the policies from the
|
|
DM server.
|
|
|
|
@returns: The value of the policy if found, else None.
|
|
"""
|
|
if refresh:
|
|
# Uses the previously provided autotest Extension.
|
|
self.obtain_policies_from_device()
|
|
|
|
if extID:
|
|
if policyName in self._obtained.extension_configured_data[extID]:
|
|
return (
|
|
self._obtained.extension_configured_data[extID][policyName]
|
|
.value)
|
|
elif policyName in self._obtained.chrome:
|
|
return self._obtained.chrome[policyName].value
|
|
return None
|
|
|
|
def updateDMServer(self):
|
|
"""Updates the Fake DM server with the current configured policy."""
|
|
fake_dm_json = self.getDMConfig()
|
|
logging.info('Policy blob {}'.format(fake_dm_json))
|
|
if not self.fake_dm_server:
|
|
raise error.TestError(
|
|
'Cannot update DM server. DM server not provided')
|
|
self.fake_dm_server.setup_policy(fake_dm_json)
|
|
|
|
def getDMConfig(self, refresh=True):
|
|
""""
|
|
Creates the DM configuration (aka Json blob) to be used by the
|
|
fake DM server
|
|
|
|
@param refresh: bool, if True, will clear any previous configuration.
|
|
If False, return the currently configured DM blob.
|
|
|
|
"""
|
|
if refresh:
|
|
self._configured.createNewFakeDMServerJson()
|
|
self._configured.updateDMJson()
|
|
self._configured._DMJSON['policy_user'] = self.username
|
|
return json.dumps(self._configured._DMJSON)
|
|
|
|
def getCloudDpc(self):
|
|
"""Gets the Cloud DPC ARC policy settings."""
|
|
expected_cloud_dpc_settings = {}
|
|
if self._arc_certs():
|
|
self._add_arc_certs(expected_cloud_dpc_settings)
|
|
self._add_shared_policies(expected_cloud_dpc_settings)
|
|
self._add_shared_arc_policy(expected_cloud_dpc_settings)
|
|
|
|
return expected_cloud_dpc_settings
|
|
|
|
def _arc_certs(self):
|
|
"""
|
|
Returns True if ArcCertificatesSyncMode is set in the configured
|
|
policies and the bool(value) is True, else False.
|
|
|
|
"""
|
|
if ('ArcCertificatesSyncMode' in self._configured.chrome and
|
|
self._configured.chrome['ArcCertificatesSyncMode'].value):
|
|
return True
|
|
return False
|
|
|
|
def _add_shared_arc_policy(self, dpc):
|
|
"""Adds the shared policies that are subset within the 'ArcPolicy'."""
|
|
Arc_Policy = self._configured.chrome.get('ArcPolicy', {})
|
|
if Arc_Policy:
|
|
Arc_Policy = Arc_Policy.value
|
|
|
|
for key in ['applications', 'accountTypesWithManagementDisabled']:
|
|
if key in Arc_Policy:
|
|
dpc[key] = Arc_Policy[key]
|
|
|
|
def _add_shared_policies(self, dpc):
|
|
"""
|
|
Add all of the configured policies that are shared with arc clouddpc,
|
|
to the "dpc" dict, with the clouddpc key. If the policy is not set, it
|
|
will not be added.
|
|
|
|
"""
|
|
for policy_name, dpc_name in CHROMEOS_CLOUDDPC.items():
|
|
if policy_name in self._configured.chrome:
|
|
dpc[dpc_name] = self._configured.chrome[policy_name].value
|
|
|
|
def _add_arc_certs(self, dpc):
|
|
open_network_config = 'OpenNetworkConfiguration'
|
|
if open_network_config in self._configured.chrome:
|
|
dpc['caCerts'] = self._configured.chrome[open_network_config].value
|
|
else:
|
|
dpc['caCerts'] = None
|
|
|
|
def get_configured_policies_as_dict(self, visual=False):
|
|
""" Returns the configured policies as a dict."""
|
|
return self._configured.get_policy_as_dict(visual)
|
|
|
|
def get_obtained_policies_as_dict(self):
|
|
""" Returns the obtained policies as a dict."""
|
|
return self._obtained.get_policy_as_dict(visual=True)
|
|
|
|
@property
|
|
def auto_updateDM(self):
|
|
""" Returns the current state of the auto_updateDM setting."""
|
|
return self._auto_updateDM
|
|
|
|
@auto_updateDM.setter
|
|
def auto_updateDM(self, value):
|
|
"""Turns on/off auto updating of the DM server."""
|
|
if not isinstance(value, bool):
|
|
raise error.TestError('Auto Update DM must be bool, got {}'
|
|
.format(value))
|
|
if value and not self.fake_dm_server:
|
|
raise error.TestError(
|
|
'Cannot autoupdate without the Fake DM server configured.')
|
|
self._auto_updateDM = value
|