mirror of
https://github.com/certbot/certbot.git
synced 2026-07-28 08:05:31 +02:00
Merge pull request #1811 from joohoi/multios_apache
Support apache plugin in different operating systems
This commit is contained in:
@@ -45,3 +45,11 @@ then
|
||||
echo "Could not install additional dependencies. Aborting bootstrap!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
if $tool list installed "httpd" >/dev/null 2>&1; then
|
||||
if ! $tool install -y mod_ssl
|
||||
then
|
||||
echo "Apache found, but mod_ssl could not be installed."
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -86,18 +86,29 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
|
||||
@classmethod
|
||||
def add_parser_arguments(cls, add):
|
||||
add("ctl", default=constants.CLI_DEFAULTS["ctl"],
|
||||
add("ctl", default=constants.os_constant("ctl"),
|
||||
help="Path to the 'apache2ctl' binary, used for 'configtest', "
|
||||
"retrieving the Apache2 version number, and initialization "
|
||||
"parameters.")
|
||||
add("enmod", default=constants.CLI_DEFAULTS["enmod"],
|
||||
add("enmod", default=constants.os_constant("enmod"),
|
||||
help="Path to the Apache 'a2enmod' binary.")
|
||||
add("dismod", default=constants.CLI_DEFAULTS["dismod"],
|
||||
add("dismod", default=constants.os_constant("dismod"),
|
||||
help="Path to the Apache 'a2dismod' binary.")
|
||||
add("le-vhost-ext", default=constants.CLI_DEFAULTS["le_vhost_ext"],
|
||||
add("le-vhost-ext", default=constants.os_constant("le_vhost_ext"),
|
||||
help="SSL vhost configuration extension.")
|
||||
add("server-root", default=constants.CLI_DEFAULTS["server_root"],
|
||||
add("server-root", default=constants.os_constant("server_root"),
|
||||
help="Apache server root directory.")
|
||||
add("vhost-root", default=constants.os_constant("vhost_root"),
|
||||
help="Apache server VirtualHost configuration root")
|
||||
add("challenge-location",
|
||||
default=constants.os_constant("challenge_location"),
|
||||
help="Directory path for challenge configuration.")
|
||||
add("handle-modules", default=constants.os_constant("handle_mods"),
|
||||
help="Let installer handle enabling required modules for you." +
|
||||
"(Only Ubuntu/Debian currently)")
|
||||
add("handle-sites", default=constants.os_constant("handle_sites"),
|
||||
help="Let installer handle enabling sites for you." +
|
||||
"(Only Ubuntu/Debian currently)")
|
||||
le_util.add_deprecated_argument(add, "init-script", 1)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -138,17 +149,13 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
"""
|
||||
# Verify Apache is installed
|
||||
for exe in (self.conf("ctl"), self.conf("enmod"), self.conf("dismod")):
|
||||
if not le_util.exe_exists(exe):
|
||||
raise errors.NoInstallationError
|
||||
if exe is not None:
|
||||
if not le_util.exe_exists(exe):
|
||||
raise errors.NoInstallationError
|
||||
|
||||
# Make sure configuration is valid
|
||||
self.config_test()
|
||||
|
||||
self.parser = parser.ApacheParser(
|
||||
self.aug, self.conf("server-root"), self.conf("ctl"))
|
||||
# Check for errors in parsing files with Augeas
|
||||
self.check_parsing_errors("httpd.aug")
|
||||
|
||||
# Set Version
|
||||
if self.version is None:
|
||||
self.version = self.get_version()
|
||||
@@ -156,6 +163,12 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
raise errors.NotSupportedError(
|
||||
"Apache Version %s not supported.", str(self.version))
|
||||
|
||||
self.parser = parser.ApacheParser(
|
||||
self.aug, self.conf("server-root"), self.conf("vhost-root"),
|
||||
self.conf("ctl"), self.version)
|
||||
# Check for errors in parsing files with Augeas
|
||||
self.check_parsing_errors("httpd.aug")
|
||||
|
||||
# Get all of the available vhosts
|
||||
self.vhosts = self.get_virtual_hosts()
|
||||
|
||||
@@ -236,9 +249,10 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
if chain_path is not None:
|
||||
self.save_notes += "\tSSLCertificateChainFile %s\n" % chain_path
|
||||
|
||||
# Make sure vhost is enabled
|
||||
if not vhost.enabled:
|
||||
self.enable_site(vhost)
|
||||
# Make sure vhost is enabled if distro with enabled / available
|
||||
if self.conf("handle-sites"):
|
||||
if not vhost.enabled:
|
||||
self.enable_site(vhost)
|
||||
|
||||
def choose_vhost(self, target_name, temp=False):
|
||||
"""Chooses a virtual host based on the given domain name.
|
||||
@@ -458,7 +472,10 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
is_ssl = True
|
||||
|
||||
filename = get_file_path(path)
|
||||
is_enabled = self.is_site_enabled(filename)
|
||||
if self.conf("handle-sites"):
|
||||
is_enabled = self.is_site_enabled(filename)
|
||||
else:
|
||||
is_enabled = True
|
||||
|
||||
macro = False
|
||||
if "/macro/" in path.lower():
|
||||
@@ -469,7 +486,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
self._add_servernames(vhost)
|
||||
return vhost
|
||||
|
||||
# TODO: make "sites-available" a configurable directory
|
||||
def get_virtual_hosts(self):
|
||||
"""Returns list of virtual hosts found in the Apache configuration.
|
||||
|
||||
@@ -478,10 +494,10 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
:rtype: list
|
||||
|
||||
"""
|
||||
# Search sites-available, httpd.conf for possible virtual hosts
|
||||
# Search vhost-root, httpd.conf for possible virtual hosts
|
||||
paths = self.aug.match(
|
||||
("/files%s/sites-available//*[label()=~regexp('%s')]" %
|
||||
(self.parser.root, parser.case_i("VirtualHost"))))
|
||||
("/files%s//*[label()=~regexp('%s')]" %
|
||||
(self.conf("vhost-root"), parser.case_i("VirtualHost"))))
|
||||
|
||||
vhs = []
|
||||
|
||||
@@ -540,10 +556,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
:param str port: Port to listen on
|
||||
|
||||
"""
|
||||
if "ssl_module" not in self.parser.modules:
|
||||
self.enable_mod("ssl", temp=temp)
|
||||
if self.version >= (2, 4) and "socache_shmcb_module" not in self.parser.modules:
|
||||
self.enable_mod("socache_shmcb", temp=temp)
|
||||
|
||||
self.prepare_https_modules(temp)
|
||||
# Check for Listen <port>
|
||||
# Note: This could be made to also look for ip:443 combo
|
||||
listens = [self.parser.get_arg(x).split()[0] for x in self.parser.find_dir("Listen")]
|
||||
@@ -584,6 +598,20 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
ip, port, self.parser.loc["listen"])
|
||||
listens.append("%s:%s" % (ip, port))
|
||||
|
||||
def prepare_https_modules(self, temp):
|
||||
"""Helper method for prepare_server_https, taking care of enabling
|
||||
needed modules
|
||||
|
||||
:param boolean temp: If the change is temporary
|
||||
"""
|
||||
|
||||
if self.conf("handle-modules"):
|
||||
if "ssl_module" not in self.parser.modules:
|
||||
self.enable_mod("ssl", temp=temp)
|
||||
if self.version >= (2, 4) and ("socache_shmcb_module" not in
|
||||
self.parser.modules):
|
||||
self.enable_mod("socache_shmcb", temp=temp)
|
||||
|
||||
def make_addrs_sni_ready(self, addrs):
|
||||
"""Checks to see if the server is ready for SNI challenges.
|
||||
|
||||
@@ -606,7 +634,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
|
||||
Duplicates vhost and adds default ssl options
|
||||
New vhost will reside as (nonssl_vhost.path) +
|
||||
``letsencrypt_apache.constants.CLI_DEFAULTS["le_vhost_ext"]``
|
||||
``letsencrypt_apache.constants.os_constant("le_vhost_ext")``
|
||||
|
||||
.. note:: This function saves the configuration
|
||||
|
||||
@@ -1068,8 +1096,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
if len(ssl_vhost.name) < (255 - (len(redirect_filename) + 1)):
|
||||
redirect_filename = "le-redirect-%s.conf" % ssl_vhost.name
|
||||
|
||||
redirect_filepath = os.path.join(
|
||||
self.parser.root, "sites-available", redirect_filename)
|
||||
redirect_filepath = os.path.join(self.conf("vhost-root"), redirect_filename)
|
||||
|
||||
# Register the new file that will be created
|
||||
# Note: always register the creation before writing to ensure file will
|
||||
@@ -1155,7 +1182,14 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
:rtype: bool
|
||||
|
||||
"""
|
||||
|
||||
enabled_dir = os.path.join(self.parser.root, "sites-enabled")
|
||||
if not os.path.isdir(enabled_dir):
|
||||
error_msg = ("Directory '{0}' does not exist. Please ensure "
|
||||
"that the values for --apache-handle-sites and "
|
||||
"--apache-server-root are correct for your "
|
||||
"environment.".format(enabled_dir))
|
||||
raise errors.ConfigurationError(error_msg)
|
||||
for entry in os.listdir(enabled_dir):
|
||||
try:
|
||||
if filecmp.cmp(avail_fp, os.path.join(enabled_dir, entry)):
|
||||
@@ -1281,7 +1315,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
|
||||
"""
|
||||
try:
|
||||
le_util.run_script([self.conf("ctl"), "-k", "graceful"])
|
||||
le_util.run_script([self.conf("ctl"), "graceful"])
|
||||
except errors.SubprocessError as err:
|
||||
raise errors.MisconfigurationError(str(err))
|
||||
|
||||
@@ -1308,7 +1342,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
|
||||
"""
|
||||
try:
|
||||
stdout, _ = le_util.run_script([self.conf("ctl"), "-v"])
|
||||
stdout, _ = le_util.run_script(
|
||||
constants.os_constant("version_cmd"))
|
||||
except errors.SubprocessError:
|
||||
raise errors.PluginError(
|
||||
"Unable to run %s -v" % self.conf("ctl"))
|
||||
|
||||
@@ -1,14 +1,56 @@
|
||||
"""Apache plugin constants."""
|
||||
import pkg_resources
|
||||
from letsencrypt import le_util
|
||||
|
||||
|
||||
CLI_DEFAULTS = dict(
|
||||
CLI_DEFAULTS_DEBIAN = dict(
|
||||
server_root="/etc/apache2",
|
||||
vhost_root="/etc/apache2/sites-available",
|
||||
ctl="apache2ctl",
|
||||
version_cmd=['apache2ctl', '-v'],
|
||||
define_cmd=['apache2ctl', '-t', '-D', 'DUMP_RUN_CFG'],
|
||||
enmod="a2enmod",
|
||||
dismod="a2dismod",
|
||||
le_vhost_ext="-le-ssl.conf",
|
||||
handle_mods=True,
|
||||
handle_sites=True,
|
||||
challenge_location="/etc/apache2"
|
||||
)
|
||||
CLI_DEFAULTS_CENTOS = dict(
|
||||
server_root="/etc/httpd",
|
||||
vhost_root="/etc/httpd/conf.d",
|
||||
ctl="apachectl",
|
||||
version_cmd=['apachectl', '-v'],
|
||||
define_cmd=['apachectl', '-t', '-D', 'DUMP_RUN_CFG'],
|
||||
enmod=None,
|
||||
dismod=None,
|
||||
le_vhost_ext="-le-ssl.conf",
|
||||
handle_mods=False,
|
||||
handle_sites=False,
|
||||
challenge_location="/etc/httpd/conf.d"
|
||||
)
|
||||
CLI_DEFAULTS_GENTOO = dict(
|
||||
server_root="/etc/apache2",
|
||||
vhost_root="/etc/apache2/vhosts.d",
|
||||
ctl="apache2ctl",
|
||||
version_cmd=['/usr/sbin/apache2', '-v'],
|
||||
define_cmd=['/usr/sbin/apache2', '-t', '-D', 'DUMP_RUN_CFG'],
|
||||
enmod=None,
|
||||
dismod=None,
|
||||
le_vhost_ext="-le-ssl.conf",
|
||||
handle_mods=False,
|
||||
handle_sites=False,
|
||||
challenge_location="/etc/apache2/vhosts.d"
|
||||
)
|
||||
CLI_DEFAULTS = {
|
||||
"debian": CLI_DEFAULTS_DEBIAN,
|
||||
"ubuntu": CLI_DEFAULTS_DEBIAN,
|
||||
"centos": CLI_DEFAULTS_CENTOS,
|
||||
"centos linux": CLI_DEFAULTS_CENTOS,
|
||||
"fedora": CLI_DEFAULTS_CENTOS,
|
||||
"red hat enterprise linux server": CLI_DEFAULTS_CENTOS,
|
||||
"gentoo base system": CLI_DEFAULTS_GENTOO
|
||||
}
|
||||
"""CLI defaults."""
|
||||
|
||||
MOD_SSL_CONF_DEST = "options-ssl-apache.conf"
|
||||
@@ -42,3 +84,15 @@ UIR_ARGS = ["always", "set", "Content-Security-Policy",
|
||||
HEADER_ARGS = {"Strict-Transport-Security": HSTS_ARGS,
|
||||
"Upgrade-Insecure-Requests": UIR_ARGS}
|
||||
|
||||
|
||||
def os_constant(key):
|
||||
"""Get a constant value for operating system
|
||||
:param key: name of cli constant
|
||||
:return: value of constant for active os
|
||||
"""
|
||||
os_info = le_util.get_os_info()
|
||||
try:
|
||||
constants = CLI_DEFAULTS[os_info[0].lower()]
|
||||
except KeyError:
|
||||
constants = CLI_DEFAULTS["debian"]
|
||||
return constants[key]
|
||||
|
||||
@@ -14,9 +14,9 @@ SSLOptions +StrictRequire
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
|
||||
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
|
||||
|
||||
CustomLog /var/log/apache2/access.log vhost_combined
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/error.log
|
||||
#CustomLog /var/log/apache2/access.log vhost_combined
|
||||
#LogLevel warn
|
||||
#ErrorLog /var/log/apache2/error.log
|
||||
|
||||
# Always ensure Cookies have "Secure" set (JAH 2012/1)
|
||||
#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"
|
||||
|
||||
@@ -8,6 +8,7 @@ import subprocess
|
||||
|
||||
from letsencrypt import errors
|
||||
|
||||
from letsencrypt_apache import constants
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -27,7 +28,7 @@ class ApacheParser(object):
|
||||
arg_var_interpreter = re.compile(r"\$\{[^ \}]*}")
|
||||
fnmatch_chars = set(["*", "?", "\\", "[", "]"])
|
||||
|
||||
def __init__(self, aug, root, ctl):
|
||||
def __init__(self, aug, root, vhostroot, ctl, version=(2, 4)):
|
||||
# Note: Order is important here.
|
||||
|
||||
# This uses the binary, so it can be done first.
|
||||
@@ -35,8 +36,8 @@ class ApacheParser(object):
|
||||
# https://httpd.apache.org/docs/2.4/mod/core.html#ifdefine
|
||||
# This only handles invocation parameters and Define directives!
|
||||
self.variables = {}
|
||||
self.unparsable = False
|
||||
self.update_runtime_variables(ctl)
|
||||
if version >= (2, 4):
|
||||
self.update_runtime_variables(ctl)
|
||||
|
||||
self.aug = aug
|
||||
# Find configuration root and make sure augeas can parse it.
|
||||
@@ -44,6 +45,8 @@ class ApacheParser(object):
|
||||
self.loc = {"root": self._find_config_root()}
|
||||
self._parse_file(self.loc["root"])
|
||||
|
||||
self.vhostroot = os.path.abspath(vhostroot)
|
||||
|
||||
# This problem has been fixed in Augeas 1.0
|
||||
self.standardize_excl()
|
||||
|
||||
@@ -56,12 +59,11 @@ class ApacheParser(object):
|
||||
# Set up rest of locations
|
||||
self.loc.update(self._set_locations())
|
||||
|
||||
# Must also attempt to parse sites-available or equivalent
|
||||
# Sites-available is not included naturally in configuration
|
||||
self._parse_file(os.path.join(self.root, "sites-available") + "/*")
|
||||
# Must also attempt to parse virtual host root
|
||||
self._parse_file(self.vhostroot + "/*.conf")
|
||||
|
||||
#check to see if there were unparsed define statements
|
||||
if self.unparsable:
|
||||
if version < (2, 4):
|
||||
if self.find_dir("Define", exclude=False):
|
||||
raise errors.PluginError("Error parsing runtime variables")
|
||||
|
||||
@@ -106,13 +108,12 @@ class ApacheParser(object):
|
||||
try:
|
||||
matches.remove("DUMP_RUN_CFG")
|
||||
except ValueError:
|
||||
self.unparsable = True
|
||||
return
|
||||
|
||||
for match in matches:
|
||||
if match.count("=") > 1:
|
||||
logger.error("Unexpected number of equal signs in "
|
||||
"apache2ctl -D DUMP_RUN_CFG")
|
||||
"runtime config dump.")
|
||||
raise errors.PluginError(
|
||||
"Error parsing Apache runtime variables")
|
||||
parts = match.partition("=")
|
||||
@@ -128,7 +129,7 @@ class ApacheParser(object):
|
||||
"""
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
[ctl, "-t", "-D", "DUMP_RUN_CFG"],
|
||||
constants.os_constant("define_cmd"),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = proc.communicate()
|
||||
@@ -552,8 +553,7 @@ class ApacheParser(object):
|
||||
|
||||
def _find_config_root(self):
|
||||
"""Find the Apache Configuration Root file."""
|
||||
location = ["apache2.conf", "httpd.conf"]
|
||||
|
||||
location = ["apache2.conf", "httpd.conf", "conf/httpd.conf"]
|
||||
for name in location:
|
||||
if os.path.isfile(os.path.join(self.root, name)):
|
||||
return os.path.join(self.root, name)
|
||||
|
||||
@@ -17,7 +17,7 @@ class AugeasConfiguratorTest(util.ApacheTest):
|
||||
super(AugeasConfiguratorTest, self).setUp()
|
||||
|
||||
self.config = util.get_apache_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir)
|
||||
self.config_path, self.vhost_path, self.config_dir, self.work_dir)
|
||||
|
||||
self.vh_truth = util.get_vh_truth(
|
||||
self.temp_dir, "debian_apache_2_4/two_vhost_80")
|
||||
|
||||
@@ -27,7 +27,7 @@ class TwoVhost80Test(util.ApacheTest):
|
||||
super(TwoVhost80Test, self).setUp()
|
||||
|
||||
self.config = util.get_apache_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir)
|
||||
self.config_path, self.vhost_path, self.config_dir, self.work_dir)
|
||||
self.config = self.mock_deploy_cert(self.config)
|
||||
self.vh_truth = util.get_vh_truth(
|
||||
self.temp_dir, "debian_apache_2_4/two_vhost_80")
|
||||
@@ -127,6 +127,24 @@ class TwoVhost80Test(util.ApacheTest):
|
||||
|
||||
self.assertEqual(found, 6)
|
||||
|
||||
# Handle case of non-debian layout get_virtual_hosts
|
||||
orig_conf = self.config.conf
|
||||
with mock.patch(
|
||||
"letsencrypt_apache.configurator.ApacheConfigurator.conf"
|
||||
) as mock_conf:
|
||||
def conf_sideeffect(key):
|
||||
"""Handle calls to configurator.conf()
|
||||
:param key: configuration key
|
||||
:return: configuration value
|
||||
"""
|
||||
if key == "handle-sites":
|
||||
return False
|
||||
else:
|
||||
return orig_conf(key)
|
||||
mock_conf.side_effect = conf_sideeffect
|
||||
vhs = self.config.get_virtual_hosts()
|
||||
self.assertEqual(len(vhs), 6)
|
||||
|
||||
@mock.patch("letsencrypt_apache.display_ops.select_vhost")
|
||||
def test_choose_vhost_none_avail(self, mock_select):
|
||||
mock_select.return_value = None
|
||||
@@ -212,6 +230,11 @@ class TwoVhost80Test(util.ApacheTest):
|
||||
self.assertFalse(self.config.is_site_enabled(self.vh_truth[1].filep))
|
||||
self.assertTrue(self.config.is_site_enabled(self.vh_truth[2].filep))
|
||||
self.assertTrue(self.config.is_site_enabled(self.vh_truth[3].filep))
|
||||
with mock.patch("os.path.isdir") as mock_isdir:
|
||||
mock_isdir.return_value = False
|
||||
self.assertRaises(errors.ConfigurationError,
|
||||
self.config.is_site_enabled,
|
||||
"irrelevant")
|
||||
|
||||
@mock.patch("letsencrypt.le_util.run_script")
|
||||
@mock.patch("letsencrypt.le_util.exe_exists")
|
||||
@@ -255,7 +278,7 @@ class TwoVhost80Test(util.ApacheTest):
|
||||
|
||||
def test_deploy_cert_newssl(self):
|
||||
self.config = util.get_apache_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir, version=(2, 4, 16))
|
||||
self.config_path, self.vhost_path, self.config_dir, self.work_dir, version=(2, 4, 16))
|
||||
|
||||
self.config.parser.modules.add("ssl_module")
|
||||
self.config.parser.modules.add("mod_ssl.c")
|
||||
@@ -288,7 +311,7 @@ class TwoVhost80Test(util.ApacheTest):
|
||||
|
||||
def test_deploy_cert_newssl_no_fullchain(self):
|
||||
self.config = util.get_apache_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir, version=(2, 4, 16))
|
||||
self.config_path, self.vhost_path, self.config_dir, self.work_dir, version=(2, 4, 16))
|
||||
self.config = self.mock_deploy_cert(self.config)
|
||||
|
||||
self.config.parser.modules.add("ssl_module")
|
||||
@@ -302,7 +325,7 @@ class TwoVhost80Test(util.ApacheTest):
|
||||
|
||||
def test_deploy_cert_old_apache_no_chain(self):
|
||||
self.config = util.get_apache_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir, version=(2, 4, 7))
|
||||
self.config_path, self.vhost_path, self.config_dir, self.work_dir, version=(2, 4, 7))
|
||||
self.config = self.mock_deploy_cert(self.config)
|
||||
|
||||
self.config.parser.modules.add("ssl_module")
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
"""Test for letsencrypt_apache.configurator."""
|
||||
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
from letsencrypt_apache import constants
|
||||
|
||||
|
||||
class ConstantsTest(unittest.TestCase):
|
||||
|
||||
@mock.patch("letsencrypt.le_util.get_os_info")
|
||||
def test_get_debian_value(self, os_info):
|
||||
os_info.return_value = ('Debian', '', '')
|
||||
self.assertEqual(constants.os_constant("ctl"), "apache2ctl")
|
||||
|
||||
@mock.patch("letsencrypt.le_util.get_os_info")
|
||||
def test_get_centos_value(self, os_info):
|
||||
os_info.return_value = ('CentOS Linux', '', '')
|
||||
self.assertEqual(constants.os_constant("ctl"), "apachectl")
|
||||
|
||||
@mock.patch("letsencrypt.le_util.get_os_info")
|
||||
def test_get_default_value(self, os_info):
|
||||
os_info.return_value = ('Nonexistent Linux', '', '')
|
||||
self.assertEqual(constants.os_constant("ctl"), "apache2ctl")
|
||||
@@ -152,7 +152,6 @@ class BasicParserTest(util.ParserTest):
|
||||
def test_update_runtime_vars_bad_output(self, mock_cfg):
|
||||
mock_cfg.return_value = "Define: TLS=443=24"
|
||||
self.parser.update_runtime_variables("ctl")
|
||||
self.assertTrue(self.parser.unparsable)
|
||||
|
||||
mock_cfg.return_value = "Define: DUMP_RUN_CFG\nDefine: TLS=443=24"
|
||||
self.assertRaises(
|
||||
@@ -188,17 +187,11 @@ class ParserInitTest(util.ApacheTest):
|
||||
@mock.patch("letsencrypt_apache.parser.ApacheParser._get_runtime_cfg")
|
||||
def test_unparsable(self, mock_cfg):
|
||||
from letsencrypt_apache.parser import ApacheParser
|
||||
def unparsable_true(self, arg):
|
||||
"""a helper to set the self unparsabale to true"""
|
||||
print "side effect has passed in arg: %s", arg
|
||||
self.unparsable = True
|
||||
with mock.patch.object(ApacheParser, 'update_runtime_variables', autospec=True) as urv:
|
||||
urv.side_effect = unparsable_true
|
||||
mock_cfg.return_value = ('Define: TEST')
|
||||
self.assertRaises(
|
||||
errors.PluginError,
|
||||
ApacheParser, self.aug, os.path.relpath(self.config_path), "ctl")
|
||||
self.assertEquals(1, 1)
|
||||
mock_cfg.return_value = ('Define: TEST')
|
||||
self.assertRaises(
|
||||
errors.PluginError,
|
||||
ApacheParser, self.aug, os.path.relpath(self.config_path),
|
||||
"/dummy/vhostpath", "ctl", version=(2, 2, 22))
|
||||
|
||||
def test_root_normalized(self):
|
||||
from letsencrypt_apache.parser import ApacheParser
|
||||
@@ -208,7 +201,9 @@ class ParserInitTest(util.ApacheTest):
|
||||
path = os.path.join(
|
||||
self.temp_dir,
|
||||
"debian_apache_2_4/////two_vhost_80/../two_vhost_80/apache2")
|
||||
parser = ApacheParser(self.aug, path, "dummy_ctl")
|
||||
|
||||
parser = ApacheParser(self.aug, path,
|
||||
"/dummy/vhostpath", "dummy_ctl")
|
||||
|
||||
self.assertEqual(parser.root, self.config_path)
|
||||
|
||||
@@ -217,7 +212,8 @@ class ParserInitTest(util.ApacheTest):
|
||||
with mock.patch("letsencrypt_apache.parser.ApacheParser."
|
||||
"update_runtime_variables"):
|
||||
parser = ApacheParser(
|
||||
self.aug, os.path.relpath(self.config_path), "dummy_ctl")
|
||||
self.aug, os.path.relpath(self.config_path),
|
||||
"/dummy/vhostpath", "dummy_ctl")
|
||||
|
||||
self.assertEqual(parser.root, self.config_path)
|
||||
|
||||
@@ -226,7 +222,8 @@ class ParserInitTest(util.ApacheTest):
|
||||
with mock.patch("letsencrypt_apache.parser.ApacheParser."
|
||||
"update_runtime_variables"):
|
||||
parser = ApacheParser(
|
||||
self.aug, self.config_path + os.path.sep, "dummy_ctl")
|
||||
self.aug, self.config_path + os.path.sep,
|
||||
"/dummy/vhostpath", "dummy_ctl")
|
||||
self.assertEqual(parser.root, self.config_path)
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class TlsSniPerformTest(util.ApacheTest):
|
||||
super(TlsSniPerformTest, self).setUp()
|
||||
|
||||
config = util.get_apache_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir)
|
||||
self.config_path, self.vhost_path, self.config_dir, self.work_dir)
|
||||
config.config.tls_sni_01_port = 443
|
||||
|
||||
from letsencrypt_apache import tls_sni_01
|
||||
|
||||
@@ -23,7 +23,8 @@ from letsencrypt_apache import obj
|
||||
class ApacheTest(unittest.TestCase): # pylint: disable=too-few-public-methods
|
||||
|
||||
def setUp(self, test_dir="debian_apache_2_4/two_vhost_80",
|
||||
config_root="debian_apache_2_4/two_vhost_80/apache2"):
|
||||
config_root="debian_apache_2_4/two_vhost_80/apache2",
|
||||
vhost_root="debian_apache_2_4/two_vhost_80/apache2/sites-available"):
|
||||
# pylint: disable=arguments-differ
|
||||
super(ApacheTest, self).setUp()
|
||||
|
||||
@@ -36,6 +37,7 @@ class ApacheTest(unittest.TestCase): # pylint: disable=too-few-public-methods
|
||||
constants.MOD_SSL_CONF_DEST)
|
||||
|
||||
self.config_path = os.path.join(self.temp_dir, config_root)
|
||||
self.vhost_path = os.path.join(self.temp_dir, vhost_root)
|
||||
|
||||
self.rsa512jwk = jose.JWKRSA.load(test_util.load_vector(
|
||||
"rsa512_key.pem"))
|
||||
@@ -44,8 +46,9 @@ class ApacheTest(unittest.TestCase): # pylint: disable=too-few-public-methods
|
||||
class ParserTest(ApacheTest): # pytlint: disable=too-few-public-methods
|
||||
|
||||
def setUp(self, test_dir="debian_apache_2_4/two_vhost_80",
|
||||
config_root="debian_apache_2_4/two_vhost_80/apache2"):
|
||||
super(ParserTest, self).setUp(test_dir, config_root)
|
||||
config_root="debian_apache_2_4/two_vhost_80/apache2",
|
||||
vhost_root="debian_apache_2_4/two_vhost_80/apache2/sites-available"):
|
||||
super(ParserTest, self).setUp(test_dir, config_root, vhost_root)
|
||||
|
||||
zope.component.provideUtility(display_util.FileDisplay(sys.stdout))
|
||||
|
||||
@@ -55,11 +58,11 @@ class ParserTest(ApacheTest): # pytlint: disable=too-few-public-methods
|
||||
with mock.patch("letsencrypt_apache.parser.ApacheParser."
|
||||
"update_runtime_variables"):
|
||||
self.parser = ApacheParser(
|
||||
self.aug, self.config_path, "dummy_ctl_path")
|
||||
self.aug, self.config_path, self.vhost_path, "dummy_ctl_path")
|
||||
|
||||
|
||||
def get_apache_configurator(
|
||||
config_path, config_dir, work_dir, version=(2, 4, 7), conf=None):
|
||||
config_path, vhost_path, config_dir, work_dir, version=(2, 4, 7), conf=None):
|
||||
"""Create an Apache Configurator with the specified options.
|
||||
|
||||
:param conf: Function that returns binary paths. self.conf in Configurator
|
||||
@@ -68,7 +71,9 @@ def get_apache_configurator(
|
||||
backups = os.path.join(work_dir, "backups")
|
||||
mock_le_config = mock.MagicMock(
|
||||
apache_server_root=config_path,
|
||||
apache_le_vhost_ext=constants.CLI_DEFAULTS["le_vhost_ext"],
|
||||
apache_vhost_root=vhost_path,
|
||||
apache_le_vhost_ext=constants.os_constant("le_vhost_ext"),
|
||||
apache_challenge_location=config_path,
|
||||
backup_dir=backups,
|
||||
config_dir=config_dir,
|
||||
temp_checkpoint_dir=os.path.join(work_dir, "temp_checkpoints"),
|
||||
|
||||
@@ -50,7 +50,7 @@ class ApacheTlsSni01(common.TLSSNI01):
|
||||
super(ApacheTlsSni01, self).__init__(*args, **kwargs)
|
||||
|
||||
self.challenge_conf = os.path.join(
|
||||
self.configurator.conf("server-root"),
|
||||
self.configurator.conf("challenge-location"),
|
||||
"le_tls_sni_01_cert_challenge.conf")
|
||||
|
||||
def perform(self):
|
||||
|
||||
Reference in New Issue
Block a user