certbot/certbot-apache/tests/parser_test.py

415 lines
17 KiB
Python
Raw Normal View History

Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
"""Tests for certbot_apache._internal.parser."""
2014-12-19 18:49:29 -05:00
import shutil
import unittest
try:
import mock
except ImportError: # pragma: no cover
from unittest import mock # type: ignore
2014-12-19 18:49:29 -05:00
from certbot import errors
2019-04-12 16:32:52 -04:00
from certbot.compat import os
import util
2014-12-19 18:49:29 -05:00
2015-07-19 19:48:27 -04:00
class BasicParserTest(util.ParserTest):
2015-01-24 08:12:45 -05:00
"""Apache Parser Test."""
2014-12-19 18:49:29 -05:00
2015-07-19 19:48:27 -04:00
def setUp(self): # pylint: disable=arguments-differ
super().setUp()
2014-12-19 18:49:29 -05:00
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)
@mock.patch("certbot_apache._internal.parser.logger")
def test_bad_save_errors(self, mock_logger):
nx_path = "/non/existent/path.conf"
self.parser.aug.set("/augeas/load/Httpd/incl[last()]", nx_path)
self.parser.add_dir(f"/files{nx_path}", "AddDirective", "test")
self.assertRaises(IOError, self.parser.save, {})
mock_logger.error.assert_called_with(
'Unable to save files: %s.%s', '/non/existent/path.conf', mock.ANY)
mock_logger.debug.assert_called_with(
"Error %s saving %s: %s", "mk_augtemp",
"/non/existent/path.conf", "No such file or directory")
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.assertIs(self.parser.check_aug_version(), False)
2015-07-24 20:05:25 -04:00
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)
2014-12-19 18:49:29 -05:00
def test_parse_file(self):
"""Test parse_file.
certbot.conf is chosen as the test file as it will not be
2014-12-19 18:49:29 -05:00
included during the normal course of execution.
"""
file_path = os.path.join(
self.config_path, "not-parsed-by-default", "certbot.conf")
2014-12-19 18:49:29 -05:00
Do not parse disabled configuration files from under sites-available on Debian / Ubuntu (#4104) This changes the apache plugin behaviour to only parse enabled configuration files and respecting the --apache-vhost-root CLI parameter for new SSL vhost creation. If --apache-vhost-root isn't defined, or doesn't exist, the SSL vhost will be created to originating non-SSL vhost directory. This PR also implements actual check for vhost enabled state, and makes sure parser.parse_file() does not discard changes in Augeas DOM, by doing an autosave. Also handles enabling the new SSL vhost, if it's on a path that's not parsed by Apache. Fixes: #1328 Fixes: #3545 Fixes: #3791 Fixes: #4523 Fixes: #4837 Fixes: #4905 * First changes * Handle rest of the errors * Test fixes * Final fixes * Make parse_files accessible and fix linter problems * Activate vhost at later time * Cleanup * Add a new test case, and fix old * Enable site later in deploy_cert * Make apache-conf-test default dummy configuration enabled * Remove is_sites_available as obsolete * Cleanup * Brought back conditional vhost_path parsing * Parenthesis * Fix merge leftovers * Fix to work with the recent changes to new file creation * Added fix and tests for non-symlink vhost in sites-enabled * Made vhostroot parameter for ApacheParser optional, and removed extra_path * Respect vhost-root, and add Include statements to root configuration if needed * Fixed site enabling order to prevent apache restart error while enabling mod_ssl * Don't exclude Ubuntu / Debian vhost-root cli argument * Changed the SSL vhost directory selection priority * Requested fixes for paths and vhost discovery * Make sure the Augeas DOM is written to disk before loading new files * Actual checking for if the file is parsed within existing Apache configuration * Fix the order of dummy SSL directives addition and enabling modules * Restructured site_enabled checks * Enabling vhost correctly for non-debian systems
2017-09-25 15:03:09 -04:00
self.parser.parse_file(file_path) # pylint: disable=protected-access
2014-12-19 18:49:29 -05:00
# 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):
2015-07-19 05:22:10 -04:00
test = self.parser.find_dir("Listen", "80")
2014-12-19 18:49:29 -05:00
# This will only look in enabled hosts
2015-07-19 05:22:10 -04:00
test2 = self.parser.find_dir("documentroot")
self.assertEqual(len(test), 1)
self.assertEqual(len(test2), 8)
2014-12-19 18:49:29 -05:00
def test_add_dir(self):
aug_default = "/files" + self.parser.loc["default"]
2014-12-20 06:43:39 -05:00
self.parser.add_dir(aug_default, "AddDirective", "test")
2014-12-19 18:49:29 -05:00
self.assertTrue(self.parser.find_dir("AddDirective", "test", aug_default))
2014-12-19 18:49:29 -05:00
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))
for name in ("empty.conf", "no-directives.conf"):
conf = "/files" + os.path.join(self.parser.root, "sites-available", name)
self.parser.add_dir_beginning(conf, "AddDirectiveBeginning", "testBegin")
self.assertGreater(
len(self.parser.find_dir("AddDirectiveBeginning", "testBegin", conf)),
0
)
def test_empty_arg(self):
self.assertIsNone(self.parser.get_arg("/files/whatever/nonexistent"))
2014-12-19 18:49:29 -05:00
def test_add_dir_to_ifmodssl(self):
"""test add_dir_to_ifmodssl.
Path must be valid before attempting to add to augeas
"""
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import get_aug_path
2015-07-19 05:22:10 -04:00
# This makes sure that find_dir will work
Disable TLS session tickets in Apache (#7771) Fixes #7350. This PR changes the parsed modules from a `set` to a `dict`, with the filepath argument as the value. Accordingly, after calling `enable_mod` to enable `ssl_module`, modules now need to be re-parsed, so call `reset_modules`. * Add mechanism for selecting apache config file, based on work done in #7191. * Check OpenSSL version * Remove os imports * debian override still needs os * Reformat remaining apache tests with modules dict syntax * Clean up more apache tests * Switch from property to method for openssl and add tests for coverage. * Sometimes the dict location will be None in which case we should in fact return None * warn thoroughly and consistently in openssl_version function * update tests for new warnings * read file as bytes, and factor out the open for testing * normalize ssl_module_location path to account for being relative to server root * Use byte literals in a python 2 and 3 compatible way * string does need to be a literal * patch builtins open * add debug, remove space * Add test to check if OpenSSL detection is working on different systems * fix relative test location for cwd * put </IfModule> on its own line in test case * Revert test file to status in master. * Call augeas load before reparsing modules to pick up the changes * fix grep, tail, and mod_ssl location on centos * strip the trailing whitespace from fedora * just use LooseVersion in test * call apache2ctl on debian systems * Use sudo for apache2ctl command * add check to make sure we're getting a version * Add boolean so we don't warn on debian/ubuntu before trying to enable mod_ssl * Reduce warnings while testing by setting mock _openssl_version. * Make sure we're not throwing away any unwritten changes to the config * test last warning case for coverage * text changes for clarity
2020-03-23 19:49:52 -04:00
self.parser.modules["mod_ssl.c"] = "/fake/path"
2015-07-19 05:22:10 -04:00
2014-12-19 18:49:29 -05:00
self.parser.add_dir_to_ifmodssl(
get_aug_path(self.parser.loc["default"]),
2015-07-17 17:09:46 -04:00
"FakeDirective", ["123"])
2014-12-19 18:49:29 -05:00
matches = self.parser.find_dir("FakeDirective", "123")
self.assertEqual(len(matches), 1)
self.assertIn("IfModule", matches[0])
2014-12-19 18:49:29 -05:00
2015-07-23 04:34:51 -04:00
def test_add_dir_to_ifmodssl_multiple(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import get_aug_path
2015-07-23 04:34:51 -04:00
# This makes sure that find_dir will work
Disable TLS session tickets in Apache (#7771) Fixes #7350. This PR changes the parsed modules from a `set` to a `dict`, with the filepath argument as the value. Accordingly, after calling `enable_mod` to enable `ssl_module`, modules now need to be re-parsed, so call `reset_modules`. * Add mechanism for selecting apache config file, based on work done in #7191. * Check OpenSSL version * Remove os imports * debian override still needs os * Reformat remaining apache tests with modules dict syntax * Clean up more apache tests * Switch from property to method for openssl and add tests for coverage. * Sometimes the dict location will be None in which case we should in fact return None * warn thoroughly and consistently in openssl_version function * update tests for new warnings * read file as bytes, and factor out the open for testing * normalize ssl_module_location path to account for being relative to server root * Use byte literals in a python 2 and 3 compatible way * string does need to be a literal * patch builtins open * add debug, remove space * Add test to check if OpenSSL detection is working on different systems * fix relative test location for cwd * put </IfModule> on its own line in test case * Revert test file to status in master. * Call augeas load before reparsing modules to pick up the changes * fix grep, tail, and mod_ssl location on centos * strip the trailing whitespace from fedora * just use LooseVersion in test * call apache2ctl on debian systems * Use sudo for apache2ctl command * add check to make sure we're getting a version * Add boolean so we don't warn on debian/ubuntu before trying to enable mod_ssl * Reduce warnings while testing by setting mock _openssl_version. * Make sure we're not throwing away any unwritten changes to the config * test last warning case for coverage * text changes for clarity
2020-03-23 19:49:52 -04:00
self.parser.modules["mod_ssl.c"] = "/fake/path"
2015-07-23 04:34:51 -04:00
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.assertIn("IfModule", matches[0])
2015-07-23 04:34:51 -04:00
2014-12-19 18:49:29 -05:00
def test_get_aug_path(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import get_aug_path
self.assertEqual("/files/etc/apache", get_aug_path("/etc/apache"))
2014-12-19 18:49:29 -05:00
def test_set_locations(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
with mock.patch("certbot_apache._internal.parser.os.path") as mock_path:
2014-12-19 18:49:29 -05:00
2016-01-26 14:40:44 -05:00
mock_path.isfile.side_effect = [False, False]
2014-12-19 18:49:29 -05:00
# pylint: disable=protected-access
2015-07-23 04:34:51 -04:00
results = self.parser._set_locations()
2014-12-19 18:49:29 -05:00
self.assertEqual(results["default"], results["listen"])
self.assertEqual(results["default"], results["name"])
2015-01-24 08:12:45 -05:00
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
@mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache._internal.parser.ApacheParser.get_arg")
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
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
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
with mock.patch("certbot_apache._internal.parser.logger") as mock_logger:
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
self.parser.parse_modules()
# Make sure that we got None return value and logged the file
self.assertIs(mock_logger.debug.called, True)
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
@mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg")
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
def test_update_runtime_variables(self, mock_cfg, _):
define_val = (
2015-07-23 04:34:51 -04:00
'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: WITH_ASSIGNMENT=URL=http://example.com\n'
'Define: EMPTY=\n'
2015-07-23 04:34:51 -04:00
'Define: example_path=Documents/path\n'
'User: name="www-data" id=33 not_used\n'
'Group: name="www-data" id=33 not_used\n'
)
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
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
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
mock_cfg.side_effect = mock_get_vars
2015-07-23 04:34:51 -04:00
expected_vars = {"TEST": "", "U_MICH": "", "TLS": "443",
"example_path": "Documents/path",
"WITH_ASSIGNMENT": "URL=http://example.com",
"EMPTY": "",
}
2015-07-23 04:34:51 -04:00
Disable TLS session tickets in Apache (#7771) Fixes #7350. This PR changes the parsed modules from a `set` to a `dict`, with the filepath argument as the value. Accordingly, after calling `enable_mod` to enable `ssl_module`, modules now need to be re-parsed, so call `reset_modules`. * Add mechanism for selecting apache config file, based on work done in #7191. * Check OpenSSL version * Remove os imports * debian override still needs os * Reformat remaining apache tests with modules dict syntax * Clean up more apache tests * Switch from property to method for openssl and add tests for coverage. * Sometimes the dict location will be None in which case we should in fact return None * warn thoroughly and consistently in openssl_version function * update tests for new warnings * read file as bytes, and factor out the open for testing * normalize ssl_module_location path to account for being relative to server root * Use byte literals in a python 2 and 3 compatible way * string does need to be a literal * patch builtins open * add debug, remove space * Add test to check if OpenSSL detection is working on different systems * fix relative test location for cwd * put </IfModule> on its own line in test case * Revert test file to status in master. * Call augeas load before reparsing modules to pick up the changes * fix grep, tail, and mod_ssl location on centos * strip the trailing whitespace from fedora * just use LooseVersion in test * call apache2ctl on debian systems * Use sudo for apache2ctl command * add check to make sure we're getting a version * Add boolean so we don't warn on debian/ubuntu before trying to enable mod_ssl * Reduce warnings while testing by setting mock _openssl_version. * Make sure we're not throwing away any unwritten changes to the config * test last warning case for coverage * text changes for clarity
2020-03-23 19:49:52 -04:00
self.parser.modules = {}
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
with mock.patch(
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
"certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
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)
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
@mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg")
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
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
Disable TLS session tickets in Apache (#7771) Fixes #7350. This PR changes the parsed modules from a `set` to a `dict`, with the filepath argument as the value. Accordingly, after calling `enable_mod` to enable `ssl_module`, modules now need to be re-parsed, so call `reset_modules`. * Add mechanism for selecting apache config file, based on work done in #7191. * Check OpenSSL version * Remove os imports * debian override still needs os * Reformat remaining apache tests with modules dict syntax * Clean up more apache tests * Switch from property to method for openssl and add tests for coverage. * Sometimes the dict location will be None in which case we should in fact return None * warn thoroughly and consistently in openssl_version function * update tests for new warnings * read file as bytes, and factor out the open for testing * normalize ssl_module_location path to account for being relative to server root * Use byte literals in a python 2 and 3 compatible way * string does need to be a literal * patch builtins open * add debug, remove space * Add test to check if OpenSSL detection is working on different systems * fix relative test location for cwd * put </IfModule> on its own line in test case * Revert test file to status in master. * Call augeas load before reparsing modules to pick up the changes * fix grep, tail, and mod_ssl location on centos * strip the trailing whitespace from fedora * just use LooseVersion in test * call apache2ctl on debian systems * Use sudo for apache2ctl command * add check to make sure we're getting a version * Add boolean so we don't warn on debian/ubuntu before trying to enable mod_ssl * Reduce warnings while testing by setting mock _openssl_version. * Make sure we're not throwing away any unwritten changes to the config * test last warning case for coverage * text changes for clarity
2020-03-23 19:49:52 -04:00
self.parser.modules = {}
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
with mock.patch(
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
"certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
Distribution specific override functionality based on class inheritance (#5202) Class inheritance based approach to distro specific overrides. How it works: The certbot-apache plugin entrypoint has been changed to entrypoint.ENTRYPOINT which is a variable containing appropriate override class for system, if available. Override classes register themselves using decorator override.register() which takes a list of distribution fingerprints (ID & LIKE variables in /etc/os-release, or platform.linux_distribution() as a fallback). These end up as keys in dict override.OVERRIDE_CLASSES and values for the keys are references to the class that called the decorator, hence allowing self-registration of override classes when they are imported. The only file importing these override classes is entrypoint.py, so adding new override classes would need only one import in addition to the actual override class file. Generic changes: Parser initialization has been moved to separate class method, allowing easy override where needed. Cleaned up configurator.py a bit, and moved some helper functions to newly created apache_util.py Split Debian specific code from configurator.py to debian_override.py Changed define_cmd to apache_cmd because the parameters are for every distribution supporting this behavior, and we're able to use the value to build the additional configuration dump commands. Moved add_parser_mod() from configurator to parser add_mod() Added two new configuration dump parsing methods to update_runtime_variables() in parser: update_includes() and update_modules(). Changed init_modules() in parser to accommodate the changes above. (ie. don't throw existing self.modules out). Moved OS based constants to their respective override classes. Refactored configurator class discovery in tests to help easier test case creation using distribution based override configurator class. tests.util.get_apache_configurator() now takes keyword argument os_info which is string of the desired mock OS fingerprint response that's used for picking the right override class. This PR includes two major generic additions that should vastly improve our parsing accuracy and quality: Includes are parsed from config dump from httpd binary. This is mandatory for some distributions (Like OpenSUSE) to get visibility over the whole configuration tree because of Include statements passed on in command line, and not via root httpd.conf file. Modules are parsed from config dump from httpd binary. This lets us jump into correct IfModule directives if for some reason we have missed the module availability (because of one being included on command line or such). Distribution specific changes Because of the generic changes, there are two distributions (or distribution families) that do not provide such functionality, so it had to be overridden in their respective override files. These distributions are: CentOS, because it deliberately limits httpd binary stdout using SELinux as a feature. We are doing opportunistic config dumps here however, in case SELinux enforcing is off. Gentoo, because it does not provide a way to invoke httpd with command line parsed from its specific configuration file. Gentoo relies heavily on Define statements that are passed over from APACHE2_OPTS variable /etc/conf.d/apache2 file and most of the configuration in root Apache configuration are dependent on these values. Debian Moved the Debian specific parts from configurator.py to Debian specific override. CentOS Parsing of /etc/sysconfig/httpd file for additional Define statements. This could hold other parameters too, but parsing everything off it would require a full Apache lexer. For CLI parameters, I think Defines are the most common ones. This is done in addition of opportunistic parsing of httpd binary config dump. Added CentOS default Apache configuration tree for realistic test cases. Gentoo Parsing Defines from /etc/conf.d/apache2 variable APACHE2_OPTS, which holds additional Define statements to enable certain functionalities, enabling parts of the configuration in the Apache2 DOM. This is done instead of trying to parse httpd binary configuration dumps. Added default Apache configuration from Gentoo to testdata, including /etc/conf.d/apache2 file for realistic test cases. * Distribution specific override functionality based on class inheritance * Need to patch get_systemd_os_like to as travis has proper os-release * Added pydoc * Move parser initialization to a method and fix Python 3 __new__ errors * Parser changes to parse HTTPD config * Try to get modules and includes from httpd process for better visibility over the configuration * Had to disable duplicate-code because of test setup (PyCQA/pylint/issues/214) * CentOS tests and linter fixes * Gentoo override, tests and linter fixes * Mock the process call in all the tests that require it * Fix CentOS test mock * Restore reseting modules list functionality for cleanup * Move OS fingerprinting and constant mocks to parent class * Fixes requested in review * New entrypoint structure and started moving OS constants to override classes * OS constants move continued, test and linter fixes * Removed dead code * Apache compatibility test changest to reflect OS constant restructure * Test fix * Requested changes * Moved Debian specific tests to own test file * Removed decorator based override class registration in favor of entrypoint dict * Fix for update_includes for some versions of Augeas * Take fedora fix into account in tests * Review fixes
2017-12-04 14:49:18 -05:00
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)
2015-07-23 04:34:51 -04:00
@mock.patch("certbot_apache._internal.apache_util.subprocess.run")
def test_update_runtime_vars_bad_ctl(self, mock_run):
mock_run.side_effect = OSError
2015-07-23 04:34:51 -04:00
self.assertRaises(
errors.MisconfigurationError,
2015-12-28 07:03:50 -05:00
self.parser.update_runtime_variables)
2015-07-23 04:34:51 -04:00
@mock.patch("certbot_apache._internal.apache_util.subprocess.run")
def test_update_runtime_vars_bad_exit(self, mock_run):
mock_proc = mock_run.return_value
mock_proc.stdout = ""
mock_proc.stderr = ""
mock_proc.returncode = -1
2015-07-23 04:34:51 -04:00
self.assertRaises(
errors.MisconfigurationError,
2015-12-28 07:03:50 -05:00
self.parser.update_runtime_variables)
2015-07-23 04:34:51 -04:00
def test_add_comment(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
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")
2018-07-11 20:33:04 -04:00
self.assertEqual(len(comm), 1)
self.assertIn(self.parser.loc["name"], comm[0])
2015-01-24 08:12:45 -05:00
2015-07-15 18:25:34 -04:00
class ParserInitTest(util.ApacheTest):
2015-07-19 19:48:27 -04:00
def setUp(self): # pylint: disable=arguments-differ
super().setUp()
2015-07-15 18:25:34 -04:00
def tearDown(self):
shutil.rmtree(self.temp_dir)
shutil.rmtree(self.config_dir)
shutil.rmtree(self.work_dir)
2021-04-05 18:04:21 -04:00
@mock.patch("certbot_apache._internal.parser.init_augeas")
def test_prepare_no_augeas(self, mock_init_augeas):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
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), self.config,
"/dummy/vhostpath", version=(2, 4, 22))
def test_init_old_aug(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
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), self.config,
"/dummy/vhostpath", version=(2, 4, 22))
@mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg")
def test_unparseable(self, mock_cfg):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import ApacheParser
2015-12-23 13:08:44 -05:00
mock_cfg.return_value = ('Define: TEST')
self.assertRaises(
errors.PluginError,
ApacheParser, os.path.relpath(self.config_path), self.config,
"/dummy/vhostpath", version=(2, 2, 22))
2015-12-09 21:51:16 -05:00
2015-07-15 18:25:34 -04:00
def test_root_normalized(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import ApacheParser
2015-07-15 18:25:34 -04:00
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
with mock.patch("certbot_apache._internal.parser.ApacheParser."
2015-07-15 18:25:34 -04:00
"update_runtime_variables"):
path = os.path.join(
self.temp_dir,
"debian_apache_2_4/////multiple_vhosts/../multiple_vhosts/apache2")
2015-12-07 05:03:54 -05:00
parser = ApacheParser(path, self.config, "/dummy/vhostpath")
2015-07-15 18:25:34 -04:00
self.assertEqual(parser.root, self.config_path)
def test_root_absolute(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import ApacheParser
with mock.patch("certbot_apache._internal.parser.ApacheParser."
2015-07-15 18:25:34 -04:00
"update_runtime_variables"):
parser = ApacheParser(
os.path.relpath(self.config_path), self.config, "/dummy/vhostpath")
2015-07-15 18:25:34 -04:00
self.assertEqual(parser.root, self.config_path)
def test_root_no_trailing_slash(self):
Make the contents of the apache plugin private (#7579) Part of #5775. Tree: ``` certbot-apache/certbot_apache ├── __init__.py ├── _internal │   ├── apache_util.py │   ├── augeas_lens │   │   ├── httpd.aug │   │   └── README │   ├── centos-options-ssl-apache.conf │   ├── configurator.py │   ├── constants.py │   ├── display_ops.py │   ├── entrypoint.py │   ├── http_01.py │   ├── __init__.py │   ├── obj.py │   ├── options-ssl-apache.conf │   ├── override_arch.py │   ├── override_centos.py │   ├── override_darwin.py │   ├── override_debian.py │   ├── override_fedora.py │   ├── override_gentoo.py │   ├── override_suse.py │   └── parser.py └── tests ├── ... ``` * Create _internal folder for certbot_apache * Move apache_util.py to _internal * Move display_ops.py to _internal * Move override_centos.py to _internal * Move override_gentoo.py to _internal * Move override_darwin.py to _internal * Move override_suse.py to _internal * Move override_debian.py to _internal * Move override_fedora.py to _internal * Move override_arch.py to _internal * Move parser.py to _internal * Move obj.py to _internal * Move http_01.py to _internal * Move entrypoint.py to _internal * Move constants.py to _internal * Move configurator.py to _internal * Move augeas_lens to _internal * Move options-ssl-apache.conf files to _internal * move augeas_lens in MANIFEST * Clean up some stray references to certbot_apache that could use _internal * Correct imports and lint
2019-11-25 12:44:40 -05:00
from certbot_apache._internal.parser import ApacheParser
with mock.patch("certbot_apache._internal.parser.ApacheParser."
2015-07-15 18:25:34 -04:00
"update_runtime_variables"):
parser = ApacheParser(
self.config_path + os.path.sep, self.config, "/dummy/vhostpath")
2015-07-15 18:25:34 -04:00
self.assertEqual(parser.root, self.config_path)
2015-07-19 22:49:44 -04:00
2015-03-26 20:39:08 -04:00
if __name__ == "__main__":
unittest.main() # pragma: no cover