From 0d10a44f4bd7a6cbd9dbc59d905876e9b0a6ca1b Mon Sep 17 00:00:00 2001 From: moratori Date: Tue, 30 Nov 2021 06:17:06 +0900 Subject: [PATCH] Added --issuance-timeout command line option (#9056) * Added --issuance-timeout command line option * clarification of command line option name,docstring and add tests * fix test case for python36 * improved the command line options --- AUTHORS.md | 1 + certbot/CHANGELOG.md | 2 ++ certbot/certbot/_internal/cli/__init__.py | 5 +++++ certbot/certbot/_internal/client.py | 7 ++++++- certbot/certbot/_internal/constants.py | 1 + certbot/certbot/configuration.py | 7 +++++++ certbot/tests/client_test.py | 20 ++++++++++++++++++++ 7 files changed, 42 insertions(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index cb60bfd87..d82ddcb76 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -138,6 +138,7 @@ Authors * [Joubin Jabbari](https://github.com/joubin) * [Juho Juopperi](https://github.com/jkjuopperi) * [Kane York](https://github.com/riking) +* [Katsuyoshi Ozaki](https://github.com/moratori) * [Kenichi Maehashi](https://github.com/kmaehashi) * [Kenneth Skovhede](https://github.com/kenkendk) * [Kevin Burke](https://github.com/kevinburke) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 0a5849d82..3f6658810 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -10,6 +10,8 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). * The function certbot.util.parse_loose_version was added to parse version strings in the same way as the now deprecated distutils.version.LooseVersion class from the Python standard library. +* Added `--issuance-timeout`. This option specifies how long (in seconds) Certbot will wait + for the server to issue a certificate. ### Changed diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index 63b0dd097..a69f96666 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -364,6 +364,11 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st 'ACME Challenges are versioned, but if you pick "http" rather ' 'than "http-01", Certbot will select the latest version ' 'automatically.') + helpful.add( + [None, "certonly", "run"], "--issuance-timeout", type=nonnegative_int, + dest="issuance_timeout", + default=flag_default("issuance_timeout"), + help=config_help("issuance_timeout")) helpful.add( "renew", "--pre-hook", help="Command to be run in a shell before obtaining any certificates." diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py index 4c472df55..fad48b3d3 100644 --- a/certbot/certbot/_internal/client.py +++ b/certbot/certbot/_internal/client.py @@ -330,9 +330,14 @@ class Client: if orderr is None: orderr = self._get_order_and_authorizations(csr.data, best_effort=False) - deadline = datetime.datetime.now() + datetime.timedelta(seconds=90) + deadline = datetime.datetime.now() + datetime.timedelta( + seconds=self.config.issuance_timeout) + + logger.debug("Will poll for certificate issuance until %s", deadline) + orderr = self.acme.finalize_order( orderr, deadline, fetch_alternative_chains=self.config.preferred_chain is not None) + fullchain = orderr.fullchain_pem if self.config.preferred_chain and orderr.alternative_fullchains_pem: fullchain = crypto_util.find_chain_with_issuer( diff --git a/certbot/certbot/_internal/constants.py b/certbot/certbot/_internal/constants.py index c2b4e6556..18160d47e 100644 --- a/certbot/certbot/_internal/constants.py +++ b/certbot/certbot/_internal/constants.py @@ -78,6 +78,7 @@ CLI_DEFAULTS: Dict[str, Any] = dict( random_sleep_on_renew=True, eab_hmac_key=None, eab_kid=None, + issuance_timeout=90, # Subparsers num=None, diff --git a/certbot/certbot/configuration.py b/certbot/certbot/configuration.py index 4648cbda1..1a72cbce7 100644 --- a/certbot/certbot/configuration.py +++ b/certbot/certbot/configuration.py @@ -293,6 +293,13 @@ class NamespaceConfig: return os.path.join(self.renewal_hooks_dir, constants.RENEWAL_POST_HOOKS_DIR) + @property + def issuance_timeout(self) -> int: + """This option specifies how long (in seconds) Certbot will wait + for the server to issue a certificate. + """ + return self.namespace.issuance_timeout + # Magic methods def __deepcopy__(self, _memo: Any) -> 'NamespaceConfig': diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 330fd2852..8d8073f6f 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -1,4 +1,5 @@ """Tests for certbot._internal.client.""" +import datetime import contextlib import platform import shutil @@ -12,6 +13,7 @@ from certbot import errors from certbot import util from certbot._internal.display import obj as display_obj from certbot._internal import account +from certbot._internal import constants from certbot.compat import os import certbot.tests.util as test_util @@ -320,6 +322,24 @@ class ClientTest(ClientTestCommon): "some issuer", True) self.config.preferred_chain = None + # Test for default issuance_timeout + expected_deadline = \ + datetime.datetime.now() + datetime.timedelta( + seconds=constants.CLI_DEFAULTS["issuance_timeout"]) + self.client.obtain_certificate_from_csr(test_csr, orderr=orderr) + ((_, deadline), _) = self.client.acme.finalize_order.call_args + self.assertTrue( + abs(expected_deadline - deadline) <= datetime.timedelta(seconds=1)) + + # Test for specific issuance_timeout (300 seconds) + expected_deadline = \ + datetime.datetime.now() + datetime.timedelta(seconds=300) + self.config.issuance_timeout = 300 + self.client.obtain_certificate_from_csr(test_csr, orderr=orderr) + ((_, deadline), _) = self.client.acme.finalize_order.call_args + self.assertTrue( + abs(expected_deadline - deadline) <= datetime.timedelta(seconds=1)) + # Test for orderr=None self.assertEqual( (mock.sentinel.cert, mock.sentinel.chain),