class ProviderBootstrapperActiveTest(unittest.TestCase): @classmethod def setUpClass(cls): factory = fake_provider.get_provider_factory() http = reactor.listenTCP(8002, factory) https = reactor.listenSSL( 0, factory, fake_provider.OpenSSLServerContextFactory()) get_port = lambda p: p.getHost().port cls.http_port = get_port(http) cls.https_port = get_port(https) def setUp(self): self.pb = ProviderBootstrapper() # At certain points we are going to be replacing these methods # directly in ProviderConfig to be able to catch calls from # new ProviderConfig objects inside the methods tested. We # need to save the old implementation and restore it in # tearDown so we are sure everything is as expected for each # test. If we do it inside each specific test, a failure in # the test will leave the implementation with the mock. self.old_gpp = util.get_path_prefix self.old_load = ProviderConfig.load self.old_save = ProviderConfig.save self.old_api_version = ProviderConfig.get_api_version self.old_api_uri = ProviderConfig.get_api_uri def tearDown(self): util.get_path_prefix = self.old_gpp ProviderConfig.load = self.old_load ProviderConfig.save = self.old_save ProviderConfig.get_api_version = self.old_api_version ProviderConfig.get_api_uri = self.old_api_uri def test_check_https_succeeds(self): # XXX: Need a proper CA signed cert to test this pass @deferred() def test_check_https_fails(self): self.pb._domain = "localhost:%s" % (self.https_port,) def check(*args): with self.assertRaises(requests.exceptions.SSLError): self.pb._check_https() return threads.deferToThread(check) @deferred() def test_second_check_https_fails(self): self.pb._domain = "localhost:1234" def check(*args): with self.assertRaises(Exception): self.pb._check_https() return threads.deferToThread(check) @deferred() def test_check_https_succeeds_if_danger(self): self.pb._domain = "localhost:%s" % (self.https_port,) self.pb._bypass_checks = True def check(*args): self.pb._check_https() return threads.deferToThread(check) def _setup_provider_config_with(self, api, path_prefix): """ Sets up the ProviderConfig with mocks for the path prefix, the api returned and load/save methods. It modifies ProviderConfig directly instead of an object because the object used is created in the method itself and we cannot control that. :param api: API to return :type api: str :param path_prefix: path prefix to be used when calculating paths :type path_prefix: str """ util.get_path_prefix = mock.MagicMock(return_value=path_prefix) ProviderConfig.get_api_version = mock.MagicMock( return_value=api) ProviderConfig.get_api_uri = mock.MagicMock( return_value="https://localhost:%s" % (self.https_port,)) ProviderConfig.load = mock.MagicMock() ProviderConfig.save = mock.MagicMock() def _setup_providerbootstrapper(self, ifneeded): """ Sets the provider bootstrapper's domain to localhost:https_port, sets it to bypass https checks and sets the download if needed based on the ifneeded value. :param ifneeded: Value for _download_if_needed :type ifneeded: bool """ self.pb._domain = "localhost:%s" % (self.https_port,) self.pb._bypass_checks = True self.pb._download_if_needed = ifneeded def _produce_dummy_provider_json(self): """ Creates a dummy provider json on disk in order to test behaviour around it (download if newer online, etc) :returns: the provider.json path used :rtype: str """ provider_dir = os.path.join(util.get_path_prefix(), "leap", "providers", self.pb._domain) mkdir_p(provider_dir) provider_path = os.path.join(provider_dir, "provider.json") with open(provider_path, "w") as p: p.write("A") return provider_path @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_domain', lambda x: where('testdomain.com')) def test_download_provider_info_new_provider(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) self.pb._download_provider_info() self.assertTrue(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_not_modified(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) provider_path = self._produce_dummy_provider_json() # set mtime to something really new os.utime(provider_path, (-1, time.time())) self.pb._download_provider_info() # we check that it doesn't save the provider # config, because it's new enough self.assertFalse(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_domain', lambda x: where('testdomain.com')) def test_download_provider_info_not_modified_and_no_cacert(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) provider_path = self._produce_dummy_provider_json() # set mtime to something really new os.utime(provider_path, (-1, time.time())) self.pb._download_provider_info() # we check that it doesn't save the provider # config, because it's new enough self.assertFalse(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_modified(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) provider_path = self._produce_dummy_provider_json() # set mtime to something really old os.utime(provider_path, (-1, 100)) self.pb._download_provider_info() self.assertTrue(ProviderConfig.load.called) self.assertTrue(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_unsupported_api_raises(self): self._setup_provider_config_with("9999999", tempfile.mkdtemp()) self._setup_providerbootstrapper(False) self._produce_dummy_provider_json() with self.assertRaises(UnsupportedProviderAPI): self.pb._download_provider_info() @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_unsupported_api(self): self._setup_provider_config_with(provider.SUPPORTED_APIS[0], tempfile.mkdtemp()) self._setup_providerbootstrapper(False) self._produce_dummy_provider_json() self.pb._download_provider_info() @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_api_uri', lambda x: 'api.uri') @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: '/cert/path') def test_check_api_certificate_skips(self): self.pb._provider_config = ProviderConfig() self.pb._session.get = mock.MagicMock(return_value=Response()) self.pb._should_proceed_cert = mock.MagicMock(return_value=False) self.pb._check_api_certificate() self.assertFalse(self.pb._session.get.called) @deferred() def test_check_api_certificate_fails(self): self.pb._provider_config = ProviderConfig() self.pb._provider_config.get_api_uri = mock.MagicMock( return_value="https://localhost:%s" % (self.https_port,)) self.pb._provider_config.get_ca_cert_path = mock.MagicMock( return_value=os.path.join( os.path.split(__file__)[0], "wrongcert.pem")) self.pb._provider_config.get_api_version = mock.MagicMock( return_value="1") self.pb._should_proceed_cert = mock.MagicMock(return_value=True) def check(*args): with self.assertRaises(requests.exceptions.SSLError): self.pb._check_api_certificate() d = threads.deferToThread(check) return d @deferred() def test_check_api_certificate_succeeds(self): self.pb._provider_config = ProviderConfig() self.pb._provider_config.get_api_uri = mock.MagicMock( return_value="https://localhost:%s" % (self.https_port,)) self.pb._provider_config.get_ca_cert_path = mock.MagicMock( return_value=where('cacert.pem')) self.pb._provider_config.get_api_version = mock.MagicMock( return_value="1") self.pb._should_proceed_cert = mock.MagicMock(return_value=True) def check(*args): self.pb._check_api_certificate() d = threads.deferToThread(check) return d
class ProviderBootstrapperActiveTest(unittest.TestCase): @classmethod def setUpClass(cls): factory = fake_provider.get_provider_factory() http = reactor.listenTCP(8002, factory) https = reactor.listenSSL(0, factory, fake_provider.OpenSSLServerContextFactory()) get_port = lambda p: p.getHost().port cls.http_port = get_port(http) cls.https_port = get_port(https) def setUp(self): self.pb = ProviderBootstrapper() # At certain points we are going to be replacing these methods # directly in ProviderConfig to be able to catch calls from # new ProviderConfig objects inside the methods tested. We # need to save the old implementation and restore it in # tearDown so we are sure everything is as expected for each # test. If we do it inside each specific test, a failure in # the test will leave the implementation with the mock. self.old_gpp = util.get_path_prefix self.old_load = ProviderConfig.load self.old_save = ProviderConfig.save self.old_api_version = ProviderConfig.get_api_version self.old_api_uri = ProviderConfig.get_api_uri def tearDown(self): util.get_path_prefix = self.old_gpp ProviderConfig.load = self.old_load ProviderConfig.save = self.old_save ProviderConfig.get_api_version = self.old_api_version ProviderConfig.get_api_uri = self.old_api_uri def test_check_https_succeeds(self): # XXX: Need a proper CA signed cert to test this pass @deferred() def test_check_https_fails(self): self.pb._domain = "localhost:%s" % (self.https_port, ) def check(*args): with self.assertRaises(requests.exceptions.SSLError): self.pb._check_https() return threads.deferToThread(check) @deferred() def test_second_check_https_fails(self): self.pb._domain = "localhost:1234" def check(*args): with self.assertRaises(Exception): self.pb._check_https() return threads.deferToThread(check) @deferred() def test_check_https_succeeds_if_danger(self): self.pb._domain = "localhost:%s" % (self.https_port, ) self.pb._bypass_checks = True def check(*args): self.pb._check_https() return threads.deferToThread(check) def _setup_provider_config_with(self, api, path_prefix): """ Sets up the ProviderConfig with mocks for the path prefix, the api returned and load/save methods. It modifies ProviderConfig directly instead of an object because the object used is created in the method itself and we cannot control that. :param api: API to return :type api: str :param path_prefix: path prefix to be used when calculating paths :type path_prefix: str """ util.get_path_prefix = mock.MagicMock(return_value=path_prefix) ProviderConfig.get_api_version = mock.MagicMock(return_value=api) ProviderConfig.get_api_uri = mock.MagicMock( return_value="https://*****:*****@mock.patch('leap.bitmask.config.providerconfig.ProviderConfig.get_domain', lambda x: where('testdomain.com')) def test_download_provider_info_new_provider(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) self.pb._download_provider_info() self.assertTrue(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_not_modified(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) provider_path = self._produce_dummy_provider_json() # set mtime to something really new os.utime(provider_path, (-1, time.time())) self.pb._download_provider_info() # we check that it doesn't save the provider # config, because it's new enough self.assertFalse(ProviderConfig.save.called) @mock.patch('leap.bitmask.config.providerconfig.ProviderConfig.get_domain', lambda x: where('testdomain.com')) def test_download_provider_info_not_modified_and_no_cacert(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) provider_path = self._produce_dummy_provider_json() # set mtime to something really new os.utime(provider_path, (-1, time.time())) self.pb._download_provider_info() # we check that it doesn't save the provider # config, because it's new enough self.assertFalse(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_modified(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) provider_path = self._produce_dummy_provider_json() # set mtime to something really old os.utime(provider_path, (-1, 100)) self.pb._download_provider_info() self.assertTrue(ProviderConfig.load.called) self.assertTrue(ProviderConfig.save.called) @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_unsupported_api_raises(self): self._setup_provider_config_with("9999999", tempfile.mkdtemp()) self._setup_providerbootstrapper(False) self._produce_dummy_provider_json() with self.assertRaises(UnsupportedProviderAPI): self.pb._download_provider_info() @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: where('cacert.pem')) def test_download_provider_info_unsupported_api(self): self._setup_provider_config_with(provider.SUPPORTED_APIS[0], tempfile.mkdtemp()) self._setup_providerbootstrapper(False) self._produce_dummy_provider_json() self.pb._download_provider_info() @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_api_uri', lambda x: 'api.uri') @mock.patch( 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', lambda x: '/cert/path') def test_check_api_certificate_skips(self): self.pb._provider_config = ProviderConfig() self.pb._session.get = mock.MagicMock(return_value=Response()) self.pb._should_proceed_cert = mock.MagicMock(return_value=False) self.pb._check_api_certificate() self.assertFalse(self.pb._session.get.called) @deferred() def test_check_api_certificate_fails(self): self.pb._provider_config = ProviderConfig() self.pb._provider_config.get_api_uri = mock.MagicMock( return_value="https://localhost:%s" % (self.https_port, )) self.pb._provider_config.get_ca_cert_path = mock.MagicMock( return_value=os.path.join( os.path.split(__file__)[0], "wrongcert.pem")) self.pb._provider_config.get_api_version = mock.MagicMock( return_value="1") self.pb._should_proceed_cert = mock.MagicMock(return_value=True) def check(*args): with self.assertRaises(requests.exceptions.SSLError): self.pb._check_api_certificate() d = threads.deferToThread(check) return d @deferred() def test_check_api_certificate_succeeds(self): self.pb._provider_config = ProviderConfig() self.pb._provider_config.get_api_uri = mock.MagicMock( return_value="https://localhost:%s" % (self.https_port, )) self.pb._provider_config.get_ca_cert_path = mock.MagicMock( return_value=where('cacert.pem')) self.pb._provider_config.get_api_version = mock.MagicMock( return_value="1") self.pb._should_proceed_cert = mock.MagicMock(return_value=True) def check(*args): self.pb._check_api_certificate() d = threads.deferToThread(check) return d