mirror of
https://github.com/certbot/certbot.git
synced 2026-06-08 00:02:14 -04:00
Merge pull request #2537 from letsencrypt/issue_2240
Apache: handle wildcards when matching server names (Issue #2240)
This commit is contained in:
commit
d674a74ba1
4 changed files with 68 additions and 15 deletions
|
|
@ -342,6 +342,21 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
self.assoc[target_name] = vhost
|
||||
return vhost
|
||||
|
||||
def included_in_wildcard(self, names, target_name):
|
||||
"""Helper function to see if alias is covered by wildcard"""
|
||||
target_name = target_name.split(".")[::-1]
|
||||
wildcards = [domain.split(".")[1:] for domain in names if domain.startswith("*")]
|
||||
for wildcard in wildcards:
|
||||
if len(wildcard) > len(target_name):
|
||||
continue
|
||||
for idx, segment in enumerate(wildcard[::-1]):
|
||||
if segment != target_name[idx]:
|
||||
break
|
||||
else:
|
||||
# https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops
|
||||
return True
|
||||
return False
|
||||
|
||||
def _find_best_vhost(self, target_name):
|
||||
"""Finds the best vhost for a target_name.
|
||||
|
||||
|
|
@ -351,16 +366,21 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
:returns: VHost or None
|
||||
|
||||
"""
|
||||
# Points 4 - Servername SSL
|
||||
# Points 3 - Address name with SSL
|
||||
# Points 2 - Servername no SSL
|
||||
# Points 6 - Servername SSL
|
||||
# Points 5 - Wildcard SSL
|
||||
# Points 4 - Address name with SSL
|
||||
# Points 3 - Servername no SSL
|
||||
# Points 2 - Wildcard no SSL
|
||||
# Points 1 - Address name with no SSL
|
||||
best_candidate = None
|
||||
best_points = 0
|
||||
for vhost in self.vhosts:
|
||||
if vhost.modmacro is True:
|
||||
continue
|
||||
if target_name in vhost.get_names():
|
||||
names = vhost.get_names()
|
||||
if target_name in names:
|
||||
points = 3
|
||||
elif self.included_in_wildcard(names, target_name):
|
||||
points = 2
|
||||
elif any(addr.get_addr() == target_name for addr in vhost.addrs):
|
||||
points = 1
|
||||
|
|
@ -370,7 +390,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
continue # pragma: no cover
|
||||
|
||||
if vhost.ssl:
|
||||
points += 2
|
||||
points += 3
|
||||
|
||||
if points > best_points:
|
||||
best_points = points
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
mock_getutility.notification = mock.MagicMock(return_value=True)
|
||||
names = self.config.get_all_names()
|
||||
self.assertEqual(names, set(
|
||||
["letsencrypt.demo", "encryption-example.demo", "ip-172-30-0-17"]))
|
||||
["letsencrypt.demo", "encryption-example.demo", "ip-172-30-0-17", "*.blue.purple.com"]))
|
||||
|
||||
@mock.patch("zope.component.getUtility")
|
||||
@mock.patch("letsencrypt_apache.configurator.socket.gethostbyaddr")
|
||||
|
|
@ -103,7 +103,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
self.config.vhosts.append(vhost)
|
||||
|
||||
names = self.config.get_all_names()
|
||||
self.assertEqual(len(names), 5)
|
||||
self.assertEqual(len(names), 6)
|
||||
self.assertTrue("zombo.com" in names)
|
||||
self.assertTrue("google.com" in names)
|
||||
self.assertTrue("letsencrypt.demo" in names)
|
||||
|
|
@ -124,7 +124,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
|
||||
"""
|
||||
vhs = self.config.get_virtual_hosts()
|
||||
self.assertEqual(len(vhs), 6)
|
||||
self.assertEqual(len(vhs), 7)
|
||||
found = 0
|
||||
|
||||
for vhost in vhs:
|
||||
|
|
@ -135,7 +135,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
else:
|
||||
raise Exception("Missed: %s" % vhost) # pragma: no cover
|
||||
|
||||
self.assertEqual(found, 6)
|
||||
self.assertEqual(found, 7)
|
||||
|
||||
# Handle case of non-debian layout get_virtual_hosts
|
||||
with mock.patch(
|
||||
|
|
@ -143,7 +143,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
) as mock_conf:
|
||||
mock_conf.return_value = False
|
||||
vhs = self.config.get_virtual_hosts()
|
||||
self.assertEqual(len(vhs), 6)
|
||||
self.assertEqual(len(vhs), 7)
|
||||
|
||||
@mock.patch("letsencrypt_apache.display_ops.select_vhost")
|
||||
def test_choose_vhost_none_avail(self, mock_select):
|
||||
|
|
@ -186,6 +186,20 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
self.assertRaises(
|
||||
errors.PluginError, self.config.choose_vhost, "none.com")
|
||||
|
||||
def test_choosevhost_select_vhost_with_wildcard(self):
|
||||
chosen_vhost = self.config.choose_vhost("blue.purple.com", temp=True)
|
||||
self.assertEqual(self.vh_truth[6], chosen_vhost)
|
||||
|
||||
def test_findbest_continues_on_short_domain(self):
|
||||
# pylint: disable=protected-access
|
||||
chosen_vhost = self.config._find_best_vhost("purple.com")
|
||||
self.assertEqual(None, chosen_vhost)
|
||||
|
||||
def test_findbest_continues_on_long_domain(self):
|
||||
# pylint: disable=protected-access
|
||||
chosen_vhost = self.config._find_best_vhost("green.red.purple.com")
|
||||
self.assertEqual(None, chosen_vhost)
|
||||
|
||||
def test_find_best_vhost(self):
|
||||
# pylint: disable=protected-access
|
||||
self.assertEqual(
|
||||
|
|
@ -211,6 +225,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
self.config.vhosts = [
|
||||
vh for vh in self.config.vhosts
|
||||
if vh.name not in ["letsencrypt.demo", "encryption-example.demo"]
|
||||
and "*.blue.purple.com" not in vh.aliases
|
||||
]
|
||||
|
||||
self.assertEqual(
|
||||
|
|
@ -218,7 +233,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
|
||||
def test_non_default_vhosts(self):
|
||||
# pylint: disable=protected-access
|
||||
self.assertEqual(len(self.config._non_default_vhosts()), 4)
|
||||
self.assertEqual(len(self.config._non_default_vhosts()), 5)
|
||||
|
||||
def test_is_site_enabled(self):
|
||||
"""Test if site is enabled.
|
||||
|
|
@ -524,7 +539,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
self.assertEqual(self.config.is_name_vhost(self.vh_truth[0]),
|
||||
self.config.is_name_vhost(ssl_vhost))
|
||||
|
||||
self.assertEqual(len(self.config.vhosts), 7)
|
||||
self.assertEqual(len(self.config.vhosts), 8)
|
||||
|
||||
def test_clean_vhost_ssl(self):
|
||||
# pylint: disable=protected-access
|
||||
|
|
@ -942,7 +957,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
|
||||
# pylint: disable=protected-access
|
||||
self.config._enable_redirect(self.vh_truth[1], "")
|
||||
self.assertEqual(len(self.config.vhosts), 7)
|
||||
self.assertEqual(len(self.config.vhosts), 8)
|
||||
|
||||
def test_create_own_redirect_for_old_apache_version(self):
|
||||
self.config.parser.modules.add("rewrite_module")
|
||||
|
|
@ -953,7 +968,7 @@ class TwoVhost80Test(util.ApacheTest):
|
|||
|
||||
# pylint: disable=protected-access
|
||||
self.config._enable_redirect(self.vh_truth[1], "")
|
||||
self.assertEqual(len(self.config.vhosts), 7)
|
||||
self.assertEqual(len(self.config.vhosts), 8)
|
||||
|
||||
def test_sift_line(self):
|
||||
# pylint: disable=protected-access
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<VirtualHost *:80>
|
||||
|
||||
ServerName ip-172-30-0-17
|
||||
ServerAdmin webmaster@localhost
|
||||
DocumentRoot /var/www/html
|
||||
ServerAlias *.blue.purple.com
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
|
||||
</VirtualHost>
|
||||
|
||||
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
|
||||
|
|
@ -150,7 +150,12 @@ def get_vh_truth(temp_dir, config_name):
|
|||
os.path.join(prefix, "default-ssl-port-only.conf"),
|
||||
os.path.join(aug_pre, ("default-ssl-port-only.conf/"
|
||||
"IfModule/VirtualHost")),
|
||||
set([obj.Addr.fromstring("_default_:443")]), True, False)
|
||||
set([obj.Addr.fromstring("_default_:443")]), True, False),
|
||||
obj.VirtualHost(
|
||||
os.path.join(prefix, "wildcard.conf"),
|
||||
os.path.join(aug_pre, "wildcard.conf/VirtualHost"),
|
||||
set([obj.Addr.fromstring("*:80")]), False, False,
|
||||
"ip-172-30-0-17", aliases=["*.blue.purple.com"])
|
||||
]
|
||||
return vh_truth
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue