refactor client.namedtuples to le_util

This commit is contained in:
James Kasten
2015-02-02 18:11:48 -08:00
parent 4540b85ade
commit 5698bc3e20
9 changed files with 34 additions and 33 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ class ApacheDvsni(object):
:ivar dvsni_chall: Data required for challenges. :ivar dvsni_chall: Data required for challenges.
where DvsniChall tuples have the following fields where DvsniChall tuples have the following fields
`domain` (`str`), `r_b64` (base64 `str`), `nonce` (hex `str`) `domain` (`str`), `r_b64` (base64 `str`), `nonce` (hex `str`)
`key` (:class:`letsencrypt.client.client.Client.Key`) `key` (:class:`letsencrypt.client.le_util.Key`)
:type dvsni_chall: `list` of :type dvsni_chall: `list` of
:class:`letsencrypt.client.challenge_util.DvsniChall` :class:`letsencrypt.client.challenge_util.DvsniChall`
+2 -2
View File
@@ -23,7 +23,7 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes
:ivar list domains: list of str domains to get authorization :ivar list domains: list of str domains to get authorization
:ivar dict authkey: Authorized Keys for each domain. :ivar dict authkey: Authorized Keys for each domain.
values are of type :class:`letsencrypt.client.client.Client.Key` values are of type :class:`letsencrypt.client.le_util.Key`
:ivar dict responses: keys: domain, values: list of dict responses :ivar dict responses: keys: domain, values: list of dict responses
:ivar dict msgs: ACME Challenge messages with domain as a key :ivar dict msgs: ACME Challenge messages with domain as a key
:ivar dict paths: optimal path for authorization. eg. paths[domain] :ivar dict paths: optimal path for authorization. eg. paths[domain]
@@ -54,7 +54,7 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes
:param dict msg: ACME challenge message :param dict msg: ACME challenge message
:param authkey: authorized key for the challenge :param authkey: authorized key for the challenge
:type authkey: :class:`letsencrypt.client.client.Client.Key` :type authkey: :class:`letsencrypt.client.le_util.Key`
""" """
if domain in self.domains: if domain in self.domains:
+1 -1
View File
@@ -37,7 +37,7 @@ def dvsni_gen_cert(filepath, name, r_b64, nonce, key):
:param str nonce: hex value of nonce :param str nonce: hex value of nonce
:param key: Key to perform challenge :param key: Key to perform challenge
:type key: :class:`letsencrypt.client.client.Client.Key` :type key: :class:`letsencrypt.client.le_util.Key`
:returns: dvsni s value jose base64 encoded :returns: dvsni s value jose base64 encoded
:rtype: str :rtype: str
+6 -11
View File
@@ -1,5 +1,4 @@
"""ACME protocol client class and helper functions.""" """ACME protocol client class and helper functions."""
import collections
import csv import csv
import logging import logging
import os import os
@@ -38,7 +37,7 @@ class Client(object):
:type network: :class:`letsencrypt.client.network.Network` :type network: :class:`letsencrypt.client.network.Network`
:ivar authkey: Authorization Key :ivar authkey: Authorization Key
:type authkey: :class:`letsencrypt.client.client.Client.Key` :type authkey: :class:`letsencrypt.client.le_util.Key`
:ivar auth_handler: Object that supports the IAuthenticator interface. :ivar auth_handler: Object that supports the IAuthenticator interface.
auth_handler contains both a dv_authenticator and a client_authenticator auth_handler contains both a dv_authenticator and a client_authenticator
@@ -50,10 +49,6 @@ class Client(object):
""" """
zope.interface.implements(interfaces.IAuthenticator) zope.interface.implements(interfaces.IAuthenticator)
Key = collections.namedtuple("Key", "file pem")
# Note: form is the type of data, "pem" or "der"
CSR = collections.namedtuple("CSR", "file data form")
def __init__(self, server, authkey, dv_auth, installer): def __init__(self, server, authkey, dv_auth, installer):
"""Initialize a client. """Initialize a client.
@@ -185,7 +180,7 @@ class Client(object):
:param list domains: list of domains to install the certificate :param list domains: list of domains to install the certificate
:param privkey: private key for certificate :param privkey: private key for certificate
:type privkey: :class:`Key` :type privkey: :class:`letsencrypt.client.le_util.Key`
:param str cert_file: certificate file path :param str cert_file: certificate file path
:param str chain_file: chain file path :param str chain_file: chain file path
@@ -312,7 +307,7 @@ def validate_key_csr(privkey, csr=None):
If csr is left as None, only the key will be validated. If csr is left as None, only the key will be validated.
:param privkey: Key associated with CSR :param privkey: Key associated with CSR
:type privkey: :class:`letsencrypt.client.client.Client.Key` :type privkey: :class:`letsencrypt.client.le_util.Key`
:param csr: CSR :param csr: CSR
:type csr: :class:`letsencrypt.client.client.Client.CSR` :type csr: :class:`letsencrypt.client.client.Client.CSR`
@@ -374,7 +369,7 @@ def init_key(key_size):
logging.info("Generating key (%d bits): %s", key_size, key_filename) logging.info("Generating key (%d bits): %s", key_size, key_filename)
return Client.Key(key_filename, key_pem) return le_util.Key(key_filename, key_pem)
def init_csr(privkey, names): def init_csr(privkey, names):
@@ -390,14 +385,14 @@ def init_csr(privkey, names):
logging.info("Creating CSR: %s", csr_filename) logging.info("Creating CSR: %s", csr_filename)
return Client.CSR(csr_filename, csr_der, "der") return le_util.CSR(csr_filename, csr_der, "der")
def csr_pem_to_der(csr): def csr_pem_to_der(csr):
"""Convert pem CSR to der.""" """Convert pem CSR to der."""
csr_obj = M2Crypto.X509.load_request_string(csr.data) csr_obj = M2Crypto.X509.load_request_string(csr.data)
return Client.CSR(csr.file, csr_obj.as_der(), "der") return le_util.CSR(csr.file, csr_obj.as_der(), "der")
def sanity_check_names(names): def sanity_check_names(names):
+16 -10
View File
@@ -1,5 +1,6 @@
"""Utilities for all Let's Encrypt.""" """Utilities for all Let"s Encrypt."""
import base64 import base64
import collections
import errno import errno
import os import os
import stat import stat
@@ -7,6 +8,11 @@ import stat
from letsencrypt.client import errors from letsencrypt.client import errors
Key = collections.namedtuple("Key", "file pem")
# Note: form is the type of data, "pem" or "der"
CSR = collections.namedtuple("CSR", "file data form")
def make_or_verify_dir(directory, mode=0o755, uid=0): def make_or_verify_dir(directory, mode=0o755, uid=0):
"""Make sure directory exists with proper permissions. """Make sure directory exists with proper permissions.
@@ -28,8 +34,8 @@ def make_or_verify_dir(directory, mode=0o755, uid=0):
if exception.errno == errno.EEXIST: if exception.errno == errno.EEXIST:
if not check_permissions(directory, mode, uid): if not check_permissions(directory, mode, uid):
raise errors.LetsEncryptClientError( raise errors.LetsEncryptClientError(
'%s exists, but does not have the proper ' "%s exists, but does not have the proper "
'permissions or owner' % directory) "permissions or owner" % directory)
else: else:
raise raise
@@ -64,7 +70,7 @@ def unique_file(path, mode=0o777):
fname = os.path.join(path, "%04d_%s" % (count, tail)) fname = os.path.join(path, "%04d_%s" % (count, tail))
try: try:
file_d = os.open(fname, os.O_CREAT | os.O_EXCL | os.O_RDWR, mode) file_d = os.open(fname, os.O_CREAT | os.O_EXCL | os.O_RDWR, mode)
return os.fdopen(file_d, 'w'), fname return os.fdopen(file_d, "w"), fname
except OSError: except OSError:
pass pass
count += 1 count += 1
@@ -92,8 +98,8 @@ def jose_b64encode(data):
""" """
if not isinstance(data, str): if not isinstance(data, str):
raise TypeError('argument should be str or bytearray') raise TypeError("argument should be str or bytearray")
return base64.urlsafe_b64encode(data).rstrip('=') return base64.urlsafe_b64encode(data).rstrip("=")
def jose_b64decode(data): def jose_b64decode(data):
@@ -111,11 +117,11 @@ def jose_b64decode(data):
""" """
if isinstance(data, unicode): if isinstance(data, unicode):
try: try:
data = data.encode('ascii') data = data.encode("ascii")
except UnicodeEncodeError: except UnicodeEncodeError:
raise ValueError( raise ValueError(
'unicode argument should contain only ASCII characters') "unicode argument should contain only ASCII characters")
elif not isinstance(data, str): elif not isinstance(data, str):
raise TypeError('argument should be a str or unicode') raise TypeError("argument should be a str or unicode")
return base64.urlsafe_b64decode(data + '=' * (4 - (len(data) % 4))) return base64.urlsafe_b64decode(data + "=" * (4 - (len(data) % 4)))
@@ -7,8 +7,8 @@ import unittest
import mock import mock
from letsencrypt.client import challenge_util from letsencrypt.client import challenge_util
from letsencrypt.client import client
from letsencrypt.client import errors from letsencrypt.client import errors
from letsencrypt.client import le_util
from letsencrypt.client.apache import configurator from letsencrypt.client.apache import configurator
from letsencrypt.client.apache import obj from letsencrypt.client.apache import obj
@@ -164,7 +164,7 @@ class TwoVhost80Test(util.ApacheTest):
def test_perform(self, mock_restart, mock_dvsni_perform): def test_perform(self, mock_restart, mock_dvsni_perform):
# Only tests functionality specific to configurator.perform # Only tests functionality specific to configurator.perform
# Note: As more challenges are offered this will have to be expanded # Note: As more challenges are offered this will have to be expanded
auth_key = client.Client.Key(self.rsa256_file, self.rsa256_pem) auth_key = le_util.Key(self.rsa256_file, self.rsa256_pem)
chall1 = challenge_util.DvsniChall( chall1 = challenge_util.DvsniChall(
"encryption-example.demo", "encryption-example.demo",
"jIq_Xy1mXGN37tb4L6Xj_es58fW571ZNyXekdZzhh7Q", "jIq_Xy1mXGN37tb4L6Xj_es58fW571ZNyXekdZzhh7Q",
@@ -6,8 +6,8 @@ import shutil
import mock import mock
from letsencrypt.client import challenge_util from letsencrypt.client import challenge_util
from letsencrypt.client import client
from letsencrypt.client import CONFIG from letsencrypt.client import CONFIG
from letsencrypt.client import le_util
from letsencrypt.client.tests.apache import util from letsencrypt.client.tests.apache import util
@@ -33,7 +33,7 @@ class DvsniPerformTest(util.ApacheTest):
rsa256_pem = pkg_resources.resource_string( rsa256_pem = pkg_resources.resource_string(
"letsencrypt.client.tests", 'testdata/rsa256_key.pem') "letsencrypt.client.tests", 'testdata/rsa256_key.pem')
auth_key = client.Client.Key(rsa256_file, rsa256_pem) auth_key = le_util.Key(rsa256_file, rsa256_pem)
self.challs = [] self.challs = []
self.challs.append(challenge_util.DvsniChall( self.challs.append(challenge_util.DvsniChall(
"encryption-example.demo", "encryption-example.demo",
@@ -8,7 +8,6 @@ import M2Crypto
import mock import mock
from letsencrypt.client import challenge_util from letsencrypt.client import challenge_util
from letsencrypt.client import client
from letsencrypt.client import CONFIG from letsencrypt.client import CONFIG
from letsencrypt.client import le_util from letsencrypt.client import le_util
@@ -32,7 +31,7 @@ class DvsniGenCertTest(unittest.TestCase):
r_b64 = le_util.jose_b64encode(dvsni_r) r_b64 = le_util.jose_b64encode(dvsni_r)
pem = pkg_resources.resource_string( pem = pkg_resources.resource_string(
__name__, os.path.join("testdata", "rsa256_key.pem")) __name__, os.path.join("testdata", "rsa256_key.pem"))
key = client.Client.Key("path", pem) key = le_util.Key("path", pem)
nonce = "12345ABCDE" nonce = "12345ABCDE"
s_b64 = self._call("tmp.crt", domain, r_b64, nonce, key) s_b64 = self._call("tmp.crt", domain, r_b64, nonce, key)
+3 -2
View File
@@ -11,8 +11,9 @@ import zope.interface
from letsencrypt.client import CONFIG from letsencrypt.client import CONFIG
from letsencrypt.client import client from letsencrypt.client import client
from letsencrypt.client import display from letsencrypt.client import display
from letsencrypt.client import interfaces
from letsencrypt.client import errors 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 log
@@ -113,7 +114,7 @@ def main(): # pylint: disable=too-many-statements,too-many-branches
if args.privkey is None: if args.privkey is None:
privkey = client.init_key(args.key_size) privkey = client.init_key(args.key_size)
else: else:
privkey = client.Client.Key(args.privkey[0], args.privkey[1]) privkey = le_util.Key(args.privkey[0], args.privkey[1])
acme = client.Client(args.server, privkey, auth, installer) acme = client.Client(args.server, privkey, auth, installer)