Skip to content

Instantly share code, notes, and snippets.

@alexzorin
Created October 5, 2020 23:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexzorin/bb3635c5d93619b52c1b1746d417eebe to your computer and use it in GitHub Desktop.
Save alexzorin/bb3635c5d93619b52c1b1746d417eebe to your computer and use it in GitHub Desktop.
commit 20225392022c23caac34c88d185d3754796e75b9
Author: Alex Zorin <alex@zorin.id.au>
Date: Sat Sep 26 18:27:47 2020 +1000
wip
diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py
index c36559032..6c881f743 100644
--- a/certbot/certbot/_internal/account.py
+++ b/certbot/certbot/_internal/account.py
@@ -94,21 +94,6 @@ class Account(object):
self.meta == other.meta)
-def report_new_account(config):
- """Informs the user about their new ACME account."""
- reporter = zope.component.queryUtility(interfaces.IReporter)
- if reporter is None:
- return
- reporter.add_message(
- "Your account credentials have been saved in your Certbot "
- "configuration directory at {0}. You should make a secure backup "
- "of this folder now. This configuration directory will also "
- "contain certificates and private keys obtained by Certbot "
- "so making regular backups of this folder is ideal.".format(
- config.config_dir),
- reporter.MEDIUM_PRIORITY)
-
-
class AccountMemoryStorage(interfaces.AccountStorage):
"""In-memory account storage."""
diff --git a/certbot/certbot/_internal/auth_handler.py b/certbot/certbot/_internal/auth_handler.py
index 7ea2a1de8..a3b0fb665 100644
--- a/certbot/certbot/_internal/auth_handler.py
+++ b/certbot/certbot/_internal/auth_handler.py
@@ -70,7 +70,7 @@ class AuthHandler(object):
resps = self.auth.perform(achalls)
# If debug is on, wait for user input before starting the verification process.
- logger.info('Waiting for verification...')
+ logger.debug('Waiting for verification...')
config = zope.component.getUtility(interfaces.IConfig)
if config.debug_challenges:
notify = zope.component.getUtility(interfaces.IDisplay).notification
@@ -78,7 +78,7 @@ class AuthHandler(object):
'Pass "-v" for more info about challenges.', pause=True)
except errors.AuthorizationError as error:
logger.critical('Failure in setting up challenges.')
- logger.info('Attempting to clean up outstanding challenges...')
+ logger.debug('Attempting to clean up outstanding challenges...')
raise error
# All challenges should have been processed by the authenticator.
assert len(resps) == len(achalls), 'Some challenges have not been performed.'
@@ -148,9 +148,9 @@ class AuthHandler(object):
# Gather failed authorizations
authzrs_failed = [authzr for authzr, _ in authzrs_to_check.values()
if authzr.body.status == messages.STATUS_INVALID]
- for authzr_failed in authzrs_failed:
- logger.warning('Challenge failed for domain %s',
- authzr_failed.body.identifier.value)
+ # for authzr_failed in authzrs_failed:
+ # logger.warning('Challenge failed for domain %s',
+ # authzr_failed.body.identifier.value)
# Accumulating all failed authzrs to build a consolidated report
# on them at the end of the polling.
authzrs_failed_to_report.extend(authzrs_failed)
@@ -193,7 +193,7 @@ class AuthHandler(object):
if authzr.body.status != messages.STATUS_VALID]
achalls = [] # type: List[achallenges.AnnotatedChallenge]
if pending_authzrs:
- logger.info("Performing the following challenges:")
+ logger.debug("Performing the following challenges:")
for authzr in pending_authzrs:
authzr_challenges = authzr.body.challenges
if self.acme.acme_version == 1:
@@ -239,7 +239,7 @@ class AuthHandler(object):
:type achalls: `list` of :class:`certbot.achallenges.AnnotatedChallenge`
"""
- logger.info("Cleaning up challenges")
+ logger.debug("Cleaning up challenges")
self.auth.cleanup(achalls)
def _challenge_factory(self, authzr, path):
@@ -278,7 +278,7 @@ def challb_to_achall(challb, account_key, domain):
"""
chall = challb.chall
- logger.info("%s challenge for %s", chall.typ, domain)
+ logger.debug("%s challenge for %s", chall.typ, domain)
if isinstance(chall, challenges.KeyAuthorizationChallenge):
return achallenges.KeyAuthorizationAnnotatedChallenge(
@@ -394,38 +394,6 @@ def _report_no_chall_path(challbs):
raise errors.AuthorizationError(msg)
-_ERROR_HELP_COMMON = (
- "To fix these errors, please make sure that your domain name was entered "
- "correctly and the DNS A/AAAA record(s) for that domain contain(s) the "
- "right IP address.")
-
-
-_ERROR_HELP = {
- "connection":
- _ERROR_HELP_COMMON + " Additionally, please check that your computer "
- "has a publicly routable IP address and that no firewalls are preventing "
- "the server from communicating with the client. If you're using the "
- "webroot plugin, you should also verify that you are serving files "
- "from the webroot path you provided.",
- "dnssec":
- _ERROR_HELP_COMMON + " Additionally, if you have DNSSEC enabled for "
- "your domain, please ensure that the signature is valid.",
- "malformed":
- "To fix these errors, please make sure that you did not provide any "
- "invalid information to the client, and try running Certbot "
- "again.",
- "serverInternal":
- "Unfortunately, an error on the ACME server prevented you from completing "
- "authorization. Please try again later.",
- "tls":
- _ERROR_HELP_COMMON + " Additionally, please check that you have an "
- "up-to-date TLS configuration that allows the server to communicate "
- "with the Certbot client.",
- "unauthorized": _ERROR_HELP_COMMON,
- "unknownHost": _ERROR_HELP_COMMON,
-}
-
-
def _report_failed_authzrs(failed_authzrs, account_key):
"""Notifies the user about failed authorizations."""
problems = {} # type: Dict[str, List[achallenges.AnnotatedChallenge]]
@@ -436,9 +404,18 @@ def _report_failed_authzrs(failed_authzrs, account_key):
for achall in failed_achalls:
problems.setdefault(achall.error.typ, []).append(achall)
- reporter = zope.component.getUtility(interfaces.IReporter)
+ config = zope.component.getUtility(interfaces.IConfig)
+ msg = ["\nCertbot encountered errors for these domains "
+ "while requesting the certificate (using the {} plugin):"
+ .format(config.authenticator)]
+
for achalls in problems.values():
- reporter.add_message(_generate_failed_chall_msg(achalls), reporter.MEDIUM_PRIORITY)
+ msg.append(_generate_failed_chall_msg(achalls))
+
+ msg.append("\nAsk for help with or search for solutions to this problem "
+ "at https://community.letsencrypt.org.\n")
+
+ logger.info("".join(msg))
def _generate_failed_chall_msg(failed_achalls):
@@ -456,14 +433,10 @@ def _generate_failed_chall_msg(failed_achalls):
typ = error.typ
if messages.is_acme_error(error):
typ = error.code
- msg = ["The following errors were reported by the server:"]
+ msg = []
for achall in failed_achalls:
- msg.append("\n\nDomain: %s\nType: %s\nDetail: %s" % (
+ msg.append("\n Domain: %s\n Type: %s\n Detail: %s\n" % (
achall.domain, typ, achall.error.detail))
- if typ in _ERROR_HELP:
- msg.append("\n\n")
- msg.append(_ERROR_HELP[typ])
-
return "".join(msg)
diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py
index ae57a6d91..47d0919d4 100644
--- a/certbot/certbot/_internal/client.py
+++ b/certbot/certbot/_internal/client.py
@@ -158,7 +158,7 @@ def register(config, account_storage, tos_cb=None):
logger.warning(msg)
raise errors.Error(msg)
if not config.dry_run:
- logger.info("Registering without email!")
+ logger.debug("Registering without email!")
# If --dry-run is used, and there is no staging account, create one with no email.
if config.dry_run:
@@ -175,7 +175,6 @@ def register(config, account_storage, tos_cb=None):
regr = perform_registration(acme, config, tos_cb)
acc = account.Account(regr, key)
- account.report_new_account(config)
account_storage.save(acc, acme)
eff.prepare_subscription(config, acc)
@@ -510,6 +509,7 @@ class Client(object):
chain_path = None if chain_path is None else os.path.abspath(chain_path)
+ logger.info("Deploying certificate.")
msg = ("Unable to install the certificate")
with error_handler.ErrorHandler(self._recovery_routine_with_msg, msg):
for dom in domains:
@@ -521,6 +521,7 @@ class Client(object):
self.installer.save() # needed by the Apache plugin
self.installer.save("Deployed ACME Certificate")
+ logger.info("Successfully deployed certificate.")
msg = ("We were unable to install your certificate, "
"however, we successfully restored your "
diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py
index 25e808571..23acc7066 100644
--- a/certbot/certbot/_internal/main.py
+++ b/certbot/certbot/_internal/main.py
@@ -61,11 +61,11 @@ def _suggest_donation_if_appropriate(config):
if config.staging:
# --dry-run implies --staging
return
- reporter_util = zope.component.getUtility(interfaces.IReporter)
- msg = ("If you like Certbot, please consider supporting our work by:\n\n"
- "Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate\n"
- "Donating to EFF: https://eff.org/donate-le\n\n")
- reporter_util.add_message(msg, reporter_util.LOW_PRIORITY)
+ zope.component.getUtility(interfaces.IDisplay).notification(
+ "If you like Certbot, please consider supporting our work by:\n"
+ " * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate\n"
+ " * Donating to EFF: https://eff.org/donate-le",
+ pause=False)
def _report_successful_dry_run(config):
"""Reports on successful dry run
@@ -113,12 +113,15 @@ def _get_and_save_cert(le_client, config, domains=None, certname=None, lineage=N
if lineage is not None:
# Renewal, where we already know the specific lineage we're
# interested in
- logger.info("Renewing an existing certificate")
+ logger.info("Renewing an existing certificate for {0}."
+ .format(display_util.summarize_domain_list(domains or
+ lineage.names())))
renewal.renew_cert(config, domains, le_client, lineage)
else:
# TREAT AS NEW REQUEST
assert domains is not None
- logger.info("Obtaining a new certificate")
+ logger.info("Requesting a certificate for {0}.".
+ format(display_util.summarize_domain_list(domains)))
lineage = le_client.obtain_and_enroll_certificate(domains, certname)
if lineage is False:
raise errors.Error("Certificate could not be obtained")
@@ -450,23 +453,18 @@ def _report_new_cert(config, cert_path, fullchain_path, key_path=None):
assert cert_path and fullchain_path, "No certificates saved to report."
expiry = crypto_util.notAfter(cert_path).date()
- reporter_util = zope.component.getUtility(interfaces.IReporter)
- # Print the path to fullchain.pem because that's what modern webservers
- # (Nginx and Apache2.4) will want.
-
- verbswitch = ' with the "certonly" option' if config.verb == "run" else ""
- privkey_statement = 'Your key file has been saved at:{br}{0}{br}'.format(
- key_path, br=os.linesep) if key_path else ""
- # XXX Perhaps one day we could detect the presence of known old webservers
- # and say something more informative here.
- msg = ('Congratulations! Your certificate and chain have been saved at:{br}'
- '{0}{br}{1}'
- 'Your cert will expire on {2}. To obtain a new or tweaked version of this '
- 'certificate in the future, simply run {3} again{4}. '
- 'To non-interactively renew *all* of your certificates, run "{3} renew"'
- .format(fullchain_path, privkey_statement, expiry, cli.cli_command, verbswitch,
- br=os.linesep))
- reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
+
+ logger.info(
+ ("Successfully received certificate.\n"
+ "Certificate is saved at: {cert_path}\n{key_msg}{symlink_msg}\n"
+ "This certificate expires on {expiry}.\n").format(
+ cert_path=fullchain_path,
+ expiry=expiry,
+ key_msg="Key is saved at: {}\n".format(key_path) if key_path else "",
+ symlink_msg="These files will be automatically updated "
+ "every time the certificate is renewed." if key_path else "",
+ )
+ )
def _determine_account(config):
@@ -490,8 +488,7 @@ def _determine_account(config):
return True
msg = ("Please read the Terms of Service at {0}. You "
"must agree in order to register with the ACME "
- "server at {1}".format(
- terms_of_service, config.server))
+ "server.".format(terms_of_service))
obj = zope.component.getUtility(interfaces.IDisplay)
result = obj.yesno(msg, "Agree", "Cancel",
cli_flag="--agree-tos", force_interactive=True)
@@ -1110,7 +1107,8 @@ def run(config, plugins):
cert_path = new_lineage.cert_path if new_lineage else None
fullchain_path = new_lineage.fullchain_path if new_lineage else None
key_path = new_lineage.key_path if new_lineage else None
- _report_new_cert(config, cert_path, fullchain_path, key_path)
+ if should_get_cert:
+ _report_new_cert(config, cert_path, fullchain_path, key_path)
_install_cert(config, le_client, domains, new_lineage)
@@ -1119,8 +1117,8 @@ def run(config, plugins):
if lineage is None or not should_get_cert:
display_ops.success_installation(domains)
- else:
- display_ops.success_renewal(domains)
+ # else:
+ # display_ops.success_renewal(domains)
_suggest_donation_if_appropriate(config)
eff.handle_subscription(config, le_client.account)
diff --git a/certbot/certbot/_internal/plugins/selection.py b/certbot/certbot/_internal/plugins/selection.py
index 0b04791c6..a05fb680f 100644
--- a/certbot/certbot/_internal/plugins/selection.py
+++ b/certbot/certbot/_internal/plugins/selection.py
@@ -171,7 +171,7 @@ def record_chosen_plugins(config, plugins, auth, inst):
"Update the config entries to reflect the plugins we actually selected."
config.authenticator = plugins.find_init(auth).name if auth else None
config.installer = plugins.find_init(inst).name if inst else None
- logger.info("Plugins selected: Authenticator %s, Installer %s",
+ logger.debug("Plugins selected: Authenticator %s, Installer %s",
config.authenticator, config.installer)
diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py
index c8402b018..c96ba6e1d 100644
--- a/certbot/certbot/_internal/renewal.py
+++ b/certbot/certbot/_internal/renewal.py
@@ -419,7 +419,6 @@ def handle_renewal_request(config):
for renewal_file in conf_files:
disp = zope.component.getUtility(interfaces.IDisplay)
- disp.notification("Processing " + renewal_file, pause=False)
lineage_config = copy.deepcopy(config)
lineagename = storage.lineagename_for_filename(renewal_file)
diff --git a/certbot/certbot/display/util.py b/certbot/certbot/display/util.py
index 05330b1a9..0ca72cf54 100644
--- a/certbot/certbot/display/util.py
+++ b/certbot/certbot/display/util.py
@@ -112,7 +112,7 @@ class FileDisplay(object):
if wrap:
message = _wrap_lines(message)
self.outfile.write(
- "{line}{frame}{line}{msg}{line}{frame}{line}".format(
+ "{frame}{line}{msg}{line}{frame}{line}".format(
line='\n', frame=SIDE_FRAME, msg=message))
self.outfile.flush()
if pause:
@@ -593,3 +593,28 @@ def _parens_around_char(label):
"""
return "({first}){rest}".format(first=label[0], rest=label[1:])
+
+
+def summarize_domain_list(domains):
+ # type: (List[str]) -> str
+ """Summarizes a list of domains in the format of:
+ example.com.com and N more domains
+ or if there is are only two domains:
+ example.com and www.example.com
+ or if there is only one domain:
+ example.com
+
+ :param list domains: `str` list of domains
+ :returns: the domain list summary
+ :rtype: str
+ """
+ if not domains:
+ return ""
+
+ l = len(domains)
+ if l == 1:
+ return domains[0]
+ elif l == 2:
+ return " and ".join(domains)
+ else:
+ return "{0} and {1} more domains".format(domains[0], l-1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment