Compare commits

...

5 Commits

Author SHA1 Message Date
Joona Hoikkala
ec5ab99e75 Import order 2017-10-20 20:11:38 +03:00
Joona Hoikkala
9bbf9d4cca Merge remote-tracking branch 'origin/master' into apache_override 2017-10-20 20:08:18 +03:00
Joona Hoikkala
fee3fb6c33 Make sure that configurator tests have the expected distro override 2017-10-11 20:31:47 +03:00
Joona Hoikkala
184925d241 Move more debian specific functionality to override and add caller access for overrides 2017-10-11 15:26:53 +03:00
Joona Hoikkala
d371b68e9f Distro override code back over current master 2017-10-11 15:26:53 +03:00
9 changed files with 341 additions and 218 deletions

View File

@@ -0,0 +1,75 @@
""" Utility functions for certbot-apache plugin """
import os
def get_mod_deps(mod_name):
"""Get known module dependencies.
.. note:: This does not need to be accurate in order for the client to
run. This simply keeps things clean if the user decides to revert
changes.
.. warning:: If all deps are not included, it may cause incorrect parsing
behavior, due to enable_mod's shortcut for updating the parser's
currently defined modules (`.ApacheConfigurator._add_parser_mod`)
This would only present a major problem in extremely atypical
configs that use ifmod for the missing deps.
"""
deps = {
"ssl": ["setenvif", "mime"]
}
return deps.get(mod_name, [])
def get_file_path(vhost_path):
"""Get file path from augeas_vhost_path.
Takes in Augeas path and returns the file name
:param str vhost_path: Augeas virtual host path
:returns: filename of vhost
:rtype: str
"""
if not vhost_path or not vhost_path.startswith("/files/"):
return None
return _split_aug_path(vhost_path)[0]
def get_internal_aug_path(vhost_path):
"""Get the Augeas path for a vhost with the file path removed.
:param str vhost_path: Augeas virtual host path
:returns: Augeas path to vhost relative to the containing file
:rtype: str
"""
return _split_aug_path(vhost_path)[1]
def _split_aug_path(vhost_path):
"""Splits an Augeas path into a file path and an internal path.
After removing "/files", this function splits vhost_path into the
file path and the remaining Augeas path.
:param str vhost_path: Augeas virtual host path
:returns: file path and internal Augeas path
:rtype: `tuple` of `str`
"""
# Strip off /files
file_path = vhost_path[6:]
internal_path = []
# Remove components from the end of file_path until it becomes valid
while not os.path.exists(file_path):
file_path, _, internal_path_part = file_path.rpartition("/")
internal_path.append(internal_path_part)
return file_path, "/".join(reversed(internal_path))

View File

@@ -19,6 +19,7 @@ from certbot import util
from certbot.plugins import common
from certbot.plugins.util import path_surgery
from certbot_apache import apache_util
from certbot_apache import augeas_configurator
from certbot_apache import constants
from certbot_apache import display_ops
@@ -122,6 +123,11 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
version = kwargs.pop("version", None)
super(ApacheConfigurator, self).__init__(*args, **kwargs)
# Detect OS and store distro based override class here to avoid
# calling the detection code every time we need something. Also provides
# access to the configurator object for the override class.
self.os_info = constants.get_override(self)
# Add name_server association dict
self.assoc = dict()
# Outstanding challenges
@@ -205,7 +211,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
# Get all of the available vhosts
self.vhosts = self.get_virtual_hosts()
install_ssl_options_conf(self.mod_ssl_conf, self.updated_mod_ssl_conf_digest)
constants.install_ssl_options_conf(self.mod_ssl_conf,
self.updated_mod_ssl_conf_digest)
# Prevent two Apache plugins from modifying a config at once
try:
@@ -585,7 +592,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
if addr.get_port() == "443":
is_ssl = True
filename = get_file_path(self.aug.get("/augeas/files%s/path" % get_file_path(path)))
filename = apache_util.get_file_path(
self.aug.get("/augeas/files%s/path" % apache_util.get_file_path(path)))
if filename is None:
return None
@@ -624,7 +632,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
new_vhost = self._create_vhost(path)
if not new_vhost:
continue
internal_path = get_internal_aug_path(new_vhost.path)
internal_path = apache_util.get_internal_aug_path(new_vhost.path)
realpath = os.path.realpath(new_vhost.filep)
if realpath not in file_paths:
file_paths[realpath] = new_vhost.filep
@@ -640,7 +648,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
for v in vhs:
if v.filep == file_paths[realpath]:
internal_paths[realpath].remove(
get_internal_aug_path(v.path))
apache_util.get_internal_aug_path(v.path))
else:
new_vhs.append(v)
vhs = new_vhs
@@ -1702,17 +1710,14 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
return redirects
@constants.override
def enable_site(self, vhost):
"""Enables an available site, Apache reload required.
.. note:: Does not make sure that the site correctly works or that all
modules are enabled appropriately.
.. todo:: This function should number subdomains before the domain
vhost
.. todo:: Make sure link is not broken...
.. note:: The distribution specific override replaces functionality
of this method where available.
:param vhost: vhost to enable
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
@@ -1724,39 +1729,17 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
if vhost.enabled:
return
# Handle non-debian systems
if not self.conf("handle-sites"):
if not self.parser.parsed_in_original(vhost.filep):
# Add direct include to root conf
self.parser.add_include(self.parser.loc["default"], vhost.filep)
vhost.enabled = True
return
if not self.parser.parsed_in_original(vhost.filep):
# Add direct include to root conf
logger.info("Enabling site %s by adding Include to root configuration",
vhost.filep)
self.save_notes += "Enabled site %s\n" % vhost.filep
self.parser.add_include(self.parser.loc["default"], vhost.filep)
vhost.enabled = True
return
enabled_path = ("%s/sites-enabled/%s" %
(self.parser.root, os.path.basename(vhost.filep)))
self.reverter.register_file_creation(False, enabled_path)
try:
os.symlink(vhost.filep, enabled_path)
except OSError as err:
if os.path.islink(enabled_path) and os.path.realpath(
enabled_path) == vhost.filep:
# Already in shape
vhost.enabled = True
return
else:
logger.warning(
"Could not symlink %s to %s, got error: %s", enabled_path,
vhost.filep, err.strerror)
errstring = ("Encountered error while trying to enable a " +
"newly created VirtualHost located at {0} by " +
"linking to it from {1}")
raise errors.NotSupportedError(errstring.format(vhost.filep,
enabled_path))
vhost.enabled = True
logger.info("Enabling available site: %s", vhost.filep)
self.save_notes += "Enabled site %s\n" % vhost.filep
def enable_mod(self, mod_name, temp=False):
@constants.override
def enable_mod(self, mod_name, temp=False): # pylint: disable=unused-argument
"""Enables module in Apache.
Both enables and reloads Apache so module is active.
@@ -1764,65 +1747,26 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
:param str mod_name: Name of the module to enable. (e.g. 'ssl')
:param bool temp: Whether or not this is a temporary action.
.. note:: The distribution specific override replaces functionality
of this method where available.
:raises .errors.NotSupportedError: If the filesystem layout is not
supported.
:raises .errors.MisconfigurationError: If a2enmod or a2dismod cannot be
run.
"""
# Support Debian specific setup
avail_path = os.path.join(self.parser.root, "mods-available")
enabled_path = os.path.join(self.parser.root, "mods-enabled")
if not os.path.isdir(avail_path) or not os.path.isdir(enabled_path):
raise errors.NotSupportedError(
"Unsupported directory layout. You may try to enable mod %s "
"and try again." % mod_name)
mod_message = ("Apache needs to have module \"{0}\" active for the " +
"requested installation options. Unfortunately Certbot is unable " +
"to install or enable it for you. Please install the module, and " +
"run Certbot again.")
raise errors.MisconfigurationError(mod_message.format(mod_name))
deps = _get_mod_deps(mod_name)
# Enable all dependencies
for dep in deps:
if (dep + "_module") not in self.parser.modules:
self._enable_mod_debian(dep, temp)
self._add_parser_mod(dep)
note = "Enabled dependency of %s module - %s" % (mod_name, dep)
if not temp:
self.save_notes += note + os.linesep
logger.debug(note)
# Enable actual module
self._enable_mod_debian(mod_name, temp)
self._add_parser_mod(mod_name)
if not temp:
self.save_notes += "Enabled %s module in Apache\n" % mod_name
logger.info("Enabled Apache %s module", mod_name)
# Modules can enable additional config files. Variables may be defined
# within these new configuration sections.
# Reload is not necessary as DUMP_RUN_CFG uses latest config.
self.parser.update_runtime_variables()
def _add_parser_mod(self, mod_name):
def add_parser_mod(self, mod_name):
"""Shortcut for updating parser modules."""
self.parser.modules.add(mod_name + "_module")
self.parser.modules.add("mod_" + mod_name + ".c")
def _enable_mod_debian(self, mod_name, temp):
"""Assumes mods-available, mods-enabled layout."""
# Generate reversal command.
# Try to be safe here... check that we can probably reverse before
# applying enmod command
if not util.exe_exists(self.conf("dismod")):
raise errors.MisconfigurationError(
"Unable to find a2dismod, please make sure a2enmod and "
"a2dismod are configured correctly for certbot.")
self.reverter.register_undo_command(
temp, [self.conf("dismod"), mod_name])
util.run_script([self.conf("enmod"), mod_name])
def restart(self):
"""Runs a config test and reloads the Apache server.
@@ -1945,84 +1889,3 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
self.restart()
self.parser.init_modules()
def _get_mod_deps(mod_name):
"""Get known module dependencies.
.. note:: This does not need to be accurate in order for the client to
run. This simply keeps things clean if the user decides to revert
changes.
.. warning:: If all deps are not included, it may cause incorrect parsing
behavior, due to enable_mod's shortcut for updating the parser's
currently defined modules (`.ApacheConfigurator._add_parser_mod`)
This would only present a major problem in extremely atypical
configs that use ifmod for the missing deps.
"""
deps = {
"ssl": ["setenvif", "mime"]
}
return deps.get(mod_name, [])
def get_file_path(vhost_path):
"""Get file path from augeas_vhost_path.
Takes in Augeas path and returns the file name
:param str vhost_path: Augeas virtual host path
:returns: filename of vhost
:rtype: str
"""
if not vhost_path or not vhost_path.startswith("/files/"):
return None
return _split_aug_path(vhost_path)[0]
def get_internal_aug_path(vhost_path):
"""Get the Augeas path for a vhost with the file path removed.
:param str vhost_path: Augeas virtual host path
:returns: Augeas path to vhost relative to the containing file
:rtype: str
"""
return _split_aug_path(vhost_path)[1]
def _split_aug_path(vhost_path):
"""Splits an Augeas path into a file path and an internal path.
After removing "/files", this function splits vhost_path into the
file path and the remaining Augeas path.
:param str vhost_path: Augeas virtual host path
:returns: file path and internal Augeas path
:rtype: `tuple` of `str`
"""
# Strip off /files
file_path = vhost_path[6:]
internal_path = []
# Remove components from the end of file_path until it becomes valid
while not os.path.exists(file_path):
file_path, _, internal_path_part = file_path.rpartition("/")
internal_path.append(internal_path_part)
return file_path, "/".join(reversed(internal_path))
def install_ssl_options_conf(options_ssl, options_ssl_digest):
"""Copy Certbot's SSL options file into the system's config dir if required."""
# XXX if we ever try to enforce a local privilege boundary (eg, running
# certbot for unprivileged users via setuid), this function will need
# to be modified.
return common.install_version_controlled_file(options_ssl, options_ssl_digest,
constants.os_constant("MOD_SSL_CONF_SRC"), constants.ALL_SSL_OPTIONS_HASHES)

View File

@@ -2,6 +2,11 @@
import pkg_resources
from certbot import util
from certbot.plugins import common
from certbot_apache import override_centos
from certbot_apache import override_debian
CLI_DEFAULTS_DEFAULT = dict(
server_root="/etc/apache2",
vhost_root="/etc/apache2/sites-available",
@@ -17,6 +22,7 @@ CLI_DEFAULTS_DEFAULT = dict(
handle_mods=False,
handle_sites=False,
challenge_location="/etc/apache2",
override_class=None,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "options-ssl-apache.conf")
)
@@ -35,6 +41,7 @@ CLI_DEFAULTS_DEBIAN = dict(
handle_mods=True,
handle_sites=True,
challenge_location="/etc/apache2",
override_class=override_debian.Override,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "options-ssl-apache.conf")
)
@@ -53,6 +60,7 @@ CLI_DEFAULTS_CENTOS = dict(
handle_mods=False,
handle_sites=False,
challenge_location="/etc/httpd/conf.d",
override_class=override_centos.Override,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "centos-options-ssl-apache.conf")
)
@@ -71,6 +79,7 @@ CLI_DEFAULTS_GENTOO = dict(
handle_mods=False,
handle_sites=False,
challenge_location="/etc/apache2/vhosts.d",
override_class=None,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "options-ssl-apache.conf")
)
@@ -89,6 +98,7 @@ CLI_DEFAULTS_DARWIN = dict(
handle_mods=False,
handle_sites=False,
challenge_location="/etc/apache2/other",
override_class=None,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "options-ssl-apache.conf")
)
@@ -107,6 +117,7 @@ CLI_DEFAULTS_SUSE = dict(
handle_mods=False,
handle_sites=False,
challenge_location="/etc/apache2/vhosts.d",
override_class=None,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "options-ssl-apache.conf")
)
@@ -125,6 +136,7 @@ CLI_DEFAULTS_ARCH = dict(
handle_mods=False,
handle_sites=False,
challenge_location="/etc/httpd/conf",
override_class=None,
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", "options-ssl-apache.conf")
)
@@ -192,6 +204,14 @@ UIR_ARGS = ["always", "set", "Content-Security-Policy",
HEADER_ARGS = {"Strict-Transport-Security": HSTS_ARGS,
"Upgrade-Insecure-Requests": UIR_ARGS}
def install_ssl_options_conf(options_ssl, options_ssl_digest):
"""Copy Certbot's SSL options file into the system's config dir if required."""
# XXX if we ever try to enforce a local privilege boundary (eg, running
# certbot for unprivileged users via setuid), this function will need
# to be modified.
return common.install_version_controlled_file(options_ssl, options_ssl_digest,
os_constant("MOD_SSL_CONF_SRC"), ALL_SSL_OPTIONS_HASHES)
def os_constant(key):
"""
@@ -227,3 +247,31 @@ def os_like_constants():
if os_name in CLI_DEFAULTS.keys():
return CLI_DEFAULTS[os_name]
return {}
def get_override(caller):
"""
Initialize the override class and pass the caller class to it
:param caller: `class` of caller
:return: Override class or `None` if not found
"""
override_class = os_constant("override_class")
if override_class:
return override_class(caller)
return None
def override(method):
"""Decorator for ApacheConfigurator for distribution specific method
overrides."""
def override_args(caller_class, *args, **kwargs):
"""Check if distro specific class overrides called method, return
overriding method if found, in other case, return the default"""
try:
# Try to find overriding method
caller = {"class": caller_class, "method": method}
return getattr(caller_class.os_info,
method.__name__)(caller, *args, **kwargs)
except AttributeError:
# Override not found, return the default
return method(caller_class, *args, **kwargs)
return override_args

View File

@@ -0,0 +1,10 @@
""" Distribution specific overrides for CentOS family (RHEL/Fedora/CentOS """
class Override(object):
"""CentOS override class"""
def __init__(self, config):
"""
Initializes the override class.
:param config: caller `certbot_apache.configurator.ApacheConfigurator`
"""
self.config = config

View File

@@ -0,0 +1,126 @@
""" Distribution specific override class for Debian family (Ubuntu/Debian) """
import logging
import os
from certbot import errors
from certbot import util
from certbot_apache import apache_util
logger = logging.getLogger(__name__)
class Override(object):
""" Debian override class """
def __init__(self, config):
"""
Initializes the override class.
:param config: caller `certbot_apache.configurator.ApacheConfigurator`
"""
self.config = config
def enable_site(self, caller, vhost):
"""Enables an available site, Apache reload required.
.. note:: Does not make sure that the site correctly works or that all
modules are enabled appropriately.
:param vhost: vhost to enable
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:raises .errors.NotSupportedError: If filesystem layout is not
supported.
"""
if vhost.enabled:
return
enabled_path = ("%s/sites-enabled/%s" %
(self.config.parser.root,
os.path.basename(vhost.filep)))
if not os.path.isdir(os.path.dirname(enabled_path)):
# For some reason, sites-enabled / sites-available do not exist
# Call the original caller method
caller["method"](caller["class"], vhost)
self.config.reverter.register_file_creation(False, enabled_path)
try:
os.symlink(vhost.filep, enabled_path)
except OSError as err:
if os.path.islink(enabled_path) and os.path.realpath(
enabled_path) == vhost.filep:
# Already in shape
vhost.enabled = True
return
else:
logger.warning(
"Could not symlink %s to %s, got error: %s", enabled_path,
vhost.filep, err.strerror)
errstring = ("Encountered error while trying to enable a " +
"newly created VirtualHost located at {0} by " +
"linking to it from {1}")
raise errors.NotSupportedError(errstring.format(vhost.filep,
enabled_path))
vhost.enabled = True
logger.info("Enabling available site: %s", vhost.filep)
self.config.save_notes += "Enabled site %s\n" % vhost.filep
def enable_mod(self, caller, mod_name, temp=False):
# pylint: disable=unused-argument
"""Enables module in Apache.
Both enables and reloads Apache so module is active.
:param str mod_name: Name of the module to enable. (e.g. 'ssl')
:param bool temp: Whether or not this is a temporary action.
:raises .errors.NotSupportedError: If the filesystem layout is not
supported.
:raises .errors.MisconfigurationError: If a2enmod or a2dismod cannot be
run.
"""
avail_path = os.path.join(self.config.parser.root, "mods-available")
enabled_path = os.path.join(self.config.parser.root, "mods-enabled")
if not os.path.isdir(avail_path) or not os.path.isdir(enabled_path):
raise errors.NotSupportedError(
"Unsupported directory layout. You may try to enable mod %s "
"and try again." % mod_name)
deps = apache_util.get_mod_deps(mod_name)
# Enable all dependencies
for dep in deps:
if (dep + "_module") not in self.config.parser.modules:
self._enable_mod_debian(dep, temp)
self.config.add_parser_mod(dep)
note = "Enabled dependency of %s module - %s" % (mod_name, dep)
if not temp:
self.config.save_notes += note + os.linesep
logger.debug(note)
# Enable actual module
self._enable_mod_debian(mod_name, temp)
self.config.add_parser_mod(mod_name)
if not temp:
self.config.save_notes += "Enabled %s module in Apache\n" % mod_name
logger.info("Enabled Apache %s module", mod_name)
# Modules can enable additional config files. Variables may be defined
# within these new configuration sections.
# Reload is not necessary as DUMP_RUN_CFG uses latest config.
self.config.parser.update_runtime_variables()
def _enable_mod_debian(self, mod_name, temp):
"""Assumes mods-available, mods-enabled layout."""
# Generate reversal command.
# Try to be safe here... check that we can probably reverse before
# applying enmod command
if not util.exe_exists(self.config.conf("dismod")):
raise errors.MisconfigurationError(
"Unable to find a2dismod, please make sure a2enmod and "
"a2dismod are configured correctly for certbot.")
self.config.reverter.register_undo_command(
temp, [self.config.conf("dismod"), mod_name])
util.run_script([self.config.conf("enmod"), mod_name])

View File

@@ -19,8 +19,6 @@ logger = logging.getLogger(__name__)
class ApacheParser(object):
"""Class handles the fine details of parsing the Apache Configuration.
.. todo:: Make parsing general... remove sites-available etc...
:ivar str root: Normalized absolute path to the server root
directory. Without trailing slash.
:ivar set modules: All module names that are currently enabled.

View File

@@ -19,10 +19,10 @@ from certbot import errors
from certbot.tests import acme_util
from certbot.tests import util as certbot_util
from certbot_apache import configurator
from certbot_apache import constants
from certbot_apache import parser
from certbot_apache import obj
from certbot_apache import apache_util
from certbot_apache.tests import util
@@ -41,6 +41,9 @@ class MultipleVhostsTest(util.ApacheTest):
"""Mock default vhost path"""
if key == "vhost_root":
return vhost_path
elif key == "override_class":
from certbot_apache import override_debian
return override_debian.Override
else:
return orig_os_constant(key)
@@ -164,13 +167,11 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertTrue("certbot.demo" in names)
def test_get_bad_path(self):
from certbot_apache.configurator import get_file_path
self.assertEqual(get_file_path(None), None)
self.assertEqual(get_file_path("nonexistent"), None)
self.assertEqual(apache_util.get_file_path(None), None)
self.assertEqual(apache_util.get_file_path("nonexistent"), None)
self.assertEqual(self.config._create_vhost("nonexistent"), None) # pylint: disable=protected-access
def test_get_aug_internal_path(self):
from certbot_apache.configurator import get_internal_aug_path
internal_paths = [
"Virtualhost", "IfModule/VirtualHost", "VirtualHost", "VirtualHost",
"Macro/VirtualHost", "IfModule/VirtualHost", "VirtualHost",
@@ -178,7 +179,8 @@ class MultipleVhostsTest(util.ApacheTest):
for i, internal_path in enumerate(internal_paths):
self.assertEqual(
get_internal_aug_path(self.vh_truth[i].path), internal_path)
apache_util.get_internal_aug_path(self.vh_truth[i].path),
internal_path)
def test_bad_servername_alias(self):
ssl_vh1 = obj.VirtualHost(
@@ -345,6 +347,14 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertRaises(
errors.MisconfigurationError, self.config.enable_mod, "ssl")
def test_enable_mod_nonexistent(self):
from certbot_apache import override_centos
self.config.os_info = override_centos.Override(self.config)
self.assertRaises(
errors.MisconfigurationError,
self.config.enable_mod,
"whatever")
def test_enable_site_already_enabled(self):
self.assertTrue(self.vh_truth[1].enabled)
self.config.enable_site(self.vh_truth[1])
@@ -356,29 +366,28 @@ class MultipleVhostsTest(util.ApacheTest):
self.config.enable_site,
obj.VirtualHost("asdf", "afsaf", set(), False, False))
def test_enable_site_nonexistent(self):
from certbot_apache import override_centos
self.config.os_info = override_centos.Override(self.config)
self.assertEqual(self.config.enable_site(self.vh_truth[1]), None)
def test_enable_site_nondebian(self):
mock_c = "certbot_apache.configurator.ApacheConfigurator.conf"
def conf_side_effect(arg):
""" Mock function for ApacheConfigurator.conf """
confvars = {"handle-sites": False}
if arg in confvars:
return confvars[arg]
from certbot_apache import override_centos
self.config.os_info = override_centos.Override(self.config)
inc_path = "/path/to/wherever"
vhost = self.vh_truth[0]
with mock.patch(mock_c) as mock_conf:
mock_conf.side_effect = conf_side_effect
vhost.enabled = False
vhost.filep = inc_path
self.assertFalse(self.config.parser.find_dir("Include", inc_path))
self.assertFalse(
os.path.dirname(inc_path) in self.config.parser.existing_paths)
self.config.enable_site(vhost)
self.assertTrue(self.config.parser.find_dir("Include", inc_path))
self.assertTrue(
os.path.dirname(inc_path) in self.config.parser.existing_paths)
self.assertTrue(
os.path.basename(inc_path) in self.config.parser.existing_paths[
os.path.dirname(inc_path)])
vhost.enabled = False
vhost.filep = inc_path
self.assertFalse(self.config.parser.find_dir("Include", inc_path))
self.assertFalse(
os.path.dirname(inc_path) in self.config.parser.existing_paths)
self.config.enable_site(vhost)
self.assertTrue(self.config.parser.find_dir("Include", inc_path))
self.assertTrue(
os.path.dirname(inc_path) in self.config.parser.existing_paths)
self.assertTrue(
os.path.basename(inc_path) in self.config.parser.existing_paths[
os.path.dirname(inc_path)])
def test_deploy_cert_enable_new_vhost(self):
# Create
@@ -427,12 +436,12 @@ class MultipleVhostsTest(util.ApacheTest):
# Verify one directive was found in the correct file
self.assertEqual(len(loc_cert), 1)
self.assertEqual(
configurator.get_file_path(loc_cert[0]),
apache_util.get_file_path(loc_cert[0]),
self.vh_truth[1].filep)
self.assertEqual(len(loc_key), 1)
self.assertEqual(
configurator.get_file_path(loc_key[0]),
apache_util.get_file_path(loc_key[0]),
self.vh_truth[1].filep)
def test_deploy_cert_newssl_no_fullchain(self):
@@ -469,25 +478,16 @@ class MultipleVhostsTest(util.ApacheTest):
def test_deploy_cert_not_parsed_path(self):
# Make sure that we add include to root config for vhosts when
# handle-sites is false
# running Debian, but missing sites-enabled structure
self.config.parser.modules.add("ssl_module")
self.config.parser.modules.add("mod_ssl.c")
tmp_path = os.path.realpath(tempfile.mkdtemp("vhostroot"))
os.chmod(tmp_path, 0o755)
mock_p = "certbot_apache.configurator.ApacheConfigurator._get_ssl_vhost_path"
mock_a = "certbot_apache.parser.ApacheParser.add_include"
mock_c = "certbot_apache.configurator.ApacheConfigurator.conf"
orig_conf = self.config.conf
def conf_side_effect(arg):
""" Mock function for ApacheConfigurator.conf """
confvars = {"handle-sites": False}
if arg in confvars:
return confvars[arg]
else:
return orig_conf("arg")
with mock.patch(mock_c) as mock_conf:
mock_conf.side_effect = conf_side_effect
with mock.patch("os.path.isdir") as mock_osp:
mock_osp.return_value = False
with mock.patch(mock_p) as mock_path:
mock_path.return_value = os.path.join(tmp_path, "whatever.conf")
with mock.patch(mock_a) as mock_add:
@@ -558,17 +558,17 @@ class MultipleVhostsTest(util.ApacheTest):
# Verify one directive was found in the correct file
self.assertEqual(len(loc_cert), 1)
self.assertEqual(
configurator.get_file_path(loc_cert[0]),
apache_util.get_file_path(loc_cert[0]),
self.vh_truth[1].filep)
self.assertEqual(len(loc_key), 1)
self.assertEqual(
configurator.get_file_path(loc_key[0]),
apache_util.get_file_path(loc_key[0]),
self.vh_truth[1].filep)
self.assertEqual(len(loc_chain), 1)
self.assertEqual(
configurator.get_file_path(loc_chain[0]),
apache_util.get_file_path(loc_chain[0]),
self.vh_truth[1].filep)
# One more time for chain directive setting
@@ -952,7 +952,7 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertTrue(isinstance(self.config.get_chall_pref(""), list))
def test_install_ssl_options_conf(self):
from certbot_apache.configurator import install_ssl_options_conf
from certbot_apache.constants import install_ssl_options_conf
path = os.path.join(self.work_dir, "test_it")
other_path = os.path.join(self.work_dir, "other_test_it")
install_ssl_options_conf(path, other_path)
@@ -1571,7 +1571,7 @@ class InstallSslOptionsConfTest(util.ApacheTest):
self.config_path, self.vhost_path, self.config_dir, self.work_dir)
def _call(self):
from certbot_apache.configurator import install_ssl_options_conf
from certbot_apache.constants import install_ssl_options_conf
install_ssl_options_conf(self.config.mod_ssl_conf, self.config.updated_mod_ssl_conf_digest)
def _current_ssl_options_hash(self):

View File

@@ -29,6 +29,7 @@ class ConstantsTest(unittest.TestCase):
self.assertEqual(constants.os_constant("server_root"), "/etc/apache2")
self.assertEqual(constants.os_constant("vhost_root"),
"/etc/apache2/sites-available")
self.assertEqual(constants.get_override(None), None)
@mock.patch("certbot.util.get_systemd_os_like")
@mock.patch("certbot.util.get_os_info")

View File

@@ -9,6 +9,7 @@ from certbot.plugins import common_test
from certbot_apache import obj
from certbot_apache.tests import util
from certbot_apache import override_debian
from six.moves import xrange # pylint: disable=redefined-builtin, import-error
@@ -25,6 +26,7 @@ class TlsSniPerformTest(util.ApacheTest):
config = util.get_apache_configurator(
self.config_path, self.vhost_path, self.config_dir, self.work_dir)
config.config.tls_sni_01_port = 443
config.os_info = override_debian.Override(config)
from certbot_apache import tls_sni_01
self.sni = tls_sni_01.ApacheTlsSni01(config)