1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-21 19:01:07 +03:00

Merge branch 'kuba-plugins'

This commit is contained in:
James Kasten
2015-03-27 12:29:40 -07:00
8 changed files with 98 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

19
docs/plugins.rst Normal file
View File

@@ -0,0 +1,19 @@
=======
Plugins
=======
Let's Encrypt client supports dynamic discovery of plugins through the
`setuptools entry points`_. This way you can, for example, create a
custom implementation of
`~letsencrypt.client.interfaces.IAuthenticator` or the
'~letsencrypt.client.interfaces.IInstaller' without having to
merge it with the core upstream source code. An example is provided in
``examples/plugins/`` directory.
Please be aware though that as this client is still in a developer-preview
stage, the API may undergo a few changes. If you believe the plugin will be
beneficial to the community, please consider submitting a pull request to the
repo and we will update it with any necessary API changes.
.. _`setuptools entry points`:
https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins

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

@@ -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

@@ -11,6 +11,8 @@ import sys
import confargparse
import zope.component
import zope.interface.exceptions
import zope.interface.verify
import letsencrypt
@@ -20,12 +22,32 @@ 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
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
def create_parser():
"""Create parser."""
parser = confargparse.ConfArgParser(
@@ -136,12 +158,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 = 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,