mirror of
https://github.com/certbot/certbot.git
synced 2026-06-05 14:54:24 -04:00
Refactor logging, "pythonic" DialogHandler
This commit is contained in:
parent
cc85f22133
commit
7e0cee00b2
11 changed files with 237 additions and 333 deletions
|
|
@ -1,5 +1,6 @@
|
|||
"""Apache Configuration based off of Augeas Configurator."""
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import pkg_resources
|
||||
import re
|
||||
|
|
@ -15,7 +16,6 @@ from letsencrypt.client import CONFIG
|
|||
from letsencrypt.client import crypto_util
|
||||
from letsencrypt.client import errors
|
||||
from letsencrypt.client import le_util
|
||||
from letsencrypt.client import logger
|
||||
|
||||
|
||||
# Configurator should be turned into a Singleton
|
||||
|
|
@ -233,13 +233,13 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
|
||||
if len(path["cert_file"]) == 0 or len(path["cert_key"]) == 0:
|
||||
# Throw some "can't find all of the directives error"
|
||||
logger.warn(("Cannot find a cert or key directive in %s"
|
||||
% vhost.path))
|
||||
logger.warn("VirtualHost was not modified")
|
||||
logging.warn(
|
||||
"Cannot find a cert or key directive in %s", vhost.path)
|
||||
logging.warn("VirtualHost was not modified")
|
||||
# Presumably break here so that the virtualhost is not modified
|
||||
return False
|
||||
|
||||
logger.info("Deploying Certificate to VirtualHost %s" % vhost.filep)
|
||||
logging.info("Deploying Certificate to VirtualHost %s", vhost.filep)
|
||||
|
||||
self.aug.set(path["cert_file"][0], cert)
|
||||
self.aug.set(path["cert_key"][0], key)
|
||||
|
|
@ -530,15 +530,15 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
|
||||
"""
|
||||
if not check_ssl_loaded():
|
||||
logger.info("Loading mod_ssl into Apache Server")
|
||||
logging.info("Loading mod_ssl into Apache Server")
|
||||
enable_mod("ssl")
|
||||
|
||||
# Check for Listen 443
|
||||
# Note: This could be made to also look for ip:443 combo
|
||||
# TODO: Need to search only open directives and IfMod mod_ssl.c
|
||||
if len(self.find_directive(case_i("Listen"), "443")) == 0:
|
||||
logger.debug("No Listen 443 directive found")
|
||||
logger.debug("Setting the Apache Server to Listen on port 443")
|
||||
logging.debug("No Listen 443 directive found")
|
||||
logging.debug("Setting the Apache Server to Listen on port 443")
|
||||
path = self._add_dir_to_ifmodssl(
|
||||
get_aug_path(self.location["listen"]), "Listen", "443")
|
||||
self.save_notes += "Added Listen 443 directive to %s\n" % path
|
||||
|
|
@ -560,15 +560,15 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
tup = addr.partition(":")
|
||||
if tup[0] == "_default_":
|
||||
if not self.is_name_vhost(default_addr):
|
||||
logger.debug(("Setting all VirtualHosts on "
|
||||
"%s to be name based vhosts" % default_addr))
|
||||
logging.debug("Setting all VirtualHosts on %s to be "
|
||||
"name based vhosts", default_addr)
|
||||
self.add_name_vhost(default_addr)
|
||||
|
||||
# No default addresses... so set each one individually
|
||||
for addr in vhost.addrs:
|
||||
if not self.is_name_vhost(addr):
|
||||
logger.debug(("Setting VirtualHost at %s "
|
||||
"to be a name based virtual host" % addr))
|
||||
logging.debug("Setting VirtualHost at %s to be a name "
|
||||
"based virtual host", addr)
|
||||
self.add_name_vhost(addr)
|
||||
|
||||
def _get_ifmod(self, aug_conf_path, mod):
|
||||
|
|
@ -709,7 +709,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
# validChars = re.compile("[a-zA-Z0-9.*?_-/]*")
|
||||
# matchObj = validChars.match(arg)
|
||||
# if matchObj.group() != arg:
|
||||
# logger.error("Error: Invalid regexp characters in %s" % arg)
|
||||
# logging.error("Error: Invalid regexp characters in %s", arg)
|
||||
# return []
|
||||
|
||||
# Standardize the include argument based on server root
|
||||
|
|
@ -775,7 +775,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
new_file.write(line)
|
||||
new_file.write("</IfModule>\n")
|
||||
except IOError:
|
||||
logger.fatal("Error writing/reading to file in make_vhost_ssl")
|
||||
logging.fatal("Error writing/reading to file in make_vhost_ssl")
|
||||
sys.exit(49)
|
||||
finally:
|
||||
orig_file.close()
|
||||
|
|
@ -809,7 +809,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
vh_p = self.aug.match(("/files%s//* [label()=~regexp('%s')]" %
|
||||
(ssl_fp, case_i('VirtualHost'))))
|
||||
if len(vh_p) != 1:
|
||||
logger.error("Error: should only be one vhost in %s" % avail_fp)
|
||||
logging.error("Error: should only be one vhost in %s", avail_fp)
|
||||
sys.exit(1)
|
||||
|
||||
self.add_dir(vh_p[0], "SSLCertificateFile",
|
||||
|
|
@ -819,7 +819,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
self.add_dir(vh_p[0], "Include", self.location["ssl_options"])
|
||||
|
||||
# Log actions and create save notes
|
||||
logger.info("Created an SSL vhost at %s" % ssl_fp)
|
||||
logging.info("Created an SSL vhost at %s", ssl_fp)
|
||||
self.save_notes += 'Created ssl vhost at %s\n' % ssl_fp
|
||||
self.save()
|
||||
|
||||
|
|
@ -838,7 +838,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
if (self.is_name_vhost(nonssl_vhost.addrs[i]) and
|
||||
not self.is_name_vhost(ssl_addrs[i])):
|
||||
self.add_name_vhost(ssl_addrs[i])
|
||||
logger.info("Enabling NameVirtualHosts on " + ssl_addrs[i])
|
||||
logging.info("Enabling NameVirtualHosts on %s", ssl_addrs[i])
|
||||
need_to_save = True
|
||||
|
||||
if need_to_save:
|
||||
|
|
@ -868,7 +868,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
general_v = self._general_vhost(ssl_vhost)
|
||||
if general_v is None:
|
||||
# Add virtual_server with redirect
|
||||
logger.debug(
|
||||
logging.debug(
|
||||
"Did not find http version of ssl virtual host... creating")
|
||||
return self.create_redirect_vhost(ssl_vhost)
|
||||
else:
|
||||
|
|
@ -876,10 +876,10 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
exists, code = self.existing_redirect(general_v)
|
||||
if exists:
|
||||
if code == 0:
|
||||
logger.debug("Redirect already added")
|
||||
logging.debug("Redirect already added")
|
||||
return True, general_v
|
||||
else:
|
||||
logger.debug("Unknown redirect exists for this vhost")
|
||||
logging.debug("Unknown redirect exists for this vhost")
|
||||
return False, general_v
|
||||
# Add directives to server
|
||||
self.add_dir(general_v.path, "RewriteEngine", "On")
|
||||
|
|
@ -992,7 +992,7 @@ LogLevel warn \n\
|
|||
# Write out file
|
||||
with open(redirect_filepath, 'w') as redirect_fd:
|
||||
redirect_fd.write(redirect_file)
|
||||
logger.info("Created redirect file: " + redirect_filename)
|
||||
logging.info("Created redirect file: %s", redirect_filename)
|
||||
|
||||
self.aug.load()
|
||||
# Make a new vhost data structure and add it to the lists
|
||||
|
|
@ -1121,8 +1121,8 @@ LogLevel warn \n\
|
|||
|
||||
# Can be removed once find directive can return ordered results
|
||||
if len(cert_path) != 1 or len(key_path) != 1:
|
||||
logger.error(("Too many cert or key directives in vhost "
|
||||
"%s" % vhost.filep))
|
||||
logging.error("Too many cert or key directives in vhost %s",
|
||||
vhost.filep)
|
||||
sys.exit(40)
|
||||
|
||||
cert = os.path.abspath(self.aug.get(cert_path[0]))
|
||||
|
|
@ -1172,7 +1172,7 @@ LogLevel warn \n\
|
|||
self.register_file_creation(False, enabled_path)
|
||||
os.symlink(vhost.filep, enabled_path)
|
||||
vhost.enabled = True
|
||||
logger.info("Enabling available site: %s" % vhost.filep)
|
||||
logging.info("Enabling available site: %s", vhost.filep)
|
||||
self.save_notes += 'Enabled site %s\n' % vhost.filep
|
||||
return True
|
||||
return False
|
||||
|
|
@ -1289,14 +1289,14 @@ LogLevel warn \n\
|
|||
stderr=subprocess.PIPE)
|
||||
text = proc.communicate()
|
||||
except (OSError, ValueError):
|
||||
logger.fatal("Unable to run /usr/sbin/apache2ctl configtest")
|
||||
logging.fatal("Unable to run /usr/sbin/apache2ctl configtest")
|
||||
sys.exit(1)
|
||||
|
||||
if proc.returncode != 0:
|
||||
# Enter recovery routine...
|
||||
logger.error("Configtest failed")
|
||||
logger.error(text[0])
|
||||
logger.error(text[1])
|
||||
logging.error("Configtest failed")
|
||||
logging.error(text[0])
|
||||
logging.error(text[1])
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
@ -1384,8 +1384,8 @@ LogLevel warn \n\
|
|||
|
||||
# Do weak validation that challenge is of expected type
|
||||
if not ("list_sni_tuple" in chall_dict and "dvsni_key" in chall_dict):
|
||||
logger.fatal("Incorrect parameter given to Apache DVSNI challenge")
|
||||
logger.fatal("Chall dict: " + str(chall_dict))
|
||||
logging.fatal("Incorrect parameter given to Apache DVSNI challenge")
|
||||
logging.fatal("Chall dict: %s", chall_dict)
|
||||
sys.exit(1)
|
||||
|
||||
addresses = []
|
||||
|
|
@ -1393,10 +1393,10 @@ LogLevel warn \n\
|
|||
for tup in chall_dict["list_sni_tuple"]:
|
||||
vhost = self.choose_virtual_host(tup[0])
|
||||
if vhost is None:
|
||||
logger.error(("No vhost exists with servername "
|
||||
"or alias of: %s" % tup[0]))
|
||||
logger.error("No _default_:443 vhost exists")
|
||||
logger.error("Please specify servernames in the Apache config")
|
||||
logging.error(
|
||||
"No vhost exists with servername or alias of: %s", tup[0])
|
||||
logging.error("No _default_:443 vhost exists")
|
||||
logging.error("Please specify servernames in the Apache config")
|
||||
return None
|
||||
|
||||
# TODO - @jdkasten review this code to make sure it makes sense
|
||||
|
|
@ -1565,8 +1565,8 @@ def enable_mod(mod_name):
|
|||
stdout=open("/dev/null", 'w'),
|
||||
stderr=open("/dev/null", 'w'))
|
||||
except (OSError, subprocess.CalledProcessError) as err:
|
||||
logger.error("Error enabling mod_" + mod_name)
|
||||
logger.error("Exception: %s" % str(err))
|
||||
logging.error("Error enabling mod_%s", mod_name)
|
||||
logging.error("Exception: %s", err)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
|
@ -1589,9 +1589,9 @@ def check_ssl_loaded():
|
|||
stderr=open(
|
||||
"/dev/null", 'w')).communicate()[0]
|
||||
except (OSError, ValueError):
|
||||
logger.error(
|
||||
"Error accessing %s for loaded modules!" % CONFIG.APACHE_CTL)
|
||||
logger.error("This may be caused by an Apache Configuration Error")
|
||||
logging.error(
|
||||
"Error accessing %s for loaded modules!", CONFIG.APACHE_CTL)
|
||||
logging.error("This may be caused by an Apache Configuration Error")
|
||||
return False
|
||||
|
||||
if "ssl_module" in proc:
|
||||
|
|
@ -1614,14 +1614,14 @@ def apache_restart():
|
|||
|
||||
if proc.returncode != 0:
|
||||
# Enter recovery routine...
|
||||
logger.error("Configtest failed")
|
||||
logger.error(text[0])
|
||||
logger.error(text[1])
|
||||
logging.error("Configtest failed")
|
||||
logging.error(text[0])
|
||||
logging.error(text[1])
|
||||
return False
|
||||
|
||||
except (OSError, ValueError):
|
||||
logger.fatal(("Apache Restart Failed - "
|
||||
"Please Check the Configuration"))
|
||||
logging.fatal(
|
||||
"Apache Restart Failed - Please Check the Configuration")
|
||||
sys.exit(1)
|
||||
|
||||
return True
|
||||
|
|
@ -1720,8 +1720,6 @@ def main():
|
|||
"""Main function used for quick testing purposes"""
|
||||
|
||||
config = ApacheConfigurator()
|
||||
logger.setLogger(logger.FileLogger(sys.stdout))
|
||||
logger.setLogLevel(logger.DEBUG)
|
||||
|
||||
# for v in config.vhosts:
|
||||
# print v.filep
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
"""Class of Augeas Configurators."""
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
|
@ -9,7 +10,6 @@ import augeas
|
|||
from letsencrypt.client import CONFIG
|
||||
from letsencrypt.client import configurator
|
||||
from letsencrypt.client import le_util
|
||||
from letsencrypt.client import logger
|
||||
|
||||
|
||||
class AugeasConfigurator(configurator.Configurator):
|
||||
|
|
@ -61,9 +61,9 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
# As aug.get may return null
|
||||
if lens_path and lens in lens_path:
|
||||
# Strip off /augeas/files and /error
|
||||
logger.error('There has been an error in parsing the file: '
|
||||
'%s' % path[13:len(path) - 6])
|
||||
logger.error(self.aug.get(path + '/message'))
|
||||
logging.error('There has been an error in parsing the file: %s',
|
||||
path[13:len(path) - 6])
|
||||
logging.error(self.aug.get(path + '/message'))
|
||||
|
||||
def save(self, title=None, temporary=False):
|
||||
"""Saves all changes to the configuration files.
|
||||
|
|
@ -90,14 +90,14 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
except (RuntimeError, IOError):
|
||||
# Check for the root of save problems
|
||||
new_errs = self.aug.match("/augeas//error")
|
||||
# logger.error("During Save - " + mod_conf)
|
||||
# logging.error("During Save - %s", mod_conf)
|
||||
# Only print new errors caused by recent save
|
||||
for err in new_errs:
|
||||
if err not in ex_errs:
|
||||
logger.error("Unable to save file - "
|
||||
"%s" % err[13:len(err)-6])
|
||||
logger.error("Attempted Save Notes")
|
||||
logger.error(self.save_notes)
|
||||
logging.error(
|
||||
"Unable to save file - %s", err[13:len(err) - 6])
|
||||
logging.error("Attempted Save Notes")
|
||||
logging.error(self.save_notes)
|
||||
# Erase Save Notes
|
||||
self.save_notes = ""
|
||||
return False
|
||||
|
|
@ -117,7 +117,7 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
valid, message = self.check_tempfile_saves(save_files)
|
||||
|
||||
if not valid:
|
||||
logger.fatal(message)
|
||||
logging.fatal(message)
|
||||
# What is the protocol in this situation?
|
||||
# This shouldn't happen if the challenge codebase is correct
|
||||
return False
|
||||
|
|
@ -153,8 +153,8 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
result = self._recover_checkpoint(self.direc["temp"])
|
||||
if result != 0:
|
||||
# We have a partial or incomplete recovery
|
||||
logger.fatal("Incomplete or failed recovery for "
|
||||
"%s" % self.direc["temp"])
|
||||
logging.fatal("Incomplete or failed recovery for %s",
|
||||
self.direc["temp"])
|
||||
sys.exit(67)
|
||||
# Remember to reload Augeas
|
||||
self.aug.load()
|
||||
|
|
@ -168,24 +168,24 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
try:
|
||||
rollback = int(rollback)
|
||||
except ValueError:
|
||||
logger.error("Rollback argument must be a positive integer")
|
||||
logging.error("Rollback argument must be a positive integer")
|
||||
# Sanity check input
|
||||
if rollback < 1:
|
||||
logger.error("Rollback argument must be a positive integer")
|
||||
logging.error("Rollback argument must be a positive integer")
|
||||
return
|
||||
|
||||
backups = os.listdir(self.direc["backup"])
|
||||
backups.sort()
|
||||
|
||||
if len(backups) < rollback:
|
||||
logger.error(("Unable to rollback %d checkpoints, only "
|
||||
"%d exist") % (rollback, len(backups)))
|
||||
logging.error("Unable to rollback %d checkpoints, only %d exist",
|
||||
rollback, len(backups))
|
||||
|
||||
while rollback > 0 and backups:
|
||||
cp_dir = self.direc["backup"] + backups.pop()
|
||||
result = self._recover_checkpoint(cp_dir)
|
||||
if result != 0:
|
||||
logger.fatal("Failed to load checkpoint during rollback")
|
||||
logging.fatal("Failed to load checkpoint during rollback")
|
||||
sys.exit(39)
|
||||
rollback -= 1
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
if filename not in existing_filepaths:
|
||||
# Tag files with index so multiple files can
|
||||
# have the same filename
|
||||
logger.debug("Creating backup of %s" % filename)
|
||||
logging.debug("Creating backup of %s", filename)
|
||||
shutil.copy2(filename, os.path.join(
|
||||
cp_dir, os.path.basename(filename) + "_" + str(idx)))
|
||||
op_fd.write(filename + '\n')
|
||||
|
|
@ -295,7 +295,7 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
path)
|
||||
except (IOError, OSError):
|
||||
# This file is required in all checkpoints.
|
||||
logger.error("Unable to recover files from %s" % cp_dir)
|
||||
logging.error("Unable to recover files from %s", cp_dir)
|
||||
return 1
|
||||
|
||||
# Remove any newly added files if they exist
|
||||
|
|
@ -304,7 +304,7 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
try:
|
||||
shutil.rmtree(cp_dir)
|
||||
except OSError:
|
||||
logger.error("Unable to remove directory: %s" % cp_dir)
|
||||
logging.error("Unable to remove directory: %s", cp_dir)
|
||||
return -1
|
||||
|
||||
return 0
|
||||
|
|
@ -354,7 +354,7 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
for file_path in files:
|
||||
new_fd.write("%s\n" % file_path)
|
||||
except (IOError, OSError):
|
||||
logger.error("ERROR: Unable to register file creation")
|
||||
logging.error("ERROR: Unable to register file creation")
|
||||
|
||||
def recovery_routine(self):
|
||||
"""Revert all previously modified files.
|
||||
|
|
@ -373,8 +373,8 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
# We have a partial or incomplete recovery
|
||||
# Not as egregious
|
||||
# TODO: Additional tests? recovery
|
||||
logger.fatal("Incomplete or failed recovery for %s" %
|
||||
self.direc["progress"])
|
||||
logging.fatal("Incomplete or failed recovery for %s",
|
||||
self.direc["progress"])
|
||||
sys.exit(68)
|
||||
|
||||
# Need to reload configuration after these changes take effect
|
||||
|
|
@ -403,13 +403,12 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
if os.path.lexists(path):
|
||||
os.remove(path)
|
||||
else:
|
||||
logger.warn((
|
||||
logging.warn(
|
||||
"File: %s - Could not be found to be deleted\n"
|
||||
"Program was probably shut down unexpectedly, "
|
||||
"in which case this is not a problem") % path)
|
||||
"Program was probably shut down unexpectedly, ")
|
||||
except (IOError, OSError):
|
||||
logger.fatal(
|
||||
"Unable to remove filepaths contained within %s" % file_list)
|
||||
logging.fatal(
|
||||
"Unable to remove filepaths contained within %s", file_list)
|
||||
sys.exit(41)
|
||||
|
||||
return True
|
||||
|
|
@ -441,12 +440,12 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
shutil.move(changes_since_tmp_path, changes_since_path)
|
||||
|
||||
except (IOError, OSError):
|
||||
logger.error("Unable to finalize checkpoint - adding title")
|
||||
logging.error("Unable to finalize checkpoint - adding title")
|
||||
return False
|
||||
try:
|
||||
os.rename(cp_dir, final_dir)
|
||||
except OSError:
|
||||
logger.error("Unable to finalize checkpoint, %s -> %s" %
|
||||
(cp_dir, final_dir))
|
||||
logging.error(
|
||||
"Unable to finalize checkpoint, %s -> %s", cp_dir, final_dir)
|
||||
return False
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""ACME challenge."""
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from letsencrypt.client import CONFIG
|
||||
from letsencrypt.client import logger
|
||||
|
||||
|
||||
class Challenge(object):
|
||||
|
|
@ -93,8 +93,8 @@ def _find_smart_path(challenges, combos):
|
|||
combo_total = 0
|
||||
|
||||
if not best_combo:
|
||||
logger.fatal("Client does not support any combination of "
|
||||
"challenges to satisfy ACME server")
|
||||
logging.fatal("Client does not support any combination of "
|
||||
"challenges to satisfy ACME server")
|
||||
sys.exit(22)
|
||||
|
||||
return best_combo
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import collections
|
||||
import csv
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import socket
|
||||
|
|
@ -21,7 +22,6 @@ from letsencrypt.client import crypto_util
|
|||
from letsencrypt.client import display
|
||||
from letsencrypt.client import errors
|
||||
from letsencrypt.client import le_util
|
||||
from letsencrypt.client import logger
|
||||
|
||||
|
||||
# it's weird to point to chocolate servers via raw IPv6 addresses, and
|
||||
|
|
@ -65,9 +65,6 @@ class Client(object):
|
|||
self.privkey = privkey
|
||||
self._validate_csr_key_cli() # TODO: catch exceptions
|
||||
|
||||
# Logger needs to be initialized before Configurator
|
||||
self.init_logger()
|
||||
|
||||
# TODO: Can probably figure out which configurator to use
|
||||
# without special packaging based on system info Command
|
||||
# line arg or client function to discover
|
||||
|
|
@ -178,8 +175,8 @@ class Client(object):
|
|||
try:
|
||||
return self.is_expected_msg(auth_dict, "authorization")
|
||||
except:
|
||||
logger.fatal("Failed Authorization procedure - "
|
||||
"cleaning up challenges")
|
||||
logging.fatal(
|
||||
"Failed Authorization procedure - cleaning up challenges")
|
||||
sys.exit(1)
|
||||
finally:
|
||||
self.cleanup_challenges(chal_objs)
|
||||
|
|
@ -193,7 +190,7 @@ class Client(object):
|
|||
:rtype: dict
|
||||
|
||||
"""
|
||||
logger.info("Preparing and sending CSR..")
|
||||
logging.info("Preparing and sending CSR...")
|
||||
return self.send_and_receive_expected(
|
||||
acme.certificate_request(csr_der, self.privkey.pem), "certificate")
|
||||
|
||||
|
|
@ -303,24 +300,23 @@ class Client(object):
|
|||
return response
|
||||
|
||||
elif response["type"] == "error":
|
||||
logger.error("%s: %s - More Info: %s" %
|
||||
(response["error"],
|
||||
response.get("message", ""),
|
||||
response.get("moreInfo", "")))
|
||||
logging.error(
|
||||
"%s: %s - More Info: %s", response["error"],
|
||||
response.get("message", ""), response.get("moreInfo", ""))
|
||||
raise errors.LetsEncryptClientError(response["error"])
|
||||
|
||||
elif response["type"] == "defer":
|
||||
logger.info("Waiting for %d seconds..." % delay)
|
||||
logging.info("Waiting for %d seconds...", delay)
|
||||
time.sleep(delay)
|
||||
response = self.send(acme.status_request(response["token"]))
|
||||
else:
|
||||
logger.fatal("Received unexpected message")
|
||||
logger.fatal("Expected: %s" % expected)
|
||||
logger.fatal("Received: " + response)
|
||||
logging.fatal("Received unexpected message")
|
||||
logging.fatal("Expected: %s" % expected)
|
||||
logging.fatal("Received: " + response)
|
||||
sys.exit(33)
|
||||
|
||||
logger.error("Server has deferred past the max of %d seconds" %
|
||||
(rounds * delay))
|
||||
logging.error(
|
||||
"Server has deferred past the max of %d seconds", rounds * delay)
|
||||
|
||||
def list_certs_keys(self):
|
||||
"""List trusted Let's Encrypt certificates."""
|
||||
|
|
@ -328,7 +324,7 @@ class Client(object):
|
|||
certs = []
|
||||
|
||||
if not os.path.isfile(list_file):
|
||||
logger.info(
|
||||
logging.info(
|
||||
"You don't have any certificates saved from letsencrypt")
|
||||
return
|
||||
|
||||
|
|
@ -399,8 +395,8 @@ class Client(object):
|
|||
cert_fd.write(
|
||||
crypto_util.b64_cert_to_pem(certificate_dict["certificate"]))
|
||||
cert_fd.close()
|
||||
logger.info("Server issued certificate; certificate written to %s" %
|
||||
cert_file)
|
||||
logging.info(
|
||||
"Server issued certificate; certificate written to %s", cert_file)
|
||||
|
||||
if certificate_dict.get("chain", None):
|
||||
chain_fd, chain_fn = le_util.unique_file(CONFIG.CHAIN_PATH, 0o644)
|
||||
|
|
@ -408,7 +404,7 @@ class Client(object):
|
|||
chain_fd.write(crypto_util.b64_cert_to_pem(cert))
|
||||
chain_fd.close()
|
||||
|
||||
logger.info("Cert chain written to %s" % chain_fn)
|
||||
logging.info("Cert chain written to %s", chain_fn)
|
||||
|
||||
# This expects a valid chain file
|
||||
cert_chain_abspath = os.path.abspath(chain_fn)
|
||||
|
|
@ -420,7 +416,7 @@ class Client(object):
|
|||
cert_chain_abspath)
|
||||
# Enable any vhost that was issued to, but not enabled
|
||||
if not host.enabled:
|
||||
logger.info("Enabling Site " + host.filep)
|
||||
logging.info("Enabling Site %s", host.filep)
|
||||
self.config.enable_site(host)
|
||||
|
||||
# sites may have been enabled / final cleanup
|
||||
|
|
@ -464,7 +460,7 @@ class Client(object):
|
|||
:param dict challenges: challenges from a challenge message
|
||||
|
||||
"""
|
||||
logger.info("Cleaning up challenges...")
|
||||
logging.info("Cleaning up challenges...")
|
||||
for chall in challenges:
|
||||
if chall["type"] in CONFIG.CONFIG_CHALLENGES:
|
||||
self.config.cleanup()
|
||||
|
|
@ -484,7 +480,7 @@ class Client(object):
|
|||
path = challenge.gen_challenge_path(
|
||||
challenge_msg["challenges"], challenge_msg.get("combinations", []))
|
||||
|
||||
logger.info("Performing the following challenges:")
|
||||
logging.info("Performing the following challenges:")
|
||||
|
||||
# Every indices element is a list of integers referring to which
|
||||
# challenges in the master list the challenge object satisfies
|
||||
|
|
@ -507,8 +503,8 @@ class Client(object):
|
|||
for index in indices[i]:
|
||||
responses[index] = response
|
||||
|
||||
logger.info("Configured Apache for challenges; " +
|
||||
"waiting for verification...")
|
||||
logging.info(
|
||||
"Configured Apache for challenges; waiting for verification...")
|
||||
|
||||
return responses, challenge_objs
|
||||
|
||||
|
|
@ -528,9 +524,10 @@ class Client(object):
|
|||
idx = 0
|
||||
|
||||
if encrypt:
|
||||
logger.error("Unfortunately securely storing the certificates/"
|
||||
"keys is not yet available. Stay tuned for the "
|
||||
"next update!")
|
||||
logging.error(
|
||||
"Unfortunately securely storing the certificates/"
|
||||
"keys is not yet available. Stay tuned for the "
|
||||
"next update!")
|
||||
return False
|
||||
|
||||
if os.path.isfile(list_file):
|
||||
|
|
@ -566,9 +563,8 @@ class Client(object):
|
|||
"""
|
||||
for ssl_vh in vhost:
|
||||
success, redirect_vhost = self.config.enable_redirect(ssl_vh)
|
||||
# pylint: disable=maybe-no-member
|
||||
logger.info("\nRedirect vhost: " + redirect_vhost.filep +
|
||||
" - " + str(success))
|
||||
logging.info(
|
||||
"\nRedirect vhost: %s - %s ", redirect_vhost.filep, success)
|
||||
# If successful, make sure redirect site is enabled
|
||||
if success:
|
||||
self.config.enable_site(redirect_vhost)
|
||||
|
|
@ -615,20 +611,20 @@ class Client(object):
|
|||
chall = challenges[index]
|
||||
|
||||
if chall["type"] == "dvsni":
|
||||
logger.info(" DVSNI challenge for name %s." % name)
|
||||
logging.info(" DVSNI challenge for name %s.", name)
|
||||
sni_satisfies.append(index)
|
||||
sni_todo.append((str(name), str(chall["r"]),
|
||||
str(chall["nonce"])))
|
||||
|
||||
elif chall["type"] == "recoveryToken":
|
||||
logger.info("\tRecovery Token Challenge for name: %s." % name)
|
||||
logging.info("\tRecovery Token Challenge for name: %s.", name)
|
||||
challenge_obj_indices.append(index)
|
||||
challenge_objs.append({
|
||||
type: "recoveryToken",
|
||||
})
|
||||
|
||||
else:
|
||||
logger.fatal("Challenge not currently supported")
|
||||
logging.fatal("Challenge not currently supported")
|
||||
sys.exit(82)
|
||||
|
||||
if sni_todo:
|
||||
|
|
@ -640,7 +636,7 @@ class Client(object):
|
|||
"dvsni_key": self.privkey,
|
||||
})
|
||||
challenge_obj_indices.append(sni_satisfies)
|
||||
logger.debug(sni_todo)
|
||||
logging.debug(sni_todo)
|
||||
|
||||
return challenge_objs, challenge_obj_indices
|
||||
|
||||
|
|
@ -663,7 +659,7 @@ class Client(object):
|
|||
key_f.write(key_pem)
|
||||
key_f.close()
|
||||
|
||||
logger.info("Generating key: %s" % key_filename)
|
||||
logging.info("Generating key: %s", key_filename)
|
||||
|
||||
self.privkey = Client.Key(key_filename, key_pem)
|
||||
|
||||
|
|
@ -678,7 +674,7 @@ class Client(object):
|
|||
csr_f.write(csr_pem)
|
||||
csr_f.close()
|
||||
|
||||
logger.info("Creating CSR: %s" % csr_filename)
|
||||
logging.info("Creating CSR: %s", csr_filename)
|
||||
|
||||
self.csr = Client.CSR(csr_filename, csr_der, "der")
|
||||
elif self.csr.type != "der":
|
||||
|
|
@ -726,22 +722,14 @@ class Client(object):
|
|||
sanity_check_names(names)
|
||||
|
||||
if not names:
|
||||
logger.fatal("No domain names were found in your apache config")
|
||||
logger.fatal("Either specify which names you would like "
|
||||
"letsencrypt to validate or add server names "
|
||||
"to your virtual hosts")
|
||||
logging.fatal("No domain names were found in your apache config")
|
||||
logging.fatal("Either specify which names you would like "
|
||||
"letsencrypt to validate or add server names "
|
||||
"to your virtual hosts")
|
||||
sys.exit(1)
|
||||
|
||||
return names
|
||||
|
||||
def init_logger(self):
|
||||
if self.use_curses:
|
||||
logger.setLogger(logger.NcursesLogger())
|
||||
logger.setLogLevel(logger.INFO)
|
||||
else:
|
||||
logger.setLogger(logger.FileLogger(sys.stdout))
|
||||
logger.setLogLevel(logger.INFO)
|
||||
|
||||
|
||||
def remove_cert_key(cert):
|
||||
"""Remove certificate key.
|
||||
|
|
@ -778,7 +766,7 @@ def sanity_check_names(names):
|
|||
"""
|
||||
for name in names:
|
||||
if not is_hostname_sane(name):
|
||||
logger.fatal(repr(name) + " is an impossible hostname")
|
||||
logging.fatal("%r is an impossible hostname", name)
|
||||
sys.exit(81)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Let's Encrypt client crypto utility functions"""
|
||||
import binascii
|
||||
import hashlib
|
||||
import logging
|
||||
import time
|
||||
|
||||
from Crypto import Random
|
||||
|
|
@ -12,7 +13,6 @@ import M2Crypto
|
|||
|
||||
from letsencrypt.client import CONFIG
|
||||
from letsencrypt.client import le_util
|
||||
from letsencrypt.client import logger
|
||||
|
||||
|
||||
# TODO: All of these functions need unit tests
|
||||
|
|
@ -53,7 +53,7 @@ def create_sig(msg, key_str, nonce=None, nonce_len=CONFIG.NONCE_SIZE):
|
|||
hashed = Crypto.Hash.SHA256.new(msg_with_nonce)
|
||||
signature = Crypto.Signature.PKCS1_v1_5.new(key).sign(hashed)
|
||||
|
||||
logger.debug('%s signed as %s' % (msg_with_nonce, signature))
|
||||
logging.debug('%s signed as %s', msg_with_nonce, signature)
|
||||
|
||||
n_bytes = binascii.unhexlify(leading_zeros(hex(key.n)[2:].rstrip("L")))
|
||||
e_bytes = binascii.unhexlify(leading_zeros(hex(key.e)[2:].rstrip("L")))
|
||||
|
|
|
|||
64
letsencrypt/client/log.py
Normal file
64
letsencrypt/client/log.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
"""Logging utilities."""
|
||||
import logging
|
||||
|
||||
import dialog
|
||||
|
||||
from letsencrypt.client import display
|
||||
|
||||
|
||||
class DialogHandler(logging.Handler):
|
||||
"""Logging handler using dialog info box.
|
||||
|
||||
:ivar int height: Height of the info box (without padding).
|
||||
:ivar int width: Width of the info box (without padding).
|
||||
:ivar list lines: Lines to be displayed in the info box.
|
||||
:ivar d: Instance of :class:`dialog.Dialog`.
|
||||
|
||||
"""
|
||||
|
||||
PADDING_HEIGHT = 2
|
||||
PADDING_WIDTH = 4
|
||||
|
||||
def __init__(self, level=logging.NOTSET, height=display.HEIGHT,
|
||||
width=display.WIDTH - 4, d=None):
|
||||
# Handler not new-style -> no super
|
||||
logging.Handler.__init__(self, level)
|
||||
self.height = height
|
||||
self.width = width
|
||||
# "dialog" collides with module name... pylint: disable=invalid-name
|
||||
self.d = dialog.Dialog() if d is None else d
|
||||
self.lines = []
|
||||
|
||||
def emit(self, record):
|
||||
"""Emit message to a dialog info box.
|
||||
|
||||
Only show the last (self.height) lines; note that lines can wrap
|
||||
at self.width, so a single line could actually be multiple
|
||||
lines.
|
||||
|
||||
"""
|
||||
for line in (record.msg % record.args).splitlines():
|
||||
# check for lines that would wrap
|
||||
cur_out = line
|
||||
while len(cur_out) > self.width:
|
||||
# find first space before self.width chars into cur_out
|
||||
last_space_pos = cur_out.rfind(' ', 0, self.width)
|
||||
|
||||
if last_space_pos == -1:
|
||||
# no spaces, just cut them off at whatever
|
||||
self.lines.append(cur_out[0:self.width])
|
||||
cur_out = cur_out[self.width:]
|
||||
else:
|
||||
# cut off at last space
|
||||
self.lines.append(cur_out[0:last_space_pos])
|
||||
cur_out = cur_out[last_space_pos + 1:]
|
||||
if cur_out != '':
|
||||
self.lines.append(cur_out)
|
||||
|
||||
# show last 16 lines
|
||||
content = '\n'.join(self.lines[-self.height:])
|
||||
|
||||
# add the padding around the box
|
||||
self.d.infobox(
|
||||
content, self.height + self.PADDING_HEIGHT,
|
||||
self.width + self.PADDING_WIDTH)
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
"""Logger."""
|
||||
import logger
|
||||
import textwrap
|
||||
import time
|
||||
|
||||
import dialog
|
||||
|
||||
from letsencrypt.client import display
|
||||
from letsencrypt.client import errors
|
||||
|
||||
|
||||
class Singleton(object):
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not cls._instance:
|
||||
cls._instance = super(
|
||||
Singleton, cls).__new__(cls, *args, **kwargs)
|
||||
return cls._instance
|
||||
|
||||
# log levels
|
||||
TRACE = 5
|
||||
DEBUG = 4
|
||||
INFO = 3
|
||||
WARN = 2
|
||||
ERROR = 1
|
||||
FATAL = 0
|
||||
NONE = -1
|
||||
|
||||
|
||||
class Logger(Singleton):
|
||||
debugLevelStr = {TRACE: 'TRACE', DEBUG: 'DEBUG', INFO: 'INFO',
|
||||
WARN: 'WARN', ERROR: 'ERROR', FATAL: 'FATAL'}
|
||||
|
||||
def __init__(self):
|
||||
self.level = INFO
|
||||
|
||||
def debugLevel(self, level=DEBUG):
|
||||
return self.debugLevelStr[level]
|
||||
|
||||
def log(self, level, data):
|
||||
raise errors.LetsEncryptClientError("No Logger defined")
|
||||
|
||||
def timefmt(self, t=None):
|
||||
if t is None:
|
||||
t = time.time()
|
||||
return time.strftime("%b %d %Y %H:%M:%S",
|
||||
time.localtime(t)) + ('%.03f' % (t - int(t)))[1:]
|
||||
|
||||
|
||||
class FileLogger(Logger):
|
||||
|
||||
def __init__(self, outfile):
|
||||
self.outfile = outfile
|
||||
|
||||
def log(self, level, data):
|
||||
msg = "%s [%s] %s" % (self.timefmt(), self.debugLevel(level), data)
|
||||
wm = textwrap.fill(msg, 80)
|
||||
self.outfile.write("%s\n" % wm)
|
||||
|
||||
|
||||
class NcursesLogger(Logger):
|
||||
|
||||
def __init__(self,
|
||||
firstmessage="",
|
||||
height=display.HEIGHT,
|
||||
width=display.WIDTH-4):
|
||||
self.lines = []
|
||||
self.all_content = ""
|
||||
self.d = dialog.Dialog()
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.add(firstmessage)
|
||||
|
||||
'''
|
||||
Only show the last (self.height) lines;
|
||||
note that lines can wrap at self.width, so
|
||||
a single line could actually be multiple lines
|
||||
'''
|
||||
def add(self, s):
|
||||
self.all_content += s
|
||||
|
||||
for line in s.splitlines():
|
||||
# check for lines that would wrap
|
||||
cur_out = line
|
||||
while len(cur_out) > self.width:
|
||||
|
||||
# find first space before self.width chars into cur_out
|
||||
last_space_pos = cur_out.rfind(' ', 0, self.width)
|
||||
|
||||
if (last_space_pos == -1):
|
||||
# no spaces, just cut them off at whatever
|
||||
self.lines.append(cur_out[0:self.width])
|
||||
cur_out = cur_out[self.width:]
|
||||
else:
|
||||
# cut off at last space
|
||||
self.lines.append(cur_out[0:last_space_pos])
|
||||
cur_out = cur_out[last_space_pos+1:]
|
||||
if cur_out != '':
|
||||
self.lines.append(cur_out)
|
||||
|
||||
# show last 16 lines
|
||||
self.content = '\n'.join(self.lines[-self.height:])
|
||||
self.show()
|
||||
|
||||
def show(self):
|
||||
# add the padding around the box
|
||||
self.d.infobox(self.content, self.height+2, self.width+4)
|
||||
|
||||
def log(self, level, data):
|
||||
self.add(str(data) + "\n")
|
||||
|
||||
|
||||
log_instance = None
|
||||
|
||||
|
||||
def setLogger(log_inst):
|
||||
global log_instance
|
||||
log_instance = log_inst
|
||||
|
||||
|
||||
def setLogLevel(log_level):
|
||||
global log_instance
|
||||
log_instance.level = log_level
|
||||
|
||||
|
||||
def log(level, data):
|
||||
global log_instance
|
||||
if level <= log_instance.level:
|
||||
log_instance.log(level, data)
|
||||
|
||||
|
||||
def trace(data):
|
||||
log(TRACE, data)
|
||||
|
||||
|
||||
def debug(data):
|
||||
log(DEBUG, data)
|
||||
|
||||
|
||||
def info(data):
|
||||
log(INFO, data)
|
||||
|
||||
|
||||
def warn(data):
|
||||
log(WARN, data)
|
||||
|
||||
|
||||
def error(data):
|
||||
log(ERROR, data)
|
||||
|
||||
|
||||
def fatal(data):
|
||||
log(FATAL, data)
|
||||
|
||||
|
||||
def none(data):
|
||||
# Uh...what?
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Unit test/example usage:
|
||||
|
||||
# Set the logging type you want to use (stdout logging):
|
||||
# logger.setLogger(FileLogger(sys.stdout))
|
||||
setLogger(NcursesLogger())
|
||||
|
||||
# Set the most verbose you want to log
|
||||
# (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, NONE)
|
||||
setLogLevel(logger.TRACE)
|
||||
|
||||
# Log a message:
|
||||
# logger.log(logger.INFO, "logger!")
|
||||
|
||||
time.sleep(0.01)
|
||||
info(("This is a long line, it's pretty long, butitalso hasbig wordsthat "
|
||||
"areprobably hardtobreak oninan easywayforthe ncurseslib, "
|
||||
"sowhatdoes itdo then?"))
|
||||
info("aa " + "a"*70 + "B")
|
||||
|
||||
for i in range(20):
|
||||
info("iteration #%d/20" % i)
|
||||
time.sleep(0.3)
|
||||
|
||||
# Alternatively, use
|
||||
error("errrrr")
|
||||
|
||||
trace("some trace data: %d - %f - %s" % (5, 8.3, 'cows'))
|
||||
|
|
@ -66,7 +66,7 @@ class NginxConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
# # validChars = re.compile("[a-zA-Z0-9.*?_-/]*")
|
||||
# # matchObj = validChars.match(arg)
|
||||
# # if matchObj.group() != arg:
|
||||
# # logger.error("Error: Invalid regexp characters in %s" % arg)
|
||||
# # logging.error("Error: Invalid regexp characters in %s", arg)
|
||||
# # return []
|
||||
|
||||
# # Standardize the include argument based on server root
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ from letsencrypt.client import apache_configurator
|
|||
from letsencrypt.client import CONFIG
|
||||
from letsencrypt.client import display
|
||||
from letsencrypt.client import errors
|
||||
from letsencrypt.client import logger
|
||||
|
||||
# pylint: disable=no-member
|
||||
UBUNTU_CONFIGS = pkg_resources.resource_filename(
|
||||
|
|
@ -30,8 +29,6 @@ def setUpModule():
|
|||
|
||||
global TEMP_DIR, CONFIG_DIR, WORK_DIR
|
||||
|
||||
logger.setLogger(logger.FileLogger(sys.stdout))
|
||||
logger.setLogLevel(logger.INFO)
|
||||
display.set_display(display.NcursesDisplay())
|
||||
|
||||
TEMP_DIR = tempfile.mkdtemp("temp")
|
||||
|
|
|
|||
43
letsencrypt/client/tests/log_test.py
Normal file
43
letsencrypt/client/tests/log_test.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
"""Tests for letsencrypt.client.log."""
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
|
||||
|
||||
class DialogHandlerTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.d = mock.MagicMock() # pylint: disable=invalid-name
|
||||
|
||||
from letsencrypt.client.log import DialogHandler
|
||||
self.handler = DialogHandler(height=2, width=6, d=self.d)
|
||||
self.handler.PADDING_HEIGHT = 2
|
||||
self.handler.PADDING_WIDTH = 4
|
||||
|
||||
def test_adds_padding(self):
|
||||
self.handler.emit(mock.MagicMock())
|
||||
self.d.infobox.assert_called_once_with(mock.ANY, 4, 10)
|
||||
|
||||
def test_args_in_msg_get_replaced(self):
|
||||
assert len('123456') <= self.handler.width
|
||||
self.handler.emit(mock.MagicMock(msg='123%s', args=(456,)))
|
||||
self.d.infobox.assert_called_once_with('123456', mock.ANY, mock.ANY)
|
||||
|
||||
def test_wraps_nospace_is_greedy(self):
|
||||
assert len('1234567') > self.handler.width
|
||||
self.handler.emit(mock.MagicMock(msg='1234%s', args=(567,)))
|
||||
self.d.infobox.assert_called_once_with('123456\n7', mock.ANY, mock.ANY)
|
||||
|
||||
def test_wraps_at_whitespace(self):
|
||||
assert len('123 567') > self.handler.width
|
||||
self.handler.emit(mock.MagicMock(msg='123 %s', args=(567,)))
|
||||
self.d.infobox.assert_called_once_with('123\n567', mock.ANY, mock.ANY)
|
||||
|
||||
def test_only_last_lines_are_printed(self):
|
||||
assert len('a\nb\nc'.split()) > self.handler.height
|
||||
self.handler.emit(mock.MagicMock(msg='a\n\nb\nc'))
|
||||
self.d.infobox.assert_called_once_with('b\nc', mock.ANY, mock.ANY)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
"""Parse command line and call the appropriate functions."""
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
|
@ -8,10 +9,7 @@ from letsencrypt.client import apache_configurator
|
|||
from letsencrypt.client import CONFIG
|
||||
from letsencrypt.client import client
|
||||
from letsencrypt.client import display
|
||||
from letsencrypt.client import logger
|
||||
|
||||
logger.setLogger(logger.FileLogger(sys.stdout))
|
||||
logger.setLogLevel(logger.INFO)
|
||||
from letsencrypt.client import log
|
||||
|
||||
|
||||
def main():
|
||||
|
|
@ -55,20 +53,26 @@ def main():
|
|||
"HTTP and HTTPS.")
|
||||
parser.add_argument("-e", "--agree-eula", dest="eula", action="store_true",
|
||||
help="Skip the end user license agreement screen.")
|
||||
parser.add_argument("-t", "--text", dest="curses", action="store_false",
|
||||
parser.add_argument("-t", "--text", dest="use_curses", action="store_false",
|
||||
help="Use the text output instead of the curses UI.")
|
||||
parser.add_argument("--test", dest="test", action="store_true",
|
||||
help="Run in test mode.")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO) # TODO: --log
|
||||
if args.use_curses:
|
||||
logger.addHandler(log.DialogHandler())
|
||||
|
||||
# Enforce '--privkey' is set along with '--csr'.
|
||||
if args.csr and not args.privkey:
|
||||
parser.error("private key file (--privkey) must be specified along{0} "
|
||||
"with the certificate signing request file (--csr)"
|
||||
.format(os.linesep))
|
||||
|
||||
if args.curses:
|
||||
if args.use_curses:
|
||||
display.set_display(display.NcursesDisplay())
|
||||
else:
|
||||
display.set_display(display.FileDisplay(sys.stdout))
|
||||
|
|
@ -93,7 +97,7 @@ def main():
|
|||
else:
|
||||
csr = client.Client.CSR(args.csr[0], args.csr[1], "pem")
|
||||
|
||||
acme = client.Client(server, csr, privkey, args.curses)
|
||||
acme = client.Client(server, csr, privkey, args.use_curses)
|
||||
if args.revoke:
|
||||
acme.list_certs_keys()
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in a new issue