mirror of
https://github.com/certbot/certbot.git
synced 2026-01-26 07:41:33 +03:00
Exposes environment variable to let hooks scripts know when the last challenge is handled (#7837)
Fixes #5484 This PRs makes Certbot expose two new environment variables in the auth and cleanup hooks of the `manual` plugin: * `CERTBOT_REMAINING_CHALLENGES` contains the number of challenges that remain after the current one (so it equals to 0 when the script is called for the last challenge) * `CERTBOT_ALL_DOMAINS` contains a comma-separated list of all domains concerned by a challenge for the current certificate With these variables, an hook script can know when it is run for the last time, and then trigger appropriate finalizers for all challenges that have been executed. This will be particularly useful for certificates with a lot of domains validated with DNS-01 challenges: instead of waiting on each hook execution to check that the relevant DNS TXT entry has been inserted, these waits can be avoided thanks to the latest hook verifying all domains in one run. * Inject environment variables in manual scripts about remaining challenges * Adapt tests * Less variables and less lines * Update manual.py * Update manual_test.py * Add documentation * Add changelog
This commit is contained in:
@@ -6,7 +6,10 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Added
|
||||
|
||||
*
|
||||
* Expose two new environment variables in the authenticator and cleanup scripts used by
|
||||
the `manual` plugin: `CERTBOT_REMAINING_CHALLENGES` is equal to the number of challenges
|
||||
remaining after the current challenge, `CERTBOT_ALL_DOMAINS` is a comma-separated list
|
||||
of all domains challenged for the current certificate.
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -35,7 +35,11 @@ class Authenticator(common.Plugin):
|
||||
'is the validation string, and $CERTBOT_TOKEN is the filename of the '
|
||||
'resource requested when performing an HTTP-01 challenge. An additional '
|
||||
'cleanup script can also be provided and can use the additional variable '
|
||||
'$CERTBOT_AUTH_OUTPUT which contains the stdout output from the auth script.')
|
||||
'$CERTBOT_AUTH_OUTPUT which contains the stdout output from the auth script.'
|
||||
'For both authenticator and cleanup script, on HTTP-01 and DNS-01 challenges,'
|
||||
'$CERTBOT_REMAINING_CHALLENGES will be equal to the number of challenges that '
|
||||
'remain after the current one, and $CERTBOT_ALL_DOMAINS contains a comma-separated '
|
||||
'list of all domains that are challenged for the current certificate.')
|
||||
_DNS_INSTRUCTIONS = """\
|
||||
Please deploy a DNS TXT record under the name
|
||||
{domain} with the following value:
|
||||
@@ -109,14 +113,13 @@ permitted by DNS standards.)
|
||||
|
||||
def perform(self, achalls): # pylint: disable=missing-function-docstring
|
||||
self._verify_ip_logging_ok()
|
||||
if self.conf('auth-hook'):
|
||||
perform_achall = self._perform_achall_with_script
|
||||
else:
|
||||
perform_achall = self._perform_achall_manually
|
||||
|
||||
responses = []
|
||||
for achall in achalls:
|
||||
perform_achall(achall)
|
||||
if self.conf('auth-hook'):
|
||||
self._perform_achall_with_script(achall, achalls)
|
||||
else:
|
||||
self._perform_achall_manually(achall)
|
||||
responses.append(achall.response(achall.account_key))
|
||||
return responses
|
||||
|
||||
@@ -134,9 +137,11 @@ permitted by DNS standards.)
|
||||
else:
|
||||
raise errors.PluginError('Must agree to IP logging to proceed')
|
||||
|
||||
def _perform_achall_with_script(self, achall):
|
||||
def _perform_achall_with_script(self, achall, achalls):
|
||||
env = dict(CERTBOT_DOMAIN=achall.domain,
|
||||
CERTBOT_VALIDATION=achall.validation(achall.account_key))
|
||||
CERTBOT_VALIDATION=achall.validation(achall.account_key),
|
||||
CERTBOT_ALL_DOMAINS=','.join(one_achall.domain for one_achall in achalls),
|
||||
CERTBOT_REMAINING_CHALLENGES=str(len(achalls) - achalls.index(achall) - 1))
|
||||
if isinstance(achall.chall, challenges.HTTP01):
|
||||
env['CERTBOT_TOKEN'] = achall.chall.encode('token')
|
||||
else:
|
||||
|
||||
@@ -738,8 +738,10 @@ the ``cleanup.sh`` script. Additionally certbot will pass relevant environment
|
||||
variables to these scripts:
|
||||
|
||||
- ``CERTBOT_DOMAIN``: The domain being authenticated
|
||||
- ``CERTBOT_VALIDATION``: The validation string (HTTP-01 and DNS-01 only)
|
||||
- ``CERTBOT_VALIDATION``: The validation string
|
||||
- ``CERTBOT_TOKEN``: Resource name part of the HTTP-01 challenge (HTTP-01 only)
|
||||
- ``CERTBOT_REMAINING_CHALLENGES``: Number of challenges remaining after the current challenge
|
||||
- ``CERTBOT_ALL_DOMAINS``: A comma-separated list of all domains challenged for the current certificate
|
||||
|
||||
Additionally for cleanup:
|
||||
|
||||
|
||||
@@ -72,16 +72,23 @@ class AuthenticatorTest(test_util.TempDirTestCase):
|
||||
self.config.manual_public_ip_logging_ok = True
|
||||
self.config.manual_auth_hook = (
|
||||
'{0} -c "from __future__ import print_function;'
|
||||
'from certbot.compat import os; print(os.environ.get(\'CERTBOT_DOMAIN\'));'
|
||||
'from certbot.compat import os;'
|
||||
'print(os.environ.get(\'CERTBOT_DOMAIN\'));'
|
||||
'print(os.environ.get(\'CERTBOT_TOKEN\', \'notoken\'));'
|
||||
'print(os.environ.get(\'CERTBOT_VALIDATION\', \'novalidation\'));"'
|
||||
'print(os.environ.get(\'CERTBOT_VALIDATION\', \'novalidation\'));'
|
||||
'print(os.environ.get(\'CERTBOT_ALL_DOMAINS\'));'
|
||||
'print(os.environ.get(\'CERTBOT_REMAINING_CHALLENGES\'));"'
|
||||
.format(sys.executable))
|
||||
dns_expected = '{0}\n{1}\n{2}'.format(
|
||||
dns_expected = '{0}\n{1}\n{2}\n{3}\n{4}'.format(
|
||||
self.dns_achall.domain, 'notoken',
|
||||
self.dns_achall.validation(self.dns_achall.account_key))
|
||||
http_expected = '{0}\n{1}\n{2}'.format(
|
||||
self.dns_achall.validation(self.dns_achall.account_key),
|
||||
','.join(achall.domain for achall in self.achalls),
|
||||
len(self.achalls) - self.achalls.index(self.dns_achall) - 1)
|
||||
http_expected = '{0}\n{1}\n{2}\n{3}\n{4}'.format(
|
||||
self.http_achall.domain, self.http_achall.chall.encode('token'),
|
||||
self.http_achall.validation(self.http_achall.account_key))
|
||||
self.http_achall.validation(self.http_achall.account_key),
|
||||
','.join(achall.domain for achall in self.achalls),
|
||||
len(self.achalls) - self.achalls.index(self.http_achall) - 1)
|
||||
|
||||
self.assertEqual(
|
||||
self.auth.perform(self.achalls),
|
||||
|
||||
Reference in New Issue
Block a user