mirror of
https://github.com/certbot/certbot.git
synced 2026-08-03 03:41:53 +02:00
second round revisions
This commit is contained in:
@@ -65,6 +65,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:ivar config: Configuration.
|
:ivar config: Configuration.
|
||||||
:type config: :class:`~letsencrypt.client.interfaces.IConfig`
|
:type config: :class:`~letsencrypt.client.interfaces.IConfig`
|
||||||
|
|
||||||
|
:ivar parser: Handles low level parsing
|
||||||
|
:type parser: :class:`letsencrypt.client.apache.parser`
|
||||||
|
|
||||||
:ivar tup version: version of Apache
|
:ivar tup version: version of Apache
|
||||||
:ivar list vhosts: All vhosts found in the configuration
|
:ivar list vhosts: All vhosts found in the configuration
|
||||||
(:class:`list` of :class:`letsencrypt.client.apache.obj.VirtualHost`)
|
(:class:`list` of :class:`letsencrypt.client.apache.obj.VirtualHost`)
|
||||||
@@ -92,13 +95,13 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
# Add name_server association dict
|
# Add name_server association dict
|
||||||
self.assoc = dict()
|
self.assoc = dict()
|
||||||
# Add number of outstanding challenges
|
# Add number of outstanding challenges
|
||||||
self.chall_out = 0
|
self._chall_out = 0
|
||||||
|
|
||||||
# These will be set in the prepare function
|
# These will be set in the prepare function
|
||||||
self.parser = None
|
self.parser = None
|
||||||
self.version = version
|
self.version = version
|
||||||
self.vhosts = None
|
self.vhosts = None
|
||||||
self.enhance_func = {"redirect": self._enable_redirect}
|
self._enhance_func = {"redirect": self._enable_redirect}
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
"""Prepare the authenticator/installer."""
|
"""Prepare the authenticator/installer."""
|
||||||
@@ -533,7 +536,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.enhance_func[enhancement](
|
return self._enhance_func[enhancement](
|
||||||
self.choose_vhost(domain), options)
|
self.choose_vhost(domain), options)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise errors.LetsEncryptConfiguratorError(
|
raise errors.LetsEncryptConfiguratorError(
|
||||||
@@ -987,7 +990,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
:rtype: list
|
:rtype: list
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.chall_out += len(chall_list)
|
self._chall_out += len(chall_list)
|
||||||
responses = [None] * len(chall_list)
|
responses = [None] * len(chall_list)
|
||||||
apache_dvsni = dvsni.ApacheDvsni(self)
|
apache_dvsni = dvsni.ApacheDvsni(self)
|
||||||
|
|
||||||
@@ -1013,10 +1016,10 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||||||
|
|
||||||
def cleanup(self, chall_list):
|
def cleanup(self, chall_list):
|
||||||
"""Revert all challenges."""
|
"""Revert all challenges."""
|
||||||
self.chall_out -= len(chall_list)
|
self._chall_out -= len(chall_list)
|
||||||
|
|
||||||
# If all of the challenges have been finished, clean up everything
|
# If all of the challenges have been finished, clean up everything
|
||||||
if self.chall_out <= 0:
|
if self._chall_out <= 0:
|
||||||
self.revert_challenge_config()
|
self.revert_challenge_config()
|
||||||
self.restart()
|
self.restart()
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ class Client(object):
|
|||||||
|
|
||||||
:param dv_auth: IAuthenticator that can solve the
|
:param dv_auth: IAuthenticator that can solve the
|
||||||
:const:`letsencrypt.client.constants.DV_CHALLENGES`.
|
:const:`letsencrypt.client.constants.DV_CHALLENGES`.
|
||||||
:func:`letsencrypt.client.interfaces.IAuthenticator.prepare`
|
The :meth:`~letsencrypt.client.interfaces.IAuthenticator.prepare`
|
||||||
|
must have already been run.
|
||||||
:type dv_auth: :class:`letsencrypt.client.interfaces.IAuthenticator`
|
:type dv_auth: :class:`letsencrypt.client.interfaces.IAuthenticator`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -349,14 +350,13 @@ def init_csr(privkey, names, cert_dir):
|
|||||||
def determine_authenticator(all_auths):
|
def determine_authenticator(all_auths):
|
||||||
"""Returns a valid IAuthenticator.
|
"""Returns a valid IAuthenticator.
|
||||||
|
|
||||||
:param list all_auths: Where each is a tuple of the form
|
:param list all_auths: Where each is a
|
||||||
('description', 'IAuthenticator', *options..) where IAuthenticator is a
|
:class:`letsencrypt.client.interfaces.IAuthenticator` object
|
||||||
:class:`letsencrypt.client.interfaces.IAuthenticator` object or class
|
|
||||||
and options are the parameters used to initialize the authenticator.
|
|
||||||
|
|
||||||
:returns: Valid Authenticator object or None
|
:returns: Valid Authenticator object or None
|
||||||
|
|
||||||
:raises :class:`letsencrypt.client.errors.LetsEncryptClientError`
|
:raises :class:`letsencrypt.client.errors.LetsEncryptClientError`: If no
|
||||||
|
authenticator is available.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Available Authenticator objects
|
# Available Authenticator objects
|
||||||
@@ -367,12 +367,11 @@ def determine_authenticator(all_auths):
|
|||||||
for pot_auth in all_auths:
|
for pot_auth in all_auths:
|
||||||
try:
|
try:
|
||||||
pot_auth.prepare()
|
pot_auth.prepare()
|
||||||
avail_auths.append(pot_auth)
|
|
||||||
except errors.LetsEncryptMisconfigurationError as err:
|
except errors.LetsEncryptMisconfigurationError as err:
|
||||||
errs[pot_auth] = err
|
errs[pot_auth] = err
|
||||||
avail_auths.append(pot_auth)
|
|
||||||
except errors.LetsEncryptNoInstallationError:
|
except errors.LetsEncryptNoInstallationError:
|
||||||
continue
|
continue
|
||||||
|
avail_auths.append(pot_auth)
|
||||||
|
|
||||||
if len(avail_auths) > 1:
|
if len(avail_auths) > 1:
|
||||||
auth = display_ops.choose_authenticator(avail_auths, errs)
|
auth = display_ops.choose_authenticator(avail_auths, errs)
|
||||||
@@ -396,14 +395,17 @@ def determine_installer(config):
|
|||||||
:param config: Configuration.
|
:param config: Configuration.
|
||||||
:type config: :class:`letsencrypt.client.interfaces.IConfig`
|
:type config: :class:`letsencrypt.client.interfaces.IConfig`
|
||||||
|
|
||||||
|
:returns: IInstaller or `None`
|
||||||
|
:rtype: :class:`~letsencrypt.client.interfaces.IInstaller` or `None`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
installer = configurator.ApacheConfigurator(config)
|
installer = configurator.ApacheConfigurator(config)
|
||||||
|
try:
|
||||||
installer.prepare()
|
installer.prepare()
|
||||||
return installer
|
return installer
|
||||||
except errors.LetsEncryptNoInstallationError:
|
except errors.LetsEncryptNoInstallationError:
|
||||||
logging.info("Unable to find a way to install the certificate.")
|
logging.info("Unable to find a way to install the certificate.")
|
||||||
return None
|
return
|
||||||
except errors.LetsEncryptMisconfigurationError:
|
except errors.LetsEncryptMisconfigurationError:
|
||||||
# This will have to be changed in the future...
|
# This will have to be changed in the future...
|
||||||
return installer
|
return installer
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from letsencrypt.client import interfaces
|
|||||||
from letsencrypt.client.display import util as display_util
|
from letsencrypt.client.display import util as display_util
|
||||||
|
|
||||||
|
|
||||||
# Used to make easier to read code.
|
# Define a helper function to avoid verbose code
|
||||||
util = zope.component.getUtility # pylint: disable=invalid-name
|
util = zope.component.getUtility # pylint: disable=invalid-name
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import zope.component
|
|||||||
from letsencrypt.client import interfaces
|
from letsencrypt.client import interfaces
|
||||||
from letsencrypt.client.display import util as display_util
|
from letsencrypt.client.display import util as display_util
|
||||||
|
|
||||||
# Convenience call to make for easier to read lines.
|
# Define a helper function to avoid verbose code
|
||||||
util = zope.component.getUtility # pylint: disable=invalid-name
|
util = zope.component.getUtility # pylint: disable=invalid-name
|
||||||
|
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ def confirm_revocation(cert):
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
|
|
||||||
"""
|
"""
|
||||||
text = ("Are you sure you would like to revoke the following "
|
return util(interfaces.IDisplay).yesno(
|
||||||
"certificate:{0}{cert}This action cannot be "
|
"Are you sure you would like to revoke the following "
|
||||||
"reversed!".format(os.linesep, cert=cert.pretty_print()))
|
"certificate:{0}{cert}This action cannot be reversed!".format(
|
||||||
return util(interfaces.IDisplay).yesno(text)
|
os.linesep, cert=cert.pretty_print()))
|
||||||
|
|
||||||
|
|
||||||
def more_info_cert(cert):
|
def more_info_cert(cert):
|
||||||
@@ -59,9 +59,10 @@ def more_info_cert(cert):
|
|||||||
:param dict cert: cert dict used throughout revoker.py
|
:param dict cert: cert dict used throughout revoker.py
|
||||||
|
|
||||||
"""
|
"""
|
||||||
text = "Certificate Information:{0}{1}".format(
|
util(interfaces.IDisplay).notification(
|
||||||
os.linesep, cert.pretty_print())
|
"Certificate Information:{0}{1}".format(
|
||||||
util(interfaces.IDisplay).notification(text, height=display_util.HEIGHT)
|
os.linesep, cert.pretty_print()),
|
||||||
|
height=display_util.HEIGHT)
|
||||||
|
|
||||||
|
|
||||||
def success_revocation(cert):
|
def success_revocation(cert):
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ class NcursesDisplay(object):
|
|||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
"""Display a notification to the user and wait for user acceptance.
|
"""Display a notification to the user and wait for user acceptance.
|
||||||
|
|
||||||
|
.. todo:: It probably makes sense to use one of the transient message
|
||||||
|
types for pause. It isn't straightforward how best to approach
|
||||||
|
the matter though given the context of our messages.
|
||||||
|
http://pythondialog.sourceforge.net/doc/widgets.html#displaying-transient-messages
|
||||||
|
|
||||||
:param str message: Message to display
|
:param str message: Message to display
|
||||||
:param int height: Height of the dialog box
|
:param int height: Height of the dialog box
|
||||||
:param bool pause: Not applicable to NcursesDisplay
|
:param bool pause: Not applicable to NcursesDisplay
|
||||||
@@ -63,15 +68,21 @@ class NcursesDisplay(object):
|
|||||||
:rtype: tuple
|
:rtype: tuple
|
||||||
|
|
||||||
"""
|
"""
|
||||||
help_button = bool(help_label)
|
menu_options = {
|
||||||
|
"choices": choices,
|
||||||
|
"ok_label": ok_label,
|
||||||
|
"cancel_label": cancel_label,
|
||||||
|
"help_button": bool(help_label),
|
||||||
|
"help_label": help_label,
|
||||||
|
"width": self.width,
|
||||||
|
"height": self.height,
|
||||||
|
"menu_height": self.height-6,
|
||||||
|
}
|
||||||
|
|
||||||
# Can accept either tuples or just the actual choices
|
# Can accept either tuples or just the actual choices
|
||||||
if choices and isinstance(choices[0], tuple):
|
if choices and isinstance(choices[0], tuple):
|
||||||
code, selection = self.dialog.menu(
|
# pylint: disable=star-args
|
||||||
message, choices=choices, ok_label=ok_label,
|
code, selection = self.dialog.menu(message, **menu_options)
|
||||||
cancel_label=cancel_label,
|
|
||||||
help_button=help_button, help_label=help_label,
|
|
||||||
width=self.width, height=self.height)
|
|
||||||
|
|
||||||
# Return the selection index
|
# Return the selection index
|
||||||
for i, choice in enumerate(choices):
|
for i, choice in enumerate(choices):
|
||||||
@@ -81,14 +92,12 @@ class NcursesDisplay(object):
|
|||||||
return code, -1
|
return code, -1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
choices = [
|
# "choices" is not formatted the way the dialog.menu expects...
|
||||||
|
menu_options["choices"] = [
|
||||||
(str(i), choice) for i, choice in enumerate(choices, 1)
|
(str(i), choice) for i, choice in enumerate(choices, 1)
|
||||||
]
|
]
|
||||||
code, tag = self.dialog.menu(
|
# pylint: disable=star-args
|
||||||
message, choices=choices, ok_label=ok_label,
|
code, tag = self.dialog.menu(message, **menu_options)
|
||||||
cancel_label=cancel_label,
|
|
||||||
help_button=help_button, help_label=help_label,
|
|
||||||
width=self.width, height=self.height)
|
|
||||||
|
|
||||||
if code == CANCEL:
|
if code == CANCEL:
|
||||||
return code, -1
|
return code, -1
|
||||||
@@ -263,8 +272,8 @@ class FileDisplay(object):
|
|||||||
while True:
|
while True:
|
||||||
self._print_menu(message, tags)
|
self._print_menu(message, tags)
|
||||||
|
|
||||||
code, ans = self.input("Select the appropriate numbers "
|
code, ans = self.input("Select the appropriate numbers separated "
|
||||||
"separated by commas and/or spaces ")
|
"by commas and/or spaces")
|
||||||
|
|
||||||
if code == OK:
|
if code == OK:
|
||||||
indices = separate_list_input(ans)
|
indices = separate_list_input(ans)
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ class IAuthenticator(zope.interface.Interface):
|
|||||||
|
|
||||||
Finish up any additional initialization.
|
Finish up any additional initialization.
|
||||||
|
|
||||||
:raises
|
:raises :class:`~.errors.LetsEncryptMisconfigurationError`: when
|
||||||
:class:`letsencrypt.client.errors.LetsEncryptMisconfigurationError`
|
full initialization cannot be completed.
|
||||||
when full initialization cannot be completed.
|
:raises :class:`~.errors.LetsEncryptNoInstallationError`: when the
|
||||||
|
necessary programs/files cannot be located.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_chall_pref(domain):
|
def get_chall_pref(domain):
|
||||||
@@ -133,9 +135,11 @@ class IInstaller(zope.interface.Interface):
|
|||||||
|
|
||||||
Finish up any additional initialization.
|
Finish up any additional initialization.
|
||||||
|
|
||||||
:raises
|
:raises :class:`~.errors.LetsEncryptMisconfigurationError`: when
|
||||||
:class:`letsencrypt.client.errors.LetsEncryptMisconfigurationError`
|
full initialization cannot be completed.
|
||||||
when full initialization cannot be completed.
|
:raises :class:`~.errors.LetsEncryptNoInstallationError`: when the
|
||||||
|
necessary programs/files cannot be located.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_all_names():
|
def get_all_names():
|
||||||
@@ -247,7 +251,7 @@ class IDisplay(zope.interface.Interface):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def input(message):
|
def input(message):
|
||||||
"""Accept input from the user
|
"""Accept input from the user.
|
||||||
|
|
||||||
:param str message: message to display to the user
|
:param str message: message to display to the user
|
||||||
|
|
||||||
|
|||||||
@@ -191,12 +191,12 @@ class Revoker(object):
|
|||||||
try:
|
try:
|
||||||
cert_sha1 = M2Crypto.X509.load_cert(
|
cert_sha1 = M2Crypto.X509.load_cert(
|
||||||
cert_path).get_fingerprint(md="sha1")
|
cert_path).get_fingerprint(md="sha1")
|
||||||
|
except (IOError, M2Crypto.X509.X509Error):
|
||||||
|
continue
|
||||||
if cert_sha1 in csha1_vhlist:
|
if cert_sha1 in csha1_vhlist:
|
||||||
csha1_vhlist[cert_sha1].append(path)
|
csha1_vhlist[cert_sha1].append(path)
|
||||||
else:
|
else:
|
||||||
csha1_vhlist[cert_sha1] = [path]
|
csha1_vhlist[cert_sha1] = [path]
|
||||||
except (IOError, M2Crypto.X509.X509Error):
|
|
||||||
continue
|
|
||||||
|
|
||||||
return csha1_vhlist
|
return csha1_vhlist
|
||||||
|
|
||||||
@@ -216,9 +216,9 @@ class Revoker(object):
|
|||||||
if self.no_confirm or revocation.confirm_revocation(cert):
|
if self.no_confirm or revocation.confirm_revocation(cert):
|
||||||
try:
|
try:
|
||||||
self._acme_revoke(cert)
|
self._acme_revoke(cert)
|
||||||
|
|
||||||
success_list.append(cert)
|
success_list.append(cert)
|
||||||
revocation.success_revocation(cert)
|
revocation.success_revocation(cert)
|
||||||
|
|
||||||
except errors.LetsEncryptClientError:
|
except errors.LetsEncryptClientError:
|
||||||
# TODO: Improve error handling when networking is set...
|
# TODO: Improve error handling when networking is set...
|
||||||
logging.error(
|
logging.error(
|
||||||
@@ -238,19 +238,21 @@ class Revoker(object):
|
|||||||
:returns: TODO
|
:returns: TODO
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# These will both have to change in the future away from M2Crypto
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
certificate = acme_util.ComparableX509(cert._cert)
|
||||||
try:
|
try:
|
||||||
certificate = acme_util.ComparableX509(cert.cert)
|
|
||||||
with open(cert.backup_key_path, "rU") as backup_key_file:
|
with open(cert.backup_key_path, "rU") as backup_key_file:
|
||||||
key = Crypto.PublicKey.RSA.importKey(backup_key_file.read())
|
key = Crypto.PublicKey.RSA.importKey(backup_key_file.read())
|
||||||
|
|
||||||
# If the key file doesn't exist... or is corrupted
|
# If the key file doesn't exist... or is corrupted
|
||||||
except (OSError, IOError):
|
except (IndexError, ValueError, TypeError):
|
||||||
raise errors.LetsEncryptRevokerError("Unable to read key file")
|
raise errors.LetsEncryptRevokerError(
|
||||||
|
"Corrupted backup key file: %s" % cert.backup_key_path)
|
||||||
|
|
||||||
# TODO: Catch error associated with already revoked and proceed.
|
# TODO: Catch error associated with already revoked and proceed.
|
||||||
return self.network.send_and_receive_expected(
|
return self.network.send_and_receive_expected(
|
||||||
messages.RevocationRequest.create(
|
messages.RevocationRequest.create(certificate=certificate, key=key),
|
||||||
certificate=certificate, key=key),
|
|
||||||
messages.Revocation)
|
messages.Revocation)
|
||||||
|
|
||||||
def _remove_certs_keys(self, cert_list): # pylint: disable=no-self-use
|
def _remove_certs_keys(self, cert_list): # pylint: disable=no-self-use
|
||||||
@@ -365,8 +367,8 @@ class Revoker(object):
|
|||||||
class Cert(object):
|
class Cert(object):
|
||||||
"""Cert object used for Revocation convenience.
|
"""Cert object used for Revocation convenience.
|
||||||
|
|
||||||
:ivar cert: M2Crypto X509 cert
|
:ivar _cert: M2Crypto X509 cert
|
||||||
:type cert: :class:`M2Crypto.X509`
|
:type _cert: :class:`M2Crypto.X509`
|
||||||
|
|
||||||
:ivar int idx: convenience index used for listing
|
:ivar int idx: convenience index used for listing
|
||||||
:ivar orig: (`str` path - original certificate, `str` status)
|
:ivar orig: (`str` path - original certificate, `str` status)
|
||||||
@@ -394,7 +396,7 @@ class Cert(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.cert = M2Crypto.X509.load_cert(cert_path)
|
self._cert = M2Crypto.X509.load_cert(cert_path)
|
||||||
except (IOError, M2Crypto.X509.X509Error):
|
except (IOError, M2Crypto.X509.X509Error):
|
||||||
raise errors.LetsEncryptRevokerError(
|
raise errors.LetsEncryptRevokerError(
|
||||||
"Error loading certificate: %s" % cert_path)
|
"Error loading certificate: %s" % cert_path)
|
||||||
@@ -464,27 +466,26 @@ class Cert(object):
|
|||||||
self.backup_path = backup
|
self.backup_path = backup
|
||||||
self.backup_key_path = backup_key
|
self.backup_key_path = backup_key
|
||||||
|
|
||||||
# I would rather not have outside classes messing with Cert directly.
|
# M2Crypto is eventually going to be replaced, hence the reason for _cert
|
||||||
# (I would like to change M2Crypto -> something else without issues)
|
|
||||||
def get_cn(self):
|
def get_cn(self):
|
||||||
"""Get common name."""
|
"""Get common name."""
|
||||||
return self.cert.get_subject().CN
|
return self._cert.get_subject().CN
|
||||||
|
|
||||||
def get_fingerprint(self):
|
def get_fingerprint(self):
|
||||||
"""Get SHA1"""
|
"""Get SHA1 fingerprint."""
|
||||||
return self.cert.get_fingerprint(md="sha1")
|
return self._cert.get_fingerprint(md="sha1")
|
||||||
|
|
||||||
def get_not_before(self):
|
def get_not_before(self):
|
||||||
"""Get not_valid_before field."""
|
"""Get not_valid_before field."""
|
||||||
return self.cert.get_not_before().get_datetime()
|
return self._cert.get_not_before().get_datetime()
|
||||||
|
|
||||||
def get_not_after(self):
|
def get_not_after(self):
|
||||||
"""Get not_valid_after field."""
|
"""Get not_valid_after field."""
|
||||||
return self.cert.get_not_after().get_datetime()
|
return self._cert.get_not_after().get_datetime()
|
||||||
|
|
||||||
def get_der(self):
|
def get_der(self):
|
||||||
"""Get certificate in der format."""
|
"""Get certificate in der format."""
|
||||||
return self.cert.as_der()
|
return self._cert.as_der()
|
||||||
|
|
||||||
def get_pub_key(self):
|
def get_pub_key(self):
|
||||||
"""Get public key size.
|
"""Get public key size.
|
||||||
@@ -492,24 +493,24 @@ class Cert(object):
|
|||||||
.. todo:: M2Crypto doesn't support ECC, this will have to be updated
|
.. todo:: M2Crypto doesn't support ECC, this will have to be updated
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return "RSA " + str(self.cert.get_pubkey().size() * 8)
|
return "RSA " + str(self._cert.get_pubkey().size() * 8)
|
||||||
|
|
||||||
def get_san(self):
|
def get_san(self):
|
||||||
"""Get subject alternative name if available."""
|
"""Get subject alternative name if available."""
|
||||||
try:
|
try:
|
||||||
return self.cert.get_ext("subjectAltName").get_value()
|
return self._cert.get_ext("subjectAltName").get_value()
|
||||||
except LookupError:
|
except LookupError:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
text = [
|
text = [
|
||||||
"Subject: %s" % self.cert.get_subject().as_text(),
|
"Subject: %s" % self._cert.get_subject().as_text(),
|
||||||
"SAN: %s" % self.get_san(),
|
"SAN: %s" % self.get_san(),
|
||||||
"Issuer: %s" % self.cert.get_issuer().as_text(),
|
"Issuer: %s" % self._cert.get_issuer().as_text(),
|
||||||
"Public Key: %s" % self.get_pub_key(),
|
"Public Key: %s" % self.get_pub_key(),
|
||||||
"Not Before: %s" % str(self.get_not_before()),
|
"Not Before: %s" % str(self.get_not_before()),
|
||||||
"Not After: %s" % str(self.get_not_after()),
|
"Not After: %s" % str(self.get_not_after()),
|
||||||
"Serial Number: %s" % self.cert.get_serial_number(),
|
"Serial Number: %s" % self._cert.get_serial_number(),
|
||||||
"SHA1: %s%s" % (self.get_fingerprint(), os.linesep),
|
"SHA1: %s%s" % (self.get_fingerprint(), os.linesep),
|
||||||
"Installed: %s" % ", ".join(self.installed),
|
"Installed: %s" % ", ".join(self.installed),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ class StandaloneAuthenticator(object):
|
|||||||
.. todo:: This should probably do the port check
|
.. todo:: This should probably do the port check
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
|
||||||
|
|
||||||
def client_signal_handler(self, sig, unused_frame):
|
def client_signal_handler(self, sig, unused_frame):
|
||||||
"""Signal handler for the parent process.
|
"""Signal handler for the parent process.
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ from letsencrypt.client import errors
|
|||||||
class DetermineAuthenticatorTest(unittest.TestCase):
|
class DetermineAuthenticatorTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
from letsencrypt.client.apache.configurator import ApacheConfigurator
|
from letsencrypt.client.apache.configurator import ApacheConfigurator
|
||||||
from letsencrypt.client.standalone_authenticator \
|
from letsencrypt.client.standalone_authenticator import (
|
||||||
import StandaloneAuthenticator
|
StandaloneAuthenticator)
|
||||||
|
|
||||||
self.mock_stand = mock.MagicMock(
|
self.mock_stand = mock.MagicMock(
|
||||||
spec=StandaloneAuthenticator, description="Apache Web Server")
|
spec=StandaloneAuthenticator, description="Apache Web Server")
|
||||||
@@ -37,16 +37,16 @@ class DetermineAuthenticatorTest(unittest.TestCase):
|
|||||||
self._call(self.all_auths[:1]), self.mock_apache)
|
self._call(self.all_auths[:1]), self.mock_apache)
|
||||||
|
|
||||||
def test_no_installation_one(self):
|
def test_no_installation_one(self):
|
||||||
self.mock_apache.prepare.side_effect = \
|
self.mock_apache.prepare.side_effect = (
|
||||||
errors.LetsEncryptNoInstallationError
|
errors.LetsEncryptNoInstallationError)
|
||||||
|
|
||||||
self.assertEqual(self._call(self.all_auths), self.mock_stand)
|
self.assertEqual(self._call(self.all_auths), self.mock_stand)
|
||||||
|
|
||||||
def test_no_installations(self):
|
def test_no_installations(self):
|
||||||
self.mock_apache.prepare.side_effect = \
|
self.mock_apache.prepare.side_effect = (
|
||||||
errors.LetsEncryptNoInstallationError
|
errors.LetsEncryptNoInstallationError)
|
||||||
self.mock_stand.prepare.side_effect = \
|
self.mock_stand.prepare.side_effect = (
|
||||||
errors.LetsEncryptNoInstallationError
|
errors.LetsEncryptNoInstallationError)
|
||||||
|
|
||||||
self.assertRaises(errors.LetsEncryptClientError,
|
self.assertRaises(errors.LetsEncryptClientError,
|
||||||
self._call,
|
self._call,
|
||||||
@@ -55,8 +55,8 @@ class DetermineAuthenticatorTest(unittest.TestCase):
|
|||||||
@mock.patch("letsencrypt.client.client.logging")
|
@mock.patch("letsencrypt.client.client.logging")
|
||||||
@mock.patch("letsencrypt.client.client.display_ops.choose_authenticator")
|
@mock.patch("letsencrypt.client.client.display_ops.choose_authenticator")
|
||||||
def test_misconfigured(self, mock_choose, unused_log):
|
def test_misconfigured(self, mock_choose, unused_log):
|
||||||
self.mock_apache.prepare.side_effect = \
|
self.mock_apache.prepare.side_effect = (
|
||||||
errors.LetsEncryptMisconfigurationError
|
errors.LetsEncryptMisconfigurationError)
|
||||||
mock_choose.return_value = self.mock_apache
|
mock_choose.return_value = self.mock_apache
|
||||||
|
|
||||||
self.assertRaises(SystemExit, self._call, self.all_auths)
|
self.assertRaises(SystemExit, self._call, self.all_auths)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class DisplayCertsTest(unittest.TestCase):
|
|||||||
code, choice = self._call(self.certs)
|
code, choice = self._call(self.certs)
|
||||||
|
|
||||||
self.assertEqual(display_util.OK, code)
|
self.assertEqual(display_util.OK, code)
|
||||||
self.assertTrue(self.certs[choice] == self.cert0)
|
self.assertEqual(self.certs[choice], self.cert0)
|
||||||
|
|
||||||
@mock.patch("letsencrypt.client.display.revocation.util")
|
@mock.patch("letsencrypt.client.display.revocation.util")
|
||||||
def test_cancel(self, mock_util):
|
def test_cancel(self, mock_util):
|
||||||
|
|||||||
@@ -42,6 +42,18 @@ class NcursesDisplayTest(DisplayT):
|
|||||||
super(NcursesDisplayTest, self).setUp()
|
super(NcursesDisplayTest, self).setUp()
|
||||||
self.displayer = display_util.NcursesDisplay()
|
self.displayer = display_util.NcursesDisplay()
|
||||||
|
|
||||||
|
self.default_menu_options = {
|
||||||
|
"choices": self.choices,
|
||||||
|
"ok_label": "OK",
|
||||||
|
"cancel_label": "Cancel",
|
||||||
|
"help_button": False,
|
||||||
|
"help_label": "",
|
||||||
|
"width": display_util.WIDTH,
|
||||||
|
"height": display_util.HEIGHT,
|
||||||
|
"menu_height": display_util.HEIGHT-6,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@mock.patch("letsencrypt.client.display.util.dialog.Dialog.msgbox")
|
@mock.patch("letsencrypt.client.display.util.dialog.Dialog.msgbox")
|
||||||
def test_notification(self, mock_msgbox):
|
def test_notification(self, mock_msgbox):
|
||||||
"""Kind of worthless... one liner."""
|
"""Kind of worthless... one liner."""
|
||||||
@@ -53,11 +65,7 @@ class NcursesDisplayTest(DisplayT):
|
|||||||
mock_menu.return_value = (display_util.OK, "First")
|
mock_menu.return_value = (display_util.OK, "First")
|
||||||
|
|
||||||
ret = self.displayer.menu("Message", self.choices)
|
ret = self.displayer.menu("Message", self.choices)
|
||||||
mock_menu.assert_called_with(
|
mock_menu.assert_called_with("Message", **self.default_menu_options)
|
||||||
"Message", choices=self.choices, ok_label="OK",
|
|
||||||
cancel_label="Cancel",
|
|
||||||
help_button=False, help_label="",
|
|
||||||
width=display_util.WIDTH, height=display_util.HEIGHT)
|
|
||||||
|
|
||||||
self.assertEqual(ret, (display_util.OK, 0))
|
self.assertEqual(ret, (display_util.OK, 0))
|
||||||
|
|
||||||
@@ -67,11 +75,7 @@ class NcursesDisplayTest(DisplayT):
|
|||||||
|
|
||||||
ret = self.displayer.menu("Message", self.choices)
|
ret = self.displayer.menu("Message", self.choices)
|
||||||
|
|
||||||
mock_menu.assert_called_with(
|
mock_menu.assert_called_with("Message", **self.default_menu_options)
|
||||||
"Message", choices=self.choices, ok_label="OK",
|
|
||||||
cancel_label="Cancel",
|
|
||||||
help_button=False, help_label="",
|
|
||||||
width=display_util.WIDTH, height=display_util.HEIGHT)
|
|
||||||
|
|
||||||
self.assertEqual(ret, (display_util.CANCEL, -1))
|
self.assertEqual(ret, (display_util.CANCEL, -1))
|
||||||
|
|
||||||
@@ -81,11 +85,9 @@ class NcursesDisplayTest(DisplayT):
|
|||||||
|
|
||||||
ret = self.displayer.menu("Message", self.tags, help_label="More Info")
|
ret = self.displayer.menu("Message", self.tags, help_label="More Info")
|
||||||
|
|
||||||
mock_menu.assert_called_with(
|
self.default_menu_options.update(
|
||||||
"Message", choices=self.tags_choices, ok_label="OK",
|
choices=self.tags_choices, help_button=True, help_label="More Info")
|
||||||
cancel_label="Cancel",
|
mock_menu.assert_called_with("Message", **self.default_menu_options)
|
||||||
help_button=True, help_label="More Info",
|
|
||||||
width=display_util.WIDTH, height=display_util.HEIGHT)
|
|
||||||
|
|
||||||
self.assertEqual(ret, (display_util.OK, 0))
|
self.assertEqual(ret, (display_util.OK, 0))
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ class RevokerTest(RevokerBase):
|
|||||||
@mock.patch("letsencrypt.client.revoker.Crypto.PublicKey.RSA.importKey")
|
@mock.patch("letsencrypt.client.revoker.Crypto.PublicKey.RSA.importKey")
|
||||||
def test_acme_revoke_failure(self, mock_crypto):
|
def test_acme_revoke_failure(self, mock_crypto):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
mock_crypto.side_effect = IOError
|
mock_crypto.side_effect = ValueError
|
||||||
self.assertRaises(errors.LetsEncryptClientError,
|
self.assertRaises(errors.LetsEncryptClientError,
|
||||||
self.revoker._acme_revoke,
|
self.revoker._acme_revoke,
|
||||||
self.certs[0])
|
self.certs[0])
|
||||||
|
|||||||
@@ -545,8 +545,8 @@ class CleanupTest(unittest.TestCase):
|
|||||||
class MoreInfoTest(unittest.TestCase):
|
class MoreInfoTest(unittest.TestCase):
|
||||||
"""Tests for more_info() method. (trivially)"""
|
"""Tests for more_info() method. (trivially)"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
from letsencrypt.client.standalone_authenticator import \
|
from letsencrypt.client.standalone_authenticator import (
|
||||||
StandaloneAuthenticator
|
StandaloneAuthenticator)
|
||||||
self.authenticator = StandaloneAuthenticator()
|
self.authenticator = StandaloneAuthenticator()
|
||||||
|
|
||||||
def test_more_info(self):
|
def test_more_info(self):
|
||||||
@@ -557,8 +557,8 @@ class MoreInfoTest(unittest.TestCase):
|
|||||||
class InitTest(unittest.TestCase):
|
class InitTest(unittest.TestCase):
|
||||||
"""Tests for more_info() method. (trivially)"""
|
"""Tests for more_info() method. (trivially)"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
from letsencrypt.client.standalone_authenticator import \
|
from letsencrypt.client.standalone_authenticator import (
|
||||||
StandaloneAuthenticator
|
StandaloneAuthenticator)
|
||||||
self.authenticator = StandaloneAuthenticator()
|
self.authenticator = StandaloneAuthenticator()
|
||||||
|
|
||||||
def test_prepare(self):
|
def test_prepare(self):
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ setenv =
|
|||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
commands =
|
commands =
|
||||||
pip install -e .[testing]
|
pip install -e .[testing]
|
||||||
python setup.py nosetests --with-coverage --cover-min-percentage=84
|
python setup.py nosetests --with-coverage --cover-min-percentage=83
|
||||||
|
|
||||||
[testenv:lint]
|
[testenv:lint]
|
||||||
# recent versions of pylint do not support Python 2.6 (#97, #187)
|
# recent versions of pylint do not support Python 2.6 (#97, #187)
|
||||||
|
|||||||
Reference in New Issue
Block a user