From 5698bc3e20cc2d9fdb62708bc2c1440766bdcb3d Mon Sep 17 00:00:00 2001 From: James Kasten Date: Mon, 2 Feb 2015 18:11:48 -0800 Subject: [PATCH] refactor client.namedtuples to le_util --- letsencrypt/client/apache/dvsni.py | 2 +- letsencrypt/client/auth_handler.py | 4 +-- letsencrypt/client/challenge_util.py | 2 +- letsencrypt/client/client.py | 17 +++++------- letsencrypt/client/le_util.py | 26 ++++++++++++------- .../client/tests/apache/configurator_test.py | 4 +-- letsencrypt/client/tests/apache/dvsni_test.py | 4 +-- .../client/tests/challenge_util_test.py | 3 +-- letsencrypt/scripts/main.py | 5 ++-- 9 files changed, 34 insertions(+), 33 deletions(-) diff --git a/letsencrypt/client/apache/dvsni.py b/letsencrypt/client/apache/dvsni.py index cf5c3bdb0..668cdc76c 100644 --- a/letsencrypt/client/apache/dvsni.py +++ b/letsencrypt/client/apache/dvsni.py @@ -17,7 +17,7 @@ class ApacheDvsni(object): :ivar dvsni_chall: Data required for challenges. where DvsniChall tuples have the following fields `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 :class:`letsencrypt.client.challenge_util.DvsniChall` diff --git a/letsencrypt/client/auth_handler.py b/letsencrypt/client/auth_handler.py index b85996818..c2d94ecec 100644 --- a/letsencrypt/client/auth_handler.py +++ b/letsencrypt/client/auth_handler.py @@ -23,7 +23,7 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes :ivar list domains: list of str domains to get authorization :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 msgs: ACME Challenge messages with domain as a key :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 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: diff --git a/letsencrypt/client/challenge_util.py b/letsencrypt/client/challenge_util.py index 1338089ab..b30eb651f 100644 --- a/letsencrypt/client/challenge_util.py +++ b/letsencrypt/client/challenge_util.py @@ -37,7 +37,7 @@ def dvsni_gen_cert(filepath, name, r_b64, nonce, key): :param str nonce: hex value of nonce :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 :rtype: str diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index ccd957885..37dcc2ead 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -1,5 +1,4 @@ """ACME protocol client class and helper functions.""" -import collections import csv import logging import os @@ -38,7 +37,7 @@ class Client(object): :type network: :class:`letsencrypt.client.network.Network` :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. auth_handler contains both a dv_authenticator and a client_authenticator @@ -50,10 +49,6 @@ class Client(object): """ 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): """Initialize a client. @@ -185,7 +180,7 @@ class Client(object): :param list domains: list of domains to install the 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 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. :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 :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) - return Client.Key(key_filename, key_pem) + return le_util.Key(key_filename, key_pem) def init_csr(privkey, names): @@ -390,14 +385,14 @@ def init_csr(privkey, names): 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): """Convert pem CSR to der.""" 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): diff --git a/letsencrypt/client/le_util.py b/letsencrypt/client/le_util.py index 59b581a45..9087ff7a3 100644 --- a/letsencrypt/client/le_util.py +++ b/letsencrypt/client/le_util.py @@ -1,5 +1,6 @@ -"""Utilities for all Let's Encrypt.""" +"""Utilities for all Let"s Encrypt.""" import base64 +import collections import errno import os import stat @@ -7,6 +8,11 @@ import stat 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): """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 not check_permissions(directory, mode, uid): raise errors.LetsEncryptClientError( - '%s exists, but does not have the proper ' - 'permissions or owner' % directory) + "%s exists, but does not have the proper " + "permissions or owner" % directory) else: raise @@ -64,7 +70,7 @@ def unique_file(path, mode=0o777): fname = os.path.join(path, "%04d_%s" % (count, tail)) try: 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: pass count += 1 @@ -92,8 +98,8 @@ def jose_b64encode(data): """ if not isinstance(data, str): - raise TypeError('argument should be str or bytearray') - return base64.urlsafe_b64encode(data).rstrip('=') + raise TypeError("argument should be str or bytearray") + return base64.urlsafe_b64encode(data).rstrip("=") def jose_b64decode(data): @@ -111,11 +117,11 @@ def jose_b64decode(data): """ if isinstance(data, unicode): try: - data = data.encode('ascii') + data = data.encode("ascii") except UnicodeEncodeError: raise ValueError( - 'unicode argument should contain only ASCII characters') + "unicode argument should contain only ASCII characters") 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))) diff --git a/letsencrypt/client/tests/apache/configurator_test.py b/letsencrypt/client/tests/apache/configurator_test.py index fc71dfbee..9ed56f89d 100644 --- a/letsencrypt/client/tests/apache/configurator_test.py +++ b/letsencrypt/client/tests/apache/configurator_test.py @@ -7,8 +7,8 @@ import unittest import mock from letsencrypt.client import challenge_util -from letsencrypt.client import client from letsencrypt.client import errors +from letsencrypt.client import le_util from letsencrypt.client.apache import configurator from letsencrypt.client.apache import obj @@ -164,7 +164,7 @@ class TwoVhost80Test(util.ApacheTest): def test_perform(self, mock_restart, mock_dvsni_perform): # Only tests functionality specific to configurator.perform # 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( "encryption-example.demo", "jIq_Xy1mXGN37tb4L6Xj_es58fW571ZNyXekdZzhh7Q", diff --git a/letsencrypt/client/tests/apache/dvsni_test.py b/letsencrypt/client/tests/apache/dvsni_test.py index 68ffa283b..8f6593113 100644 --- a/letsencrypt/client/tests/apache/dvsni_test.py +++ b/letsencrypt/client/tests/apache/dvsni_test.py @@ -6,8 +6,8 @@ import shutil import mock from letsencrypt.client import challenge_util -from letsencrypt.client import client from letsencrypt.client import CONFIG +from letsencrypt.client import le_util from letsencrypt.client.tests.apache import util @@ -33,7 +33,7 @@ class DvsniPerformTest(util.ApacheTest): rsa256_pem = pkg_resources.resource_string( "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.append(challenge_util.DvsniChall( "encryption-example.demo", diff --git a/letsencrypt/client/tests/challenge_util_test.py b/letsencrypt/client/tests/challenge_util_test.py index 759ee34ce..7ce4d5aef 100644 --- a/letsencrypt/client/tests/challenge_util_test.py +++ b/letsencrypt/client/tests/challenge_util_test.py @@ -8,7 +8,6 @@ import M2Crypto import mock from letsencrypt.client import challenge_util -from letsencrypt.client import client from letsencrypt.client import CONFIG from letsencrypt.client import le_util @@ -32,7 +31,7 @@ class DvsniGenCertTest(unittest.TestCase): r_b64 = le_util.jose_b64encode(dvsni_r) pem = pkg_resources.resource_string( __name__, os.path.join("testdata", "rsa256_key.pem")) - key = client.Client.Key("path", pem) + key = le_util.Key("path", pem) nonce = "12345ABCDE" s_b64 = self._call("tmp.crt", domain, r_b64, nonce, key) diff --git a/letsencrypt/scripts/main.py b/letsencrypt/scripts/main.py index 4f78de968..c133c98f3 100755 --- a/letsencrypt/scripts/main.py +++ b/letsencrypt/scripts/main.py @@ -11,8 +11,9 @@ import zope.interface from letsencrypt.client import CONFIG from letsencrypt.client import client from letsencrypt.client import display -from letsencrypt.client import interfaces from letsencrypt.client import errors +from letsencrypt.client import interfaces +from letsencrypt.client import le_util from letsencrypt.client import log @@ -113,7 +114,7 @@ def main(): # pylint: disable=too-many-statements,too-many-branches if args.privkey is None: privkey = client.init_key(args.key_size) 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)