Add null installer, integration tests for install/run

Fixes #438.
This commit is contained in:
Jakub Warmuz 2015-06-26 09:59:46 +00:00
parent 7a24499f15
commit 7d775ae9f3
No known key found for this signature in database
GPG key ID: 2A7BAD3A489B52EA
8 changed files with 113 additions and 19 deletions

View file

@ -193,6 +193,7 @@ def auth(args, config, plugins):
domains, authenticator, installer, plugins):
return "Certificate could not be obtained"
def install(args, config, plugins):
"""Install a previously obtained cert in a server."""
# XXX: Update for renewer/RenewableCert
@ -621,6 +622,16 @@ def main(cli_args=sys.argv[1:]):
args = create_parser(plugins, cli_args).parse_args(cli_args)
config = configuration.NamespaceConfig(args)
# Setup logging ASAP, otherwise "No handlers could be found for
# logger ..." TODO: this should be done before plugins discovery
for directory in config.config_dir, config.work_dir:
le_util.make_or_verify_dir(
directory, constants.CONFIG_DIRS_MODE, os.geteuid())
# TODO: logs might contain sensitive data such as contents of the
# private key! #525
le_util.make_or_verify_dir(args.logs_dir, 0o700, os.geteuid())
_setup_logging(args)
# Displayer
if args.text_mode:
displayer = display_util.FileDisplay(sys.stdout)
@ -628,14 +639,6 @@ def main(cli_args=sys.argv[1:]):
displayer = display_util.NcursesDisplay()
zope.component.provideUtility(displayer)
for directory in config.config_dir, config.work_dir:
le_util.make_or_verify_dir(
directory, constants.CONFIG_DIRS_MODE, os.geteuid())
# TODO: logs might contain sensitive data such as contents of the
# private key! #525
le_util.make_or_verify_dir(args.logs_dir, 0o700, os.geteuid())
_setup_logging(args)
# do not log `args`, as it contains sensitive data (e.g. revoke --key)!
logger.debug("Arguments: %r", cli_args)
logger.debug("Discovered plugins: %r", plugins)

View file

@ -83,6 +83,8 @@ class IPlugin(zope.interface.Interface):
Should describe the steps taken and any relevant info to help the user
decide which plugin to use.
:rtype str:
"""
@ -200,7 +202,11 @@ class IInstaller(IPlugin):
"""
def get_all_names():
"""Returns all names that may be authenticated."""
"""Returns all names that may be authenticated.
:rtype: `list` of `str`
"""
def deploy_cert(domain, cert_path, key_path, chain_path=None):
"""Deploy certificate.

View file

@ -71,11 +71,11 @@ class PluginEntryPoint(object):
for iface in ifaces: # zope.interface.providedBy(plugin)
try:
zope.interface.verify.verifyObject(iface, self.init())
except zope.interface.exceptions.BrokenImplementation:
except zope.interface.exceptions.BrokenImplementation as error:
if iface.implementedBy(self.plugin_cls):
logger.debug(
"%s implements %s but object does "
"not verify", self.plugin_cls, iface.__name__)
"%s implements %s but object does not verify: %s",
self.plugin_cls, iface.__name__, error)
return False
return True

View file

@ -11,19 +11,20 @@ from acme import challenges
from acme import jose
from letsencrypt import interfaces
from letsencrypt.plugins import common
from letsencrypt.plugins import null
logger = logging.getLogger(__name__)
class ManualAuthenticator(common.Plugin):
class ManualAuthenticator(null.Installer):
"""Manual Authenticator.
.. todo:: Support for `~.challenges.DVSNI`.
"""
zope.interface.implements(interfaces.IAuthenticator)
zope.interface.implements(
interfaces.IAuthenticator, interfaces.IInstaller)
zope.interface.classProvides(interfaces.IPluginFactory)
description = "Manual Authenticator"

View file

@ -0,0 +1,57 @@
"""Null plugin."""
import logging
import zope.component
import zope.interface
from letsencrypt import interfaces
from letsencrypt.plugins import common
logger = logging.getLogger(__name__)
class Installer(common.Plugin):
"""Null installer."""
zope.interface.implements(interfaces.IInstaller)
zope.interface.classProvides(interfaces.IPluginFactory)
description = "Null Installer"
# pylint: disable=missing-docstring,no-self-use
def prepare(self):
pass # pragma: no cover
def more_info(self):
return "Installer that doesn't do anything (for testing)."
def get_all_names(self):
return []
def deploy_cert(self, domain, cert_path, key_path, chain_path=None):
pass # pragma: no cover
def enhance(self, domain, enhancement, options=None):
pass # pragma: no cover
def supported_enhancements(self):
return []
def get_all_certs_keys(self):
return []
def save(self, title=None, temporary=False):
pass # pragma: no cover
def rollback_checkpoints(self, rollback=1):
pass # pragma: no cover
def view_config_changes(self):
pass # pragma: no cover
def config_test(self):
pass # pragma: no cover
def restart(self):
pass # pragma: no cover

View file

@ -0,0 +1,22 @@
"""Tests for letsencrypt.plugins.null."""
import unittest
import mock
class InstallerTest(unittest.TestCase):
"""Tests for letsencrypt.plugins.null.Installer."""
def setUp(self):
from letsencrypt.plugins.null import Installer
self.installer = Installer(config=mock.MagicMock(), name="null")
def test_it(self):
self.assertTrue(isinstance(self.installer.more_info(), str))
self.assertEqual([], self.installer.get_all_names())
self.assertEqual([], self.installer.supported_enhancements())
self.assertEqual([], self.installer.get_all_certs_keys())
if __name__ == "__main__":
unittest.main() # pragma: no cover

View file

@ -181,6 +181,8 @@ setup(
],
'letsencrypt.plugins': [
'manual = letsencrypt.plugins.manual:ManualAuthenticator',
# TODO: null should probably not be presented to the user
'null = letsencrypt.plugins.null:Installer',
'standalone = letsencrypt.plugins.standalone.authenticator'
':StandaloneAuthenticator',

View file

@ -19,13 +19,16 @@ common() {
--agree-eula \
--email "" \
--authenticator standalone \
--installer null \
-vvvvvvv "$@"
}
common --domains le.wtf auth
common --domains le1.wtf auth
common --domains le2.wtf run
common --domains le3.wtf install
export CSR_PATH="${root}/csr.der" OPENSSL_CNF=examples/openssl.cnf
./examples/generate-csr.sh le.wtf
./examples/generate-csr.sh le4.wtf
common auth --csr "$CSR_PATH" \
--cert-path "${root}/csr/cert.pem" \
--chain-path "${root}/csr/chain.pem"
@ -39,10 +42,10 @@ renew_before_expiry = 10 years
deploy_before_expiry = 10 years
EOF
letsencrypt-renewer $store_flags
dir="$root/conf/archive/le.wtf"
dir="$root/conf/archive/le1.wtf"
for x in cert chain fullchain privkey;
do
latest="$(ls -1t $dir/ | grep -e "^${x}" | head -n1)"
live="$(readlink -f "$root/conf/live/le.wtf/${x}.pem")"
live="$(readlink -f "$root/conf/live/le1.wtf/${x}.pem")"
#[ "${dir}/${latest}" = "$live" ] # renewer fails this test
done