mirror of
https://github.com/certbot/certbot.git
synced 2026-01-21 19:01:07 +03:00
more unit tests/better flow
This commit is contained in:
@@ -58,6 +58,7 @@ class ConstantTest(unittest.TestCase):
|
||||
self.MockConstant = MockConstant # pylint: disable=invalid-name
|
||||
self.const_a = MockConstant('a')
|
||||
self.const_b = MockConstant('b')
|
||||
self.const_a_prime = MockConstant('a')
|
||||
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual('a', self.const_a.to_partial_json())
|
||||
@@ -75,6 +76,12 @@ class ConstantTest(unittest.TestCase):
|
||||
self.assertEqual('MockConstant(a)', repr(self.const_a))
|
||||
self.assertEqual('MockConstant(b)', repr(self.const_b))
|
||||
|
||||
def test_equality(self):
|
||||
self.assertFalse(self.const_a == self.const_b)
|
||||
self.assertTrue(self.const_a == self.const_a_prime)
|
||||
|
||||
self.assertTrue(self.const_a != self.const_b)
|
||||
self.assertFalse(self.const_a != self.const_a_prime)
|
||||
|
||||
class RegistrationTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.acme.messages2.Registration."""
|
||||
|
||||
@@ -180,18 +180,21 @@ class Account(object):
|
||||
:rtype: :class:`letsencrypt.client.account.Account`
|
||||
|
||||
"""
|
||||
code, email = zope.component.getUtility(interfaces.IDisplay).input(
|
||||
"Enter email address (optional)")
|
||||
if code == display_util.OK:
|
||||
email = email if email != "" else None
|
||||
while True:
|
||||
code, email = zope.component.getUtility(interfaces.IDisplay).input(
|
||||
"Enter email address (optional, press Enter to skip)")
|
||||
|
||||
le_util.make_or_verify_dir(
|
||||
config.account_keys_dir, 0o700, os.geteuid())
|
||||
key = crypto_util.init_save_key(
|
||||
config.rsa_key_size, config.account_keys_dir, email)
|
||||
return cls(config, key, email)
|
||||
if code == display_util.OK:
|
||||
if email == "" or cls.safe_email(email):
|
||||
email = email if email != "" else None
|
||||
|
||||
return None
|
||||
le_util.make_or_verify_dir(
|
||||
config.account_keys_dir, 0o700, os.geteuid())
|
||||
key = crypto_util.init_save_key(
|
||||
config.rsa_key_size, config.account_keys_dir, email)
|
||||
return cls(config, key, email)
|
||||
else:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def safe_email(cls, email):
|
||||
|
||||
@@ -51,12 +51,14 @@ class NamespaceConfig(object):
|
||||
@property
|
||||
def accounts_dir(self): #pylint: disable=missing-docstring
|
||||
return os.path.join(
|
||||
self.namespace.config_dir, "accounts", self.namespace.server)
|
||||
self.namespace.config_dir, constants.ACCOUNTS_DIR,
|
||||
self.namespace.server.partition(":")[0])
|
||||
|
||||
@property
|
||||
def account_keys_dir(self): #pylint: disable=missing-docstring
|
||||
return os.path.join(self.namespace.config_dir, "accounts",
|
||||
self.namespace.server, "keys")
|
||||
return os.path.join(
|
||||
self.namespace.config_dir, constants.ACCOUNTS_DIR,
|
||||
self.namespace.server.partition(":")[0], constants.ACCOUNT_KEYS_DIR)
|
||||
|
||||
# TODO: This should probably include the server name
|
||||
@property
|
||||
|
||||
@@ -61,6 +61,12 @@ CERT_KEY_BACKUP_DIR = "keys-certs"
|
||||
"""Directory where all certificates and keys are stored (relative to
|
||||
IConfig.work_dir. Used for easy revocation."""
|
||||
|
||||
ACCOUNTS_DIR = "accounts"
|
||||
"""Directory where all accounts are saved."""
|
||||
|
||||
ACCOUNT_KEYS_DIR = "keys"
|
||||
"""Directory where account keys are saved. Relative to ACCOUNTS_DIR."""
|
||||
|
||||
REC_TOKEN_DIR = "recovery_tokens"
|
||||
"""Directory where all recovery tokens are saved (relative to
|
||||
IConfig.work_dir)."""
|
||||
|
||||
@@ -30,6 +30,9 @@ def init_save_key(key_size, key_dir, keyname="key-letsencrypt.pem"):
|
||||
:param str key_dir: Key save directory.
|
||||
:param str keyname: Filename of key
|
||||
|
||||
:returns: Key
|
||||
:rtype: :class:`letsencrypt.client.le_util.Key`
|
||||
|
||||
:raises ValueError: If unable to generate the key given key_size.
|
||||
|
||||
"""
|
||||
@@ -40,7 +43,7 @@ def init_save_key(key_size, key_dir, keyname="key-letsencrypt.pem"):
|
||||
raise err
|
||||
|
||||
# Save file
|
||||
le_util.make_or_verify_dir(key_dir, 0o700)
|
||||
le_util.make_or_verify_dir(key_dir, 0o700, os.geteuid())
|
||||
key_f, key_path = le_util.unique_file(
|
||||
os.path.join(key_dir, keyname), 0o600)
|
||||
key_f.write(key_pem)
|
||||
@@ -51,7 +54,7 @@ def init_save_key(key_size, key_dir, keyname="key-letsencrypt.pem"):
|
||||
return le_util.Key(key_path, key_pem)
|
||||
|
||||
|
||||
def init_save_csr(privkey, names, cert_dir):
|
||||
def init_save_csr(privkey, names, cert_dir, csrname="csr-letsencrypt.pem"):
|
||||
"""Initialize a CSR with the given private key.
|
||||
|
||||
:param privkey: Key to include in the CSR
|
||||
@@ -61,13 +64,16 @@ def init_save_csr(privkey, names, cert_dir):
|
||||
|
||||
:param str cert_dir: Certificate save directory.
|
||||
|
||||
:returns: CSR
|
||||
:rtype: :class:`letsencrypt.client.le_util.CSR`
|
||||
|
||||
"""
|
||||
csr_pem, csr_der = make_csr(privkey.pem, names)
|
||||
|
||||
# Save CSR
|
||||
le_util.make_or_verify_dir(cert_dir, 0o755)
|
||||
csr_f, csr_filename = le_util.unique_file(
|
||||
os.path.join(cert_dir, "csr-letsencrypt.pem"), 0o644)
|
||||
os.path.join(cert_dir, csrname), 0o644)
|
||||
csr_f.write(csr_pem)
|
||||
csr_f.close()
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ class Network(object):
|
||||
|
||||
try:
|
||||
# TODO: This is insufficient or doesn't work as intended.
|
||||
logging.error("Error: %s", jobj)
|
||||
logging.error("Response from server: %s", response.content)
|
||||
raise messages2.Error.from_json(jobj)
|
||||
except jose.DeserializationError as error:
|
||||
# Couldn't deserialize JSON object
|
||||
@@ -536,9 +538,15 @@ class Network(object):
|
||||
def revoke(self, certr, when=messages2.Revocation.NOW):
|
||||
"""Revoke certificate.
|
||||
|
||||
:param certr: Certificate Resource
|
||||
:type certr: `.CertificateResource`
|
||||
|
||||
:param when: When should the revocation take place? Takes
|
||||
the same values as `.messages2.Revocation.revoke`.
|
||||
|
||||
:raises letsencrypt.client.errors.NetworkError: If revocation is
|
||||
unsuccessful.
|
||||
|
||||
"""
|
||||
rev = messages2.Revocation(revoke=when, authorizations=tuple(
|
||||
authzr.uri for authzr in certr.authzrs))
|
||||
|
||||
@@ -10,7 +10,8 @@ class NamespaceConfigTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.client.configuration import NamespaceConfig
|
||||
namespace = mock.MagicMock(
|
||||
work_dir='/tmp/foo', foo='bar', server='acme-server.org:443')
|
||||
config_dir='/tmp/config', work_dir='/tmp/foo', foo='bar',
|
||||
server='acme-server.org:443')
|
||||
self.config = NamespaceConfig(namespace)
|
||||
|
||||
def test_proxy_getattr(self):
|
||||
@@ -23,11 +24,19 @@ class NamespaceConfigTest(unittest.TestCase):
|
||||
constants.IN_PROGRESS_DIR = '../p'
|
||||
constants.CERT_KEY_BACKUP_DIR = 'c/'
|
||||
constants.REC_TOKEN_DIR = '/r'
|
||||
constants.ACCOUNTS_DIR = 'acc'
|
||||
constants.ACCOUNT_KEYS_DIR = 'keys'
|
||||
|
||||
self.assertEqual(self.config.temp_checkpoint_dir, '/tmp/foo/t')
|
||||
self.assertEqual(self.config.in_progress_dir, '/tmp/foo/../p')
|
||||
self.assertEqual(
|
||||
self.config.cert_key_backup, '/tmp/foo/c/acme-server.org')
|
||||
self.assertEqual(self.config.rec_token_dir, '/r')
|
||||
self.assertEqual(
|
||||
self.config.accounts_dir, '/tmp/config/acc/acme-server.org')
|
||||
self.assertEqual(
|
||||
self.config.account_keys_dir,
|
||||
'/tmp/config/acc/acme-server.org/keys')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,15 +1,70 @@
|
||||
"""Tests for letsencrypt.client.crypto_util."""
|
||||
import logging
|
||||
import os
|
||||
import pkg_resources
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import M2Crypto
|
||||
import mock
|
||||
|
||||
|
||||
RSA256_KEY = pkg_resources.resource_string(__name__, 'testdata/rsa256_key.pem')
|
||||
RSA512_KEY = pkg_resources.resource_string(__name__, 'testdata/rsa512_key.pem')
|
||||
|
||||
|
||||
class InitSaveKeyTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.client.crypto_util.init_save_key."""
|
||||
def setUp(self):
|
||||
logging.disable(logging.CRITICAL)
|
||||
self.key_dir = tempfile.mkdtemp('key_dir')
|
||||
|
||||
def tearDown(self):
|
||||
logging.disable(logging.NOTSET)
|
||||
shutil.rmtree(self.key_dir)
|
||||
|
||||
@classmethod
|
||||
def _call(cls, key_size, key_dir):
|
||||
from letsencrypt.client.crypto_util import init_save_key
|
||||
return init_save_key(key_size, key_dir, 'key-letsencrypt.pem')
|
||||
|
||||
@mock.patch('letsencrypt.client.crypto_util.make_key')
|
||||
def test_success(self, mock_make):
|
||||
mock_make.return_value = 'key_pem'
|
||||
key = self._call(1024, self.key_dir)
|
||||
self.assertEqual(key.pem, 'key_pem')
|
||||
self.assertTrue('key-letsencrypt.pem' in key.file)
|
||||
|
||||
@mock.patch('letsencrypt.client.crypto_util.make_key')
|
||||
def test_key_failure(self, mock_make):
|
||||
mock_make.side_effect = ValueError
|
||||
self.assertRaises(ValueError, self._call, 431, self.key_dir)
|
||||
|
||||
|
||||
class InitSaveCSRTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.client.crypto_util.init_save_csr."""
|
||||
|
||||
def setUp(self):
|
||||
self.csr_dir = tempfile.mkdtemp('csr_dir')
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.csr_dir)
|
||||
|
||||
@mock.patch('letsencrypt.client.crypto_util.make_csr')
|
||||
@mock.patch('letsencrypt.client.crypto_util.le_util.make_or_verify_dir')
|
||||
def test_it(self, unused_mock_verify, mock_csr):
|
||||
from letsencrypt.client.crypto_util import init_save_csr
|
||||
|
||||
mock_csr.return_value = ('csr_pem', 'csr_der')
|
||||
|
||||
csr = init_save_csr(
|
||||
mock.Mock(pem='dummy_key'), 'example.com', self.csr_dir,
|
||||
'csr-letsencrypt.pem')
|
||||
|
||||
self.assertEqual(csr.data, 'csr_der')
|
||||
self.assertTrue('csr-letsencrypt.pem' in csr.file)
|
||||
|
||||
class ValidCSRTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.client.crypto_util.valid_csr."""
|
||||
|
||||
|
||||
@@ -162,7 +162,11 @@ def main(): # pylint: disable=too-many-branches, too-many-statements
|
||||
sys.exit()
|
||||
|
||||
if args.revoke or args.rev_cert is not None or args.rev_key is not None:
|
||||
client.revoke(config, args.no_confirm, args.rev_cert, args.rev_key)
|
||||
# This depends on the renewal config and cannot be completed yet.
|
||||
zope.component.getUtility(interfaces.IDisplay).notification(
|
||||
"Revocation is not available with the new Boulder server yet.")
|
||||
|
||||
# client.revoke(config, args.no_confirm, args.rev_cert, args.rev_key)
|
||||
sys.exit()
|
||||
|
||||
if args.rollback > 0:
|
||||
@@ -207,6 +211,9 @@ def main(): # pylint: disable=too-many-branches, too-many-statements
|
||||
# le_util.Key(args.authkey[0], args.authkey[1])
|
||||
account = client.determine_account(config)
|
||||
|
||||
if account is None:
|
||||
sys.exit(0)
|
||||
|
||||
acme = client.Client(config, account, auth, installer)
|
||||
|
||||
# Validate the key and csr
|
||||
|
||||
Reference in New Issue
Block a user