Merge pull request #125 from kuba/pr/117

Clean up after #117, fixes #123
This commit is contained in:
James Kasten
2014-12-10 13:40:03 -08:00
3 changed files with 73 additions and 134 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ import jsonschema
from letsencrypt.client import crypto_util from letsencrypt.client import crypto_util
from letsencrypt.client import le_util from letsencrypt.client import le_util
# pylint: disable=no-member
SCHEMATA = dict([ SCHEMATA = dict([
(schema, json.load(open(pkg_resources.resource_filename( (schema, json.load(open(pkg_resources.resource_filename(
__name__, "schemata/%s.json" % schema)))) for schema in [ __name__, "schemata/%s.json" % schema)))) for schema in [
+2 -8
View File
@@ -57,19 +57,15 @@ class VH(object):
""" """
def __init__(self, filep, path, addrs, ssl, enabled): def __init__(self, filep, path, addrs, ssl, enabled, names=None):
"""Initialize a VH.""" """Initialize a VH."""
self.filep = filep self.filep = filep
self.path = path self.path = path
self.addrs = addrs self.addrs = addrs
self.names = [] self.names = [] if names is None else names
self.ssl = ssl self.ssl = ssl
self.enabled = enabled self.enabled = enabled
def set_names(self, list_of_names):
"""Set names."""
self.names = list_of_names
def add_name(self, name): def add_name(self, name):
"""Add name to vhost.""" """Add name to vhost."""
self.names.append(name) self.names.append(name)
@@ -354,7 +350,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
.. todo:: Make sure that files are included .. todo:: Make sure that files are included
""" """
root = self._find_config_root() root = self._find_config_root()
default = self._set_user_config_file() default = self._set_user_config_file()
@@ -371,7 +366,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
def _find_config_root(self): def _find_config_root(self):
"""Find the Apache Configuration Root file.""" """Find the Apache Configuration Root file."""
location = ["apache2.conf", "httpd.conf"] location = ["apache2.conf", "httpd.conf"]
for name in location: for name in location:
@@ -1,6 +1,4 @@
"""A series of unit tests for the Apache Configurator.""" """Test for letsencrypt.client.apache_configurator."""
import mock
import os import os
import pkg_resources import pkg_resources
import re import re
@@ -9,107 +7,89 @@ import sys
import tempfile import tempfile
import unittest import unittest
import mock
from letsencrypt.client import apache_configurator from letsencrypt.client import apache_configurator
from letsencrypt.client import CONFIG from letsencrypt.client import CONFIG
from letsencrypt.client import display from letsencrypt.client import display
from letsencrypt.client import errors from letsencrypt.client import errors
from letsencrypt.client import logger from letsencrypt.client import logger
# pylint: disable=no-member
UBUNTU_CONFIGS = pkg_resources.resource_filename( UBUNTU_CONFIGS = pkg_resources.resource_filename(
"letsencrypt.client.tests", "testdata/debian_apache_2_4") __name__, "testdata/debian_apache_2_4")
TEMP_DIR = ""
CONFIG_DIR = ""
WORK_DIR = ""
# pylint: disable=invalid-name class TwoVhost80Test(unittest.TestCase):
def setUpModule(): """Test two standard well configured HTTP vhosts."""
"""Run once before all unittests."""
global TEMP_DIR, CONFIG_DIR, WORK_DIR def setUp(self):
logger.setLogger(logger.FileLogger(sys.stdout))
logger.setLogLevel(logger.INFO)
display.set_display(display.NcursesDisplay())
logger.setLogger(logger.FileLogger(sys.stdout)) self.temp_dir = os.path.join(
logger.setLogLevel(logger.INFO) tempfile.mkdtemp("temp"), "debian_apache_2_4")
display.set_display(display.NcursesDisplay()) self.config_dir = tempfile.mkdtemp("config")
self.work_dir = tempfile.mkdtemp("work")
TEMP_DIR = tempfile.mkdtemp("temp") shutil.copytree(UBUNTU_CONFIGS, self.temp_dir, symlinks=True)
CONFIG_DIR = tempfile.mkdtemp("config")
WORK_DIR = tempfile.mkdtemp("work")
shutil.copytree(UBUNTU_CONFIGS, temp_options = pkg_resources.resource_filename(
os.path.join(TEMP_DIR, "debian_apache_2_4"), symlinks=True) "letsencrypt.client", os.path.basename(CONFIG.OPTIONS_SSL_CONF))
TEMP_DIR = os.path.join(TEMP_DIR, "debian_apache_2_4") shutil.copyfile(
temp_options, os.path.join(self.config_dir, "options-ssl.conf"))
temp_options = pkg_resources.resource_filename( # Final slash is currently important
"letsencrypt.client", os.path.basename(CONFIG.OPTIONS_SSL_CONF)) self.config_path = os.path.join(self.temp_dir, "two_vhost_80/apache2/")
shutil.copyfile(temp_options, os.path.join(CONFIG_DIR, "options-ssl.conf")) self.ssl_options = os.path.join(self.config_dir, "options-ssl.conf")
backups = os.path.join(self.work_dir, "backups")
# pylint: disable=invalid-name
def tearDownModule():
"""Run once after all unittests."""
shutil.rmtree(TEMP_DIR)
shutil.rmtree(CONFIG_DIR)
shutil.rmtree(WORK_DIR)
class TwoVhost80(unittest.TestCase):
"""Standard two http vhosts that are well configured."""
def setUp(self): # pylint: disable=invalid-name
"""Run before each and every test."""
with mock.patch("letsencrypt.client.apache_configurator." with mock.patch("letsencrypt.client.apache_configurator."
"subprocess.Popen") as mock_popen: "subprocess.Popen") as mock_popen:
# This just states that the ssl module is already loaded # This just states that the ssl module is already loaded
mock_popen.return_value = MyPopen(("ssl_module", "")) mock_popen().communicate.return_value = ("ssl_module", "")
# Final slash is currently important
self.config_path = os.path.join(TEMP_DIR, "two_vhost_80/apache2/")
self.ssl_options = os.path.join(CONFIG_DIR, "options-ssl.conf")
backups = os.path.join(WORK_DIR, "backups")
self.config = apache_configurator.ApacheConfigurator( self.config = apache_configurator.ApacheConfigurator(
self.config_path, self.config_path,
{"backup": backups, {
"temp": os.path.join(WORK_DIR, "temp_checkpoint"), "backup": backups,
"progress": os.path.join(backups, "IN_PROGRESS"), "temp": os.path.join(self.work_dir, "temp_checkpoint"),
"config": CONFIG_DIR, "progress": os.path.join(backups, "IN_PROGRESS"),
"work": WORK_DIR}, "config": self.config_dir,
"work": self.work_dir,
},
self.ssl_options, self.ssl_options,
(2, 4, 7)) (2, 4, 7))
self.aug_path = "/files" + self.config_path prefix = os.path.join(
self.temp_dir, "two_vhost_80/apache2/sites-available")
prefix = os.path.join(TEMP_DIR, "two_vhost_80/apache2/sites-available/")
aug_pre = "/files" + prefix aug_pre = "/files" + prefix
self.vh_truth = [] self.vh_truth = [
self.vh_truth.append(apache_configurator.VH( apache_configurator.VH(
os.path.join(prefix + "encryption-example.conf"), os.path.join(prefix, "encryption-example.conf"),
os.path.join(aug_pre, "encryption-example.conf/VirtualHost"), os.path.join(aug_pre, "encryption-example.conf/VirtualHost"),
["*:80"], False, True)) ["*:80"], False, True, ["encryption-example.demo"]),
self.vh_truth.append(apache_configurator.VH( apache_configurator.VH(
os.path.join(prefix, "default-ssl.conf"), os.path.join(prefix, "default-ssl.conf"),
os.path.join(aug_pre, "default-ssl.conf/IfModule/VirtualHost"), os.path.join(aug_pre, "default-ssl.conf/IfModule/VirtualHost"),
["_default_:443"], True, False)) ["_default_:443"], True, False),
self.vh_truth.append(apache_configurator.VH( apache_configurator.VH(
os.path.join(prefix, "000-default.conf"), os.path.join(prefix, "000-default.conf"),
os.path.join(aug_pre, "000-default.conf/VirtualHost"), os.path.join(aug_pre, "000-default.conf/VirtualHost"),
["*:80"], False, True)) ["*:80"], False, True, ["ip-172-30-0-17"]),
self.vh_truth.append(apache_configurator.VH( apache_configurator.VH(
os.path.join(prefix, "letsencrypt.conf"), os.path.join(prefix, "letsencrypt.conf"),
os.path.join(aug_pre, "letsencrypt.conf/VirtualHost"), os.path.join(aug_pre, "letsencrypt.conf/VirtualHost"),
["*:80"], False, True)) ["*:80"], False, True, ["letsencrypt.demo"]),
self.vh_truth[0].add_name("encryption-example.demo") ]
self.vh_truth[2].add_name("ip-172-30-0-17")
self.vh_truth[3].add_name("letsencrypt.demo") def tearDown(self):
shutil.rmtree(self.temp_dir)
shutil.rmtree(self.config_dir)
shutil.rmtree(self.work_dir)
# pylint: disable=protected-access
def test_parse_file(self): def test_parse_file(self):
"""test parse_file. """Test parse_file.
letsencrypt.conf is chosen as the test file as it will not be letsencrypt.conf is chosen as the test file as it will not be
included during the normal course of execution. included during the normal course of execution.
@@ -117,7 +97,7 @@ class TwoVhost80(unittest.TestCase):
""" """
file_path = os.path.join( file_path = os.path.join(
self.config_path, "sites-available", "letsencrypt.conf") self.config_path, "sites-available", "letsencrypt.conf")
self.config._parse_file(file_path) self.config._parse_file(file_path) # pylint: disable=protected-access
# search for the httpd incl # search for the httpd incl
matches = self.config.aug.match( matches = self.config.aug.match(
@@ -126,13 +106,11 @@ class TwoVhost80(unittest.TestCase):
self.assertTrue(matches) self.assertTrue(matches)
def test_get_all_names(self): def test_get_all_names(self):
"""test get_all_names."""
names = self.config.get_all_names() names = self.config.get_all_names()
self.assertEqual(set(names), set( self.assertEqual(set(names), set(
['letsencrypt.demo', 'encryption-example.demo', 'ip-172-30-0-17'])) ['letsencrypt.demo', 'encryption-example.demo', 'ip-172-30-0-17']))
def test_find_directive(self): def test_find_directive(self):
"""test find_directive."""
test = self.config.find_directive( test = self.config.find_directive(
apache_configurator.case_i("Listen"), "443") apache_configurator.case_i("Listen"), "443")
# This will only look in enabled hosts # This will only look in enabled hosts
@@ -142,7 +120,6 @@ class TwoVhost80(unittest.TestCase):
self.assertEqual(len(test2), 3) self.assertEqual(len(test2), 3)
def test_get_virtual_hosts(self): def test_get_virtual_hosts(self):
"""inefficient get_virtual_hosts check."""
vhs = self.config.get_virtual_hosts() vhs = self.config.get_virtual_hosts()
self.assertEqual(len(vhs), 4) self.assertEqual(len(vhs), 4)
found = 0 found = 0
@@ -155,14 +132,12 @@ class TwoVhost80(unittest.TestCase):
self.assertEqual(found, 4) self.assertEqual(found, 4)
def test_is_site_enabled(self): def test_is_site_enabled(self):
"""test is_site_enabled"""
self.assertTrue(self.config.is_site_enabled(self.vh_truth[0].filep)) self.assertTrue(self.config.is_site_enabled(self.vh_truth[0].filep))
self.assertFalse(self.config.is_site_enabled(self.vh_truth[1].filep)) 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[2].filep))
self.assertTrue(self.config.is_site_enabled(self.vh_truth[3].filep)) self.assertTrue(self.config.is_site_enabled(self.vh_truth[3].filep))
def test_add_dir(self): def test_add_dir(self):
"""test add_dir."""
aug_default = "/files" + self.config.location["default"] aug_default = "/files" + self.config.location["default"]
self.config.add_dir( self.config.add_dir(
aug_default, "AddDirective", "test") aug_default, "AddDirective", "test")
@@ -171,7 +146,6 @@ class TwoVhost80(unittest.TestCase):
self.config.find_directive("AddDirective", "test", aug_default)) self.config.find_directive("AddDirective", "test", aug_default))
def test_deploy_cert(self): def test_deploy_cert(self):
"""This test modifies the default-ssl vhost SSL directives."""
self.config.deploy_cert( self.config.deploy_cert(
self.vh_truth[1], self.vh_truth[1],
"example/cert.pem", "example/key.pem", "example/cert_chain.pem") "example/cert.pem", "example/key.pem", "example/cert_chain.pem")
@@ -197,29 +171,26 @@ class TwoVhost80(unittest.TestCase):
self.assertEqual(len(loc_chain), 1) self.assertEqual(len(loc_chain), 1)
self.assertEqual(apache_configurator.get_file_path(loc_chain[0]), self.assertEqual(apache_configurator.get_file_path(loc_chain[0]),
self.vh_truth[1].filep) self.vh_truth[1].filep)
def test_is_name_vhost(self): def test_is_name_vhost(self):
"""test is_name_vhost."""
self.assertTrue(self.config.is_name_vhost("*:80")) self.assertTrue(self.config.is_name_vhost("*:80"))
self.config.version = (2, 2) self.config.version = (2, 2)
self.assertFalse(self.config.is_name_vhost("*:80")) self.assertFalse(self.config.is_name_vhost("*:80"))
def test_add_name_vhost(self): def test_add_name_vhost(self):
"""test add_name_vhost."""
self.config.add_name_vhost("*:443") self.config.add_name_vhost("*:443")
# self.config.save(temporary=True) # self.config.save(temporary=True)
self.assertTrue(self.config.find_directive( self.assertTrue(self.config.find_directive(
"NameVirtualHost", re.escape("*:443"))) "NameVirtualHost", re.escape("*:443")))
# pylint: disable=protected-access
def test_add_dir_to_ifmodssl(self): def test_add_dir_to_ifmodssl(self):
"""test _add_dir_to_ifmodssl. """test _add_dir_to_ifmodssl.
Path must be valid before attempting to add to augeas Path must be valid before attempting to add to augeas
""" """
self.config._add_dir_to_ifmodssl( self.config._add_dir_to_ifmodssl( # pylint: disable=protected-access
"/files" + self.config.location["default"], "FakeDirective", "123") "/files" + self.config.location["default"], "FakeDirective", "123")
matches = self.config.find_directive("FakeDirective", "123") matches = self.config.find_directive("FakeDirective", "123")
@@ -228,7 +199,6 @@ class TwoVhost80(unittest.TestCase):
self.assertTrue("IfModule" in matches[0]) self.assertTrue("IfModule" in matches[0])
def test_make_vhost_ssl(self): def test_make_vhost_ssl(self):
"""test make_vhost_ssl."""
ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0]) ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])
self.assertEqual( self.assertEqual(
@@ -258,22 +228,21 @@ class TwoVhost80(unittest.TestCase):
@mock.patch("letsencrypt.client.apache_configurator." @mock.patch("letsencrypt.client.apache_configurator."
"subprocess.Popen") "subprocess.Popen")
def test_get_version(self, mock_popen): def test_get_version(self, mock_popen):
"""test get_version.""" mock_popen().communicate.return_value = (
mock_popen.return_value = MyPopen( "Server Version: Apache/2.4.2 (Debian)", "")
("Server Version: Apache/2.4.2 (Debian)", ""))
self.assertEqual(self.config.get_version(), (2, 4, 2)) self.assertEqual(self.config.get_version(), (2, 4, 2))
mock_popen.return_value = MyPopen( mock_popen().communicate.return_value = (
("Server Version: Apache/2 (Linux)", "")) "Server Version: Apache/2 (Linux)", "")
self.assertEqual(self.config.get_version(), tuple([2])) self.assertEqual(self.config.get_version(), (2,))
mock_popen.return_value = MyPopen( mock_popen().communicate.return_value = (
("Server Version: Apache (Debian)", "")) "Server Version: Apache (Debian)", "")
self.assertRaises( self.assertRaises(
errors.LetsEncryptConfiguratorError, self.config.get_version) errors.LetsEncryptConfiguratorError, self.config.get_version)
mock_popen.return_value = MyPopen( mock_popen().communicate.return_value = (
("Server Version: Apache/2.3\n Apache/2.4.7", "")) "Server Version: Apache/2.3\n Apache/2.4.7", "")
self.assertRaises( self.assertRaises(
errors.LetsEncryptConfiguratorError, self.config.get_version) errors.LetsEncryptConfiguratorError, self.config.get_version)
@@ -281,30 +250,6 @@ class TwoVhost80(unittest.TestCase):
self.assertRaises( self.assertRaises(
errors.LetsEncryptConfiguratorError, self.config.get_version) errors.LetsEncryptConfiguratorError, self.config.get_version)
# def _verify_redirect(self, config_path):
# """Verifies that the vhost contains the REWRITE."""
# with open(config_path, 'r') as config_fd:
# conf = config_fd.read()
# return CONFIG.REWRITE_HTTPS_ARGS[1] in conf
# def debug_file(filepath):
# """Print out the file."""
# with open(filepath, 'r')as file_d:
# print file_d.read()
# I am sure there is a cleaner way to do this... but it works
# pylint: disable=too-few-public-methods
class MyPopen(object):
"""Made for mock popen object."""
def __init__(self, tup):
self.tup = tup
def communicate(self): # pylint: disable=no-self-use
"""Simply return that ssl_module is in output."""
return self.tup
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()