1# Copyright 2019 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import pickle 6import re 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.cros.enterprise import enterprise_policy_base 10from autotest_lib.client.cros.enterprise import enterprise_network_api 11 12 13class policy_GlobalNetworkSettings( 14 enterprise_policy_base.EnterprisePolicyTest): 15 version = 1 16 17 18 def cleanup(self): 19 """Re-enable ethernet after the test is completed.""" 20 if hasattr(self, 'net_api'): 21 self.net_api.chrome_net_context.enable_network_device('Ethernet') 22 super(policy_GlobalNetworkSettings, self).cleanup() 23 24 25 def _test_only_connect_if_available(self, policy_error, user_error): 26 """ 27 Verify the AllowOnlyPolicyNetworksToConnectIfAvailable policy. 28 29 If both networks are available, only the policy network should 30 connect. If the policy network is unavailable, then the user network 31 may connect. Ensure the errors are caused by the policy blocking or 32 allowing the correct connections. 33 34 @param policy_error: Error (if any) raised from connecting to policy 35 network. 36 @param user_error: Error (if any) raised from connecting to user 37 network. 38 39 @raises error.TestFail: If errors do not match policy behavior. 40 41 """ 42 OUT_OF_RANGE_ERROR = 'The SSID: .* is not in WiFi range of the DUT' 43 BLOCKED_ERROR = ('Could not connect to .* network. ' 44 'Error returned by chrome.networkingPrivate.' 45 'startConnect API: blocked-by-policy') 46 47 if policy_error and user_error: 48 raise error.TestFail( 49 'Unable to connect to user or policy network: %s' 50 % policy_error) 51 elif not policy_error and user_error: 52 if not re.match(BLOCKED_ERROR, str(user_error)): 53 raise error.TestFail('Network API received unrecognized ' 54 'error connecting to the user ' 55 'network: %s' % user_error) 56 elif policy_error and not user_error: 57 if not re.match(OUT_OF_RANGE_ERROR, str(policy_error)): 58 raise error.TestFail('Network API received unrecognized ' 59 'error connecting to the policy ' 60 'network: %s' % policy_error) 61 elif not (policy_error or user_error): 62 raise error.TestFail('User network connected despite policy ' 63 'network being available') 64 65 66 def _test_wifi_disabled_policy(self, policy_error, user_error): 67 """ 68 Verify the DisableNetworkTypes policy on WiFi. 69 70 Both networks should show the 'No wifi networks found' error. 71 72 @param policy_error: Error (if any) raised from connecting to policy 73 network. 74 @param user_error: Error (if any) raised from connecting to user 75 network. 76 77 @raises error.TestFail: If errors do not match policy behavior. 78 79 """ 80 for err in [policy_error, user_error]: 81 if err is None: 82 raise error.TestFail('DUT was able to connect to WiFi, but ' 83 'WiFi should be blocked.') 84 elif str(err) != 'No wifi networks found.': 85 raise error.TestFail('Network API received unrecognized ' 86 'error connecting to network: %s' 87 % err) 88 89 90 def _test_autoconnect_policy(self, ssid, policy_network, user_network): 91 """ 92 Verify the AllowOnlyPolicyNetworksToAutoconnect policy. 93 94 Disconnect from the network. The policy network should reconnect, 95 and the user network should not. 96 97 @param ssid: SSID of connected network. 98 @param policy_network: Network policy defined network. 99 @param user_network: User defined network. 100 101 @raises error.TestFail: If errors do not match policy behavior. 102 103 """ 104 self.net_api.disconnect_from_network(ssid) 105 106 if self.net_api.is_network_connected(ssid): 107 if ssid == user_network.ssid: 108 raise error.TestFail( 109 'User network autoconnected despite ' 110 'AllowOnlyPolicyNetworksToAutoconnect=True') 111 elif ssid == policy_network.ssid: 112 raise error.TestFail( 113 'Policy network did not autoconnect, despite ' 114 'AllowOnlyPolicyNetworksToAutoconnect=True') 115 116 117 def _test_allow_only_policy(self, policy_error, user_error): 118 """ 119 Verify the AllowOnlyPolicyNetworksToConnect policy. 120 121 policy_error should be None, user_error should not. 122 123 @param policy_error: Error (if any) raised from connecting to policy 124 network. 125 @param user_error: Error (if any) raised from connecting to user 126 network. 127 128 @raises error.TestFail: If errors do not match policy behavior. 129 130 """ 131 if policy_error: 132 raise error.TestFail('DUT should have connected to policy ' 133 'network, but did not: %s' % policy_error) 134 if not user_error: 135 raise error.TestFail('DUT was able to connect to user ' 136 'network, but should have been blocked.') 137 138 139 def test_global_settings(self, gnc_settings, policy_network, user_network): 140 """ 141 Attempt to connect to the policy network, then the user_network. 142 143 Ensure connection behavior matches GlobalNetworkConfiguration. 144 145 @param gnc_settings: GlobalNetworkConfiguration dictionary value. 146 @param policy_network_pickle: NetworkConfig object representing 147 the policy network configuration. 148 @param user_network_pickle: NetworkConfig object representing 149 user network configuration. 150 151 @raise error.TestFail: DUT behavior does not match policy settings. 152 153 """ 154 # Store connection errors to check later. 155 network_errors = {} 156 for ssid in [policy_network.ssid, user_network.ssid]: 157 network_errors[ssid] = None 158 try: 159 self.net_api.connect_to_network(ssid) 160 except error.TestFail as e: 161 network_errors[ssid] = e 162 continue 163 164 if gnc_settings.get('AllowOnlyPolicyNetworksToAutoconnect'): 165 self._test_autoconnect_policy(ssid, 166 policy_network, 167 user_network) 168 continue 169 170 if not self.net_api.is_network_connected(ssid): 171 raise error.TestFail( 172 'Did not connect to network (%s)' % ssid) 173 174 policy_error = network_errors[policy_network.ssid] 175 user_error = network_errors[user_network.ssid] 176 177 if gnc_settings.get('AllowOnlyPolicyNetworksToConnectIfAvailable'): 178 self._test_only_connect_if_available(policy_error, user_error) 179 180 elif 'WiFi' in gnc_settings.get('DisableNetworkTypes', {}): 181 self._test_wifi_disabled_policy(policy_error, user_error) 182 183 elif gnc_settings.get('AllowOnlyPolicyNetworksToConnect'): 184 self._test_allow_only_policy(policy_error, user_error) 185 186 187 def run_once(self, gnc_settings=None, policy_network_pickle=None, 188 user_network_pickle=None): 189 """ 190 Setup and run the test configured for the specified test case. 191 192 policy_network is in the network policy, and user_network is not. 193 The GlobalNetworkConfiguration settings modify how the DUT is able to 194 connect to both of these networks. 195 196 @param gnc_settings: GlobalNetworkConfiguration dictionary value. 197 @param policy_network_pickle: Pickled NetworkConfig object to set as 198 the policy network configuration. 199 @param user_network_pickle: Pickled NetworkConfig object to set as the 200 user network configuration. 201 202 @raises error.TestFail: If DUT's actions do not match policy settings. 203 204 """ 205 if policy_network_pickle is None or user_network_pickle is None: 206 raise error.TestError('Networks cannot be None') 207 208 policy_network = pickle.loads(policy_network_pickle) 209 user_network = pickle.loads(user_network_pickle) 210 211 self.setup_case( 212 user_policies={'OpenNetworkConfiguration': policy_network.policy()}, 213 device_policies={'DeviceOpenNetworkConfiguration': { 214 'GlobalNetworkConfiguration': gnc_settings}}, 215 extension_paths=[ 216 enterprise_network_api.NETWORK_TEST_EXTENSION_PATH 217 ], 218 enroll=True 219 ) 220 221 self.net_api = enterprise_network_api.\ 222 ChromeEnterpriseNetworkContext(self.cr) 223 # Disable ethernet so device will default to WiFi 224 self.net_api.disable_network_device('Ethernet') 225 226 self.test_global_settings(gnc_settings, policy_network, user_network) 227