mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 19:02:52 +02:00
Address most of first round of comments
This commit is contained in:
@@ -17,6 +17,8 @@ from letsencrypt import errors
|
|||||||
from letsencrypt import interfaces
|
from letsencrypt import interfaces
|
||||||
from letsencrypt import le_util
|
from letsencrypt import le_util
|
||||||
|
|
||||||
|
from letsencrypt.plugins import common
|
||||||
|
|
||||||
from letsencrypt_apache import augeas_configurator
|
from letsencrypt_apache import augeas_configurator
|
||||||
from letsencrypt_apache import constants
|
from letsencrypt_apache import constants
|
||||||
from letsencrypt_apache import display_ops
|
from letsencrypt_apache import display_ops
|
||||||
@@ -48,6 +50,15 @@ logger = logging.getLogger(__name__)
|
|||||||
# transactional due to the use of register_file_creation()
|
# transactional due to the use of register_file_creation()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Verify permissions on configuration root... it is easier than
|
||||||
|
# checking permissions on each of the relative directories and less error
|
||||||
|
# prone.
|
||||||
|
# TODO: Write a server protocol finder. Listen <port> <protocol> or
|
||||||
|
# Protocol <protocol>. This can verify partial setups are correct
|
||||||
|
# TODO: Add directives to sites-enabled... not sites-available.
|
||||||
|
# sites-available doesn't allow immediate find_dir search even with save()
|
||||||
|
# and load()
|
||||||
|
|
||||||
class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||||
# pylint: disable=too-many-instance-attributes,too-many-public-methods
|
# pylint: disable=too-many-instance-attributes,too-many-public-methods
|
||||||
"""Apache configurator.
|
"""Apache configurator.
|
||||||
@@ -55,15 +66,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
State of Configurator: This code has been been tested and built for Ubuntu
|
State of Configurator: This code has been been tested and built for Ubuntu
|
||||||
14.04 Apache 2.4 and it works for Ubuntu 12.04 Apache 2.2
|
14.04 Apache 2.4 and it works for Ubuntu 12.04 Apache 2.2
|
||||||
|
|
||||||
.. todo:: Verify permissions on configuration root... it is easier than
|
|
||||||
checking permissions on each of the relative directories and less error
|
|
||||||
prone.
|
|
||||||
.. todo:: Write a server protocol finder. Listen <port> <protocol> or
|
|
||||||
Protocol <protocol>. This can verify partial setups are correct
|
|
||||||
.. todo:: Add directives to sites-enabled... not sites-available.
|
|
||||||
sites-available doesn't allow immediate find_dir search even with save()
|
|
||||||
and load()
|
|
||||||
|
|
||||||
:ivar config: Configuration.
|
:ivar config: Configuration.
|
||||||
:type config: :class:`~letsencrypt.interfaces.IConfig`
|
:type config: :class:`~letsencrypt.interfaces.IConfig`
|
||||||
|
|
||||||
@@ -82,14 +84,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
description = "Apache Web Server - Alpha"
|
description = "Apache Web Server - Alpha"
|
||||||
|
|
||||||
# Kept in same function to avoid multiple compilations of the regex
|
|
||||||
|
|
||||||
private_ips_regex = re.compile(
|
|
||||||
r"(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|"
|
|
||||||
r"(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)")
|
|
||||||
hostname_regex = re.compile(
|
|
||||||
r"^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*[a-z]+$", re.IGNORECASE)
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_parser_arguments(cls, add):
|
def add_parser_arguments(cls, add):
|
||||||
@@ -136,7 +130,14 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
return os.path.join(self.config.config_dir, constants.MOD_SSL_CONF_DEST)
|
return os.path.join(self.config.config_dir, constants.MOD_SSL_CONF_DEST)
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
"""Prepare the authenticator/installer."""
|
"""Prepare the authenticator/installer.
|
||||||
|
|
||||||
|
:raises .errors.NoInstallationError: If Apache configs cannot be found
|
||||||
|
:raises .errors.MisconfigurationError: If Apache is misconfigured
|
||||||
|
:raises .errors.NotSupportedError: If Apache version is not supported
|
||||||
|
:raises .errors.PluginError: If there is any other error
|
||||||
|
|
||||||
|
"""
|
||||||
# Make sure configuration is valid
|
# Make sure configuration is valid
|
||||||
self.config_test()
|
self.config_test()
|
||||||
|
|
||||||
@@ -170,6 +171,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
.. todo:: Might be nice to remove chain directive if none exists
|
.. todo:: Might be nice to remove chain directive if none exists
|
||||||
This shouldn't happen within letsencrypt though
|
This shouldn't happen within letsencrypt though
|
||||||
|
|
||||||
|
:raises errors.PluginError: When unable to deploy certificate due to
|
||||||
|
a lack of directives
|
||||||
|
|
||||||
"""
|
"""
|
||||||
vhost = self.choose_vhost(domain)
|
vhost = self.choose_vhost(domain)
|
||||||
|
|
||||||
@@ -235,7 +239,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:returns: ssl vhost associated with name
|
:returns: ssl vhost associated with name
|
||||||
:rtype: :class:`~letsencrypt_apache.obj.VirtualHost`
|
:rtype: :class:`~letsencrypt_apache.obj.VirtualHost`
|
||||||
|
|
||||||
:raises .errors.PluginError: If no vhost is available
|
:raises .errors.PluginError: If no vhost is available or chosen
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Allows for domain names to be associated with a virtual host
|
# Allows for domain names to be associated with a virtual host
|
||||||
@@ -251,21 +255,34 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
self.assoc[target_name] = vhost
|
self.assoc[target_name] = vhost
|
||||||
return vhost
|
return vhost
|
||||||
|
|
||||||
|
return self._choose_vhost_from_list(target_name)
|
||||||
|
|
||||||
|
def _choose_vhost_from_list(self, target_name):
|
||||||
# Select a vhost from a list
|
# Select a vhost from a list
|
||||||
vhost = display_ops.select_vhost(target_name, self.vhosts)
|
vhost = display_ops.select_vhost(target_name, self.vhosts)
|
||||||
if vhost is not None:
|
if vhost is None:
|
||||||
self.assoc[target_name] = vhost
|
|
||||||
else:
|
|
||||||
logger.error(
|
logger.error(
|
||||||
"No vhost exists with servername or alias of: %s. "
|
"No vhost exists with servername or alias of: %s. "
|
||||||
"No vhost was selected. Please specify servernames "
|
"No vhost was selected. Please specify servernames "
|
||||||
"in the Apache config", target_name)
|
"in the Apache config", target_name)
|
||||||
raise errors.PluginError("No vhost selected")
|
raise errors.PluginError("No vhost selected")
|
||||||
|
|
||||||
# TODO: Ask the user if they would like to add ServerName/Alias to VH
|
if not vhost.ssl:
|
||||||
|
addrs = self._get_proposed_addrs(vhost, "443")
|
||||||
|
# TODO: Conflicts is too conservative
|
||||||
|
if not any(vhost.enabled and vhost.conflicts(addrs) for vhost in self.vhosts):
|
||||||
|
vhost = self.make_vhost_ssl(vhost)
|
||||||
|
self.assoc[target_name] = vhost
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
"The selected vhost would conflict with other HTTPS "
|
||||||
|
"VirtualHosts within Apache. Please select another "
|
||||||
|
"vhost or add ServerNames to your configuration.")
|
||||||
|
raise errors.PluginError(
|
||||||
|
"VirtualHost not able to be selected.")
|
||||||
return vhost
|
return vhost
|
||||||
|
|
||||||
|
|
||||||
def _find_best_vhost(self, target_name):
|
def _find_best_vhost(self, target_name):
|
||||||
"""Finds the best vhost for a target_name.
|
"""Finds the best vhost for a target_name.
|
||||||
|
|
||||||
@@ -328,7 +345,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
all_names.update(vhost.get_names())
|
all_names.update(vhost.get_names())
|
||||||
|
|
||||||
for addr in vhost.addrs:
|
for addr in vhost.addrs:
|
||||||
if ApacheConfigurator.hostname_regex.match(addr.get_addr()):
|
if common.hostname_regex.match(addr.get_addr()):
|
||||||
all_names.add(addr.get_addr())
|
all_names.add(addr.get_addr())
|
||||||
else:
|
else:
|
||||||
name = self.get_name_from_ip(addr)
|
name = self.get_name_from_ip(addr)
|
||||||
@@ -348,7 +365,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
# If it isn't a private IP, do a reverse DNS lookup
|
# If it isn't a private IP, do a reverse DNS lookup
|
||||||
if not ApacheConfigurator.private_ips_regex.match(addr.get_addr()):
|
if not common.private_ips_regex.match(addr.get_addr()):
|
||||||
try:
|
try:
|
||||||
socket.inet_aton(addr.get_addr())
|
socket.inet_aton(addr.get_addr())
|
||||||
return socket.gethostbyaddr(addr.get_addr())[0]
|
return socket.gethostbyaddr(addr.get_addr())[0]
|
||||||
@@ -366,9 +383,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
"""
|
"""
|
||||||
# Take the final ServerName as each overrides the previous
|
# Take the final ServerName as each overrides the previous
|
||||||
servername_match = self.parser.find_dir(
|
servername_match = self.parser.find_dir(
|
||||||
"ServerName", None, host.path, exclude=False)
|
"ServerName", None, start=host.path, exclude=False)
|
||||||
serveralias_match = self.parser.find_dir(
|
serveralias_match = self.parser.find_dir(
|
||||||
"ServerAlias", None, host.path, exclude=False)
|
"ServerAlias", None, start=host.path, exclude=False)
|
||||||
|
|
||||||
for alias in serveralias_match:
|
for alias in serveralias_match:
|
||||||
host.aliases.add(self.parser.get_arg(alias))
|
host.aliases.add(self.parser.get_arg(alias))
|
||||||
@@ -392,7 +409,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
addrs.add(obj.Addr.fromstring(self.parser.get_arg(arg)))
|
addrs.add(obj.Addr.fromstring(self.parser.get_arg(arg)))
|
||||||
is_ssl = False
|
is_ssl = False
|
||||||
|
|
||||||
if self.parser.find_dir("SSLEngine", "on", path, exclude=False):
|
if self.parser.find_dir("SSLEngine", "on", start=path, exclude=False):
|
||||||
is_ssl = True
|
is_ssl = True
|
||||||
|
|
||||||
filename = get_file_path(path)
|
filename = get_file_path(path)
|
||||||
@@ -430,8 +447,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
now NameVirtualHosts. If version is earlier than 2.4, check if addr
|
now NameVirtualHosts. If version is earlier than 2.4, check if addr
|
||||||
has a NameVirtualHost directive in the Apache config
|
has a NameVirtualHost directive in the Apache config
|
||||||
|
|
||||||
:param target_addr: vhost address
|
:param letsencrypt_apache.obj.Addr target_addr: vhost address
|
||||||
:type target_addr: :class:~letsencrypt_apache.obj.Addr
|
|
||||||
|
|
||||||
:returns: Success
|
:returns: Success
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
@@ -449,7 +465,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
"""Adds NameVirtualHost directive for given address.
|
"""Adds NameVirtualHost directive for given address.
|
||||||
|
|
||||||
:param addr: Address that will be added as NameVirtualHost directive
|
:param addr: Address that will be added as NameVirtualHost directive
|
||||||
:type addr: :class:~letsencrypt_apache.obj.Addr
|
:type addr: :class:`~letsencrypt_apache.obj.Addr`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
loc = parser.get_aug_path(self.parser.loc["name"])
|
loc = parser.get_aug_path(self.parser.loc["name"])
|
||||||
@@ -672,13 +688,17 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
See :const:`~letsencrypt.constants.ENHANCEMENTS`
|
See :const:`~letsencrypt.constants.ENHANCEMENTS`
|
||||||
documentation for appropriate parameter.
|
documentation for appropriate parameter.
|
||||||
|
|
||||||
|
:raises .errors.PluginError: If Enhancement is not supported, or if
|
||||||
|
there is any other problem with the enhancement.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self._enhance_func[enhancement](
|
func = self._enhance_func[enhancement]
|
||||||
self.choose_vhost(domain), options)
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise errors.PluginError(
|
raise errors.PluginError(
|
||||||
"Unsupported enhancement: {0}".format(enhancement))
|
"Unsupported enhancement: {0}".format(enhancement))
|
||||||
|
try:
|
||||||
|
func(self.choose_vhost(domain), options)
|
||||||
except errors.PluginError:
|
except errors.PluginError:
|
||||||
logger.warn("Failed %s for %s", enhancement, domain)
|
logger.warn("Failed %s for %s", enhancement, domain)
|
||||||
raise
|
raise
|
||||||
@@ -705,6 +725,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:returns: Success, general_vhost (HTTP vhost)
|
:returns: Success, general_vhost (HTTP vhost)
|
||||||
:rtype: (bool, :class:`~letsencrypt_apache.obj.VirtualHost`)
|
:rtype: (bool, :class:`~letsencrypt_apache.obj.VirtualHost`)
|
||||||
|
|
||||||
|
:raises .errors.PluginError: If no viable HTTP host can be created or
|
||||||
|
used for the redirect.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if "rewrite_module" not in self.parser.modules:
|
if "rewrite_module" not in self.parser.modules:
|
||||||
self.enable_mod("rewrite")
|
self.enable_mod("rewrite")
|
||||||
@@ -714,7 +737,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
# Add virtual_server with redirect
|
# Add virtual_server with redirect
|
||||||
logger.debug("Did not find http version of ssl virtual host "
|
logger.debug("Did not find http version of ssl virtual host "
|
||||||
"attempting to create")
|
"attempting to create")
|
||||||
redirect_addrs = self._get_redirect_addrs(ssl_vhost)
|
redirect_addrs = self._get_proposed_addrs(ssl_vhost)
|
||||||
for vhost in self.vhosts:
|
for vhost in self.vhosts:
|
||||||
if vhost.enabled and vhost.conflicts(redirect_addrs):
|
if vhost.enabled and vhost.conflicts(redirect_addrs):
|
||||||
raise errors.PluginError(
|
raise errors.PluginError(
|
||||||
@@ -752,8 +775,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:raises errors.PluginError: When another redirection exists
|
:raises errors.PluginError: When another redirection exists
|
||||||
|
|
||||||
"""
|
"""
|
||||||
rewrite_path = self.parser.find_dir("RewriteRule", None, vhost.path)
|
rewrite_path = self.parser.find_dir(
|
||||||
redirect_path = self.parser.find_dir("Redirect", None, vhost.path)
|
"RewriteRule", None, start=vhost.path)
|
||||||
|
redirect_path = self.parser.find_dir("Redirect", None, start=vhost.path)
|
||||||
|
|
||||||
if redirect_path:
|
if redirect_path:
|
||||||
# "Existing Redirect directive for virtualhost"
|
# "Existing Redirect directive for virtualhost"
|
||||||
@@ -800,7 +824,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
serveralias = ""
|
serveralias = ""
|
||||||
servername = ""
|
servername = ""
|
||||||
|
|
||||||
|
|
||||||
if ssl_vhost.name is not None:
|
if ssl_vhost.name is not None:
|
||||||
servername = "ServerName " + ssl_vhost.name
|
servername = "ServerName " + ssl_vhost.name
|
||||||
if ssl_vhost.aliases:
|
if ssl_vhost.aliases:
|
||||||
@@ -817,7 +840,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
"ErrorLog /var/log/apache2/redirect.error.log\n"
|
"ErrorLog /var/log/apache2/redirect.error.log\n"
|
||||||
"LogLevel warn\n"
|
"LogLevel warn\n"
|
||||||
"</VirtualHost>\n"
|
"</VirtualHost>\n"
|
||||||
% (" ".join(str(addr) for addr in self._get_redirect_addrs(ssl_vhost)),
|
% (" ".join(str(addr) for addr in self._get_proposed_addrs(ssl_vhost)),
|
||||||
servername, serveralias,
|
servername, serveralias,
|
||||||
" ".join(constants.REWRITE_HTTPS_ARGS)))
|
" ".join(constants.REWRITE_HTTPS_ARGS)))
|
||||||
|
|
||||||
@@ -860,10 +883,18 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_redirect_addrs(self, ssl_vhost): # pylint: disable=no-self-use
|
def _get_proposed_addrs(self, vhost, port="80"): # pylint: disable=no-self-use
|
||||||
|
"""Return all addrs of vhost with the port replaced with the specified.
|
||||||
|
|
||||||
|
:param obj.VirtualHost ssl_vhost: Original Vhost
|
||||||
|
:param str port: Desired port for new addresses
|
||||||
|
|
||||||
|
:returns: `set` of :class:`~obj.Addr`
|
||||||
|
|
||||||
|
"""
|
||||||
redirects = set()
|
redirects = set()
|
||||||
for addr in ssl_vhost.addrs:
|
for addr in vhost.addrs:
|
||||||
redirects.add(addr.get_addr_obj("80"))
|
redirects.add(addr.get_addr_obj(port))
|
||||||
|
|
||||||
return redirects
|
return redirects
|
||||||
|
|
||||||
@@ -884,9 +915,11 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
for vhost in self.vhosts:
|
for vhost in self.vhosts:
|
||||||
if vhost.ssl:
|
if vhost.ssl:
|
||||||
cert_path = self.parser.find_dir(
|
cert_path = self.parser.find_dir(
|
||||||
"SSLCertificateFile", None, vhost.path, exclude=False)
|
"SSLCertificateFile", None,
|
||||||
|
start=vhost.path, exclude=False)
|
||||||
key_path = self.parser.find_dir(
|
key_path = self.parser.find_dir(
|
||||||
"SSLCertificateKeyFile", None, vhost.path, exclude=False)
|
"SSLCertificateKeyFile", None,
|
||||||
|
start=vhost.path, exclude=False)
|
||||||
|
|
||||||
if cert_path and key_path:
|
if cert_path and key_path:
|
||||||
cert = os.path.abspath(self.parser.get_arg(cert_path[-1]))
|
cert = os.path.abspath(self.parser.get_arg(cert_path[-1]))
|
||||||
@@ -924,6 +957,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:param vhost: vhost to enable
|
:param vhost: vhost to enable
|
||||||
:type vhost: :class:`~letsencrypt_apache.obj.VirtualHost`
|
:type vhost: :class:`~letsencrypt_apache.obj.VirtualHost`
|
||||||
|
|
||||||
|
:raises .errors.NotSupportedError: If filesystem layout is not
|
||||||
|
supported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.is_site_enabled(vhost.filep):
|
if self.is_site_enabled(vhost.filep):
|
||||||
return
|
return
|
||||||
@@ -943,7 +979,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
logger.info("Enabling available site: %s", vhost.filep)
|
logger.info("Enabling available site: %s", vhost.filep)
|
||||||
self.save_notes += "Enabled site %s\n" % vhost.filep
|
self.save_notes += "Enabled site %s\n" % vhost.filep
|
||||||
else:
|
else:
|
||||||
raise errors.MisconfigurationError(
|
raise errors.NotSupportedError(
|
||||||
"Unsupported filesystem layout. "
|
"Unsupported filesystem layout. "
|
||||||
"sites-available/enabled expected.")
|
"sites-available/enabled expected.")
|
||||||
|
|
||||||
@@ -955,6 +991,11 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:param str mod_name: Name of the module to enable. (e.g. 'ssl')
|
:param str mod_name: Name of the module to enable. (e.g. 'ssl')
|
||||||
:param bool temp: Whether or not this is a temporary action.
|
: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.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Support Debian specific setup
|
# Support Debian specific setup
|
||||||
if (not os.path.isdir(os.path.join(self.parser.root, "mods-available"))
|
if (not os.path.isdir(os.path.join(self.parser.root, "mods-available"))
|
||||||
@@ -995,8 +1036,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
.. todo:: This function will be converted to using reload
|
.. todo:: This function will be converted to using reload
|
||||||
|
|
||||||
:returns: Success
|
:raises .errors.MisconfigurationError: If unable to restart due to a
|
||||||
:rtype: bool
|
configuration problem, or if the restart subprocess cannot be run.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return apache_restart(self.conf("init-script"))
|
return apache_restart(self.conf("init-script"))
|
||||||
@@ -1112,9 +1153,8 @@ def apache_restart(apache_init_script):
|
|||||||
need to be moved into the class again. Perhaps
|
need to be moved into the class again. Perhaps
|
||||||
this version can live on... for testing purposes.
|
this version can live on... for testing purposes.
|
||||||
|
|
||||||
:raises .errors.PluginError: If unable to restart with apache_init_script
|
|
||||||
:raises .errors.MisconfigurationError: If unable to restart due to a
|
:raises .errors.MisconfigurationError: If unable to restart due to a
|
||||||
configuration problem.
|
configuration problem, or if the restart subprocess cannot be run.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -240,7 +240,6 @@ class ApacheParser(object):
|
|||||||
Directives should be in the form of a case insensitive regex currently
|
Directives should be in the form of a case insensitive regex currently
|
||||||
|
|
||||||
.. todo:: arg should probably be a list
|
.. todo:: arg should probably be a list
|
||||||
.. todo:: Check //* notation for including directories
|
|
||||||
|
|
||||||
Note: Augeas is inherently case sensitive while Apache is case
|
Note: Augeas is inherently case sensitive while Apache is case
|
||||||
insensitive. Augeas 1.0 allows case insensitive regexes like
|
insensitive. Augeas 1.0 allows case insensitive regexes like
|
||||||
|
|||||||
@@ -110,10 +110,31 @@ class TwoVhost80Test(util.ApacheTest):
|
|||||||
errors.PluginError, self.config.choose_vhost, "none.com")
|
errors.PluginError, self.config.choose_vhost, "none.com")
|
||||||
|
|
||||||
@mock.patch("letsencrypt_apache.display_ops.select_vhost")
|
@mock.patch("letsencrypt_apache.display_ops.select_vhost")
|
||||||
def test_choose_vhost_select_vhost(self, mock_select):
|
def test_choose_vhost_select_vhost_ssl(self, mock_select):
|
||||||
mock_select.return_value = self.vh_truth[3]
|
mock_select.return_value = self.vh_truth[1]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.vh_truth[3], self.config.choose_vhost("none.com"))
|
self.vh_truth[1], self.config.choose_vhost("none.com"))
|
||||||
|
|
||||||
|
@mock.patch("letsencrypt_apache.display_ops.select_vhost")
|
||||||
|
def test_choose_vhost_select_vhost_non_ssl(self, mock_select):
|
||||||
|
mock_select.return_value = self.vh_truth[0]
|
||||||
|
chosen_vhost = self.config.choose_vhost("none.com")
|
||||||
|
self.assertEqual(
|
||||||
|
self.vh_truth[0].get_names(), chosen_vhost.get_names())
|
||||||
|
|
||||||
|
# Make sure we go from HTTP -> HTTPS
|
||||||
|
self.assertFalse(self.vh_truth[0].ssl)
|
||||||
|
self.assertTrue(chosen_vhost.ssl)
|
||||||
|
|
||||||
|
@mock.patch("letsencrypt_apache.display_ops.select_vhost")
|
||||||
|
def test_choose_vhost_select_vhost_conflicting_non_ssl(self, mock_select):
|
||||||
|
mock_select.return_value = self.vh_truth[3]
|
||||||
|
conflicting_vhost = obj.VirtualHost(
|
||||||
|
"path", "aug_path", set([obj.Addr.fromstring("*:443")]), True, True)
|
||||||
|
self.config.vhosts.append(conflicting_vhost)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
errors.PluginError, self.config.choose_vhost, "none.com")
|
||||||
|
|
||||||
def test_find_best_vhost(self):
|
def test_find_best_vhost(self):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
@@ -207,7 +228,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||||||
|
|
||||||
def test_enable_site_failure(self):
|
def test_enable_site_failure(self):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
errors.MisconfigurationError,
|
errors.NotSupportedError,
|
||||||
self.config.enable_site,
|
self.config.enable_site,
|
||||||
obj.VirtualHost("asdf", "afsaf", set(), False, False))
|
obj.VirtualHost("asdf", "afsaf", set(), False, False))
|
||||||
|
|
||||||
|
|||||||
@@ -244,22 +244,15 @@ class NginxConfigurator(common.Plugin):
|
|||||||
"""
|
"""
|
||||||
all_names = set()
|
all_names = set()
|
||||||
|
|
||||||
# Kept in same function to avoid multiple compilations of the regex
|
|
||||||
priv_ip_regex = (r"(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|"
|
|
||||||
r"(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)")
|
|
||||||
private_ips = re.compile(priv_ip_regex)
|
|
||||||
hostname_regex = r"^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*[a-z]+$"
|
|
||||||
hostnames = re.compile(hostname_regex, re.IGNORECASE)
|
|
||||||
|
|
||||||
for vhost in self.parser.get_vhosts():
|
for vhost in self.parser.get_vhosts():
|
||||||
all_names.update(vhost.names)
|
all_names.update(vhost.names)
|
||||||
|
|
||||||
for addr in vhost.addrs:
|
for addr in vhost.addrs:
|
||||||
host = addr.get_addr()
|
host = addr.get_addr()
|
||||||
if hostnames.match(host):
|
if common.hostname_regex.match(host):
|
||||||
# If it's a hostname, add it to the names.
|
# If it's a hostname, add it to the names.
|
||||||
all_names.add(host)
|
all_names.add(host)
|
||||||
elif not private_ips.match(host):
|
elif not common.private_ips_regex.match(host):
|
||||||
# If it isn't a private IP, do a reverse DNS lookup
|
# If it isn't a private IP, do a reverse DNS lookup
|
||||||
# TODO: IPv6 support
|
# TODO: IPv6 support
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -83,10 +83,6 @@ def pick_plugin(config, default, plugins, question, ifaces):
|
|||||||
plugin_ep = prepared.values()[0]
|
plugin_ep = prepared.values()[0]
|
||||||
logger.debug("Single candidate plugin: %s", plugin_ep)
|
logger.debug("Single candidate plugin: %s", plugin_ep)
|
||||||
if plugin_ep.misconfigured:
|
if plugin_ep.misconfigured:
|
||||||
logger.warning(
|
|
||||||
"Only candidate plugin, %s, is misconfigured. "
|
|
||||||
"Please fix the configuration before proceeding.",
|
|
||||||
plugin_ep.name)
|
|
||||||
return None
|
return None
|
||||||
return plugin_ep.init()
|
return plugin_ep.init()
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""Plugin common functions."""
|
"""Plugin common functions."""
|
||||||
import os
|
import os
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
@@ -22,6 +23,12 @@ def dest_namespace(name):
|
|||||||
"""ArgumentParser dest namespace (prefix of all destinations)."""
|
"""ArgumentParser dest namespace (prefix of all destinations)."""
|
||||||
return name + "_"
|
return name + "_"
|
||||||
|
|
||||||
|
private_ips_regex = re.compile( # pylint: disable=invalid-name
|
||||||
|
r"(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|"
|
||||||
|
r"(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)")
|
||||||
|
hostname_regex = re.compile( # pylint: disable=invalid-name
|
||||||
|
r"^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*[a-z]+$", re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
"""Generic plugin."""
|
"""Generic plugin."""
|
||||||
|
|||||||
@@ -457,7 +457,8 @@ def get_new_files(dire):
|
|||||||
|
|
||||||
def get_undo_commands(dire):
|
def get_undo_commands(dire):
|
||||||
"""Get new files."""
|
"""Get new files."""
|
||||||
return csv.reader(open(os.path.join(dire, "COMMANDS")))
|
with open(os.path.join(dire, "COMMANDS")) as csvfile:
|
||||||
|
return list(csv.reader(csvfile))
|
||||||
|
|
||||||
|
|
||||||
def read_in(path):
|
def read_in(path):
|
||||||
|
|||||||
Reference in New Issue
Block a user