certbot/certbot-compatibility-test/certbot_compatibility_test/test_driver.py

408 lines
14 KiB
Python
Raw Normal View History

"""Tests Certbot plugins against different server configurations."""
2015-07-14 21:04:43 -04:00
import argparse
import contextlib
2015-07-21 21:14:57 -04:00
import filecmp
2015-07-14 21:04:43 -04:00
import logging
2015-07-21 21:14:57 -04:00
import os
import shutil
import socket
import sys
2015-07-21 21:14:57 -04:00
import tempfile
2015-08-03 21:32:32 -04:00
import time
from typing import Any
from typing import Dict
from typing import Generator
from typing import Iterable
from typing import List
from typing import Optional
from typing import Tuple
from typing import Type
2015-07-14 21:04:43 -04:00
from certbot_compatibility_test import errors
from certbot_compatibility_test import util
from certbot_compatibility_test import validator
from certbot_compatibility_test.configurators import common
from certbot_compatibility_test.configurators.apache import common as a_common
from certbot_compatibility_test.configurators.nginx import common as n_common
from OpenSSL import crypto
from urllib3.util import connection
2015-07-21 21:14:57 -04:00
from acme import challenges
from acme import crypto_util
from acme import messages
from certbot import achallenges
from certbot import errors as le_errors
Deprecate zope.component in favor of an direct calls to functions from `certbot.display.util` module (#8835) * Implement certbot services * Various fixes * Local oldest requirements * Clean imports * Add unit tests for certbot.services * Clean code * Protect against nullity of global services * Fix CLI * Fix tests * Consistent test behavior * Various fixes * Clean code * Remove reporter service, migrate display service in certbot.display.util. * Fix test * Fix apache compatibility test * Fix oldest test * Setup certbot.display.service module * Reintegrate in util * Fix imports * Fix tests and documentation * Refactor * Cleanup * Cleanup * Clean imports * Add unit tests * Borrow sphinx build fix from #8863 * Fix type * Add comment * Do not reuse existing display service, which never exist at that time * Make get_display() private * Fix lint * Make display internal * Fix circular dependencies * Fixing circular dependencies * Rename patch methods and update docstring * Update deprecation messages * Update certbot/certbot/_internal/display/obj.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Add links * Avoid relying on internal certbot packages from certbot-apache * Keep same behavior for patch_get_utility* * Better diff * Add changelog * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
2021-07-19 20:09:06 -04:00
from certbot._internal.display import obj as display_obj
from certbot.display import util as display_util
from certbot.tests import acme_util
2015-07-14 21:04:43 -04:00
DESCRIPTION = """
Tests Certbot plugins against different server configurations. It is
assumed that Docker is already installed. If no test type is specified, all
2015-07-16 19:57:47 -04:00
tests that the plugin supports are performed.
2015-07-14 21:04:43 -04:00
"""
PLUGINS: Dict[str, Type[common.Proxy]] = {"apache": a_common.Proxy, "nginx": n_common.Proxy}
2015-07-14 21:04:43 -04:00
logger = logging.getLogger(__name__)
def test_authenticator(plugin: common.Proxy, config: str, temp_dir: str) -> bool:
2015-07-23 20:09:09 -04:00
"""Tests authenticator, returning True if the tests are successful"""
2015-07-22 21:25:09 -04:00
backup = _create_backup(config, temp_dir)
2015-07-21 21:14:57 -04:00
achalls = _create_achalls(plugin)
2015-07-22 21:25:09 -04:00
if not achalls:
2015-08-03 14:38:22 -04:00
logger.error("The plugin and this program support no common "
"challenge types")
return False
2015-07-22 21:25:09 -04:00
try:
responses = plugin.perform(achalls)
except le_errors.Error:
logger.error("Performing challenges on %s caused an error:", config, exc_info=True)
2015-07-23 20:09:09 -04:00
return False
2015-07-21 21:14:57 -04:00
2015-07-23 20:09:09 -04:00
success = True
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
for i, response in enumerate(responses):
achall = achalls[i]
if not response:
2015-07-23 20:09:09 -04:00
logger.error(
"Plugin failed to complete %s for %s in %s",
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
type(achall), achall.domain, config)
2015-07-23 20:09:09 -04:00
success = False
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
elif isinstance(response, challenges.HTTP01Response):
# We fake the DNS resolution to ensure that any domain is resolved
# to the local HTTP server setup for the compatibility tests
with _fake_dns_resolution("127.0.0.1"):
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
verified = response.simple_verify(
achall.chall, achall.domain,
util.JWK.public_key(), port=plugin.http_port)
if verified:
2015-07-23 20:09:09 -04:00
logger.info(
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
"http-01 verification for %s succeeded", achall.domain)
2015-07-23 20:09:09 -04:00
else:
logger.error(
"**** http-01 verification for %s in %s failed",
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
achall.domain, config)
2015-07-23 20:09:09 -04:00
success = False
if success:
try:
plugin.cleanup(achalls)
except le_errors.Error:
logger.error("Challenge cleanup for %s caused an error:", config, exc_info=True)
2015-07-23 20:09:09 -04:00
success = False
if _dirs_are_unequal(config, backup):
logger.error("Challenge cleanup failed for %s", config)
return False
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
logger.info("Challenge cleanup succeeded")
2015-07-23 20:09:09 -04:00
return success
2015-07-21 21:14:57 -04:00
def _create_achalls(plugin: common.Proxy) -> List[achallenges.AnnotatedChallenge]:
2015-07-21 21:14:57 -04:00
"""Returns a list of annotated challenges to test on plugin"""
achalls: List[achallenges.AnnotatedChallenge] = []
2015-07-21 21:14:57 -04:00
names = plugin.get_testable_domain_names()
for domain in names:
prefs = plugin.get_chall_pref(domain)
for chall_type in prefs:
if chall_type == challenges.HTTP01:
Move compatibility tests off of certbot-auto and Python 2 (#8248) Fixes https://github.com/certbot/certbot/issues/8162. I had to update the base of the Dockerfile to get a new enough version of Python 3. I also simplified things a lot and removed a lot of the comments that were essentially just describing how Dockerfiles work. The most complicated changes here are in `testdata`. You can find a diff of the changes to `nginx.tar.gz` at https://gist.github.com/c7727db0cecf3f15f02439f085c73848. The first problem was that there were some complaints from the new Apache/nginx/OpenSSL version about the 1024 bit RSA key so I updated `empty_cert.pem` both inside and outside of the tarball as well as the corresponding private key in the tarball to use a 2048 bit key. The 2nd problem is trickier to understand. If you look at the output from nginx after loading the config from `lots/` you'll see it complaining about conflicting `server_name` directives for the directives I deleted. See https://dev.azure.com/certbot/certbot/_build/results?buildId=2578&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e&t=9baa2014-9673-5e78-8f4f-7a463caf2bfa&l=1516. After switching the tests to Python 3, tests on that domain started failing. What I believe to be happening is we were just lucky these tests were passing to begin with. In both the Apache and Nginx plugin, if there are conflicting virtual hosts like this, we just arbitrarily pick one. The relevant code here for nginx is https://github.com/certbot/certbot/blob/575092d6030330ed8379babaa4cbbfe43e7bf721/certbot-nginx/certbot_nginx/_internal/configurator.py#L455 I played around with a debugger and confirmed that before I removed the conflicting server names, there were two exact matches for the domain we were searching for here. I think all that's going on is with the switch to Python 3, the vhost we happen to choose changes and "breaks" the test. I suspect this to be due to something like getting values out of a dict somewhere where the order of items in a dict while iterating over it is different between Python 2 and 3. I didn't track where this difference happens down, but I personally don't think it's a good use of time since I think the real problem here is that the nginx config being tested was invalid with conflicting `server` blocks. I removed all references to the `server_name` causing conflicts in that nginx configuration because both server blocks had other domains that are being tested, but I could add either back if you prefer. You can see the `nginx_compat` test passing with these changes at https://dev.azure.com/certbot/certbot/_build/results?buildId=2587&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e. * update Dockerfile * Fix apache_compat on py3. * Update empty_cert.pem. The command used here was `openssl req -key certbot/certbot/tests/testdata/rsa2048_key.pem -new -subj '/CN=example.com' -x509 > certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem`. * update nginx.tar.gz * Remove conflicting server_names
2020-09-09 18:16:52 -04:00
# challenges.HTTP01.TOKEN_SIZE is a float but os.urandom
# expects an integer.
chall = challenges.HTTP01(
Move compatibility tests off of certbot-auto and Python 2 (#8248) Fixes https://github.com/certbot/certbot/issues/8162. I had to update the base of the Dockerfile to get a new enough version of Python 3. I also simplified things a lot and removed a lot of the comments that were essentially just describing how Dockerfiles work. The most complicated changes here are in `testdata`. You can find a diff of the changes to `nginx.tar.gz` at https://gist.github.com/c7727db0cecf3f15f02439f085c73848. The first problem was that there were some complaints from the new Apache/nginx/OpenSSL version about the 1024 bit RSA key so I updated `empty_cert.pem` both inside and outside of the tarball as well as the corresponding private key in the tarball to use a 2048 bit key. The 2nd problem is trickier to understand. If you look at the output from nginx after loading the config from `lots/` you'll see it complaining about conflicting `server_name` directives for the directives I deleted. See https://dev.azure.com/certbot/certbot/_build/results?buildId=2578&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e&t=9baa2014-9673-5e78-8f4f-7a463caf2bfa&l=1516. After switching the tests to Python 3, tests on that domain started failing. What I believe to be happening is we were just lucky these tests were passing to begin with. In both the Apache and Nginx plugin, if there are conflicting virtual hosts like this, we just arbitrarily pick one. The relevant code here for nginx is https://github.com/certbot/certbot/blob/575092d6030330ed8379babaa4cbbfe43e7bf721/certbot-nginx/certbot_nginx/_internal/configurator.py#L455 I played around with a debugger and confirmed that before I removed the conflicting server names, there were two exact matches for the domain we were searching for here. I think all that's going on is with the switch to Python 3, the vhost we happen to choose changes and "breaks" the test. I suspect this to be due to something like getting values out of a dict somewhere where the order of items in a dict while iterating over it is different between Python 2 and 3. I didn't track where this difference happens down, but I personally don't think it's a good use of time since I think the real problem here is that the nginx config being tested was invalid with conflicting `server` blocks. I removed all references to the `server_name` causing conflicts in that nginx configuration because both server blocks had other domains that are being tested, but I could add either back if you prefer. You can see the `nginx_compat` test passing with these changes at https://dev.azure.com/certbot/certbot/_build/results?buildId=2587&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e. * update Dockerfile * Fix apache_compat on py3. * Update empty_cert.pem. The command used here was `openssl req -key certbot/certbot/tests/testdata/rsa2048_key.pem -new -subj '/CN=example.com' -x509 > certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem`. * update nginx.tar.gz * Remove conflicting server_names
2020-09-09 18:16:52 -04:00
token=os.urandom(int(challenges.HTTP01.TOKEN_SIZE)))
2015-07-21 21:14:57 -04:00
challb = acme_util.chall_to_challb(
chall, messages.STATUS_PENDING)
2015-11-07 13:10:56 -05:00
achall = achallenges.KeyAuthorizationAnnotatedChallenge(
challb=challb, domain=domain, account_key=util.JWK)
2015-07-21 21:14:57 -04:00
achalls.append(achall)
return achalls
def test_installer(args: argparse.Namespace, plugin: common.Proxy, config: str,
temp_dir: str) -> bool:
2015-07-21 21:14:57 -04:00
"""Tests plugin as an installer"""
2015-07-22 21:25:09 -04:00
backup = _create_backup(config, temp_dir)
2015-07-21 21:14:57 -04:00
2015-07-23 20:09:09 -04:00
names_match = plugin.get_all_names() == plugin.get_all_names_answer()
if names_match:
2015-07-22 21:25:09 -04:00
logger.info("get_all_names test succeeded")
2015-07-21 21:14:57 -04:00
else:
logger.error("**** get_all_names test failed for config %s", config)
2015-07-21 21:14:57 -04:00
domains = list(plugin.get_testable_domain_names())
2015-07-23 20:09:09 -04:00
success = test_deploy_cert(plugin, temp_dir, domains)
if success and args.enhance:
success = test_enhancements(plugin, domains)
2015-07-22 21:25:09 -04:00
2015-07-23 20:09:09 -04:00
good_rollback = test_rollback(plugin, config, backup)
return names_match and success and good_rollback
2015-07-22 21:25:09 -04:00
def test_deploy_cert(plugin: common.Proxy, temp_dir: str, domains: List[str]) -> bool:
2015-07-22 21:25:09 -04:00
"""Tests deploy_cert returning True if the tests are successful"""
2015-07-21 21:14:57 -04:00
cert = crypto_util.gen_ss_cert(util.KEY, domains)
cert_path = os.path.join(temp_dir, "cert.pem")
Move compatibility tests off of certbot-auto and Python 2 (#8248) Fixes https://github.com/certbot/certbot/issues/8162. I had to update the base of the Dockerfile to get a new enough version of Python 3. I also simplified things a lot and removed a lot of the comments that were essentially just describing how Dockerfiles work. The most complicated changes here are in `testdata`. You can find a diff of the changes to `nginx.tar.gz` at https://gist.github.com/c7727db0cecf3f15f02439f085c73848. The first problem was that there were some complaints from the new Apache/nginx/OpenSSL version about the 1024 bit RSA key so I updated `empty_cert.pem` both inside and outside of the tarball as well as the corresponding private key in the tarball to use a 2048 bit key. The 2nd problem is trickier to understand. If you look at the output from nginx after loading the config from `lots/` you'll see it complaining about conflicting `server_name` directives for the directives I deleted. See https://dev.azure.com/certbot/certbot/_build/results?buildId=2578&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e&t=9baa2014-9673-5e78-8f4f-7a463caf2bfa&l=1516. After switching the tests to Python 3, tests on that domain started failing. What I believe to be happening is we were just lucky these tests were passing to begin with. In both the Apache and Nginx plugin, if there are conflicting virtual hosts like this, we just arbitrarily pick one. The relevant code here for nginx is https://github.com/certbot/certbot/blob/575092d6030330ed8379babaa4cbbfe43e7bf721/certbot-nginx/certbot_nginx/_internal/configurator.py#L455 I played around with a debugger and confirmed that before I removed the conflicting server names, there were two exact matches for the domain we were searching for here. I think all that's going on is with the switch to Python 3, the vhost we happen to choose changes and "breaks" the test. I suspect this to be due to something like getting values out of a dict somewhere where the order of items in a dict while iterating over it is different between Python 2 and 3. I didn't track where this difference happens down, but I personally don't think it's a good use of time since I think the real problem here is that the nginx config being tested was invalid with conflicting `server` blocks. I removed all references to the `server_name` causing conflicts in that nginx configuration because both server blocks had other domains that are being tested, but I could add either back if you prefer. You can see the `nginx_compat` test passing with these changes at https://dev.azure.com/certbot/certbot/_build/results?buildId=2587&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e. * update Dockerfile * Fix apache_compat on py3. * Update empty_cert.pem. The command used here was `openssl req -key certbot/certbot/tests/testdata/rsa2048_key.pem -new -subj '/CN=example.com' -x509 > certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem`. * update nginx.tar.gz * Remove conflicting server_names
2020-09-09 18:16:52 -04:00
with open(cert_path, "wb") as f:
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
2015-07-21 21:14:57 -04:00
for domain in domains:
2015-07-23 20:09:09 -04:00
try:
plugin.deploy_cert(domain, cert_path, util.KEY_PATH, cert_path, cert_path)
2016-06-06 17:17:11 -04:00
plugin.save() # Needed by the Apache plugin
except le_errors.Error:
logger.error("**** Plugin failed to deploy certificate for %s:", domain, exc_info=True)
2015-07-23 20:09:09 -04:00
return False
if not _save_and_restart(plugin, "deployed"):
return False
2015-07-22 21:25:09 -04:00
success = True
time.sleep(3)
2015-07-22 21:25:09 -04:00
for domain in domains:
verified = validator.Validator().certificate(
cert, domain, "127.0.0.1", plugin.https_port)
if not verified:
logger.error("**** Could not verify certificate for domain %s", domain)
2015-07-22 21:25:09 -04:00
success = False
if success:
logger.info("HTTPS validation succeeded")
return success
def test_enhancements(plugin: common.Proxy, domains: Iterable[str]) -> bool:
2015-07-23 20:09:09 -04:00
"""Tests supported enhancements returning True if successful"""
2015-07-22 21:25:09 -04:00
supported = plugin.supported_enhancements()
if "redirect" not in supported:
logger.error("The plugin and this program support no common "
"enhancements")
return False
2015-07-22 21:25:09 -04:00
domains_and_info: List[Tuple[str, List[bool]]] = [(domain, []) for domain in domains]
for domain, info in domains_and_info:
2015-07-23 20:09:09 -04:00
try:
previous_redirect = validator.Validator().any_redirect(
"localhost", plugin.http_port, headers={"Host": domain})
info.append(previous_redirect)
2015-07-23 20:09:09 -04:00
plugin.enhance(domain, "redirect")
2016-06-06 17:17:11 -04:00
plugin.save() # Needed by the Apache plugin
2015-08-04 15:18:10 -04:00
except le_errors.PluginError as error:
2015-08-03 21:32:32 -04:00
# Don't immediately fail because a redirect may already be enabled
logger.warning("*** Plugin failed to enable redirect for %s:", domain)
2015-08-03 21:32:32 -04:00
logger.warning("%s", error)
except le_errors.Error:
logger.error("*** An error occurred while enabling redirect for %s:",
domain, exc_info=True)
2015-07-22 21:25:09 -04:00
2015-07-23 20:09:09 -04:00
if not _save_and_restart(plugin, "enhanced"):
return False
2015-07-21 21:14:57 -04:00
2015-07-22 21:25:09 -04:00
success = True
for domain, info in domains_and_info:
previous_redirect = info[0]
if not previous_redirect:
verified = validator.Validator().redirect(
"localhost", plugin.http_port, headers={"Host": domain})
if not verified:
logger.error("*** Improper redirect for domain %s", domain)
success = False
2015-07-22 21:25:09 -04:00
if success:
logger.info("Enhancements test succeeded")
2015-07-22 21:25:09 -04:00
2015-07-23 20:09:09 -04:00
return success
def _save_and_restart(plugin: common.Proxy, title: Optional[str] = None) -> bool:
2015-07-23 20:09:09 -04:00
"""Saves and restart the plugin, returning True if no errors occurred"""
try:
plugin.save(title)
plugin.restart()
return True
except le_errors.Error:
logger.error("*** Plugin failed to save and restart server:", exc_info=True)
2015-07-23 20:09:09 -04:00
return False
2015-07-22 21:25:09 -04:00
def test_rollback(plugin: common.Proxy, config: str, backup: str) -> bool:
2015-07-22 21:25:09 -04:00
"""Tests the rollback checkpoints function"""
2015-07-23 20:09:09 -04:00
try:
2015-08-03 14:38:22 -04:00
plugin.rollback_checkpoints(1337)
except le_errors.Error:
logger.error("*** Plugin raised an exception during rollback:", exc_info=True)
2015-07-23 20:09:09 -04:00
return False
2015-07-22 21:25:09 -04:00
if _dirs_are_unequal(config, backup):
logger.error("*** Rollback failed for config `%s`", config)
2015-07-23 20:09:09 -04:00
return False
logger.info("Rollback succeeded")
return True
2015-07-22 21:25:09 -04:00
def _create_backup(config: str, temp_dir: str) -> str:
2015-07-22 21:25:09 -04:00
"""Creates a backup of config in temp_dir"""
backup = os.path.join(temp_dir, "backup")
shutil.rmtree(backup, ignore_errors=True)
shutil.copytree(config, backup, symlinks=True)
return backup
2015-07-21 21:14:57 -04:00
def _dirs_are_unequal(dir1: str, dir2: str) -> bool:
2015-08-03 22:23:01 -04:00
"""Returns True if dir1 and dir2 are unequal"""
dircmps = [filecmp.dircmp(dir1, dir2)]
while dircmps:
2015-08-03 22:23:01 -04:00
dircmp = dircmps.pop()
if dircmp.left_only or dircmp.right_only:
logger.error("The following files and directories are only "
"present in one directory")
if dircmp.left_only:
logger.error(str(dircmp.left_only))
2015-08-03 22:23:01 -04:00
else:
logger.error(str(dircmp.right_only))
2015-08-03 22:23:01 -04:00
return True
elif dircmp.common_funny or dircmp.funny_files:
logger.error("The following files and directories could not be "
"compared:")
if dircmp.common_funny:
logger.error(str(dircmp.common_funny))
2015-08-03 22:23:01 -04:00
else:
logger.error(str(dircmp.funny_files))
2015-08-03 22:23:01 -04:00
return True
elif dircmp.diff_files:
logger.error("The following files differ:")
logger.error(str(dircmp.diff_files))
2015-08-03 22:23:01 -04:00
return True
Move compatibility tests off of certbot-auto and Python 2 (#8248) Fixes https://github.com/certbot/certbot/issues/8162. I had to update the base of the Dockerfile to get a new enough version of Python 3. I also simplified things a lot and removed a lot of the comments that were essentially just describing how Dockerfiles work. The most complicated changes here are in `testdata`. You can find a diff of the changes to `nginx.tar.gz` at https://gist.github.com/c7727db0cecf3f15f02439f085c73848. The first problem was that there were some complaints from the new Apache/nginx/OpenSSL version about the 1024 bit RSA key so I updated `empty_cert.pem` both inside and outside of the tarball as well as the corresponding private key in the tarball to use a 2048 bit key. The 2nd problem is trickier to understand. If you look at the output from nginx after loading the config from `lots/` you'll see it complaining about conflicting `server_name` directives for the directives I deleted. See https://dev.azure.com/certbot/certbot/_build/results?buildId=2578&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e&t=9baa2014-9673-5e78-8f4f-7a463caf2bfa&l=1516. After switching the tests to Python 3, tests on that domain started failing. What I believe to be happening is we were just lucky these tests were passing to begin with. In both the Apache and Nginx plugin, if there are conflicting virtual hosts like this, we just arbitrarily pick one. The relevant code here for nginx is https://github.com/certbot/certbot/blob/575092d6030330ed8379babaa4cbbfe43e7bf721/certbot-nginx/certbot_nginx/_internal/configurator.py#L455 I played around with a debugger and confirmed that before I removed the conflicting server names, there were two exact matches for the domain we were searching for here. I think all that's going on is with the switch to Python 3, the vhost we happen to choose changes and "breaks" the test. I suspect this to be due to something like getting values out of a dict somewhere where the order of items in a dict while iterating over it is different between Python 2 and 3. I didn't track where this difference happens down, but I personally don't think it's a good use of time since I think the real problem here is that the nginx config being tested was invalid with conflicting `server` blocks. I removed all references to the `server_name` causing conflicts in that nginx configuration because both server blocks had other domains that are being tested, but I could add either back if you prefer. You can see the `nginx_compat` test passing with these changes at https://dev.azure.com/certbot/certbot/_build/results?buildId=2587&view=logs&j=250aa146-b243-5f8f-bf86-17a529c9fb7e. * update Dockerfile * Fix apache_compat on py3. * Update empty_cert.pem. The command used here was `openssl req -key certbot/certbot/tests/testdata/rsa2048_key.pem -new -subj '/CN=example.com' -x509 > certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem`. * update nginx.tar.gz * Remove conflicting server_names
2020-09-09 18:16:52 -04:00
for subdir in dircmp.subdirs.values():
2015-08-03 22:23:01 -04:00
dircmps.append(subdir)
2015-07-21 21:14:57 -04:00
2015-08-03 22:23:01 -04:00
return False
2015-07-21 21:14:57 -04:00
def get_args() -> argparse.Namespace:
2015-07-14 21:04:43 -04:00
"""Returns parsed command line arguments."""
2015-07-16 19:57:47 -04:00
parser = argparse.ArgumentParser(
description=DESCRIPTION,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
2015-07-14 21:04:43 -04:00
2015-07-16 02:00:18 -04:00
group = parser.add_argument_group("general")
2015-07-14 21:04:43 -04:00
group.add_argument(
2015-07-16 02:00:18 -04:00
"-c", "--configs", default="configs.tar.gz",
help="a directory or tarball containing server configurations")
2015-07-14 21:04:43 -04:00
group.add_argument(
2015-07-16 02:00:18 -04:00
"-p", "--plugin", default="apache", help="the plugin to be tested")
2015-07-17 19:21:17 -04:00
group.add_argument(
"-v", "--verbose", dest="verbose_count", action="count",
2015-07-17 20:33:32 -04:00
default=0, help="you know how to use this")
2015-07-14 21:04:43 -04:00
group.add_argument(
2015-07-16 02:00:18 -04:00
"-a", "--auth", action="store_true",
2015-07-16 19:57:47 -04:00
help="tests the challenges the plugin supports")
2015-07-14 21:04:43 -04:00
group.add_argument(
2015-07-16 02:00:18 -04:00
"-i", "--install", action="store_true",
help="tests the plugin as an installer")
2015-07-14 21:04:43 -04:00
group.add_argument(
2015-07-16 19:57:47 -04:00
"-e", "--enhance", action="store_true", help="tests the enhancements "
"the plugin supports (implicitly includes installer tests)")
2015-07-14 21:04:43 -04:00
Lint certbot code on Python 3, and update Pylint to the latest version (#7551) Part of #7550 This PR makes appropriate corrections to run pylint on Python 3. Why not keeping the dependencies unchanged and just run pylint on Python 3? Because the old version of pylint breaks horribly on Python 3 because of unsupported version of astroid. Why updating pylint + astroid to the latest version ? Because this version only fixes some internal errors occuring during the lint of Certbot code, and is also ready to run gracefully on Python 3.8. Why upgrading mypy ? Because the old version does not support the new version of astroid required to run pylint correctly. Why not upgrading mypy to its latest version ? Because this latest version includes a new typshed version, that adds a lot of new type definitions, and brings dozens of new errors on the Certbot codebase. I would like to fix that in a future PR. That said so, the work has been to find the correct set of new dependency versions, then configure pylint for sane configuration errors in our situation, disable irrelevant lintings errors, then fixing (or ignoring for good reason) the remaining mypy errors. I also made PyLint and MyPy checks run correctly on Windows. * Start configuration * Reconfigure travis * Suspend a check specific to python 3. Start fixing code. * Repair call_args * Fix return + elif lints * Reconfigure development to run mainly on python3 * Remove incompatible Python 3.4 jobs * Suspend pylint in some assertions * Remove pylint in dev * Take first mypy that supports typed-ast>=1.4.0 to limit the migration path * Various return + else lint errors * Find a set of deps that is working with current mypy version * Update local oldest requirements * Remove all current pylint errors * Rebuild letsencrypt-auto * Update mypy to fix pylint with new astroid version, and fix mypy issues * Explain type: ignore * Reconfigure tox, fix none path * Simplify pinning * Remove useless directive * Remove debugging code * Remove continue * Update requirements * Disable unsubscriptable-object check * Disable one check, enabling two more * Plug certbot dev version for oldest requirements * Remove useless disable directives * Remove useless no-member disable * Remove no-else-* checks. Use elif in symetric branches. * Add back assertion * Add new line * Remove unused pylint disable * Remove other pylint disable
2019-12-10 17:12:50 -05:00
for plugin in PLUGINS.values():
2015-07-14 21:04:43 -04:00
plugin.add_parser_arguments(parser)
args = parser.parse_args()
2015-07-16 19:57:47 -04:00
if args.enhance:
2015-07-14 21:04:43 -04:00
args.install = True
elif not (args.auth or args.install):
2015-07-22 21:25:09 -04:00
args.auth = args.install = args.enhance = True
2015-07-14 21:04:43 -04:00
return args
def setup_logging(args: argparse.Namespace) -> None:
2015-07-14 21:04:43 -04:00
"""Prepares logging for the program"""
handler = logging.StreamHandler()
root_logger = logging.getLogger()
2015-08-03 14:38:22 -04:00
root_logger.setLevel(logging.ERROR - args.verbose_count * 10)
2015-07-14 21:04:43 -04:00
root_logger.addHandler(handler)
2015-07-10 14:42:10 -04:00
def setup_display() -> None:
""""Prepares a display utility instance for the Certbot plugins """
Command-line UX overhaul (#8852) Streamline and reorganize Certbot's CLI output. This change is a substantial command-line UX overhaul, based on previous user research. The main goal was to streamline and clarify output. To see more verbose output, use the -v or -vv flags. --- * nginx,apache: CLI logging changes - Add "Successfully deployed ..." message using display_util - Remove IReporter usage and replace with display_util - Standardize "... could not find a VirtualHost ..." error This changes also bumps the version of certbot required by certbot-nginx and certbot-apache to take use of the new display_util function. * fix certbot_compatibility_test since the http plugins now require IDisplay, we need to inject it * fix dependency version on certbot * use better asserts * try fix oldest deps because certbot 1.10.0 depends on acme>=1.8.0, we need to use acme==1.8.0 in the -oldest tests * cli: redesign output of new certificate reporting Changes the output of run, certonly and certonly --csr. No longer uses IReporter. * cli: redesign output of failed authz reporting * fix problem sorting to be stable between py2 & 3 * add some catch-all error text * cli: dont use IReporter for EFF donation prompt * add per-authenticator hints * pass achalls to auth_hint, write some tests * exclude static auth hints from coverage * dont call auth_hint unless derived from .Plugin * dns fallback hint: dont assume --dns-blah works --dns-blah won't work for third-party plugins, they need to be specified using --authenticator dns-blah. * add code comments about the auth_hint interface * renew: don't restart the installer for dry-runs Prevents Certbot from superfluously invoking the installer restart during dry-run renewals. (This does not affect authenticator restarts). Additionally removes some CLI output that was reporting the fullchain path of the renewed certificate. * update CHANGELOG.md * cli: redesign output when cert installation failed - Display a message when certificate installation begins. - Don't use IReporter, just log errors immediately if restart/rollback fails. - Prompt the user with a command to retry the installation process once they have fixed any underlying problems. * vary by preconfigured_renewal and move expiry date to be above the renewal advice * update code comment Co-authored-by: ohemorange <ebportnoy@gmail.com> * update code comment Co-authored-by: ohemorange <ebportnoy@gmail.com> * fix lint * derve cert name from cert_path, if possible * fix type annotation * text change in nginx hint Co-authored-by: ohemorange <ebportnoy@gmail.com> * print message when restarting server after renewal * log: print "advice" when exiting with an error When running in non-quiet mode. * try fix -oldest lock_test.py * fix docstring * s/Restarting/Reloading/ when notifying the user * fix test name Co-authored-by: ohemorange <ebportnoy@gmail.com> * type annotations * s/using the {} plugin/installer: {}/ * copy: avoid "plugin" where possible * link to user guide#automated-renewals when not running with --preconfigured-renewal * cli: reduce default logging verbosity * fix lock_test: -vv is needed to see logger.debug * Change comment in log.py to match the change to default verbosity * Audit and adjust logging levels in apache module * Audit and adjust logging levels in nginx module * Audit, adjust logging levels, and improve logging calls in certbot module * Fix tests to mock correct methods and classes * typo in non-preconfigured-renewal message Co-authored-by: ohemorange <ebportnoy@gmail.com> * fix test * revert acme version bump * catch up to python3 changes * Revert "revert acme version bump" This reverts commit fa83d6a51cf8d0e7e17da53c6b751ad12945d0cf. * Change ocsp check error to warning since it's non-fatal * Update storage_test in parallel with last change * get rid of leading newline on "Deploying [...]" * shrink renewal and installation success messages * print logfile rather than logdir in exit handler * Decrease logging level to info for idempotent operation where enhancement is already set * Display cert not yet due for renewal message when renewing and no other action will be taken, and change cert to certificate * also write to logger so it goes in the log file * Don't double write to log file; fix main test * cli: remove trailing newline on new cert reporting * ignore type error * revert accidental changes to dependencies * Pass tests in any timezone by using utcfromtimestamp * Add changelog entry * fix nits * Improve wording of try again message * minor wording change to changelog * hooks: send hook stdout to CLI stdout includes both --manual and --{pre,post,renew} hooks * update docstrings and remove TODO * add a pending deprecation on execute_command * add test coverage for both * update deprecation text Co-authored-by: ohemorange <ebportnoy@gmail.com> Co-authored-by: Alex Zorin <alex@zorin.id.au> Co-authored-by: alexzorin <alex@zor.io>
2021-05-24 20:47:39 -04:00
displayer = display_util.NoninteractiveDisplay(sys.stdout)
Deprecate zope.component in favor of an direct calls to functions from `certbot.display.util` module (#8835) * Implement certbot services * Various fixes * Local oldest requirements * Clean imports * Add unit tests for certbot.services * Clean code * Protect against nullity of global services * Fix CLI * Fix tests * Consistent test behavior * Various fixes * Clean code * Remove reporter service, migrate display service in certbot.display.util. * Fix test * Fix apache compatibility test * Fix oldest test * Setup certbot.display.service module * Reintegrate in util * Fix imports * Fix tests and documentation * Refactor * Cleanup * Cleanup * Clean imports * Add unit tests * Borrow sphinx build fix from #8863 * Fix type * Add comment * Do not reuse existing display service, which never exist at that time * Make get_display() private * Fix lint * Make display internal * Fix circular dependencies * Fixing circular dependencies * Rename patch methods and update docstring * Update deprecation messages * Update certbot/certbot/_internal/display/obj.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> * Add links * Avoid relying on internal certbot packages from certbot-apache * Keep same behavior for patch_get_utility* * Better diff * Add changelog * Update certbot/certbot/tests/util.py Co-authored-by: Brad Warren <bmw@users.noreply.github.com> Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
2021-07-19 20:09:06 -04:00
display_obj.set_display(displayer)
Command-line UX overhaul (#8852) Streamline and reorganize Certbot's CLI output. This change is a substantial command-line UX overhaul, based on previous user research. The main goal was to streamline and clarify output. To see more verbose output, use the -v or -vv flags. --- * nginx,apache: CLI logging changes - Add "Successfully deployed ..." message using display_util - Remove IReporter usage and replace with display_util - Standardize "... could not find a VirtualHost ..." error This changes also bumps the version of certbot required by certbot-nginx and certbot-apache to take use of the new display_util function. * fix certbot_compatibility_test since the http plugins now require IDisplay, we need to inject it * fix dependency version on certbot * use better asserts * try fix oldest deps because certbot 1.10.0 depends on acme>=1.8.0, we need to use acme==1.8.0 in the -oldest tests * cli: redesign output of new certificate reporting Changes the output of run, certonly and certonly --csr. No longer uses IReporter. * cli: redesign output of failed authz reporting * fix problem sorting to be stable between py2 & 3 * add some catch-all error text * cli: dont use IReporter for EFF donation prompt * add per-authenticator hints * pass achalls to auth_hint, write some tests * exclude static auth hints from coverage * dont call auth_hint unless derived from .Plugin * dns fallback hint: dont assume --dns-blah works --dns-blah won't work for third-party plugins, they need to be specified using --authenticator dns-blah. * add code comments about the auth_hint interface * renew: don't restart the installer for dry-runs Prevents Certbot from superfluously invoking the installer restart during dry-run renewals. (This does not affect authenticator restarts). Additionally removes some CLI output that was reporting the fullchain path of the renewed certificate. * update CHANGELOG.md * cli: redesign output when cert installation failed - Display a message when certificate installation begins. - Don't use IReporter, just log errors immediately if restart/rollback fails. - Prompt the user with a command to retry the installation process once they have fixed any underlying problems. * vary by preconfigured_renewal and move expiry date to be above the renewal advice * update code comment Co-authored-by: ohemorange <ebportnoy@gmail.com> * update code comment Co-authored-by: ohemorange <ebportnoy@gmail.com> * fix lint * derve cert name from cert_path, if possible * fix type annotation * text change in nginx hint Co-authored-by: ohemorange <ebportnoy@gmail.com> * print message when restarting server after renewal * log: print "advice" when exiting with an error When running in non-quiet mode. * try fix -oldest lock_test.py * fix docstring * s/Restarting/Reloading/ when notifying the user * fix test name Co-authored-by: ohemorange <ebportnoy@gmail.com> * type annotations * s/using the {} plugin/installer: {}/ * copy: avoid "plugin" where possible * link to user guide#automated-renewals when not running with --preconfigured-renewal * cli: reduce default logging verbosity * fix lock_test: -vv is needed to see logger.debug * Change comment in log.py to match the change to default verbosity * Audit and adjust logging levels in apache module * Audit and adjust logging levels in nginx module * Audit, adjust logging levels, and improve logging calls in certbot module * Fix tests to mock correct methods and classes * typo in non-preconfigured-renewal message Co-authored-by: ohemorange <ebportnoy@gmail.com> * fix test * revert acme version bump * catch up to python3 changes * Revert "revert acme version bump" This reverts commit fa83d6a51cf8d0e7e17da53c6b751ad12945d0cf. * Change ocsp check error to warning since it's non-fatal * Update storage_test in parallel with last change * get rid of leading newline on "Deploying [...]" * shrink renewal and installation success messages * print logfile rather than logdir in exit handler * Decrease logging level to info for idempotent operation where enhancement is already set * Display cert not yet due for renewal message when renewing and no other action will be taken, and change cert to certificate * also write to logger so it goes in the log file * Don't double write to log file; fix main test * cli: remove trailing newline on new cert reporting * ignore type error * revert accidental changes to dependencies * Pass tests in any timezone by using utcfromtimestamp * Add changelog entry * fix nits * Improve wording of try again message * minor wording change to changelog * hooks: send hook stdout to CLI stdout includes both --manual and --{pre,post,renew} hooks * update docstrings and remove TODO * add a pending deprecation on execute_command * add test coverage for both * update deprecation text Co-authored-by: ohemorange <ebportnoy@gmail.com> Co-authored-by: Alex Zorin <alex@zorin.id.au> Co-authored-by: alexzorin <alex@zor.io>
2021-05-24 20:47:39 -04:00
def main() -> None:
2015-07-10 14:42:10 -04:00
"""Main test script execution."""
2015-07-14 21:04:43 -04:00
args = get_args()
2015-07-17 19:21:17 -04:00
setup_logging(args)
Command-line UX overhaul (#8852) Streamline and reorganize Certbot's CLI output. This change is a substantial command-line UX overhaul, based on previous user research. The main goal was to streamline and clarify output. To see more verbose output, use the -v or -vv flags. --- * nginx,apache: CLI logging changes - Add "Successfully deployed ..." message using display_util - Remove IReporter usage and replace with display_util - Standardize "... could not find a VirtualHost ..." error This changes also bumps the version of certbot required by certbot-nginx and certbot-apache to take use of the new display_util function. * fix certbot_compatibility_test since the http plugins now require IDisplay, we need to inject it * fix dependency version on certbot * use better asserts * try fix oldest deps because certbot 1.10.0 depends on acme>=1.8.0, we need to use acme==1.8.0 in the -oldest tests * cli: redesign output of new certificate reporting Changes the output of run, certonly and certonly --csr. No longer uses IReporter. * cli: redesign output of failed authz reporting * fix problem sorting to be stable between py2 & 3 * add some catch-all error text * cli: dont use IReporter for EFF donation prompt * add per-authenticator hints * pass achalls to auth_hint, write some tests * exclude static auth hints from coverage * dont call auth_hint unless derived from .Plugin * dns fallback hint: dont assume --dns-blah works --dns-blah won't work for third-party plugins, they need to be specified using --authenticator dns-blah. * add code comments about the auth_hint interface * renew: don't restart the installer for dry-runs Prevents Certbot from superfluously invoking the installer restart during dry-run renewals. (This does not affect authenticator restarts). Additionally removes some CLI output that was reporting the fullchain path of the renewed certificate. * update CHANGELOG.md * cli: redesign output when cert installation failed - Display a message when certificate installation begins. - Don't use IReporter, just log errors immediately if restart/rollback fails. - Prompt the user with a command to retry the installation process once they have fixed any underlying problems. * vary by preconfigured_renewal and move expiry date to be above the renewal advice * update code comment Co-authored-by: ohemorange <ebportnoy@gmail.com> * update code comment Co-authored-by: ohemorange <ebportnoy@gmail.com> * fix lint * derve cert name from cert_path, if possible * fix type annotation * text change in nginx hint Co-authored-by: ohemorange <ebportnoy@gmail.com> * print message when restarting server after renewal * log: print "advice" when exiting with an error When running in non-quiet mode. * try fix -oldest lock_test.py * fix docstring * s/Restarting/Reloading/ when notifying the user * fix test name Co-authored-by: ohemorange <ebportnoy@gmail.com> * type annotations * s/using the {} plugin/installer: {}/ * copy: avoid "plugin" where possible * link to user guide#automated-renewals when not running with --preconfigured-renewal * cli: reduce default logging verbosity * fix lock_test: -vv is needed to see logger.debug * Change comment in log.py to match the change to default verbosity * Audit and adjust logging levels in apache module * Audit and adjust logging levels in nginx module * Audit, adjust logging levels, and improve logging calls in certbot module * Fix tests to mock correct methods and classes * typo in non-preconfigured-renewal message Co-authored-by: ohemorange <ebportnoy@gmail.com> * fix test * revert acme version bump * catch up to python3 changes * Revert "revert acme version bump" This reverts commit fa83d6a51cf8d0e7e17da53c6b751ad12945d0cf. * Change ocsp check error to warning since it's non-fatal * Update storage_test in parallel with last change * get rid of leading newline on "Deploying [...]" * shrink renewal and installation success messages * print logfile rather than logdir in exit handler * Decrease logging level to info for idempotent operation where enhancement is already set * Display cert not yet due for renewal message when renewing and no other action will be taken, and change cert to certificate * also write to logger so it goes in the log file * Don't double write to log file; fix main test * cli: remove trailing newline on new cert reporting * ignore type error * revert accidental changes to dependencies * Pass tests in any timezone by using utcfromtimestamp * Add changelog entry * fix nits * Improve wording of try again message * minor wording change to changelog * hooks: send hook stdout to CLI stdout includes both --manual and --{pre,post,renew} hooks * update docstrings and remove TODO * add a pending deprecation on execute_command * add test coverage for both * update deprecation text Co-authored-by: ohemorange <ebportnoy@gmail.com> Co-authored-by: Alex Zorin <alex@zorin.id.au> Co-authored-by: alexzorin <alex@zor.io>
2021-05-24 20:47:39 -04:00
setup_display()
2015-07-16 02:00:18 -04:00
if args.plugin not in PLUGINS:
raise errors.Error("Unknown plugin {0}".format(args.plugin))
2015-07-17 19:21:17 -04:00
2015-07-21 21:14:57 -04:00
temp_dir = tempfile.mkdtemp()
2015-07-17 19:21:17 -04:00
plugin = PLUGINS[args.plugin](args)
2015-07-16 19:57:47 -04:00
try:
overall_success = True
2015-07-17 19:21:17 -04:00
while plugin.has_more_configs():
2015-07-23 20:09:09 -04:00
success = True
2015-07-17 19:21:17 -04:00
try:
2015-07-21 21:14:57 -04:00
config = plugin.load_config()
logger.info("Loaded configuration: %s", config)
if args.auth:
2015-07-23 20:09:09 -04:00
success = test_authenticator(plugin, config, temp_dir)
if success and args.install:
success = test_installer(args, plugin, config, temp_dir)
except errors.Error:
logger.error("Tests on %s raised:", config, exc_info=True)
2015-07-23 20:09:09 -04:00
success = False
if success:
logger.info("All tests on %s succeeded", config)
else:
overall_success = False
2015-07-23 20:09:09 -04:00
logger.error("Tests on %s failed", config)
2015-07-16 19:57:47 -04:00
finally:
2015-07-17 19:21:17 -04:00
plugin.cleanup_from_tests()
2015-07-10 14:42:10 -04:00
if overall_success:
logger.warning("All compatibility tests succeeded")
sys.exit(0)
else:
logger.warning("One or more compatibility tests failed")
sys.exit(1)
2015-07-10 14:42:10 -04:00
@contextlib.contextmanager
def _fake_dns_resolution(resolved_ip: str) -> Generator[None, None, None]:
"""Monkey patch urllib3 to make any hostname be resolved to the provided IP"""
_original_create_connection = connection.create_connection
def _patched_create_connection(address: Tuple[str, str],
*args: Any, **kwargs: Any) -> socket.socket:
_, port = address
return _original_create_connection((resolved_ip, port), *args, **kwargs)
try:
connection.create_connection = _patched_create_connection
yield
finally:
connection.create_connection = _original_create_connection
2015-07-16 02:00:18 -04:00
if __name__ == "__main__":
2015-07-14 21:04:43 -04:00
main()