Merge branch 'plugins' of git://github.com/kuba/lets-encrypt-preview into kuba-plugins

This commit is contained in:
James Kasten 2015-03-26 13:48:33 -07:00
commit 1b206e495b
9 changed files with 87 additions and 20 deletions

View file

@ -7,6 +7,7 @@ Welcome to the Let's Encrypt client documentation!
intro
using
contributing
plugins
.. toctree::
:maxdepth: 1

5
docs/plugins.rst Normal file
View file

@ -0,0 +1,5 @@
=======
Plugins
=======
You can find an example in ``examples/plugins/`` directory.

View file

@ -0,0 +1,16 @@
"""Example Let's Encrypt plugins."""
import zope.interface
from letsencrypt.client import interfaces
class Authenticator(object):
zope.interface.implements(interfaces.IAuthenticator)
description = 'Example Authenticator plugin'
def __init__(self, config):
self.config = config
# Implement all methods from IAuthenticator, remembering to add
# "self" as first argument, e.g. def prepare(self)...

16
examples/plugins/setup.py Normal file
View file

@ -0,0 +1,16 @@
from setuptools import setup
setup(
name='letsencrypt-example-plugins',
package='letsencrypt_example_plugins.py',
install_requires=[
'letsencrypt',
'zope.interface',
],
entry_points={
'letsencrypt.authenticators': [
'example = letsencrypt_example_plugins:Authenticator',
],
},
)

View file

@ -1,11 +1,15 @@
"""ACME protocol client class and helper functions."""
import logging
import os
import pkg_resources
import sys
import Crypto.PublicKey.RSA
import M2Crypto
import zope.interface.exceptions
import zope.interface.verify
from letsencrypt.acme import messages
from letsencrypt.acme.jose import util as jose_util
@ -13,6 +17,7 @@ from letsencrypt.client import auth_handler
from letsencrypt.client import client_authenticator
from letsencrypt.client import crypto_util
from letsencrypt.client import errors
from letsencrypt.client import interfaces
from letsencrypt.client import le_util
from letsencrypt.client import network
from letsencrypt.client import reverter
@ -23,6 +28,28 @@ from letsencrypt.client.display import ops as display_ops
from letsencrypt.client.display import enhancements
SETUPTOOLS_AUTHENTICATORS_ENTRY_POINT = "letsencrypt.authenticators"
"""Setuptools entry point group name for Authenticator plugins."""
def init_auths(config):
"""Find (setuptools entry points) and initialize Authenticators."""
auths = {}
for entrypoint in pkg_resources.iter_entry_points(
SETUPTOOLS_AUTHENTICATORS_ENTRY_POINT):
auth_cls = entrypoint.load()
auth = auth_cls(config)
try:
zope.interface.verify.verifyObject(interfaces.IAuthenticator, auth)
except zope.interface.exceptions.BrokenImplementation:
logging.debug(
"%r object does not provide IAuthenticator, skipping",
entrypoint.name)
else:
auths[auth] = entrypoint.name
return auths
class Client(object):
"""ACME protocol client.

View file

@ -33,7 +33,7 @@ class StandaloneAuthenticator(object):
description = "Standalone Authenticator"
def __init__(self):
def __init__(self, unused_config):
self.child_pid = None
self.parent_pid = os.getpid()
self.subproc_state = None

View file

@ -51,7 +51,7 @@ class ChallPrefTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
def test_chall_pref(self):
self.assertEqual(self.authenticator.get_chall_pref("example.com"),
@ -63,7 +63,7 @@ class SNICallbackTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
test_key = pkg_resources.resource_string(
__name__, "testdata/rsa256_key.pem")
key = le_util.Key("foo", test_key)
@ -106,7 +106,7 @@ class ClientSignalHandlerTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
self.authenticator.tasks = {"foononce.acme.invalid": "stuff"}
self.authenticator.child_pid = 12345
@ -135,7 +135,7 @@ class SubprocSignalHandlerTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
self.authenticator.tasks = {"foononce.acme.invalid": "stuff"}
self.authenticator.child_pid = 12345
self.authenticator.parent_pid = 23456
@ -187,7 +187,7 @@ class AlreadyListeningTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
@mock.patch("letsencrypt.client.standalone_authenticator.psutil."
"net_connections")
@ -290,7 +290,7 @@ class PerformTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
test_key = pkg_resources.resource_string(
__name__, "testdata/rsa256_key.pem")
@ -367,7 +367,7 @@ class StartListenerTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
@mock.patch("letsencrypt.client.standalone_authenticator."
"Crypto.Random.atfork")
@ -402,7 +402,7 @@ class DoParentProcessTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
@mock.patch("letsencrypt.client.standalone_authenticator.signal.signal")
@mock.patch("letsencrypt.client.standalone_authenticator."
@ -452,7 +452,7 @@ class DoChildProcessTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
test_key = pkg_resources.resource_string(
__name__, "testdata/rsa256_key.pem")
key = le_util.Key("foo", test_key)
@ -545,7 +545,7 @@ class CleanupTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import \
StandaloneAuthenticator
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
self.achall = achallenges.DVSNI(
chall=challenges.DVSNI(r="whee", nonce="foononce"),
domain="foo.example.com", key="key")
@ -575,7 +575,7 @@ class MoreInfoTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import (
StandaloneAuthenticator)
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
def test_more_info(self):
"""Make sure exceptions aren't raised."""
@ -587,7 +587,7 @@ class InitTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.standalone_authenticator import (
StandaloneAuthenticator)
self.authenticator = StandaloneAuthenticator()
self.authenticator = StandaloneAuthenticator(None)
def test_prepare(self):
"""Make sure exceptions aren't raised.

View file

@ -20,8 +20,6 @@ from letsencrypt.client import errors
from letsencrypt.client import interfaces
from letsencrypt.client import le_util
from letsencrypt.client import log
from letsencrypt.client import standalone_authenticator as standalone
from letsencrypt.client.apache import configurator
from letsencrypt.client.display import util as display_util
from letsencrypt.client.display import ops as display_ops
@ -136,12 +134,10 @@ def main(): # pylint: disable=too-many-branches, too-many-statements
if not args.eula:
display_eula()
all_auths = [
configurator.ApacheConfigurator(config),
standalone.StandaloneAuthenticator(),
]
all_auths = client.init_auths(config)
logging.debug('Initialized authenticators: %s', all_auths.values())
try:
auth = client.determine_authenticator(all_auths)
auth = client.determine_authenticator(all_auths.keys())
except errors.LetsEncryptClientError:
logging.critical("No authentication mechanisms were found on your "
"system.")

View file

@ -119,6 +119,12 @@ setup(
'letsencrypt = letsencrypt.scripts.main:main',
'jws = letsencrypt.acme.jose.jws:CLI.run',
],
'letsencrypt.authenticators': [
'apache = letsencrypt.client.apache.configurator'
':ApacheConfigurator',
'standalone = letsencrypt.client.standalone_authenticator'
':StandaloneAuthenticator',
],
},
zip_safe=False,