From 3c645a991629c8c4bf5022a08112fd59c23c0742 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Tue, 5 May 2015 19:07:40 +0000 Subject: [PATCH 1/5] messages2.Error.__str__ (more readable exceptions) This partially fixes #349. --- letsencrypt/acme/messages2.py | 5 +++++ letsencrypt/acme/messages2_test.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/letsencrypt/acme/messages2.py b/letsencrypt/acme/messages2.py index 93f77a3e9..a2829ff57 100644 --- a/letsencrypt/acme/messages2.py +++ b/letsencrypt/acme/messages2.py @@ -46,6 +46,11 @@ class Error(jose.JSONObjectWithFields, Exception): """Hardcoded error description based on its type.""" return self.ERROR_TYPE_DESCRIPTIONS[self.typ] + def __str__(self): + if self.typ is not None: + return ' :: '.join([self.typ, self.description, self.detail]) + else: + return str(self.detail) class _Constant(jose.JSONDeSerializable): """ACME constant.""" diff --git a/letsencrypt/acme/messages2_test.py b/letsencrypt/acme/messages2_test.py index d45aa7f9e..9b114e861 100644 --- a/letsencrypt/acme/messages2_test.py +++ b/letsencrypt/acme/messages2_test.py @@ -50,6 +50,12 @@ class ErrorTest(unittest.TestCase): from letsencrypt.acme.messages2 import Error hash(Error.from_json(self.error.to_json())) + def test_str(self): + self.assertEqual( + 'malformed :: The request message was malformed :: foo', + str(self.error)) + self.assertEqual('foo', str(self.error.update(typ=None))) + class ConstantTest(unittest.TestCase): """Tests for letsencrypt.acme.messages2._Constant.""" From 6580d3a85bf566013286f9fd915d927d50da86c2 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Tue, 5 May 2015 19:09:35 +0000 Subject: [PATCH 2/5] Add test for ChallengeBody proxy behaviour --- letsencrypt/acme/messages2_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/letsencrypt/acme/messages2_test.py b/letsencrypt/acme/messages2_test.py index 9b114e861..9e8ef33c8 100644 --- a/letsencrypt/acme/messages2_test.py +++ b/letsencrypt/acme/messages2_test.py @@ -169,6 +169,9 @@ class ChallengeBodyTest(unittest.TestCase): from letsencrypt.acme.messages2 import ChallengeBody hash(ChallengeBody.from_json(self.jobj_from)) + def test_proxy(self): + self.assertEqual('foo', self.challb.token) + class AuthorizationTest(unittest.TestCase): """Tests for letsencrypt.acme.messages2.Authorization.""" From 73679a4e8556c49093ff69291a758a23672d33ec Mon Sep 17 00:00:00 2001 From: James Kasten Date: Tue, 5 May 2015 14:15:48 -0700 Subject: [PATCH 3/5] generate a separate key for the certificate --- letsencrypt/client/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index a4e98fa41..0422563c3 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -99,9 +99,7 @@ class Client(object): :meth:`.register` must be called before :meth:`.obtain_certificate` - .. todo:: This function currently uses the account key for the cert. - This should be changed to an independent key once renewal is sorted - out. + .. todo:: This function does not currently handle csr correctly... :param set domains: domains to get a certificate @@ -127,8 +125,10 @@ class Client(object): # Create CSR from names if csr is None: + cert_key = crypto_util.init_save_key( + self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr( - self.account.key, domains, self.config.cert_dir) + cert_key, domains, self.config.cert_dir) # Retrieve certificate certr = self.network.request_issuance( From 394e18c4c6ab0d34b6364b3a44e00dd3f065a37c Mon Sep 17 00:00:00 2001 From: James Kasten Date: Tue, 5 May 2015 14:43:00 -0700 Subject: [PATCH 4/5] use certificate_key throughout --- letsencrypt/client/client.py | 11 +++++------ letsencrypt/scripts/main.py | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index 0422563c3..58cccc3af 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -124,11 +124,10 @@ class Client(object): authzr = self.auth_handler.get_authorizations(domains) # Create CSR from names - if csr is None: - cert_key = crypto_util.init_save_key( - self.config.rsa_key_size, self.config.key_dir) - csr = crypto_util.init_save_csr( - cert_key, domains, self.config.cert_dir) + cert_key = crypto_util.init_save_key( + self.config.rsa_key_size, self.config.key_dir) + csr = crypto_util.init_save_csr( + cert_key, domains, self.config.cert_dir) # Retrieve certificate certr = self.network.request_issuance( @@ -143,7 +142,7 @@ class Client(object): revoker.Revoker.store_cert_key( cert_file, self.account.key.file, self.config) - return cert_file, chain_file + return cert_key, cert_file, chain_file def save_certificate(self, certr, cert_path, chain_path): # pylint: disable=no-self-use diff --git a/letsencrypt/scripts/main.py b/letsencrypt/scripts/main.py index ae15f22dd..254df5bdd 100644 --- a/letsencrypt/scripts/main.py +++ b/letsencrypt/scripts/main.py @@ -244,9 +244,9 @@ def main(): # pylint: disable=too-many-branches, too-many-statements acme.register() except errors.LetsEncryptClientError: sys.exit(0) - cert_file, chain_file = acme.obtain_certificate(doms) + cert_key, cert_file, chain_file = acme.obtain_certificate(doms) if installer is not None and cert_file is not None: - acme.deploy_certificate(doms, acc.key, cert_file, chain_file) + acme.deploy_certificate(doms, cert_key, cert_file, chain_file) if installer is not None: acme.enhance_config(doms, args.redirect) From 94d8a1ca018464479f37c61c6b668439ed8507d0 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Tue, 5 May 2015 14:54:15 -0700 Subject: [PATCH 5/5] update documentation of obtain_certificate --- letsencrypt/client/client.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index 58cccc3af..8518c56b9 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -107,8 +107,8 @@ class Client(object): this CSR can be different than self.authkey :type csr: :class:`CSR` - :returns: cert_file, chain_file (paths to respective files) - :rtype: `tuple` of `str` + :returns: cert_key, cert_path, chain_path + :rtype: `tuple` of (:class:`letsencrypt.client.le_util.Key`, str, str) """ if self.auth_handler is None: @@ -136,13 +136,13 @@ class Client(object): authzr) # Save Certificate - cert_file, chain_file = self.save_certificate( + cert_path, chain_path = self.save_certificate( certr, self.config.cert_path, self.config.chain_path) revoker.Revoker.store_cert_key( - cert_file, self.account.key.file, self.config) + cert_path, self.account.key.file, self.config) - return cert_key, cert_file, chain_file + return cert_key, cert_path, chain_path def save_certificate(self, certr, cert_path, chain_path): # pylint: disable=no-self-use