1*9c5db199SXin Li# Copyright 2019 The Chromium OS Authors. All rights reserved. 2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 3*9c5db199SXin Li# found in the LICENSE file. 4*9c5db199SXin Li 5*9c5db199SXin Liimport logging 6*9c5db199SXin Li 7*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 8*9c5db199SXin Li 9*9c5db199SXin Li 10*9c5db199SXin Liclass Policy(object): 11*9c5db199SXin Li """ 12*9c5db199SXin Li Class structure for a single policy object. 13*9c5db199SXin Li 14*9c5db199SXin Li A policy has the following attributes: 15*9c5db199SXin Li value 16*9c5db199SXin Li source 17*9c5db199SXin Li level 18*9c5db199SXin Li scope 19*9c5db199SXin Li name 20*9c5db199SXin Li 21*9c5db199SXin Li All of the attributes are protected in @setter's. To set a value simply 22*9c5db199SXin Li create a policy object (e.g. "somePolicy = Policy()") and set the desired 23*9c5db199SXin Li value (somePolicy.value=True). 24*9c5db199SXin Li 25*9c5db199SXin Li This class will be used by the policy_manager for configuring and checking 26*9c5db199SXin Li policies for Enterprise tests. 27*9c5db199SXin Li 28*9c5db199SXin Li """ 29*9c5db199SXin Li 30*9c5db199SXin Li def __init__(self): 31*9c5db199SXin Li self._value = None 32*9c5db199SXin Li self._source = None 33*9c5db199SXin Li self._scope = None 34*9c5db199SXin Li self._level = None 35*9c5db199SXin Li self._name = None 36*9c5db199SXin Li 37*9c5db199SXin Li def is_formatted_value(self, data): 38*9c5db199SXin Li """ 39*9c5db199SXin Li Checks if the received value is a a dict containing all policy stats. 40*9c5db199SXin Li 41*9c5db199SXin Li """ 42*9c5db199SXin Li if not isinstance(data, dict): 43*9c5db199SXin Li return False 44*9c5db199SXin Li received_keys = set(['scope', 'source', 'level', 'value']) 45*9c5db199SXin Li return received_keys.issubset(set(data.keys())) 46*9c5db199SXin Li 47*9c5db199SXin Li def get_policy_as_dict(self): 48*9c5db199SXin Li """ 49*9c5db199SXin Li Returns the policy as a dict, in the same format as in the 50*9c5db199SXin Li chrome://policy json file. 51*9c5db199SXin Li 52*9c5db199SXin Li """ 53*9c5db199SXin Li return {self.name: {'scope': self._scope, 54*9c5db199SXin Li 'source': self._source, 55*9c5db199SXin Li 'level': self._level, 56*9c5db199SXin Li 'value': self._value}} 57*9c5db199SXin Li 58*9c5db199SXin Li def set_policy_from_dict(self, data): 59*9c5db199SXin Li """ 60*9c5db199SXin Li Sets the policy attributes from a provided dict matching the following 61*9c5db199SXin Li format: 62*9c5db199SXin Li 63*9c5db199SXin Li {"scope": scopeValue, "source": sourceValue, "level": levelValue, 64*9c5db199SXin Li "value": value} 65*9c5db199SXin Li 66*9c5db199SXin Li @param data: a dict representing the policy values, as specified above. 67*9c5db199SXin Li 68*9c5db199SXin Li """ 69*9c5db199SXin Li if not self.is_formatted_value(data): 70*9c5db199SXin Li raise error.TestError("""Incorrect input data provided. Value 71*9c5db199SXin Li provided must be dict with the keys: "scope", "source", 72*9c5db199SXin Li "level", "value". Got {}""".format(data)) 73*9c5db199SXin Li self.scope = data['scope'] 74*9c5db199SXin Li self.source = data['source'] 75*9c5db199SXin Li self.level = data['level'] 76*9c5db199SXin Li self.value = data['value'] 77*9c5db199SXin Li if data.get('error', None): 78*9c5db199SXin Li logging.warning('\n[Policy Error] error reported with policy:\n{}' 79*9c5db199SXin Li .format(data['error'])) 80*9c5db199SXin Li 81*9c5db199SXin Li @property 82*9c5db199SXin Li def value(self): 83*9c5db199SXin Li return self._value 84*9c5db199SXin Li 85*9c5db199SXin Li @value.setter 86*9c5db199SXin Li def value(self, value): 87*9c5db199SXin Li self._value = value 88*9c5db199SXin Li 89*9c5db199SXin Li @property 90*9c5db199SXin Li def name(self): 91*9c5db199SXin Li return self._name 92*9c5db199SXin Li 93*9c5db199SXin Li @name.setter 94*9c5db199SXin Li def name(self, name): 95*9c5db199SXin Li self._name = name 96*9c5db199SXin Li 97*9c5db199SXin Li @property 98*9c5db199SXin Li def level(self): 99*9c5db199SXin Li return self._level 100*9c5db199SXin Li 101*9c5db199SXin Li @level.setter 102*9c5db199SXin Li def level(self, level): 103*9c5db199SXin Li self._level = level 104*9c5db199SXin Li 105*9c5db199SXin Li @property 106*9c5db199SXin Li def scope(self): 107*9c5db199SXin Li return self._scope 108*9c5db199SXin Li 109*9c5db199SXin Li @scope.setter 110*9c5db199SXin Li def scope(self, scope): 111*9c5db199SXin Li self._scope = scope 112*9c5db199SXin Li 113*9c5db199SXin Li @property 114*9c5db199SXin Li def source(self): 115*9c5db199SXin Li return self._source 116*9c5db199SXin Li 117*9c5db199SXin Li @source.setter 118*9c5db199SXin Li def source(self, source): 119*9c5db199SXin Li self._source = source 120*9c5db199SXin Li 121*9c5db199SXin Li @property 122*9c5db199SXin Li def group(self): 123*9c5db199SXin Li return None 124*9c5db199SXin Li 125*9c5db199SXin Li @group.setter 126*9c5db199SXin Li def group(self, group): 127*9c5db199SXin Li """ 128*9c5db199SXin Li If setting a policy, you can also set it from a group ("user", 129*9c5db199SXin Li "suggested_user", "device"). Doing this will automatically set the other 130*9c5db199SXin Li policy attributes. 131*9c5db199SXin Li 132*9c5db199SXin Li If the group is None, nothing will be set. 133*9c5db199SXin Li 134*9c5db199SXin Li @param group: None or value of the policy group. 135*9c5db199SXin Li 136*9c5db199SXin Li """ 137*9c5db199SXin Li if not group: 138*9c5db199SXin Li return 139*9c5db199SXin Li self._source = 'cloud' 140*9c5db199SXin Li if group != 'suggested_user': 141*9c5db199SXin Li self._level = 'mandatory' 142*9c5db199SXin Li else: 143*9c5db199SXin Li self._level = 'recommended' 144*9c5db199SXin Li if group == 'device': 145*9c5db199SXin Li self._scope = 'machine' 146*9c5db199SXin Li else: 147*9c5db199SXin Li self._scope = 'user' 148*9c5db199SXin Li 149*9c5db199SXin Li def __ne__(self, other): 150*9c5db199SXin Li return not self.__eq__(other) 151*9c5db199SXin Li 152*9c5db199SXin Li def __eq__(self, other): 153*9c5db199SXin Li """ 154*9c5db199SXin Li Override of the "==" statment. Verify one policy object verse another. 155*9c5db199SXin Li 156*9c5db199SXin Li Will return True if the policy value, source, scope, and level are 157*9c5db199SXin Li equal, otherwise False. 158*9c5db199SXin Li 159*9c5db199SXin Li There is a special check for the Network Policy, due to a displayed 160*9c5db199SXin Li policy having visual obfuscation (********). 161*9c5db199SXin Li 162*9c5db199SXin Li """ 163*9c5db199SXin Li if self.value != other.value: 164*9c5db199SXin Li if is_network_policy(other.name): 165*9c5db199SXin Li return check_obfuscation(other.value) 166*9c5db199SXin Li else: 167*9c5db199SXin Li logging.info('value configured {} != received {}' 168*9c5db199SXin Li .format(self.value, other.value)) 169*9c5db199SXin Li return False 170*9c5db199SXin Li if self.source != other.source: 171*9c5db199SXin Li logging.info('source configured {} != received {}' 172*9c5db199SXin Li .format(self.source, other.source)) 173*9c5db199SXin Li return False 174*9c5db199SXin Li if self.scope != other.scope: 175*9c5db199SXin Li logging.info('scope configured {} != received {}' 176*9c5db199SXin Li .format(self.scope, other.scope)) 177*9c5db199SXin Li return False 178*9c5db199SXin Li if self.level != other.level: 179*9c5db199SXin Li logging.info('level configured {} != received {}' 180*9c5db199SXin Li .format(self.level, other.level)) 181*9c5db199SXin Li return False 182*9c5db199SXin Li return True 183*9c5db199SXin Li 184*9c5db199SXin Li def __repr__(self): 185*9c5db199SXin Li policy_data = self.get_policy_as_dict() 186*9c5db199SXin Li return "<POLICY DATA OBJECT> | {}".format(policy_data) 187*9c5db199SXin Li 188*9c5db199SXin Li 189*9c5db199SXin Lidef is_network_policy(policy_name): 190*9c5db199SXin Li """ 191*9c5db199SXin Li Returns true if the policy name is that of an OpenNetworkConfiguration. 192*9c5db199SXin Li 193*9c5db199SXin Li """ 194*9c5db199SXin Li if policy_name.endswith('OpenNetworkConfiguration'): 195*9c5db199SXin Li return True 196*9c5db199SXin Li 197*9c5db199SXin Li 198*9c5db199SXin Lidef check_obfuscation(other_value): 199*9c5db199SXin Li """Checks if value is a network policy, and is obfuscated.""" 200*9c5db199SXin Li DISPLAY_PWORD = '*' * 8 201*9c5db199SXin Li 202*9c5db199SXin Li for network in other_value.get('NetworkConfigurations', []): 203*9c5db199SXin Li wifi = network.get('WiFi', {}) 204*9c5db199SXin Li if 'Passphrase' in wifi and wifi['Passphrase'] != DISPLAY_PWORD: 205*9c5db199SXin Li return False 206*9c5db199SXin Li if ('EAP' in wifi and 207*9c5db199SXin Li 'Password' in wifi['EAP'] and 208*9c5db199SXin Li wifi['EAP']['Password'] != DISPLAY_PWORD): 209*9c5db199SXin Li return False 210*9c5db199SXin Li for cert in other_value.get('Certificates', []): 211*9c5db199SXin Li if 'PKCS12' in cert: 212*9c5db199SXin Li if cert['PKCS12'] != DISPLAY_PWORD: 213*9c5db199SXin Li return False 214*9c5db199SXin Li return True 215