mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 19:02:52 +02:00
Merge pull request #1423 from ArchimedesPi/apache-chainfile
Appropriately set and update Apache certificate directives
This commit is contained in:
@@ -182,6 +182,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
vhost = self.choose_vhost(domain)
|
vhost = self.choose_vhost(domain)
|
||||||
|
self._clean_vhost(vhost)
|
||||||
|
|
||||||
# This is done first so that ssl module is enabled and cert_path,
|
# This is done first so that ssl module is enabled and cert_path,
|
||||||
# cert_key... can all be parsed appropriately
|
# cert_key... can all be parsed appropriately
|
||||||
@@ -205,16 +206,27 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
"Unable to find cert and/or key directives")
|
"Unable to find cert and/or key directives")
|
||||||
|
|
||||||
logger.info("Deploying Certificate to VirtualHost %s", vhost.filep)
|
logger.info("Deploying Certificate to VirtualHost %s", vhost.filep)
|
||||||
|
logger.debug("Apache version is %s",
|
||||||
|
".".join(str(i) for i in self.version))
|
||||||
|
|
||||||
# Assign the final directives; order is maintained in find_dir
|
if self.version < (2, 4, 8) or (chain_path and not fullchain_path):
|
||||||
self.aug.set(path["cert_path"][-1], cert_path)
|
# install SSLCertificateFile, SSLCertificateKeyFile,
|
||||||
self.aug.set(path["cert_key"][-1], key_path)
|
# and SSLCertificateChainFile directives
|
||||||
if chain_path is not None:
|
set_cert_path = cert_path
|
||||||
if not path["chain_path"]:
|
self.aug.set(path["cert_path"][-1], cert_path)
|
||||||
self.parser.add_dir(
|
self.aug.set(path["cert_key"][-1], key_path)
|
||||||
vhost.path, "SSLCertificateChainFile", chain_path)
|
if chain_path is not None:
|
||||||
|
self.parser.add_dir(vhost.path,
|
||||||
|
"SSLCertificateChainFile", chain_path)
|
||||||
else:
|
else:
|
||||||
self.aug.set(path["chain_path"][-1], chain_path)
|
raise errors.PluginError("--chain-path is required for your version of Apache")
|
||||||
|
else:
|
||||||
|
if not fullchain_path:
|
||||||
|
raise errors.PluginError("Please provide the --fullchain-path\
|
||||||
|
option pointing to your full chain file")
|
||||||
|
set_cert_path = fullchain_path
|
||||||
|
self.aug.set(path["cert_path"][-1], fullchain_path)
|
||||||
|
self.aug.set(path["cert_key"][-1], key_path)
|
||||||
|
|
||||||
# Save notes about the transaction that took place
|
# Save notes about the transaction that took place
|
||||||
self.save_notes += ("Changed vhost at %s with addresses of %s\n"
|
self.save_notes += ("Changed vhost at %s with addresses of %s\n"
|
||||||
@@ -222,7 +234,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
"\tSSLCertificateKeyFile %s\n" %
|
"\tSSLCertificateKeyFile %s\n" %
|
||||||
(vhost.filep,
|
(vhost.filep,
|
||||||
", ".join(str(addr) for addr in vhost.addrs),
|
", ".join(str(addr) for addr in vhost.addrs),
|
||||||
cert_path, key_path))
|
set_cert_path, key_path))
|
||||||
if chain_path is not None:
|
if chain_path is not None:
|
||||||
self.save_notes += "\tSSLCertificateChainFile %s\n" % chain_path
|
self.save_notes += "\tSSLCertificateChainFile %s\n" % chain_path
|
||||||
|
|
||||||
@@ -663,6 +675,25 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
return ssl_addrs
|
return ssl_addrs
|
||||||
|
|
||||||
|
def _clean_vhost(self, vhost):
|
||||||
|
# remove duplicated or conflicting ssl directives
|
||||||
|
self._deduplicate_directives(vhost.path,
|
||||||
|
["SSLCertificateFile", "SSLCertificateKeyFile"])
|
||||||
|
# remove all problematic directives
|
||||||
|
self._remove_directives(vhost.path, ["SSLCertificateChainFile"])
|
||||||
|
|
||||||
|
def _deduplicate_directives(self, vh_path, directives):
|
||||||
|
for directive in directives:
|
||||||
|
while len(self.parser.find_dir(directive, None, vh_path, False)) > 1:
|
||||||
|
directive_path = self.parser.find_dir(directive, None, vh_path, False)
|
||||||
|
self.aug.remove(re.sub(r"/\w*$", "", directive_path[0]))
|
||||||
|
|
||||||
|
def _remove_directives(self, vh_path, directives):
|
||||||
|
for directive in directives:
|
||||||
|
while len(self.parser.find_dir(directive, None, vh_path, False)) > 0:
|
||||||
|
directive_path = self.parser.find_dir(directive, None, vh_path, False)
|
||||||
|
self.aug.remove(re.sub(r"/\w*$", "", directive_path[0]))
|
||||||
|
|
||||||
def _add_dummy_ssl_directives(self, vh_path):
|
def _add_dummy_ssl_directives(self, vh_path):
|
||||||
self.parser.add_dir(vh_path, "SSLCertificateFile",
|
self.parser.add_dir(vh_path, "SSLCertificateFile",
|
||||||
"insert_cert_file_path")
|
"insert_cert_file_path")
|
||||||
|
|||||||
@@ -236,6 +236,64 @@ class TwoVhost80Test(util.ApacheTest):
|
|||||||
self.config.enable_site,
|
self.config.enable_site,
|
||||||
obj.VirtualHost("asdf", "afsaf", set(), False, False))
|
obj.VirtualHost("asdf", "afsaf", set(), False, False))
|
||||||
|
|
||||||
|
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.parser.modules.add("ssl_module")
|
||||||
|
self.config.parser.modules.add("mod_ssl.c")
|
||||||
|
|
||||||
|
# Get the default 443 vhost
|
||||||
|
self.config.assoc["random.demo"] = self.vh_truth[1]
|
||||||
|
self.config.deploy_cert(
|
||||||
|
"random.demo", "example/cert.pem", "example/key.pem",
|
||||||
|
"example/cert_chain.pem", "example/fullchain.pem")
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
# Verify ssl_module was enabled.
|
||||||
|
self.assertTrue(self.vh_truth[1].enabled)
|
||||||
|
self.assertTrue("ssl_module" in self.config.parser.modules)
|
||||||
|
|
||||||
|
loc_cert = self.config.parser.find_dir(
|
||||||
|
"sslcertificatefile", "example/fullchain.pem", self.vh_truth[1].path)
|
||||||
|
loc_key = self.config.parser.find_dir(
|
||||||
|
"sslcertificateKeyfile", "example/key.pem", self.vh_truth[1].path)
|
||||||
|
|
||||||
|
# Verify one directive was found in the correct file
|
||||||
|
self.assertEqual(len(loc_cert), 1)
|
||||||
|
self.assertEqual(configurator.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]),
|
||||||
|
self.vh_truth[1].filep)
|
||||||
|
|
||||||
|
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.parser.modules.add("ssl_module")
|
||||||
|
self.config.parser.modules.add("mod_ssl.c")
|
||||||
|
|
||||||
|
# Get the default 443 vhost
|
||||||
|
self.config.assoc["random.demo"] = self.vh_truth[1]
|
||||||
|
self.assertRaises(errors.PluginError,
|
||||||
|
lambda: self.config.deploy_cert(
|
||||||
|
"random.demo", "example/cert.pem", "example/key.pem"))
|
||||||
|
|
||||||
|
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.parser.modules.add("ssl_module")
|
||||||
|
self.config.parser.modules.add("mod_ssl.c")
|
||||||
|
|
||||||
|
# Get the default 443 vhost
|
||||||
|
self.config.assoc["random.demo"] = self.vh_truth[1]
|
||||||
|
self.assertRaises(errors.PluginError,
|
||||||
|
lambda: self.config.deploy_cert(
|
||||||
|
"random.demo", "example/cert.pem", "example/key.pem"))
|
||||||
|
|
||||||
def test_deploy_cert(self):
|
def test_deploy_cert(self):
|
||||||
self.config.parser.modules.add("ssl_module")
|
self.config.parser.modules.add("ssl_module")
|
||||||
self.config.parser.modules.add("mod_ssl.c")
|
self.config.parser.modules.add("mod_ssl.c")
|
||||||
@@ -353,6 +411,65 @@ class TwoVhost80Test(util.ApacheTest):
|
|||||||
|
|
||||||
self.assertEqual(len(self.config.vhosts), 6)
|
self.assertEqual(len(self.config.vhosts), 6)
|
||||||
|
|
||||||
|
def test_clean_vhost_ssl(self):
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
for directive in ["SSLCertificateFile", "SSLCertificateKeyFile",
|
||||||
|
"SSLCertificateChainFile", "SSLCACertificatePath"]:
|
||||||
|
for _ in range(10):
|
||||||
|
self.config.parser.add_dir(self.vh_truth[1].path, directive, ["bogus"])
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
self.config._clean_vhost(self.vh_truth[1])
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
loc_cert = self.config.parser.find_dir(
|
||||||
|
'SSLCertificateFile', None, self.vh_truth[1].path, False)
|
||||||
|
loc_key = self.config.parser.find_dir(
|
||||||
|
'SSLCertificateKeyFile', None, self.vh_truth[1].path, False)
|
||||||
|
loc_chain = self.config.parser.find_dir(
|
||||||
|
'SSLCertificateChainFile', None, self.vh_truth[1].path, False)
|
||||||
|
loc_cacert = self.config.parser.find_dir(
|
||||||
|
'SSLCACertificatePath', None, self.vh_truth[1].path, False)
|
||||||
|
|
||||||
|
self.assertEqual(len(loc_cert), 1)
|
||||||
|
self.assertEqual(len(loc_key), 1)
|
||||||
|
|
||||||
|
self.assertEqual(len(loc_chain), 0)
|
||||||
|
|
||||||
|
self.assertEqual(len(loc_cacert), 10)
|
||||||
|
|
||||||
|
def test_deduplicate_directives(self):
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
DIRECTIVE = "Foo"
|
||||||
|
for _ in range(10):
|
||||||
|
self.config.parser.add_dir(self.vh_truth[1].path, DIRECTIVE, ["bar"])
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
self.config._deduplicate_directives(self.vh_truth[1].path, [DIRECTIVE])
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
len(self.config.parser.find_dir(
|
||||||
|
DIRECTIVE, None, self.vh_truth[1].path, False)),
|
||||||
|
1)
|
||||||
|
|
||||||
|
def test_remove_directives(self):
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
DIRECTIVES = ["Foo", "Bar"]
|
||||||
|
for directive in DIRECTIVES:
|
||||||
|
for _ in range(10):
|
||||||
|
self.config.parser.add_dir(self.vh_truth[1].path, directive, ["baz"])
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
self.config._remove_directives(self.vh_truth[1].path, DIRECTIVES)
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
for directive in DIRECTIVES:
|
||||||
|
self.assertEqual(
|
||||||
|
len(self.config.parser.find_dir(
|
||||||
|
directive, None, self.vh_truth[1].path, False)),
|
||||||
|
0)
|
||||||
|
|
||||||
def test_make_vhost_ssl_extra_vhs(self):
|
def test_make_vhost_ssl_extra_vhs(self):
|
||||||
self.config.aug.match = mock.Mock(return_value=["p1", "p2"])
|
self.config.aug.match = mock.Mock(return_value=["p1", "p2"])
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
|
|||||||
Reference in New Issue
Block a user