def run(self): """High-level command to run openvpn with the assembled command-line. Shuts down openvpn after a timeout. Waits this time for openvpn to startup and writes the environment files from the scripts. As soon as they are present iptables rules are applied. If something goes wrong call the panic method :returns: True if everything went fine or running in daemon mode. """ config_dict = resources.get_config()["openvpn"] self.cleanup() printer = Printer() printer.info("Running openvpn with '{}'".format(self.cmd)) with subprocess.Popen(self.cmd) as ovpn: # give openvpn a maximum of 60 seconds to startup. A lower value is bad if # asked for username/password. # pylint: disable=unused-variable for i in range(300): try: if self.is_running(ovpn): # delay initialization of iptables until resource files are # created. If none are created the delay still applies as normal # timeout time.sleep(0.2) for script in config_dict["scripts"]: stage = script["stage"] if stage in ("up", "always"): resources.get_stats_file( stats_name=script["creates"], create=False ) else: self.panic(ovpn, "Openvpn process stopped unexpected.") if iptables.apply_config_dir(self.server, self.protocol): resources.write_stats(self.server, stats_name="server") stats_dict = resources.get_stats() stats_dict["last_server"] = {} stats_dict["last_server"]["domain"] = self.domain stats_dict["last_server"]["protocol"] = self.protocol resources.write_stats(stats_dict) else: self.panic(ovpn, "Applying iptables failed.") break except resources.ResourceNotFoundError: pass ### for else: self.panic(ovpn, "Timeout reached.") if self.is_running(ovpn): ovpn.wait() return True
def process_iptables_cmd(args): """Process 'iptables' command :param object args: command-line arguments as Namespace :returns: True if processing was successful """ if args.iptables_sub == "flush": if args.no_fallback: iptables.reset(fallback=False) else: iptables.reset(fallback=True) elif args.iptables_sub == "apply": config_file = iptables.get_config_path(args.table, args.fallback, ipv6=args.ipv6) if args.fallback: server = None protocol = None else: try: server = resources.get_stats(stats_name="server") protocol = resources.get_stats()["last_server"]["protocol"] except (resources.ResourceNotFoundError, KeyError): raise iptables.IptablesError( "Cannot apply 'rules' files when not connected to a NordVPN server." ) return iptables.apply_config(config_file, server, protocol) elif args.iptables_sub == "reload": try: server = resources.get_stats(stats_name="server") protocol = resources.get_stats()["last_server"]["protocol"] filetype = "rules" except (resources.ResourceNotFoundError, KeyError): filetype = "fallback" return iptables.apply_config_dir(server, protocol, filetype=filetype) elif args.iptables_sub == "list": return process_list_ipt_cmd(args) else: raise NotImplementedError("Not implemented") return True
def test_get_stats_when_invalid_yaml(mocker): # setup mockbase = MockBase("resources") mockbase.mock_user_is_root(mocker, True) mockbase.setup(resources) stats_file = "tests/fixtures/config_invalid_yaml_fixture.yml" mocked_stats_file = _mock_get_stats_file(mocker, stats_file) # run try: resources.get_stats() except resources.MalformedResourceError as error: assert error.resource_file == stats_file assert error.problem == "expected <block end>, but found '-'" assert ( error.problem_mark # pylint: disable=line-too-long == ' in "tests/fixtures/config_invalid_yaml_fixture.yml", line 4, column 3' ) # assert mocked_stats_file.assert_called_once()
def test_get_stats_when_stats_dict_is_none(mocker): # setup mockbase = MockBase("resources") mockbase.mock_user_is_root(mocker, True) mockbase.setup(resources) stats_file = "tests/fixtures/config_valid_yaml_fixture.yml" mocked_stats_file = _mock_get_stats_file(mocker, stats_file) mocked_safe_load = mocker.patch("connord.resources.yaml.safe_load", return_value=None) expected_result = dict() # run actual_result = resources.get_stats() # assert mocked_stats_file.assert_called_once() mocked_safe_load.assert_called_once() assert actual_result == expected_result
def test_get_stats_when_valid_yaml(mocker): # setup mockbase = MockBase("resources") mockbase.mock_user_is_root(mocker, True) mockbase.setup(resources) stats_file = "tests/fixtures/config_valid_yaml_fixture.yml" mocked_stats_file = _mock_get_stats_file(mocker, stats_file) import yaml with open(stats_file) as stats_fd: expected_result = yaml.safe_load(stats_fd) # run actual_result = resources.get_stats() # assert mocked_stats_file.assert_called_once() assert actual_result == expected_result