1"""Test for certbot_apache._internal.configurator for Centos overrides""" 2import unittest 3 4try: 5 import mock 6except ImportError: # pragma: no cover 7 from unittest import mock # type: ignore 8 9from certbot import errors 10from certbot.compat import filesystem 11from certbot.compat import os 12from certbot_apache._internal import obj 13from certbot_apache._internal import override_centos 14import util 15 16 17def get_vh_truth(temp_dir, config_name): 18 """Return the ground truth for the specified directory.""" 19 prefix = os.path.join( 20 temp_dir, config_name, "httpd/conf.d") 21 22 aug_pre = "/files" + prefix 23 vh_truth = [ 24 obj.VirtualHost( 25 os.path.join(prefix, "centos.example.com.conf"), 26 os.path.join(aug_pre, "centos.example.com.conf/VirtualHost"), 27 {obj.Addr.fromstring("*:80")}, 28 False, True, "centos.example.com"), 29 obj.VirtualHost( 30 os.path.join(prefix, "ssl.conf"), 31 os.path.join(aug_pre, "ssl.conf/VirtualHost"), 32 {obj.Addr.fromstring("_default_:443")}, 33 True, True, None) 34 ] 35 return vh_truth 36 37class FedoraRestartTest(util.ApacheTest): 38 """Tests for Fedora specific self-signed certificate override""" 39 40 def setUp(self): # pylint: disable=arguments-differ 41 test_dir = "centos7_apache/apache" 42 config_root = "centos7_apache/apache/httpd" 43 vhost_root = "centos7_apache/apache/httpd/conf.d" 44 super().setUp(test_dir=test_dir, 45 config_root=config_root, 46 vhost_root=vhost_root) 47 self.config = util.get_apache_configurator( 48 self.config_path, self.vhost_path, self.config_dir, self.work_dir, 49 os_info="fedora_old") 50 self.vh_truth = get_vh_truth( 51 self.temp_dir, "centos7_apache/apache") 52 53 def _run_fedora_test(self): 54 self.assertIsInstance(self.config, override_centos.CentOSConfigurator) 55 with mock.patch("certbot.util.get_os_info") as mock_info: 56 mock_info.return_value = ["fedora", "28"] 57 self.config.config_test() 58 59 def test_non_fedora_error(self): 60 c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test" 61 with mock.patch(c_test) as mock_test: 62 mock_test.side_effect = errors.MisconfigurationError 63 with mock.patch("certbot.util.get_os_info") as mock_info: 64 mock_info.return_value = ["not_fedora"] 65 self.assertRaises(errors.MisconfigurationError, 66 self.config.config_test) 67 68 def test_fedora_restart_error(self): 69 c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test" 70 with mock.patch(c_test) as mock_test: 71 # First call raises error, second doesn't 72 mock_test.side_effect = [errors.MisconfigurationError, ''] 73 with mock.patch("certbot.util.run_script") as mock_run: 74 mock_run.side_effect = errors.SubprocessError 75 self.assertRaises(errors.MisconfigurationError, 76 self._run_fedora_test) 77 78 def test_fedora_restart(self): 79 c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test" 80 with mock.patch(c_test) as mock_test: 81 with mock.patch("certbot.util.run_script") as mock_run: 82 # First call raises error, second doesn't 83 mock_test.side_effect = [errors.MisconfigurationError, ''] 84 self._run_fedora_test() 85 self.assertEqual(mock_test.call_count, 2) 86 self.assertEqual(mock_run.call_args[0][0], 87 ['systemctl', 'restart', 'httpd']) 88 89 90class MultipleVhostsTestCentOS(util.ApacheTest): 91 """Multiple vhost tests for CentOS / RHEL family of distros""" 92 93 _multiprocess_can_split_ = True 94 95 def setUp(self): # pylint: disable=arguments-differ 96 test_dir = "centos7_apache/apache" 97 config_root = "centos7_apache/apache/httpd" 98 vhost_root = "centos7_apache/apache/httpd/conf.d" 99 super().setUp(test_dir=test_dir, 100 config_root=config_root, 101 vhost_root=vhost_root) 102 103 self.config = util.get_apache_configurator( 104 self.config_path, self.vhost_path, self.config_dir, self.work_dir, 105 os_info="centos") 106 self.vh_truth = get_vh_truth( 107 self.temp_dir, "centos7_apache/apache") 108 109 def test_get_parser(self): 110 self.assertIsInstance(self.config.parser, override_centos.CentOSParser) 111 112 @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") 113 def test_opportunistic_httpd_runtime_parsing(self, mock_get): 114 define_val = ( 115 'Define: TEST1\n' 116 'Define: TEST2\n' 117 'Define: DUMP_RUN_CFG\n' 118 ) 119 mod_val = ( 120 'Loaded Modules:\n' 121 ' mock_module (static)\n' 122 ' another_module (static)\n' 123 ) 124 def mock_get_cfg(command): 125 """Mock httpd process stdout""" 126 if command == ['apachectl', '-t', '-D', 'DUMP_RUN_CFG']: 127 return define_val 128 elif command == ['apachectl', '-t', '-D', 'DUMP_MODULES']: 129 return mod_val 130 return "" 131 mock_get.side_effect = mock_get_cfg 132 self.config.parser.modules = {} 133 self.config.parser.variables = {} 134 135 with mock.patch("certbot.util.get_os_info") as mock_osi: 136 # Make sure we have the have the CentOS httpd constants 137 mock_osi.return_value = ("centos", "7") 138 self.config.parser.update_runtime_variables() 139 140 self.assertEqual(mock_get.call_count, 3) 141 self.assertEqual(len(self.config.parser.modules), 4) 142 self.assertEqual(len(self.config.parser.variables), 2) 143 self.assertTrue("TEST2" in self.config.parser.variables) 144 self.assertTrue("mod_another.c" in self.config.parser.modules) 145 146 def test_get_virtual_hosts(self): 147 """Make sure all vhosts are being properly found.""" 148 vhs = self.config.get_virtual_hosts() 149 self.assertEqual(len(vhs), 2) 150 found = 0 151 152 for vhost in vhs: 153 for centos_truth in self.vh_truth: 154 if vhost == centos_truth: 155 found += 1 156 break 157 else: 158 raise Exception("Missed: %s" % vhost) # pragma: no cover 159 self.assertEqual(found, 2) 160 161 @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") 162 def test_get_sysconfig_vars(self, mock_cfg): 163 """Make sure we read the sysconfig OPTIONS variable correctly""" 164 # Return nothing for the process calls 165 mock_cfg.return_value = "" 166 self.config.parser.sysconfig_filep = filesystem.realpath( 167 os.path.join(self.config.parser.root, "../sysconfig/httpd")) 168 self.config.parser.variables = {} 169 170 with mock.patch("certbot.util.get_os_info") as mock_osi: 171 # Make sure we have the have the CentOS httpd constants 172 mock_osi.return_value = ("centos", "7") 173 self.config.parser.update_runtime_variables() 174 175 self.assertTrue("mock_define" in self.config.parser.variables) 176 self.assertTrue("mock_define_too" in self.config.parser.variables) 177 self.assertTrue("mock_value" in self.config.parser.variables) 178 self.assertEqual("TRUE", self.config.parser.variables["mock_value"]) 179 self.assertTrue("MOCK_NOSEP" in self.config.parser.variables) 180 self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"]) 181 182 @mock.patch("certbot_apache._internal.configurator.util.run_script") 183 def test_alt_restart_works(self, mock_run_script): 184 mock_run_script.side_effect = [None, errors.SubprocessError, None] 185 self.config.restart() 186 self.assertEqual(mock_run_script.call_count, 3) 187 188 @mock.patch("certbot_apache._internal.configurator.util.run_script") 189 def test_alt_restart_errors(self, mock_run_script): 190 mock_run_script.side_effect = [None, 191 errors.SubprocessError, 192 errors.SubprocessError] 193 self.assertRaises(errors.MisconfigurationError, self.config.restart) 194 195 196if __name__ == "__main__": 197 unittest.main() # pragma: no cover 198