Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'certbot-apache/tests/parser_test.py')
-rw-r--r--certbot-apache/tests/parser_test.py401
1 files changed, 401 insertions, 0 deletions
diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py
new file mode 100644
index 000000000..b334ce52e
--- /dev/null
+++ b/certbot-apache/tests/parser_test.py
@@ -0,0 +1,401 @@
+"""Tests for certbot_apache._internal.parser."""
+import shutil
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.compat import os
+import util
+
+
+class BasicParserTest(util.ParserTest):
+ """Apache Parser Test."""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(BasicParserTest, self).setUp()
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+
+ def test_bad_parse(self):
+ self.parser.parse_file(os.path.join(self.parser.root,
+ "conf-available", "bad_conf_file.conf"))
+ self.assertRaises(
+ errors.PluginError, self.parser.check_parsing_errors, "httpd.aug")
+
+ def test_bad_save(self):
+ mock_save = mock.Mock()
+ mock_save.side_effect = IOError
+ self.parser.aug.save = mock_save
+ self.assertRaises(errors.PluginError, self.parser.unsaved_files)
+
+ def test_aug_version(self):
+ mock_match = mock.Mock(return_value=["something"])
+ self.parser.aug.match = mock_match
+ # pylint: disable=protected-access
+ self.assertEqual(self.parser.check_aug_version(),
+ ["something"])
+ self.parser.aug.match.side_effect = RuntimeError
+ self.assertFalse(self.parser.check_aug_version())
+
+ def test_find_config_root_no_root(self):
+ # pylint: disable=protected-access
+ os.remove(self.parser.loc["root"])
+ self.assertRaises(
+ errors.NoInstallationError, self.parser._find_config_root)
+
+ def test_parse_file(self):
+ """Test parse_file.
+
+ certbot.conf is chosen as the test file as it will not be
+ included during the normal course of execution.
+
+ """
+ file_path = os.path.join(
+ self.config_path, "not-parsed-by-default", "certbot.conf")
+
+ self.parser.parse_file(file_path) # pylint: disable=protected-access
+
+ # search for the httpd incl
+ matches = self.parser.aug.match(
+ "/augeas/load/Httpd/incl [. ='%s']" % file_path)
+
+ self.assertTrue(matches)
+
+ def test_find_dir(self):
+ test = self.parser.find_dir("Listen", "80")
+ # This will only look in enabled hosts
+ test2 = self.parser.find_dir("documentroot")
+
+ self.assertEqual(len(test), 1)
+ self.assertEqual(len(test2), 8)
+
+ def test_add_dir(self):
+ aug_default = "/files" + self.parser.loc["default"]
+ self.parser.add_dir(aug_default, "AddDirective", "test")
+
+ self.assertTrue(
+ self.parser.find_dir("AddDirective", "test", aug_default))
+
+ self.parser.add_dir(aug_default, "AddList", ["1", "2", "3", "4"])
+ matches = self.parser.find_dir("AddList", None, aug_default)
+ for i, match in enumerate(matches):
+ self.assertEqual(self.parser.aug.get(match), str(i + 1))
+
+ def test_add_dir_beginning(self):
+ aug_default = "/files" + self.parser.loc["default"]
+ self.parser.add_dir_beginning(aug_default,
+ "AddDirectiveBeginning",
+ "testBegin")
+
+ self.assertTrue(
+ self.parser.find_dir("AddDirectiveBeginning", "testBegin", aug_default))
+
+ self.assertEqual(
+ self.parser.aug.get(aug_default+"/directive[1]"),
+ "AddDirectiveBeginning")
+ self.parser.add_dir_beginning(aug_default, "AddList", ["1", "2", "3", "4"])
+ matches = self.parser.find_dir("AddList", None, aug_default)
+ for i, match in enumerate(matches):
+ self.assertEqual(self.parser.aug.get(match), str(i + 1))
+
+ def test_empty_arg(self):
+ self.assertEqual(None,
+ self.parser.get_arg("/files/whatever/nonexistent"))
+
+ def test_add_dir_to_ifmodssl(self):
+ """test add_dir_to_ifmodssl.
+
+ Path must be valid before attempting to add to augeas
+
+ """
+ from certbot_apache._internal.parser import get_aug_path
+ # This makes sure that find_dir will work
+ self.parser.modules.add("mod_ssl.c")
+
+ self.parser.add_dir_to_ifmodssl(
+ get_aug_path(self.parser.loc["default"]),
+ "FakeDirective", ["123"])
+
+ matches = self.parser.find_dir("FakeDirective", "123")
+
+ self.assertEqual(len(matches), 1)
+ self.assertTrue("IfModule" in matches[0])
+
+ def test_add_dir_to_ifmodssl_multiple(self):
+ from certbot_apache._internal.parser import get_aug_path
+ # This makes sure that find_dir will work
+ self.parser.modules.add("mod_ssl.c")
+
+ self.parser.add_dir_to_ifmodssl(
+ get_aug_path(self.parser.loc["default"]),
+ "FakeDirective", ["123", "456", "789"])
+
+ matches = self.parser.find_dir("FakeDirective")
+
+ self.assertEqual(len(matches), 3)
+ self.assertTrue("IfModule" in matches[0])
+
+ def test_get_aug_path(self):
+ from certbot_apache._internal.parser import get_aug_path
+ self.assertEqual("/files/etc/apache", get_aug_path("/etc/apache"))
+
+ def test_set_locations(self):
+ with mock.patch("certbot_apache._internal.parser.os.path") as mock_path:
+
+ mock_path.isfile.side_effect = [False, False]
+
+ # pylint: disable=protected-access
+ results = self.parser._set_locations()
+
+ self.assertEqual(results["default"], results["listen"])
+ self.assertEqual(results["default"], results["name"])
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.get_arg")
+ def test_parse_modules_bad_syntax(self, mock_arg, mock_find):
+ mock_find.return_value = ["1", "2", "3", "4", "5", "6", "7", "8"]
+ mock_arg.return_value = None
+ with mock.patch("certbot_apache._internal.parser.logger") as mock_logger:
+ self.parser.parse_modules()
+ # Make sure that we got None return value and logged the file
+ self.assertTrue(mock_logger.debug.called)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_update_runtime_variables(self, mock_cfg, _):
+ define_val = (
+ 'ServerRoot: "/etc/apache2"\n'
+ 'Main DocumentRoot: "/var/www"\n'
+ 'Main ErrorLog: "/var/log/apache2/error.log"\n'
+ 'Mutex ssl-stapling: using_defaults\n'
+ 'Mutex ssl-cache: using_defaults\n'
+ 'Mutex default: dir="/var/lock/apache2" mechanism=fcntl\n'
+ 'Mutex watchdog-callback: using_defaults\n'
+ 'PidFile: "/var/run/apache2/apache2.pid"\n'
+ 'Define: TEST\n'
+ 'Define: DUMP_RUN_CFG\n'
+ 'Define: U_MICH\n'
+ 'Define: TLS=443\n'
+ 'Define: example_path=Documents/path\n'
+ 'User: name="www-data" id=33 not_used\n'
+ 'Group: name="www-data" id=33 not_used\n'
+ )
+ inc_val = (
+ 'Included configuration files:\n'
+ ' (*) /etc/apache2/apache2.conf\n'
+ ' (146) /etc/apache2/mods-enabled/access_compat.load\n'
+ ' (146) /etc/apache2/mods-enabled/alias.load\n'
+ ' (146) /etc/apache2/mods-enabled/auth_basic.load\n'
+ ' (146) /etc/apache2/mods-enabled/authn_core.load\n'
+ ' (146) /etc/apache2/mods-enabled/authn_file.load\n'
+ ' (146) /etc/apache2/mods-enabled/authz_core.load\n'
+ ' (146) /etc/apache2/mods-enabled/authz_host.load\n'
+ ' (146) /etc/apache2/mods-enabled/authz_user.load\n'
+ ' (146) /etc/apache2/mods-enabled/autoindex.load\n'
+ ' (146) /etc/apache2/mods-enabled/deflate.load\n'
+ ' (146) /etc/apache2/mods-enabled/dir.load\n'
+ ' (146) /etc/apache2/mods-enabled/env.load\n'
+ ' (146) /etc/apache2/mods-enabled/filter.load\n'
+ ' (146) /etc/apache2/mods-enabled/mime.load\n'
+ ' (146) /etc/apache2/mods-enabled/mpm_event.load\n'
+ ' (146) /etc/apache2/mods-enabled/negotiation.load\n'
+ ' (146) /etc/apache2/mods-enabled/reqtimeout.load\n'
+ ' (146) /etc/apache2/mods-enabled/setenvif.load\n'
+ ' (146) /etc/apache2/mods-enabled/socache_shmcb.load\n'
+ ' (146) /etc/apache2/mods-enabled/ssl.load\n'
+ ' (146) /etc/apache2/mods-enabled/status.load\n'
+ ' (147) /etc/apache2/mods-enabled/alias.conf\n'
+ ' (147) /etc/apache2/mods-enabled/autoindex.conf\n'
+ ' (147) /etc/apache2/mods-enabled/deflate.conf\n'
+ )
+ mod_val = (
+ 'Loaded Modules:\n'
+ ' core_module (static)\n'
+ ' so_module (static)\n'
+ ' watchdog_module (static)\n'
+ ' http_module (static)\n'
+ ' log_config_module (static)\n'
+ ' logio_module (static)\n'
+ ' version_module (static)\n'
+ ' unixd_module (static)\n'
+ ' access_compat_module (shared)\n'
+ ' alias_module (shared)\n'
+ ' auth_basic_module (shared)\n'
+ ' authn_core_module (shared)\n'
+ ' authn_file_module (shared)\n'
+ ' authz_core_module (shared)\n'
+ ' authz_host_module (shared)\n'
+ ' authz_user_module (shared)\n'
+ ' autoindex_module (shared)\n'
+ ' deflate_module (shared)\n'
+ ' dir_module (shared)\n'
+ ' env_module (shared)\n'
+ ' filter_module (shared)\n'
+ ' mime_module (shared)\n'
+ ' mpm_event_module (shared)\n'
+ ' negotiation_module (shared)\n'
+ ' reqtimeout_module (shared)\n'
+ ' setenvif_module (shared)\n'
+ ' socache_shmcb_module (shared)\n'
+ ' ssl_module (shared)\n'
+ ' status_module (shared)\n'
+ )
+
+ def mock_get_vars(cmd):
+ """Mock command output"""
+ if cmd[-1] == "DUMP_RUN_CFG":
+ return define_val
+ elif cmd[-1] == "DUMP_INCLUDES":
+ return inc_val
+ elif cmd[-1] == "DUMP_MODULES":
+ return mod_val
+ return None # pragma: no cover
+
+ mock_cfg.side_effect = mock_get_vars
+
+ expected_vars = {"TEST": "", "U_MICH": "", "TLS": "443",
+ "example_path": "Documents/path"}
+
+ self.parser.modules = set()
+ with mock.patch(
+ "certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
+ self.parser.update_runtime_variables()
+ self.assertEqual(self.parser.variables, expected_vars)
+ self.assertEqual(len(self.parser.modules), 58)
+ # None of the includes in inc_val should be in parsed paths.
+ # Make sure we tried to include them all.
+ self.assertEqual(mock_parse.call_count, 25)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_update_runtime_variables_alt_values(self, mock_cfg, _):
+ inc_val = (
+ 'Included configuration files:\n'
+ ' (*) {0}\n'
+ ' (146) /etc/apache2/mods-enabled/access_compat.load\n'
+ ' (146) {1}/mods-enabled/alias.load\n'
+ ).format(self.parser.loc["root"],
+ os.path.dirname(self.parser.loc["root"]))
+
+ mock_cfg.return_value = inc_val
+ self.parser.modules = set()
+
+ with mock.patch(
+ "certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
+ self.parser.update_runtime_variables()
+ # No matching modules should have been found
+ self.assertEqual(len(self.parser.modules), 0)
+ # Only one of the three includes do not exist in already parsed
+ # path derived from root configuration Include statements
+ self.assertEqual(mock_parse.call_count, 1)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_update_runtime_vars_bad_output(self, mock_cfg):
+ mock_cfg.return_value = "Define: TLS=443=24"
+ self.parser.update_runtime_variables()
+
+ mock_cfg.return_value = "Define: DUMP_RUN_CFG\nDefine: TLS=443=24"
+ self.assertRaises(
+ errors.PluginError, self.parser.update_runtime_variables)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.option")
+ @mock.patch("certbot_apache._internal.parser.subprocess.Popen")
+ def test_update_runtime_vars_bad_ctl(self, mock_popen, mock_opt):
+ mock_popen.side_effect = OSError
+ mock_opt.return_value = "nonexistent"
+ self.assertRaises(
+ errors.MisconfigurationError,
+ self.parser.update_runtime_variables)
+
+ @mock.patch("certbot_apache._internal.parser.subprocess.Popen")
+ def test_update_runtime_vars_bad_exit(self, mock_popen):
+ mock_popen().communicate.return_value = ("", "")
+ mock_popen.returncode = -1
+ self.assertRaises(
+ errors.MisconfigurationError,
+ self.parser.update_runtime_variables)
+
+ def test_add_comment(self):
+ from certbot_apache._internal.parser import get_aug_path
+ self.parser.add_comment(get_aug_path(self.parser.loc["name"]), "123456")
+ comm = self.parser.find_comments("123456")
+ self.assertEqual(len(comm), 1)
+ self.assertTrue(self.parser.loc["name"] in comm[0])
+
+
+class ParserInitTest(util.ApacheTest):
+ def setUp(self): # pylint: disable=arguments-differ
+ super(ParserInitTest, self).setUp()
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.init_augeas")
+ def test_prepare_no_augeas(self, mock_init_augeas):
+ from certbot_apache._internal.parser import ApacheParser
+ mock_init_augeas.side_effect = errors.NoInstallationError
+ self.config.config_test = mock.Mock()
+ self.assertRaises(
+ errors.NoInstallationError, ApacheParser,
+ os.path.relpath(self.config_path), "/dummy/vhostpath",
+ version=(2, 4, 22), configurator=self.config)
+
+ def test_init_old_aug(self):
+ from certbot_apache._internal.parser import ApacheParser
+ with mock.patch("certbot_apache._internal.parser.ApacheParser.check_aug_version") as mock_c:
+ mock_c.return_value = False
+ self.assertRaises(
+ errors.NotSupportedError,
+ ApacheParser, os.path.relpath(self.config_path),
+ "/dummy/vhostpath", version=(2, 4, 22), configurator=self.config)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_unparseable(self, mock_cfg):
+ from certbot_apache._internal.parser import ApacheParser
+ mock_cfg.return_value = ('Define: TEST')
+ self.assertRaises(
+ errors.PluginError,
+ ApacheParser, os.path.relpath(self.config_path),
+ "/dummy/vhostpath", version=(2, 2, 22), configurator=self.config)
+
+ def test_root_normalized(self):
+ from certbot_apache._internal.parser import ApacheParser
+
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ path = os.path.join(
+ self.temp_dir,
+ "debian_apache_2_4/////multiple_vhosts/../multiple_vhosts/apache2")
+
+ parser = ApacheParser(path, "/dummy/vhostpath", configurator=self.config)
+
+ self.assertEqual(parser.root, self.config_path)
+
+ def test_root_absolute(self):
+ from certbot_apache._internal.parser import ApacheParser
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ parser = ApacheParser(
+ os.path.relpath(self.config_path),
+ "/dummy/vhostpath", configurator=self.config)
+
+ self.assertEqual(parser.root, self.config_path)
+
+ def test_root_no_trailing_slash(self):
+ from certbot_apache._internal.parser import ApacheParser
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ parser = ApacheParser(
+ self.config_path + os.path.sep,
+ "/dummy/vhostpath", configurator=self.config)
+ self.assertEqual(parser.root, self.config_path)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover