diff --git a/.azure-pipelines/main.yml b/.azure-pipelines/main.yml index 1975d36db..cae4f799c 100644 --- a/.azure-pipelines/main.yml +++ b/.azure-pipelines/main.yml @@ -5,3 +5,4 @@ pr: jobs: - template: templates/jobs/standard-tests-jobs.yml + diff --git a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml index 0c92136e8..cffedfcb2 100644 --- a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml @@ -21,26 +21,24 @@ jobs: PYTHON_VERSION: 3.7 TOXENV: py37 CERTBOT_NO_PIN: 1 + linux-external-mock: + TOXENV: external-mock linux-boulder-v1-integration-certbot-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-certbot-oldest ACME_SERVER: boulder-v1 linux-boulder-v2-integration-certbot-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-certbot-oldest ACME_SERVER: boulder-v2 linux-boulder-v1-integration-nginx-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-nginx-oldest ACME_SERVER: boulder-v1 linux-boulder-v2-integration-nginx-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-nginx-oldest ACME_SERVER: boulder-v2 - linux-boulder-v1-py27-integration: - PYTHON_VERSION: 2.7 - TOXENV: integration - ACME_SERVER: boulder-v1 - linux-boulder-v2-py27-integration: - PYTHON_VERSION: 2.7 - TOXENV: integration - ACME_SERVER: boulder-v2 linux-boulder-v1-py36-integration: PYTHON_VERSION: 3.6 TOXENV: integration diff --git a/.azure-pipelines/templates/jobs/packaging-jobs.yml b/.azure-pipelines/templates/jobs/packaging-jobs.yml index 900be9b2f..28255919f 100644 --- a/.azure-pipelines/templates/jobs/packaging-jobs.yml +++ b/.azure-pipelines/templates/jobs/packaging-jobs.yml @@ -56,7 +56,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: 3.7 + versionSpec: 3.8 architecture: x86 addToPath: true - script: python windows-installer/construct.py diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index 39cd628bc..fec11c6c5 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -4,10 +4,10 @@ jobs: PYTHON_VERSION: 3.9 strategy: matrix: - macos-py27: + macos-py36: IMAGE_NAME: macOS-10.15 - PYTHON_VERSION: 2.7 - TOXENV: py27 + PYTHON_VERSION: 3.6 + TOXENV: py36 macos-py39: IMAGE_NAME: macOS-10.15 PYTHON_VERSION: 3.9 @@ -16,24 +16,22 @@ jobs: IMAGE_NAME: vs2017-win2016 PYTHON_VERSION: 3.6 TOXENV: py36 - windows-py37-cover: + windows-py38-cover: IMAGE_NAME: vs2017-win2016 - PYTHON_VERSION: 3.7 - TOXENV: py37-cover + PYTHON_VERSION: 3.8 + TOXENV: py38-cover windows-integration-certbot: IMAGE_NAME: vs2017-win2016 - PYTHON_VERSION: 3.7 + PYTHON_VERSION: 3.8 TOXENV: integration-certbot linux-oldest-tests-1: IMAGE_NAME: ubuntu-18.04 - TOXENV: py27-{acme,apache,apache-v2,certbot}-oldest + PYTHON_VERSION: 3.6 + TOXENV: '{acme,apache,apache-v2,certbot}-oldest' linux-oldest-tests-2: IMAGE_NAME: ubuntu-18.04 - TOXENV: py27-{dns,nginx}-oldest - linux-py27: - IMAGE_NAME: ubuntu-18.04 - PYTHON_VERSION: 2.7 - TOXENV: py27 + PYTHON_VERSION: 3.6 + TOXENV: '{dns,nginx}-oldest' linux-py36: IMAGE_NAME: ubuntu-18.04 PYTHON_VERSION: 3.6 @@ -63,13 +61,18 @@ jobs: TOXENV: modification apacheconftest: IMAGE_NAME: ubuntu-18.04 - PYTHON_VERSION: 2.7 + PYTHON_VERSION: 3.6 TOXENV: apacheconftest-with-pebble nginxroundtrip: IMAGE_NAME: ubuntu-18.04 - PYTHON_VERSION: 2.7 + PYTHON_VERSION: 3.6 TOXENV: nginxroundtrip pool: vmImage: $(IMAGE_NAME) steps: - template: ../steps/tox-steps.yml + - job: test_sphinx_builds + pool: + vmImage: ubuntu-20.04 + steps: + - template: ../steps/sphinx-steps.yml diff --git a/.azure-pipelines/templates/stages/notify-failure-stage.yml b/.azure-pipelines/templates/stages/notify-failure-stage.yml index 1542f5ebc..c47342690 100644 --- a/.azure-pipelines/templates/stages/notify-failure-stage.yml +++ b/.azure-pipelines/templates/stages/notify-failure-stage.yml @@ -5,7 +5,7 @@ stages: variables: - group: certbot-common pool: - vmImage: ubuntu-latest + vmImage: ubuntu-20.04 steps: - bash: | set -e diff --git a/.azure-pipelines/templates/steps/sphinx-steps.yml b/.azure-pipelines/templates/steps/sphinx-steps.yml new file mode 100644 index 000000000..23c258bbc --- /dev/null +++ b/.azure-pipelines/templates/steps/sphinx-steps.yml @@ -0,0 +1,23 @@ +steps: + - bash: | + FINAL_STATUS=0 + declare -a FAILED_BUILDS + python3 -m venv .venv + source .venv/bin/activate + python tools/pipstrap.py + for doc_path in */docs + do + echo "" + echo "##[group]Building $doc_path" + pip install -q -e $doc_path/..[docs] + if ! sphinx-build -W --keep-going -b html $doc_path $doc_path/_build/html; then + FINAL_STATUS=1 + FAILED_BUILDS[${#FAILED_BUILDS[@]}]="${doc_path%/docs}" + fi + echo "##[endgroup]" + done + if [[ $FINAL_STATUS -ne 0 ]]; then + echo "##[error]The following builds failed: ${FAILED_BUILDS[*]}" + exit 1 + fi + displayName: Build Sphinx Documentation diff --git a/.azure-pipelines/templates/steps/tox-steps.yml b/.azure-pipelines/templates/steps/tox-steps.yml index a9f78d36b..ecf3d6032 100644 --- a/.azure-pipelines/templates/steps/tox-steps.yml +++ b/.azure-pipelines/templates/steps/tox-steps.yml @@ -45,11 +45,7 @@ steps: export TARGET_BRANCH="`echo "${BUILD_SOURCEBRANCH}" | sed -E 's!refs/(heads|tags)/!!g'`" [ -z "${SYSTEM_PULLREQUEST_TARGETBRANCH}" ] || export TARGET_BRANCH="${SYSTEM_PULLREQUEST_TARGETBRANCH}" env - if [[ "${TOXENV}" == *"oldest"* ]]; then - tools/run_oldest_tests.sh - else - python -m tox - fi + python -m tox env: AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) diff --git a/.dockerignore b/.dockerignore index b94bf7960..2ce8a8209 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,5 +8,4 @@ .git .tox venv -venv3 docs diff --git a/.envrc b/.envrc index 4d2077ebb..43c3170d6 100644 --- a/.envrc +++ b/.envrc @@ -3,7 +3,7 @@ # activated and then deactivated when you cd elsewhere. Developers have to have # direnv set up and run `direnv allow` to allow this file to execute on their # system. You can find more information at https://direnv.net/. -. venv3/bin/activate +. venv/bin/activate # direnv doesn't support modifying PS1 so we unset it to squelch the error # it'll otherwise print about this being done in the activate script. See # https://github.com/direnv/direnv/wiki/PS1. If you would like your shell diff --git a/AUTHORS.md b/AUTHORS.md index ff5c61613..cb60bfd87 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1,6 +1,7 @@ Authors ======= +* [Aaron Gable](https://github.com/aarongable) * [Aaron Zirbes](https://github.com/aaronzirbes) * Aaron Zuehlke * Ada Lovelace @@ -60,6 +61,7 @@ Authors * [DanCld](https://github.com/DanCld) * [Daniel Albers](https://github.com/AID) * [Daniel Aleksandersen](https://github.com/da2x) +* [Daniel Almasi](https://github.com/almasen) * [Daniel Convissor](https://github.com/convissor) * [Daniel "Drex" Drexler](https://github.com/aeturnum) * [Daniel Huang](https://github.com/dhuang) diff --git a/Dockerfile-dev b/Dockerfile-dev index ae197b1cb..86847f8fd 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -15,6 +15,6 @@ RUN apt-get update && \ /tmp/* \ /var/tmp/* -RUN VENV_NAME="../venv3" python3 tools/venv3.py +RUN VENV_NAME="../venv" python3 tools/venv.py -ENV PATH /opt/certbot/venv3/bin:$PATH +ENV PATH /opt/certbot/venv/bin:$PATH diff --git a/acme/acme/__init__.py b/acme/acme/__init__.py index 3ec5203bf..8b6ce88c0 100644 --- a/acme/acme/__init__.py +++ b/acme/acme/__init__.py @@ -6,7 +6,6 @@ This module is an implementation of the `ACME protocol`_. """ import sys -import warnings # This code exists to keep backwards compatibility with people using acme.jose # before it became the standalone josepy package. @@ -20,10 +19,3 @@ for mod in list(sys.modules): # preserved (acme.jose.* is josepy.*) if mod == 'josepy' or mod.startswith('josepy.'): sys.modules['acme.' + mod.replace('josepy', 'jose', 1)] = sys.modules[mod] - -if sys.version_info[0] == 2: - warnings.warn( - "Python 2 support will be dropped in the next release of acme. " - "Please upgrade your Python version.", - PendingDeprecationWarning, - ) # pragma: no cover diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index b9c6b7eb2..376e9a382 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -150,7 +150,7 @@ class KeyAuthorizationChallenge(_TokenChallenge): """Challenge based on Key Authorization. :param response_cls: Subclass of `KeyAuthorizationChallengeResponse` - that will be used to generate `response`. + that will be used to generate ``response``. :param str typ: type of the challenge """ typ = NotImplemented diff --git a/acme/acme/client.py b/acme/acme/client.py index d413ce13d..6adfe4b78 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -6,7 +6,6 @@ from email.utils import parsedate_tz import heapq import logging import re -import sys import time import josepy as jose @@ -30,17 +29,6 @@ from acme.mixins import VersionedLEACMEMixin logger = logging.getLogger(__name__) -# Prior to Python 2.7.9 the stdlib SSL module did not allow a user to configure -# many important security related options. On these platforms we use PyOpenSSL -# for SSL, which does allow these options to be configured. -# https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning -if sys.version_info < (2, 7, 9): # pragma: no cover - try: - requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3() # type: ignore - except AttributeError: - import urllib3.contrib.pyopenssl - urllib3.contrib.pyopenssl.inject_into_urllib3() - DEFAULT_NETWORK_TIMEOUT = 45 DER_CONTENT_TYPE = 'application/pkix-cert' diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index cabc7f4d1..4b58db328 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -166,7 +166,7 @@ def probe_sni(name, host, port=443, timeout=300, # pylint: disable=too-many-argu " from {0}:{1}".format( source_address[0], source_address[1] - ) if socket_kwargs else "" + ) if any(source_address) else "" ) socket_tuple = (host, port) # type: Tuple[str, int] sock = socket.create_connection(socket_tuple, **socket_kwargs) # type: ignore diff --git a/acme/acme/errors.py b/acme/acme/errors.py index 806657940..5ca5a4fa2 100644 --- a/acme/acme/errors.py +++ b/acme/acme/errors.py @@ -49,7 +49,7 @@ class MissingNonce(NonceError): Replay-Nonce header field in each successful response to a POST it provides to a client (...)". - :ivar requests.Response response: HTTP Response + :ivar requests.Response ~.response: HTTP Response """ def __init__(self, response, *args, **kwargs): diff --git a/acme/acme/messages.py b/acme/acme/messages.py index 6325ed57f..3a505843d 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -275,7 +275,7 @@ class Resource(jose.JSONObjectWithFields): class ResourceWithURI(Resource): """ACME Resource with URI. - :ivar unicode uri: Location of the resource. + :ivar unicode ~.uri: Location of the resource. """ uri = jose.Field('uri') # no ChallengeResource.uri @@ -627,7 +627,7 @@ class Order(ResourceBody): :ivar str finalize: URL to POST to to request issuance once all authorizations have "valid" status. :ivar datetime.datetime expires: When the order expires. - :ivar .Error error: Any error that occurred during finalization, if applicable. + :ivar ~.Error error: Any error that occurred during finalization, if applicable. """ identifiers = jose.Field('identifiers', omitempty=True) status = jose.Field('status', decoder=Status.from_json, diff --git a/acme/docs/conf.py b/acme/docs/conf.py index d3e7be371..9d3c4d05c 100644 --- a/acme/docs/conf.py +++ b/acme/docs/conf.py @@ -85,7 +85,10 @@ language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = [ + '_build', + 'man/*' +] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/acme/setup.py b/acme/setup.py index f8f9efaad..745169cbf 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -1,40 +1,26 @@ -from distutils.version import LooseVersion import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ - # load_pem_private/public_key (>=0.6) - # rsa_recover_prime_factors (>=0.8) - 'cryptography>=1.2.3', + 'cryptography>=2.1.4', # formerly known as acme.jose: # 1.1.0+ is required to avoid the warnings described at # https://github.com/certbot/josepy/issues/13. 'josepy>=1.1.0', - # Connection.set_tlsext_host_name (>=0.13) + matching Xenial requirements (>=0.15.1) - 'PyOpenSSL>=0.15.1', + 'PyOpenSSL>=17.3.0', 'pyrfc3339', 'pytz', - 'requests[security]>=2.6.0', # security extras added in 2.4.1 + 'requests>=2.6.0', 'requests-toolbelt>=0.3.0', - 'setuptools', - 'six>=1.9.0', # needed for python_2_unicode_compatible + 'setuptools>=39.0.1', + 'six>=1.11.0', ] -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - dev_extras = [ 'pytest', 'pytest-xdist', @@ -54,14 +40,12 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/acme/tests/challenges_test.py b/acme/tests/challenges_test.py index 70371051c..22e67be3c 100644 --- a/acme/tests/challenges_test.py +++ b/acme/tests/challenges_test.py @@ -1,12 +1,9 @@ """Tests for acme.challenges.""" import unittest +from unittest import mock import josepy as jose import OpenSSL -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore import requests from six.moves.urllib import parse as urllib_parse diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index c84878c42..a1be59056 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -4,12 +4,9 @@ import copy import datetime import json import unittest +from unittest import mock import josepy as jose -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore import OpenSSL import requests from six.moves import http_client # pylint: disable=import-error diff --git a/acme/tests/errors_test.py b/acme/tests/errors_test.py index fb90a3f0d..11c57059c 100644 --- a/acme/tests/errors_test.py +++ b/acme/tests/errors_test.py @@ -1,10 +1,6 @@ """Tests for acme.errors.""" import unittest - -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore +from unittest import mock class BadNonceTest(unittest.TestCase): diff --git a/acme/tests/magic_typing_test.py b/acme/tests/magic_typing_test.py index 9e4fd29f5..048995916 100644 --- a/acme/tests/magic_typing_test.py +++ b/acme/tests/magic_typing_test.py @@ -1,11 +1,7 @@ """Tests for acme.magic_typing.""" import sys import unittest - -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore +from unittest import mock class MagicTypingTest(unittest.TestCase): diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 70b05b419..74d1737ec 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -1,11 +1,8 @@ """Tests for acme.messages.""" import unittest +from unittest import mock import josepy as jose -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore from acme import challenges import test_util diff --git a/acme/tests/standalone_test.py b/acme/tests/standalone_test.py index 3d068fb46..5bbc2ccce 100644 --- a/acme/tests/standalone_test.py +++ b/acme/tests/standalone_test.py @@ -2,12 +2,9 @@ import socket import threading import unittest +from unittest import mock import josepy as jose -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore import requests from six.moves import http_client # pylint: disable=import-error from six.moves import socketserver # type: ignore # pylint: disable=import-error diff --git a/certbot-apache/certbot_apache/_internal/override_suse.py b/certbot-apache/certbot_apache/_internal/override_suse.py index eee9b0b64..afce98dfa 100644 --- a/certbot-apache/certbot_apache/_internal/override_suse.py +++ b/certbot-apache/certbot_apache/_internal/override_suse.py @@ -14,10 +14,10 @@ class OpenSUSEConfigurator(configurator.ApacheConfigurator): vhost_root="/etc/apache2/vhosts.d", vhost_files="*.conf", logs_root="/var/log/apache2", - ctl="apache2ctl", - version_cmd=['apache2ctl', '-v'], - restart_cmd=['apache2ctl', 'graceful'], - conftest_cmd=['apache2ctl', 'configtest'], + ctl="apachectl", + version_cmd=['apachectl', '-v'], + restart_cmd=['apachectl', 'graceful'], + conftest_cmd=['apachectl', 'configtest'], enmod="a2enmod", dismod="a2dismod", le_vhost_ext="-le-ssl.conf", diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 8b908ade7..f129343b3 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,11 +1,7 @@ -from distutils.version import LooseVersion -import sys - -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. @@ -13,20 +9,11 @@ install_requires = [ 'acme>=0.29.0', 'certbot>=1.6.0', 'python-augeas', - 'setuptools', + 'setuptools>=39.0.1', 'zope.component', 'zope.interface', ] -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - dev_extras = [ 'apacheconfig>=0.3.2', ] @@ -39,7 +26,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -47,8 +34,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-auto b/certbot-auto index ee12d4706..002fd5ffc 100755 --- a/certbot-auto +++ b/certbot-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.10.1" +LE_AUTO_VERSION="1.12.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -803,7 +803,9 @@ if [ -f /etc/debian_version ]; then elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/redhat-release ]; then + DEPRECATED_OS=1 # Run DeterminePythonVersion to decide on the basis of available Python versions # whether to use 2.x or 3.x on RedHat-like systems. # Then, revert LE_PYTHON to its previous state. @@ -836,12 +838,7 @@ elif [ -f /etc/redhat-release ]; then INTERACTIVE_BOOTSTRAP=1 fi - Bootstrap() { - BootstrapMessage "Legacy RedHat-based OSes that will use Python3" - BootstrapRpmPython3Legacy - } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3Legacy $BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION" # Try now to enable SCL rh-python36 for systems already bootstrapped # NB: EnablePython36SCL has been defined along with BootstrapRpmPython3Legacy in certbot-auto @@ -860,43 +857,38 @@ elif [ -f /etc/redhat-release ]; then fi if [ "$RPM_USE_PYTHON_3" = 1 ]; then - Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 - } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" - else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" fi fi LE_PYTHON="$prev_le_python" elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/arch-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/manjaro-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/gentoo-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq FreeBSD ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq Darwin ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then - Bootstrap() { - ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 else DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 fi # We handle this case after determining the normal bootstrap version to allow @@ -1125,7 +1117,9 @@ if [ "$1" = "--le-auto-phase2" ]; then fi if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then - error "Certbot will no longer receive updates." + error "certbot-auto and its Certbot installation will no longer receive updates." + error "You will not receive any bug fixes including those fixing server compatibility" + error "or security problems." error "Please visit https://certbot.eff.org/ to check for other alternatives." "$VENV_BIN/letsencrypt" "$@" exit 0 @@ -1493,18 +1487,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.10.1 \ - --hash=sha256:011ac980fa21b9f29e02c9b8d8b86e8a4bf4670b51b6ad91656e401e9d2d2231 \ - --hash=sha256:0d9ee3fc09e0d03b2d1b1f1c4916e61ecfc6904b4216ddef4e6a5ca1424d9cb7 -acme==1.10.1 \ - --hash=sha256:752d598e54e98ad1e874de53fd50c61044f1b566d6deb790db5676ce9c573546 \ - --hash=sha256:fcbb559aedc96b404edf593e78517dcd7291984d5a37036c3fc77f3c5c122fd8 -certbot-apache==1.10.1 \ - --hash=sha256:f077b4b7f166627ef5e0921fe7cde57700670fc86e9ad9dbdfaf2c573cc0f2fa \ - --hash=sha256:97ed637b4c7b03820db6c69aa90145dc989933351d46a3d62baf6b71674f0a10 -certbot-nginx==1.10.1 \ - --hash=sha256:7c36459021f8a1ec3b6c062e4c4fc866bfaa1dbf26ccd29e043dd6848003be08 \ - --hash=sha256:c0bbeccf85f46b728fd95e6bb8c2649d32d3383d7f47ea4b9c312d12bf04d2f0 +certbot==1.12.0 \ + --hash=sha256:f4bb3da5391e4a28e9a2e52ab54986171c0864feff17eaaaca6729a1d4c433a6 \ + --hash=sha256:5ee738773479bcb7794e43fedd2415acc0969b75bdd2a21f451e3bff9d99df59 +acme==1.12.0 \ + --hash=sha256:ca4ad044429f1b8b670b958e5c7ea38159def9d601f4af2359355993918c3317 \ + --hash=sha256:aa363474d50e9fdda27acb8b1aa7efb26fecc5650e02039a0de3a3f0e696c2f2 +certbot-apache==1.12.0 \ + --hash=sha256:38899f6fa08799de9535795d919acf968f288d7208909baf7733f9a763c15227 \ + --hash=sha256:e5679b40d99bd241f4fcd9fe44b73e6e25ccc969a617131ff6ebc90d562a49f2 +certbot-nginx==1.12.0 \ + --hash=sha256:332cd70067bbcf6db52a002650ffa4844d0bd9780279d662aa6725b43f776c14 \ + --hash=sha256:3fb6a55290d37ad466681a89a85ceca4c4026fdd8702f3010b87a74266a6fe7b UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 546f96305..2d3d93669 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -9,7 +9,7 @@ import shutil import subprocess import time -from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, SECP384R1 +from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, SECP384R1, SECP521R1 from cryptography.x509 import NameOID import pytest @@ -148,6 +148,17 @@ def test_certonly(context): """Test the certonly verb on certbot.""" context.certbot(['certonly', '--cert-name', 'newname', '-d', context.get_domain('newname')]) + assert_cert_count_for_lineage(context.config_dir, 'newname', 1) + + +def test_certonly_webroot(context): + """Test the certonly verb with webroot plugin""" + with misc.create_http_server(context.http_01_port) as webroot: + certname = context.get_domain('webroot') + context.certbot(['certonly', '-a', 'webroot', '--webroot-path', webroot, '-d', certname]) + + assert_cert_count_for_lineage(context.config_dir, certname, 1) + def test_auth_and_install_with_csr(context): """Test certificate issuance and install using an existing CSR.""" @@ -476,6 +487,28 @@ def test_default_curve_type(context): assert_elliptic_key(key1, SECP256R1) +@pytest.mark.parametrize('curve,curve_cls,skip_servers', [ + # Curve name, Curve class, ACME servers to skip + ('secp256r1', SECP256R1, []), + ('secp384r1', SECP384R1, []), + ('secp521r1', SECP521R1, ['boulder-v1', 'boulder-v2'])] +) +def test_ecdsa_curves(context, curve, curve_cls, skip_servers): + """Test issuance for each supported ECDSA curve""" + if context.acme_server in skip_servers: + pytest.skip('ACME server {} does not support ECDSA curve {}' + .format(context.acme_server, curve)) + + domain = context.get_domain('curve') + context.certbot([ + 'certonly', + '--key-type', 'ecdsa', '--elliptic-curve', curve, + '--force-renewal', '-d', domain, + ]) + key = join(context.config_dir, "live", domain, 'privkey.pem') + assert_elliptic_key(key, curve_cls) + + def test_renew_with_ec_keys(context): """Test proper renew with updated private key complexity.""" certname = context.get_domain('renew') diff --git a/certbot-ci/setup.py b/certbot-ci/setup.py index 4d4557939..3277df1c0 100644 --- a/certbot-ci/setup.py +++ b/certbot-ci/setup.py @@ -40,14 +40,12 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-compatibility-test/Dockerfile b/certbot-compatibility-test/Dockerfile index f66e4c945..e0a439d01 100644 --- a/certbot-compatibility-test/Dockerfile +++ b/certbot-compatibility-test/Dockerfile @@ -8,11 +8,11 @@ RUN apt-get update && \ WORKDIR /opt/certbot/src # We copy all contents of the build directory to allow us to easily use -# things like tools/venv3.py which expects all of our packages to be available. +# things like tools/venv.py which expects all of our packages to be available. COPY . . -RUN tools/venv3.py -ENV PATH /opt/certbot/src/venv3/bin:$PATH +RUN tools/venv.py +ENV PATH /opt/certbot/src/venv/bin:$PATH # install in editable mode (-e) to save space: it's not possible to # "rm -rf /opt/certbot/src" (it's stays in the underlaying image); diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index b6fbe2817..2b3f94581 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -2,11 +2,8 @@ import os import shutil import subprocess +from unittest import mock -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore import zope.interface from certbot import errors as le_errors diff --git a/certbot-compatibility-test/certbot_compatibility_test/validator_test.py b/certbot-compatibility-test/certbot_compatibility_test/validator_test.py index 0b1056561..711d1b38e 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/validator_test.py +++ b/certbot-compatibility-test/certbot_compatibility_test/validator_test.py @@ -1,10 +1,7 @@ """Tests for certbot_compatibility_test.validator.""" import unittest +from unittest import mock -try: - import mock -except ImportError: # pragma: no cover - from unittest import mock # type: ignore import OpenSSL import requests diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index c894e5dee..0236773f0 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -1,11 +1,9 @@ -from distutils.version import LooseVersion import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' install_requires = [ 'certbot', @@ -15,15 +13,6 @@ install_requires = [ 'zope.interface', ] -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - if sys.version_info < (2, 7, 9): # For secure SSL connexion with Python 2.7 (InsecurePlatformWarning) install_requires.append('ndg-httpsclient') @@ -38,14 +27,12 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-cloudflare/docs/conf.py b/certbot-dns-cloudflare/docs/conf.py index 21c1d9b72..b80bdbc97 100644 --- a/certbot-dns-cloudflare/docs/conf.py +++ b/certbot-dns-cloudflare/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index a00f06a8a..eab6cdb70 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'cloudflare>=1.5.1', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-cloudxns/docs/conf.py b/certbot-dns-cloudxns/docs/conf.py index de6f554da..5a350b1b1 100644 --- a/certbot-dns-cloudxns/docs/conf.py +++ b/certbot-dns-cloudxns/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 3771c1d34..83513ef7c 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-digitalocean/docs/conf.py b/certbot-dns-digitalocean/docs/conf.py index ab653a2b0..5951e3f98 100644 --- a/certbot-dns-digitalocean/docs/conf.py +++ b/certbot-dns-digitalocean/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index f168ee06a..8c6ac78d5 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -1,19 +1,17 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'python-digitalocean>=1.11', - 'setuptools', - 'six', + 'setuptools>=39.0.1', + 'six>=1.11.0', 'zope.interface', ] @@ -28,15 +26,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -50,7 +39,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -58,8 +47,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-dnsimple/docs/conf.py b/certbot-dns-dnsimple/docs/conf.py index 4c6e6b52e..7f88e6387 100644 --- a/certbot-dns-dnsimple/docs/conf.py +++ b/certbot-dns-dnsimple/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index f23bd6668..f1fcfd11d 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -1,17 +1,15 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -26,15 +24,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - # This package normally depends on dns-lexicon>=3.2.1 to address the # problem described in https://github.com/AnalogJ/lexicon/issues/387, # however, the fix there has been backported to older versions of @@ -60,7 +49,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -68,8 +57,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-dnsmadeeasy/docs/conf.py b/certbot-dns-dnsmadeeasy/docs/conf.py index 1dfc1bd89..efe2f36f4 100644 --- a/certbot-dns-dnsmadeeasy/docs/conf.py +++ b/certbot-dns-dnsmadeeasy/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index e654ed421..185048a2d 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-gehirn/docs/conf.py b/certbot-dns-gehirn/docs/conf.py index 75e3705dd..2cc968fe0 100644 --- a/certbot-dns-gehirn/docs/conf.py +++ b/certbot-dns-gehirn/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index a856f1cde..0ae9c1bf7 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -1,17 +1,15 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'dns-lexicon>=2.1.22', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -26,15 +24,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -48,7 +37,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -56,8 +45,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-google/docs/conf.py b/certbot-dns-google/docs/conf.py index 8c4a800f7..06bb99f46 100644 --- a/certbot-dns-google/docs/conf.py +++ b/certbot-dns-google/docs/conf.py @@ -112,7 +112,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 82c2a9102..b16d014c6 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -1,19 +1,17 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'google-api-python-client>=1.5.5', 'oauth2client>=4.0', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', # already a dependency of google-api-python-client, but added for consistency 'httplib2' @@ -30,15 +28,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -52,7 +41,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -60,8 +49,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-linode/docs/conf.py b/certbot-dns-linode/docs/conf.py index 6305b694c..c916b5097 100644 --- a/certbot-dns-linode/docs/conf.py +++ b/certbot-dns-linode/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index a6f159757..21ccf9d42 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,17 +1,15 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'dns-lexicon>=2.2.3', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -26,15 +24,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -48,7 +37,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -56,8 +45,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-luadns/docs/conf.py b/certbot-dns-luadns/docs/conf.py index 6a11ce7aa..5790a85a7 100644 --- a/certbot-dns-luadns/docs/conf.py +++ b/certbot-dns-luadns/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index ff4a1b41d..2312d6fcc 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-nsone/docs/conf.py b/certbot-dns-nsone/docs/conf.py index 7e66a0613..4bc13fe2b 100644 --- a/certbot-dns-nsone/docs/conf.py +++ b/certbot-dns-nsone/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 887d5120a..658027b9a 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-ovh/docs/conf.py b/certbot-dns-ovh/docs/conf.py index c8a1575c4..18ebccaac 100644 --- a/certbot-dns-ovh/docs/conf.py +++ b/certbot-dns-ovh/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index d519a9e18..b4f73ddb4 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'dns-lexicon>=2.7.14', # Correct proxy use on OVH provider - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py index a3a943660..57e9506f2 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py @@ -1,13 +1,3 @@ -# type: ignore -# pylint: disable=no-member -# Many attributes of dnspython are now dynamically defined which causes both -# mypy and pylint to error about accessing attributes they think do not exist. -# This is the case even in up-to-date versions of mypy and pylint which as of -# writing this are 0.790 and 2.6.0 respectively. This problem may be fixed in -# dnspython 2.1.0. See https://github.com/rthalley/dnspython/issues/598. For -# now, let's disable these checks. This is done at the very top of the file -# like this because "type: ignore" must be the first line in the file to be -# respected by mypy. """DNS Authenticator using RFC 2136 Dynamic Updates.""" import logging diff --git a/certbot-dns-rfc2136/docs/conf.py b/certbot-dns-rfc2136/docs/conf.py index bc0e9c845..782f494f1 100644 --- a/certbot-dns-rfc2136/docs/conf.py +++ b/certbot-dns-rfc2136/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 540fc1a67..ce74611cd 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'dnspython', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,15 +25,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -49,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -57,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-route53/MANIFEST.in b/certbot-dns-route53/MANIFEST.in index fc62028b0..5a661cef6 100644 --- a/certbot-dns-route53/MANIFEST.in +++ b/certbot-dns-route53/MANIFEST.in @@ -1,5 +1,5 @@ include LICENSE.txt -include README +include README.rst recursive-include docs * recursive-include tests * global-exclude __pycache__ diff --git a/certbot-dns-route53/README.md b/certbot-dns-route53/README.md deleted file mode 100644 index 4af66aa00..000000000 --- a/certbot-dns-route53/README.md +++ /dev/null @@ -1,35 +0,0 @@ -## Route53 plugin for Let's Encrypt client - -### Before you start - -It's expected that the root hosted zone for the domain in question already -exists in your account. - -### Setup - -1. Create a virtual environment - -2. Update its pip and setuptools (`VENV/bin/pip install -U setuptools pip`) -to avoid problems with cryptography's dependency on setuptools>=11.3. - -3. Make sure you have libssl-dev and libffi (or your regional equivalents) -installed. You might have to set compiler flags to pick things up (I have to -use `CPPFLAGS=-I/usr/local/opt/openssl/include -LDFLAGS=-L/usr/local/opt/openssl/lib` on my macOS to pick up brew's openssl, -for example). - -4. Install this package. - -### How to use it - -Make sure you have access to AWS's Route53 service, either through IAM roles or -via `.aws/credentials`. Check out -[sample-aws-policy.json](examples/sample-aws-policy.json) for the necessary permissions. - -To generate a certificate: -``` -certbot certonly \ - -n --agree-tos --email DEVOPS@COMPANY.COM \ - --dns-route53 \ - -d MY.DOMAIN.NAME -``` diff --git a/certbot-dns-route53/README.rst b/certbot-dns-route53/README.rst new file mode 100644 index 000000000..cf63762ca --- /dev/null +++ b/certbot-dns-route53/README.rst @@ -0,0 +1 @@ +Amazon Web Services Route 53 DNS Authenticator plugin for Certbot diff --git a/certbot-dns-route53/docs/conf.py b/certbot-dns-route53/docs/conf.py index f9c5fdf74..bb7808d66 100644 --- a/certbot-dns-route53/docs/conf.py +++ b/certbot-dns-route53/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index cffa16367..8def9a702 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,18 +1,16 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'boto3', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -27,14 +25,10 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') +docs_extras = [ + 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags + 'sphinx_rtd_theme', +] setup( name='certbot-dns-route53', @@ -44,7 +38,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -52,8 +46,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', @@ -70,6 +62,9 @@ setup( include_package_data=True, install_requires=install_requires, keywords=['certbot', 'route53', 'aws'], + extras_require={ + 'docs': docs_extras, + }, entry_points={ 'certbot.plugins': [ 'dns-route53 = certbot_dns_route53._internal.dns_route53:Authenticator', diff --git a/certbot-dns-sakuracloud/docs/conf.py b/certbot-dns-sakuracloud/docs/conf.py index 9d6d3c871..b84b97e1d 100644 --- a/certbot-dns-sakuracloud/docs/conf.py +++ b/certbot-dns-sakuracloud/docs/conf.py @@ -111,7 +111,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +#html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 2c88f1226..6f4f8e506 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -1,17 +1,15 @@ -from distutils.version import LooseVersion import os import sys -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'dns-lexicon>=2.1.23', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] @@ -26,15 +24,6 @@ elif 'bdist_wheel' in sys.argv[1:]: if os.environ.get('SNAP_BUILD'): install_requires.append('packaging') -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -48,7 +37,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -56,8 +45,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 0ed164da2..385f4cc17 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,32 +1,19 @@ -from distutils.version import LooseVersion -import sys - -from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.11.0.dev0' +version = '1.13.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=1.4.0', 'certbot>=1.6.0', - 'PyOpenSSL', - 'pyparsing>=1.5.5', # Python3 support - 'setuptools', + 'PyOpenSSL>=17.3.0', + 'pyparsing>=2.2.0', + 'setuptools>=39.0.1', 'zope.interface', ] -setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - setup( name='certbot-nginx', version=version, @@ -35,7 +22,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -43,8 +30,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 4c8de11af..1333d2420 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,7 +2,56 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). -## 1.11.0 - master +## 1.13.0 - master + +### Added + +* + +### Changed + +* Certbot no longer conditionally depends on an external mock module. Certbot's + test API will continue to use it if it is available for backwards + compatibility, however, this behavior has been deprecated and will be removed + in a future release. +* The acme library no longer depends on the `security` extras from `requests` + which was needed to support SNI in TLS requests when using old versions of + Python 2. + +### Fixed + +* + +More details about these changes can be found on our GitHub repo. + +## 1.12.0 - 2021-02-02 + +### Added + +* + +### Changed + +* The `--preferred-chain` flag now only checks the Issuer Common Name of the + topmost (closest to the root) certificate in the chain, instead of checking + every certificate in the chain. + See [#8577](https://github.com/certbot/certbot/issues/8577). +* Support for Python 2 has been removed. +* In previous releases, we caused certbot-auto to stop updating its Certbot + installation. In this release, we are beginning to disable updates to the + certbot-auto script itself. This release includes Amazon Linux users, and all + other systems that are not based on Debian or RHEL. We plan to make this + change to the certbot-auto script for all users in the coming months. + +### Fixed + +* Fixed the apache component on openSUSE Tumbleweed which no longer provides + an apache2ctl symlink and uses apachectl instead. +* Fixed a typo in `certbot/crypto_util.py` causing an error upon attempting `secp521r1` key generation + +More details about these changes can be found on our GitHub repo. + +## 1.11.0 - 2021-01-05 ### Added diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 98009a71b..be06b5803 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,13 +1,3 @@ """Certbot client.""" -import warnings -import sys - # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '1.11.0.dev0' - -if sys.version_info[0] == 2: - warnings.warn( - "Python 2 support will be dropped in the next release of Certbot. " - "Please upgrade your Python version.", - PendingDeprecationWarning, - ) # pragma: no cover +__version__ = '1.13.0.dev0' diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py index 8cfe5ea11..b4619beba 100644 --- a/certbot/certbot/_internal/account.py +++ b/certbot/certbot/_internal/account.py @@ -20,6 +20,7 @@ from certbot import interfaces from certbot import util from certbot._internal import constants from certbot.compat import os +from certbot.compat import filesystem logger = logging.getLogger(__name__) @@ -324,7 +325,7 @@ class AccountFileStorage(interfaces.AccountStorage): if server_path in reused_servers: next_server_path = reused_servers[server_path] next_dir_path = link_func(next_server_path) - if os.path.islink(next_dir_path) and os.readlink(next_dir_path) == dir_path: + if os.path.islink(next_dir_path) and filesystem.readlink(next_dir_path) == dir_path: possible_next_link = True server_path = next_server_path dir_path = next_dir_path @@ -332,7 +333,7 @@ class AccountFileStorage(interfaces.AccountStorage): # if there's not a next one up to delete, then delete me # and whatever I link to while os.path.islink(dir_path): - target = os.readlink(dir_path) + target = filesystem.readlink(dir_path) os.unlink(dir_path) dir_path = target diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index e50cb338a..c69bb3564 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -28,7 +28,8 @@ from certbot._internal.cli.cli_constants import ( ARGPARSE_PARAMS_TO_REMOVE, EXIT_ACTIONS, ZERO_ARG_ACTIONS, - VAR_MODIFIERS + VAR_MODIFIERS, + DEPRECATED_OPTIONS ) from certbot._internal.cli.cli_utils import ( @@ -471,6 +472,11 @@ def set_by_cli(var): (CLI or config file) including if the user explicitly set it to the default. Returns False if the variable was assigned a default value. """ + # We should probably never actually hit this code. But if we do, + # a deprecated option has logically never been set by the CLI. + if var in DEPRECATED_OPTIONS: + return False + detector = set_by_cli.detector # type: ignore if detector is None and helpful_parser is not None: # Setup on first run: `detector` is a weird version of config in which @@ -531,6 +537,9 @@ def option_was_set(option, value): :rtype: bool """ + # If an option is deprecated, it was effectively not set by the user. + if option in DEPRECATED_OPTIONS: + return False return set_by_cli(option) or not has_default_value(option, value) diff --git a/certbot/certbot/_internal/cli/cli_constants.py b/certbot/certbot/_internal/cli/cli_constants.py index 4bc84bfe7..dc199e152 100644 --- a/certbot/certbot/_internal/cli/cli_constants.py +++ b/certbot/certbot/_internal/cli/cli_constants.py @@ -105,3 +105,8 @@ VAR_MODIFIERS = {"account": {"server",}, "renew_hook": {"deploy_hook",}, "server": {"dry_run", "staging",}, "webroot_map": {"webroot_path",}} + +# This is a list of all CLI options that we have ever deprecated. It lets us +# opt out of the default detection, which can interact strangely with option +# deprecation. See https://github.com/certbot/certbot/issues/8540 for more info. +DEPRECATED_OPTIONS = {"manual_public_ip_logging_ok",} diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index e96868b65..87b7eddec 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -5,7 +5,6 @@ from __future__ import print_function import functools import logging.handlers import sys -import warnings import configobj import josepy as jose @@ -691,7 +690,7 @@ def unregister(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -731,7 +730,7 @@ def register(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` or a string indicating and error :rtype: None or str @@ -761,7 +760,7 @@ def update_account(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` or a string indicating and error :rtype: None or str @@ -838,7 +837,7 @@ def install(config, plugins): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -921,7 +920,7 @@ def plugins_cmd(config, plugins): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -960,7 +959,7 @@ def enhance(config, plugins): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1019,7 +1018,7 @@ def rollback(config, plugins): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1037,7 +1036,7 @@ def update_symlinks(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1055,7 +1054,7 @@ def rename(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1073,7 +1072,7 @@ def delete(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1089,7 +1088,7 @@ def certificates(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1106,7 +1105,7 @@ def revoke(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` or string indicating error in case of error :rtype: None or str @@ -1151,7 +1150,7 @@ def run(config, plugins): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1248,7 +1247,7 @@ def renew_cert(config, plugins, lineage): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :param lineage: Certificate lineage object :type lineage: storage.RenewableCert @@ -1293,7 +1292,7 @@ def certonly(config, plugins): :type config: interfaces.IConfig :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1343,7 +1342,7 @@ def renew(config, unused_plugins): :type config: interfaces.IConfig :param unused_plugins: List of plugins (deprecated) - :type unused_plugins: `list` of `str` + :type unused_plugins: plugins_disco.PluginsRegistry :returns: `None` :rtype: None @@ -1439,13 +1438,6 @@ def main(cli_args=None): if config.func != plugins_cmd: # pylint: disable=comparison-with-callable raise - if sys.version_info[0] == 2: - warnings.warn( - "Python 2 support will be dropped in the next release of Certbot. " - "Please upgrade your Python version.", - PendingDeprecationWarning, - ) # pragma: no cover - set_displayer(config) # Reporter diff --git a/certbot/certbot/_internal/plugins/webroot.py b/certbot/certbot/_internal/plugins/webroot.py index 484d209d6..88e02998d 100644 --- a/certbot/certbot/_internal/plugins/webroot.py +++ b/certbot/certbot/_internal/plugins/webroot.py @@ -157,7 +157,8 @@ to serve all files under specified web root ({0}).""" "--webroot-path and --domains, or --webroot-map. Run with " " --help webroot for examples.") for name, path in path_map.items(): - self.full_roots[name] = os.path.join(path, challenges.HTTP01.URI_ROOT_PATH) + self.full_roots[name] = os.path.join(path, os.path.normcase( + challenges.HTTP01.URI_ROOT_PATH)) logger.debug("Creating root challenges validation dir at %s", self.full_roots[name]) diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py index 3a550d355..f4c7b4502 100644 --- a/certbot/certbot/_internal/renewal.py +++ b/certbot/certbot/_internal/renewal.py @@ -85,6 +85,7 @@ def _reconstitute(config, full_path): return None # Now restore specific values along with their data types, if # those elements are present. + renewalparams = _remove_deprecated_config_elements(renewalparams) try: restore_required_config_elements(config, renewalparams) _restore_plugin_configs(config, renewalparams) @@ -188,6 +189,19 @@ def restore_required_config_elements(config, renewalparams): setattr(config, item_name, value) +def _remove_deprecated_config_elements(renewalparams): + """Removes deprecated config options from the parsed renewalparams. + + :param dict renewalparams: list of parsed renewalparams + + :returns: list of renewalparams with deprecated config options removed + :rtype: dict + + """ + return {option_name: v for (option_name, v) in renewalparams.items() + if option_name not in cli.DEPRECATED_OPTIONS} + + def _restore_pref_challs(unused_name, value): """Restores preferred challenges from a renewal config file. diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index a7f319197..ff58313e5 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -214,7 +214,7 @@ def get_link_target(link): """ try: - target = os.readlink(link) + target = filesystem.readlink(link) except OSError: raise errors.CertStorageError( "Expected {0} to be a symlink".format(link)) @@ -223,6 +223,7 @@ def get_link_target(link): target = os.path.join(os.path.dirname(link), target) return os.path.abspath(target) + def _write_live_readme_to(readme_path, is_base_dir=False): prefix = "" if is_base_dir: @@ -665,7 +666,7 @@ class RenewableCert(interfaces.RenewableCert): current_link = getattr(self, kind) if os.path.lexists(current_link): os.unlink(current_link) - os.symlink(os.readlink(previous_link), current_link) + os.symlink(filesystem.readlink(previous_link), current_link) for _, link in previous_symlinks: if os.path.exists(link): @@ -846,7 +847,7 @@ class RenewableCert(interfaces.RenewableCert): link = getattr(self, kind) filename = "{0}{1}.pem".format(kind, version) # Relative rather than absolute target directory - target_directory = os.path.dirname(os.readlink(link)) + target_directory = os.path.dirname(filesystem.readlink(link)) # TODO: it could be safer to make the link first under a temporary # filename, then unlink the old link, then rename the new link # to the old link; this ensures that this process is able to @@ -1121,7 +1122,7 @@ class RenewableCert(interfaces.RenewableCert): # The behavior below keeps the prior key by creating a new # symlink to the old key or the target of the old key symlink. if os.path.islink(old_privkey): - old_privkey = os.readlink(old_privkey) + old_privkey = filesystem.readlink(old_privkey) else: old_privkey = "privkey{0}.pem".format(prior_version) logger.debug("Writing symlink to old private key, %s.", old_privkey) diff --git a/certbot/certbot/_internal/updater.py b/certbot/certbot/_internal/updater.py index 961436ca5..23ba06da3 100644 --- a/certbot/certbot/_internal/updater.py +++ b/certbot/certbot/_internal/updater.py @@ -18,7 +18,7 @@ def run_generic_updaters(config, lineage, plugins): :type lineage: storage.RenewableCert :param plugins: List of plugins - :type plugins: `list` of `str` + :type plugins: certbot._internal.plugins.disco.PluginsRegistry :returns: `None` :rtype: None diff --git a/certbot/certbot/achallenges.py b/certbot/certbot/achallenges.py index 70588683d..7171c271c 100644 --- a/certbot/certbot/achallenges.py +++ b/certbot/certbot/achallenges.py @@ -33,7 +33,7 @@ class AnnotatedChallenge(jose.ImmutableMap): Wraps around server provided challenge and annotates with data useful for the client. - :ivar challb: Wrapped `~.ChallengeBody`. + :ivar ~.challb: Wrapped `~.ChallengeBody`. """ __slots__ = ('challb',) diff --git a/certbot/certbot/compat/filesystem.py b/certbot/certbot/compat/filesystem.py index 0c8a7514b..0152685e9 100644 --- a/certbot/certbot/compat/filesystem.py +++ b/certbot/certbot/compat/filesystem.py @@ -4,6 +4,7 @@ from __future__ import absolute_import import errno import os # pylint: disable=os-module-forbidden import stat +import sys from acme.magic_typing import List @@ -361,7 +362,8 @@ def realpath(file_path): """ original_path = file_path - if POSIX_MODE: + # Since Python 3.8, os.path.realpath also resolves symlinks on Windows. + if POSIX_MODE or sys.version_info >= (3, 8): path = os.path.realpath(file_path) if os.path.islink(path): # If path returned by realpath is still a link, it means that it failed to @@ -383,8 +385,36 @@ def realpath(file_path): return os.path.abspath(file_path) +def readlink(link_path): + # type: (str) -> str + """ + Return a string representing the path to which the symbolic link points. + + :param str link_path: The symlink path to resolve + :return: The path the symlink points to + :returns: str + :raise: ValueError if a long path (260> characters) is encountered on Windows + """ + path = os.readlink(link_path) + + if POSIX_MODE or not path.startswith('\\\\?\\'): + return path + + # At this point, we know we are on Windows and that the path returned uses + # the extended form which is done for all paths in Python 3.8+ + + # Max length of a normal path is 260 characters on Windows, including the non printable + # termination character "". The termination character is not included in Python + # strings, giving a max length of 259 characters, + 4 characters for the extended form + # prefix, to an effective max length 263 characters on a string representing a normal path. + if len(path) < 264: + return path[4:] + + raise ValueError("Long paths are not supported by Certbot on Windows.") + + # On Windows is_executable run from an unprivileged shell may claim that a path is -# executable when it is excutable only if run from a privileged shell. This result +# executable when it is executable only if run from a privileged shell. This result # is due to the fact that GetEffectiveRightsFromAcl calculate effective rights # without taking into consideration if the target user has currently required the # elevated privileges or not. However this is not a problem since certbot always diff --git a/certbot/certbot/compat/os.py b/certbot/certbot/compat/os.py index b4aea054f..2f0899bd7 100644 --- a/certbot/certbot/compat/os.py +++ b/certbot/certbot/compat/os.py @@ -7,6 +7,10 @@ This module has the same API as the os module in the Python standard library except for the functions defined below. """ + +# NOTE: If adding a new documented function to compat.os, ensure that it is added to the +# ':members:' list in certbot/docs/api/certbot.compat.os.rst. + # isort:skip_file # pylint: disable=function-redefined from __future__ import absolute_import @@ -152,3 +156,14 @@ def fstat(*unused_args, **unused_kwargs): raise RuntimeError('Usage of os.fstat() is forbidden. ' 'Use certbot.compat.filesystem functions instead ' '(eg. has_min_permissions, has_same_ownership).') + + +# Method os.readlink has a significant behavior change with Python 3.8+. Starting +# with this version, it will return the resolved path in its "extended-style" form +# unconditionally, which allows to use more than 259 characters, and its string +# representation is prepended with "\\?\". Problem is that it does it for any path, +# and will make equality comparison fail with paths that will use the simple form. +def readlink(*unused_args, **unused_kwargs): + """Method os.readlink() is forbidden""" + raise RuntimeError('Usage of os.readlink() is forbidden. ' + 'Use certbot.compat.filesystem.realpath() instead.') diff --git a/certbot/certbot/crypto_util.py b/certbot/certbot/crypto_util.py index 2f3622d94..6feb6e4b9 100644 --- a/certbot/certbot/crypto_util.py +++ b/certbot/certbot/crypto_util.py @@ -205,7 +205,7 @@ def make_key(bits=1024, key_type="rsa", elliptic_curve=None): elif key_type == 'ecdsa': try: name = elliptic_curve.upper() - if name in ('SECP256R1', 'SECP384R1', 'SECP512R1'): + if name in ('SECP256R1', 'SECP384R1', 'SECP521R1'): _key = ec.generate_private_key( curve=getattr(ec, elliptic_curve.upper(), None)(), backend=default_backend() @@ -291,7 +291,7 @@ def verify_signed_payload(public_key, signature, payload, signature_hash_algorit :param RSAPublicKey/EllipticCurvePublicKey public_key: the public_key to check signature :param bytes signature: the signature bytes :param bytes payload: the payload bytes - :param cryptography.hazmat.primitives.hashes.HashAlgorithm + :param cryptography.hazmat.primitives.hashes.HashAlgorithm \ signature_hash_algorithm: algorithm used to hash the payload :raises InvalidSignature: If signature verification fails. @@ -586,8 +586,9 @@ def get_serial_from_cert(cert_path): def find_chain_with_issuer(fullchains, issuer_cn, warn_on_no_match=False): - """Chooses the first certificate chain from fullchains which contains an - Issuer Subject Common Name matching issuer_cn. + """Chooses the first certificate chain from fullchains whose topmost + intermediate has an Issuer Common Name matching issuer_cn (in other words + the first chain which chains to a root whose name matches issuer_cn). :param fullchains: The list of fullchains in PEM chain format. :type fullchains: `list` of `str` @@ -598,14 +599,11 @@ def find_chain_with_issuer(fullchains, issuer_cn, warn_on_no_match=False): :rtype: `str` """ for chain in fullchains: - certs = [x509.load_pem_x509_certificate(cert, default_backend()) \ - for cert in CERT_PEM_REGEX.findall(chain.encode())] - # Iterate the fullchain beginning from the leaf. For each certificate encountered, - # match against Issuer Subject CN. - for cert in certs: - cert_issuer_cn = cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME) - if cert_issuer_cn and cert_issuer_cn[0].value == issuer_cn: - return chain + certs = CERT_PEM_REGEX.findall(chain.encode()) + top_cert = x509.load_pem_x509_certificate(certs[-1], default_backend()) + top_issuer_cn = top_cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME) + if top_issuer_cn and top_issuer_cn[0].value == issuer_cn: + return chain # Nothing matched, return whatever was first in the list. if warn_on_no_match: diff --git a/certbot/certbot/interfaces.py b/certbot/certbot/interfaces.py index 6ba28bd56..28c6f2ac1 100644 --- a/certbot/certbot/interfaces.py +++ b/certbot/certbot/interfaces.py @@ -262,9 +262,9 @@ class IConfig(zope.interface.Interface): " with \"renew\" verb should be disabled.") preferred_chain = zope.interface.Attribute( - "If the CA offers multiple certificate chains, prefer the chain with " - "an issuer matching this Subject Common Name. If no match, the default " - "offered chain will be used." + "If the CA offers multiple certificate chains, prefer the chain whose " + "topmost certificate was issued from this Subject Common Name. " + "If no match, the default offered chain will be used." ) diff --git a/certbot/certbot/plugins/util.py b/certbot/certbot/plugins/util.py index 87eb45fe9..04a741da6 100644 --- a/certbot/certbot/plugins/util.py +++ b/certbot/certbot/plugins/util.py @@ -10,9 +10,11 @@ logger = logging.getLogger(__name__) def get_prefixes(path): """Retrieves all possible path prefixes of a path, in descending order - of length. For instance, - (linux) /a/b/c returns ['/a/b/c', '/a/b', '/a', '/'] - (windows) C:\\a\\b\\c returns ['C:\\a\\b\\c', 'C:\\a\\b', 'C:\\a', 'C:'] + of length. For instance: + + * (Linux) `/a/b/c` returns `['/a/b/c', '/a/b', '/a', '/']` + * (Windows) `C:\\a\\b\\c` returns `['C:\\a\\b\\c', 'C:\\a\\b', 'C:\\a', 'C:']` + :param str path: the path to break into prefixes :returns: all possible path prefixes of given path in descending order diff --git a/certbot/certbot/tests/testdata/sample-renewal-deprecated-option.conf b/certbot/certbot/tests/testdata/sample-renewal-deprecated-option.conf new file mode 100644 index 000000000..2b777d3de --- /dev/null +++ b/certbot/certbot/tests/testdata/sample-renewal-deprecated-option.conf @@ -0,0 +1,14 @@ +# renew_before_expiry = 30 days +version = 1.11.0 +archive_dir = MAGICDIR/live/sample-renewal-deprecated-option +cert = MAGICDIR/live/sample-renewal-deprecated-option/cert.pem +privkey = MAGICDIR/live/sample-renewal-deprecated-option/privkey.pem +chain = MAGICDIR/live/sample-renewal-deprecated-option/chain.pem +fullchain = MAGICDIR/live/sample-renewal-deprecated-option/fullchain.pem + +# Options used in the renewal process +[renewalparams] +account = ffffffffffffffffffffffffffffffff +authenticator = nginx +installer = nginx +manual_public_ip_logging_ok = None diff --git a/certbot/certbot/tests/util.py b/certbot/certbot/tests/util.py index b9d5caa08..acb31819f 100644 --- a/certbot/certbot/tests/util.py +++ b/certbot/certbot/tests/util.py @@ -6,12 +6,19 @@ import shutil import sys import tempfile import unittest +import warnings from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization import josepy as jose try: import mock + warnings.warn( + "The external mock module is being used for backwards compatibility " + "since it is available, however, future versions of Certbot's tests will " + "use unittest.mock. Be sure to update your code accordingly.", + PendingDeprecationWarning + ) except ImportError: # pragma: no cover from unittest import mock # type: ignore import OpenSSL diff --git a/certbot/docs/api/certbot.compat.os.rst b/certbot/docs/api/certbot.compat.os.rst index 3a4c9fe47..c46cee668 100644 --- a/certbot/docs/api/certbot.compat.os.rst +++ b/certbot/docs/api/certbot.compat.os.rst @@ -2,6 +2,4 @@ certbot.compat.os module ======================== .. automodule:: certbot.compat.os - :members: - :undoc-members: - :show-inheritance: + :members: chmod, umask, chown, open, mkdir, makedirs, rename, replace, access, stat, fstat diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt index a320b30e8..4482ea439 100644 --- a/certbot/docs/cli-help.txt +++ b/certbot/docs/cli-help.txt @@ -99,9 +99,9 @@ optional arguments: before submitting to CA (default: False) --preferred-chain PREFERRED_CHAIN If the CA offers multiple certificate chains, prefer - the chain with an issuer matching this Subject Common - Name. If no match, the default offered chain will be - used. (default: None) + the chain whose topmost certificate was issued from + this Subject Common Name. If no match, the default + offered chain will be used. (default: None) --preferred-challenges PREF_CHALLS A sorted, comma delimited list of the preferred challenge to use during authorization with the most @@ -118,7 +118,7 @@ optional arguments: case, and to know when to deprecate support for past Python versions and flags. If you wish to hide this information from the Let's Encrypt server, set this to - "". (default: CertbotACMEClient/1.10.1 + "". (default: CertbotACMEClient/1.12.0 (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the @@ -539,8 +539,8 @@ dns-cloudxns: CloudXNS credentials INI file. (default: None) dns-digitalocean: - Obtain certs using a DNS TXT record (if you are using DigitalOcean for - DNS). + Obtain certificates using a DNS TXT record (if you are using DigitalOcean + for DNS). --dns-digitalocean-propagation-seconds DNS_DIGITALOCEAN_PROPAGATION_SECONDS The number of seconds to wait for DNS to propagate @@ -601,7 +601,8 @@ dns-google: therequired permissions.) (default: None) dns-linode: - Obtain certs using a DNS TXT record (if you are using Linode for DNS). + Obtain certificates using a DNS TXT record (if you are using Linode for + DNS). --dns-linode-propagation-seconds DNS_LINODE_PROPAGATION_SECONDS The number of seconds to wait for DNS to propagate diff --git a/certbot/docs/conf.py b/certbot/docs/conf.py index dbd4067d5..52820b69d 100644 --- a/certbot/docs/conf.py +++ b/certbot/docs/conf.py @@ -95,7 +95,12 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = [ + '_build', + 'man', + 'challenges.rst', + 'ciphers.rst' +] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/certbot/docs/contributing.rst b/certbot/docs/contributing.rst index e130f0548..def2c7fcd 100644 --- a/certbot/docs/contributing.rst +++ b/certbot/docs/contributing.rst @@ -56,18 +56,18 @@ Set up the Python virtual environment that will host your Certbot local instance .. code-block:: shell cd certbot - python tools/venv3.py + python tools/venv.py .. note:: You may need to repeat this when Certbot's dependencies change or when a new plugin is introduced. You can now run the copy of Certbot from git either by executing -``venv3/bin/certbot``, or by activating the virtual environment. You can do the +``venv/bin/certbot``, or by activating the virtual environment. You can do the latter by running: .. code-block:: shell - source venv3/bin/activate + source venv/bin/activate After running this command, ``certbot`` and development tools like ``ipdb``, ``ipython``, ``pytest``, and ``tox`` are available in the shell where you ran @@ -169,7 +169,7 @@ To do so you need: - Docker installed, and a user with access to the Docker client, - an available `local copy`_ of Certbot. -The virtual environment set up with `python tools/venv3.py` contains two CLI tools +The virtual environment set up with `python tools/venv.py` contains two CLI tools that can be used once the virtual environment is activated: .. code-block:: shell @@ -197,8 +197,8 @@ using an HTTP-01 challenge on a machine with Python 3: .. code-block:: shell - python tools/venv3.py - source venv3/bin/activate + python tools/venv.py + source venv/bin/activate run_acme_server & certbot_test certonly --standalone -d test.example.com # To stop Pebble, launch `fg` to get back the background job, then press CTRL+C @@ -470,11 +470,8 @@ Mypy type annotations ===================== Certbot uses the `mypy`_ static type checker. Python 3 natively supports official type annotations, -which can then be tested for consistency using mypy. Python 2 doesn’t, but type annotations can -be `added in comments`_. Mypy does some type checks even without type annotations; we can find -bugs in Certbot even without a fully annotated codebase. - -Certbot supports both Python 2 and 3, so we’re using Python 2-style annotations. +which can then be tested for consistency using mypy. Mypy does some type checks even without type +annotations; we can find bugs in Certbot even without a fully annotated codebase. Zulip wrote a `great guide`_ to using mypy. It’s useful, but you don’t have to read the whole thing to start contributing to Certbot. diff --git a/certbot/docs/install.rst b/certbot/docs/install.rst index c2d79dc33..4366080e0 100644 --- a/certbot/docs/install.rst +++ b/certbot/docs/install.rst @@ -28,7 +28,7 @@ your system. System Requirements =================== -Certbot currently requires Python 2.7 or 3.6+ running on a UNIX-like operating +Certbot currently requires Python 3.6+ running on a UNIX-like operating system. By default, it requires root access in order to write to ``/etc/letsencrypt``, ``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to port 80 (if you use the ``standalone`` plugin) and to read and @@ -197,12 +197,12 @@ Optionally to install the Certbot Apache plugin, you can use: .. code-block:: shell - sudo dnf install certbot python2-certbot-apache + sudo dnf install certbot python3-certbot-apache **FreeBSD** * Port: ``cd /usr/ports/security/py-certbot && make install clean`` - * Package: ``pkg install py27-certbot`` + * Package: ``pkg install py37-certbot`` **Gentoo** @@ -223,7 +223,7 @@ They need to be installed separately if you require their functionality. **NetBSD** * Build from source: ``cd /usr/pkgsrc/security/py-certbot && make install clean`` - * Install pre-compiled package: ``pkg_add py27-certbot`` + * Install pre-compiled package: ``pkg_add py37-certbot`` **OpenBSD** @@ -240,6 +240,11 @@ look at the :doc:`packaging`. Certbot-Auto ------------ +.. toctree:: + :hidden: + + uninstall + We used to have a shell script named ``certbot-auto`` to help people install Certbot on UNIX operating systems, however, this script is no longer supported. diff --git a/certbot/examples/cli.ini b/certbot/examples/cli.ini index dfb1d6fff..8471558ee 100644 --- a/certbot/examples/cli.ini +++ b/certbot/examples/cli.ini @@ -24,3 +24,11 @@ rsa-key-size = 4096 # path to the public_html / webroot folder being served by your web server. # authenticator = webroot # webroot-path = /usr/share/nginx/html + +# Uncomment to automatically agree to the terms of service of the ACME server +# agree-tos = true + +# An example of using an alternate ACME server that uses EAB credentials +# server = https://acme.sectigo.com/v2/InCommonRSAOV +# eab-kid = somestringofstuffwithoutquotes +# eab-hmac-key = yaddayaddahexhexnotquoted diff --git a/certbot/setup.py b/certbot/setup.py index ea87d2301..4ea98e574 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -40,16 +40,16 @@ install_requires = [ # saying so here causes a runtime error against our temporary fork of 0.9.3 # in which we added 2.6 support (see #2243), so we relax the requirement. 'ConfigArgParse>=0.9.3', - 'configobj', - 'cryptography>=1.2.3', # load_pem_x509_certificate + 'configobj>=5.0.6', + 'cryptography>=2.1.4', 'distro>=1.0.1', # 1.1.0+ is required to avoid the warnings described at # https://github.com/certbot/josepy/issues/13. 'josepy>=1.1.0', - 'parsedatetime>=1.3', # Calendar.parseDT + 'parsedatetime>=2.4', 'pyrfc3339', 'pytz', - 'setuptools', + 'setuptools>=39.0.1', 'zope.component', 'zope.interface', ] @@ -59,7 +59,7 @@ install_requires = [ # However environment markers are supported only with setuptools >= 36.2. # So this dependency is not added for old Linux distributions with old setuptools, # in order to allow these systems to build certbot from sources. -pywin32_req = 'pywin32>=227' # do not forget to edit pywin32 dependency accordingly in windows-installer/construct.py +pywin32_req = 'pywin32>=300' # do not forget to edit pywin32 dependency accordingly in windows-installer/construct.py setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) if setuptools_known_environment_markers: install_requires.append(pywin32_req + " ; sys_platform == 'win32'") @@ -72,16 +72,14 @@ elif os.name == 'nt': # setuptools, pywin32 will not be specified as a dependency. install_requires.append(pywin32_req) -if setuptools_known_environment_markers: - install_requires.append('mock ; python_version < "3.3"') -elif 'bdist_wheel' in sys.argv[1:]: - raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' - 'of setuptools. Version 36.2+ of setuptools is required.') -elif sys.version_info < (3,3): - install_requires.append('mock') - dev_extras = [ + 'astroid', + 'azure-devops', 'coverage', + 'ipdb', + 'mypy', + 'PyGithub', + 'pylint', 'pytest', 'pytest-cov', 'pytest-xdist', @@ -90,15 +88,6 @@ dev_extras = [ 'wheel', ] -dev3_extras = [ - 'astroid', - 'azure-devops', - 'ipdb', - 'mypy', - 'PyGithub', - 'pylint', -] - docs_extras = [ # If you have Sphinx<1.5.1, you need docutils<0.13.1 # https://github.com/sphinx-doc/sphinx/issues/3212 @@ -116,7 +105,7 @@ setup( author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', @@ -125,8 +114,6 @@ setup( 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', @@ -146,7 +133,6 @@ setup( install_requires=install_requires, extras_require={ 'dev': dev_extras, - 'dev3': dev3_extras, 'docs': docs_extras, }, diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index 7158827dc..f9c218cd3 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -113,11 +113,16 @@ class AccountFileStorageTest(test_util.ConfigTestCase): from certbot._internal.account import Account new_authzr_uri = "hi" + meta = Account.Meta( + creation_host="test.example.org", + creation_dt=datetime.datetime( + 2021, 1, 5, 14, 4, 10, tzinfo=pytz.UTC)) self.acc = Account( regr=messages.RegistrationResource( uri=None, body=messages.Registration(), new_authzr_uri=new_authzr_uri), - key=KEY) + key=KEY, + meta=meta) self.mock_client = mock.MagicMock() self.mock_client.directory.new_authz = new_authzr_uri diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index a551e4400..b26c1f624 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -99,7 +99,7 @@ class UpdateLiveSymlinksTest(BaseCertManagerTest): for kind in ALL_FOUR: os.chdir(os.path.dirname(self.config_files[domain][kind])) self.assertEqual( - filesystem.realpath(os.readlink(self.config_files[domain][kind])), + filesystem.realpath(filesystem.readlink(self.config_files[domain][kind])), filesystem.realpath(archive_paths[domain][kind])) finally: os.chdir(prev_dir) diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index 263029cb0..ea48c9d1c 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -597,6 +597,32 @@ class IsExecutableTest(test_util.TempDirTestCase): self.assertFalse(filesystem.is_executable("exe")) +class ReadlinkTest(unittest.TestCase): + @unittest.skipUnless(POSIX_MODE, reason='Tests specific to Linux') + @mock.patch("certbot.compat.filesystem.os.readlink") + def test_path_posix(self, mock_readlink): + mock_readlink.return_value = "/normal/path" + self.assertEqual(filesystem.readlink("dummy"), "/normal/path") + + @unittest.skipIf(POSIX_MODE, reason='Tests specific to Windows') + @mock.patch("certbot.compat.filesystem.os.readlink") + def test_normal_path_windows(self, mock_readlink): + # Python <3.8 + mock_readlink.return_value = "C:\\short\\path" + self.assertEqual(filesystem.readlink("dummy"), "C:\\short\\path") + + # Python >=3.8 (os.readlink always returns the extended form) + mock_readlink.return_value = "\\\\?\\C:\\short\\path" + self.assertEqual(filesystem.readlink("dummy"), "C:\\short\\path") + + @unittest.skipIf(POSIX_MODE, reason='Tests specific to Windows') + @mock.patch("certbot.compat.filesystem.os.readlink") + def test_extended_path_windows(self, mock_readlink): + # Following path is largely over the 260 characters permitted in the normal form. + mock_readlink.return_value = "\\\\?\\C:\\long" + 1000 * "\\path" + with self.assertRaises(ValueError): + filesystem.readlink("dummy") + @contextlib.contextmanager def _fix_windows_runtime(): if os.name != 'nt': diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index 8f428b271..7ff7bbeb9 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -184,11 +184,13 @@ class MakeKeyTest(unittest.TestCase): def test_ec(self): # pylint: disable=no-self-use # ECDSA Key Type Tests from certbot.crypto_util import make_key - # Do not test larger keys as it takes too long. - # Try a good key size for ECDSA - OpenSSL.crypto.load_privatekey( - OpenSSL.crypto.FILETYPE_PEM, make_key(elliptic_curve="secp256r1", key_type='ecdsa')) + for (name, bits) in [('secp256r1', 256), ('secp384r1', 384), ('secp521r1', 521)]: + pkey = OpenSSL.crypto.load_privatekey( + OpenSSL.crypto.FILETYPE_PEM, + make_key(elliptic_curve=name, key_type='ecdsa') + ) + self.assertEqual(pkey.bits(), bits) def test_bad_key_sizes(self): from certbot.crypto_util import make_key @@ -502,6 +504,19 @@ class FindChainWithIssuerTest(unittest.TestCase): matched = self._call(fullchains, "Pebble Root CA 0cc6f0") self.assertEqual(matched, fullchains[1]) + @mock.patch('certbot.crypto_util.logger.info') + def test_intermediate_match(self, mock_info): + """Don't pick a chain where only an intermediate matches""" + fullchains = self._all_fullchains() + # Make the second chain actually only contain "Pebble Root CA 0cc6f0" + # as an intermediate, not as the root. This wouldn't be a valid chain + # (the CERT_ISSUER cert didn't issue the CERT_ALT_ISSUER cert), but the + # function under test here doesn't care about that. + fullchains[1] = fullchains[1] + CERT_ISSUER.decode() + matched = self._call(fullchains, "Pebble Root CA 0cc6f0") + self.assertEqual(matched, fullchains[0]) + mock_info.assert_not_called() + @mock.patch('certbot.crypto_util.logger.info') def test_no_match(self, mock_info): fullchains = self._all_fullchains() diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index c50bc6be1..6fc762cc7 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -814,8 +814,10 @@ class MainTest(test_util.ConfigTestCase): self._call_no_clientmock(['delete']) self.assertEqual(1, mock_cert_manager.call_count) + @mock.patch('certbot._internal.main.plugins_disco') + @mock.patch('certbot._internal.main.cli.HelpfulArgumentParser.determine_help_topics') @mock.patch('certbot._internal.log.post_arg_parse_setup') - def test_plugins(self, _): + def test_plugins(self, _, _det, mock_disco): flags = ['--init', '--prepare', '--authenticators', '--installers'] for args in itertools.chain( *(itertools.combinations(flags, r) diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index 4af8c6e7f..7c9c53fb4 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -1,4 +1,6 @@ """Tests for certbot._internal.renewal""" +import copy + import unittest try: @@ -98,6 +100,23 @@ class RenewalTest(test_util.ConfigTestCase): assert self.config.elliptic_curve == 'secp256r1' + @test_util.patch_get_utility() + @mock.patch('certbot._internal.renewal.cli.set_by_cli') + def test_remove_deprecated_config_elements(self, mock_set_by_cli, unused_mock_get_utility): + mock_set_by_cli.return_value = False + config = configuration.NamespaceConfig(self.config) + config.certname = "sample-renewal-deprecated-option" + + rc_path = test_util.make_lineage( + self.config.config_dir, 'sample-renewal-deprecated-option.conf') + + from certbot._internal import renewal + lineage_config = copy.deepcopy(self.config) + renewal_candidate = renewal._reconstitute(lineage_config, rc_path) + # This means that manual_public_ip_logging_ok was not modified in the config based on its + # value in the renewal conf file + self.assertTrue(isinstance(lineage_config.manual_public_ip_logging_ok, mock.MagicMock)) + class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): """Tests for certbot._internal.renewal.restore_required_config_elements.""" diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index b67c4cbce..914304cd4 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -77,6 +77,17 @@ class RelevantValuesTest(unittest.TestCase): self.assertEqual(self._call(self.values), expected_relevant_values) + @mock.patch("certbot._internal.cli.set_by_cli") + def test_deprecated_item(self, unused_mock_set_by_cli): + # deprecated items should never be relevant to store + expected_relevant_values = self.values.copy() + self.values["manual_public_ip_logging_ok"] = None + self.assertEqual(self._call(self.values), expected_relevant_values) + self.values["manual_public_ip_logging_ok"] = True + self.assertEqual(self._call(self.values), expected_relevant_values) + self.values["manual_public_ip_logging_ok"] = False + self.assertEqual(self._call(self.values), expected_relevant_values) + class BaseRenewableCertTest(test_util.ConfigTestCase): """Base class for setting up Renewable Cert tests. @@ -330,7 +341,7 @@ class RenewableCertTests(BaseRenewableCertTest): self.test_rc._update_link_to("chain", 3000) # However, current_version doesn't allow querying the resulting # version (because it's a broken link). - self.assertEqual(os.path.basename(os.readlink(self.test_rc.chain)), + self.assertEqual(os.path.basename(filesystem.readlink(self.test_rc.chain)), "chain3000.pem") def test_version(self): @@ -514,7 +525,7 @@ class RenewableCertTests(BaseRenewableCertTest): # privkey. for i in (6, 7, 8): self.assertTrue(os.path.islink(self.test_rc.version("privkey", i))) - self.assertEqual("privkey3.pem", os.path.basename(os.readlink( + self.assertEqual("privkey3.pem", os.path.basename(filesystem.readlink( self.test_rc.version("privkey", i)))) for kind in ALL_FOUR: diff --git a/letsencrypt-auto b/letsencrypt-auto index ee12d4706..002fd5ffc 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.10.1" +LE_AUTO_VERSION="1.12.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -803,7 +803,9 @@ if [ -f /etc/debian_version ]; then elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/redhat-release ]; then + DEPRECATED_OS=1 # Run DeterminePythonVersion to decide on the basis of available Python versions # whether to use 2.x or 3.x on RedHat-like systems. # Then, revert LE_PYTHON to its previous state. @@ -836,12 +838,7 @@ elif [ -f /etc/redhat-release ]; then INTERACTIVE_BOOTSTRAP=1 fi - Bootstrap() { - BootstrapMessage "Legacy RedHat-based OSes that will use Python3" - BootstrapRpmPython3Legacy - } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3Legacy $BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION" # Try now to enable SCL rh-python36 for systems already bootstrapped # NB: EnablePython36SCL has been defined along with BootstrapRpmPython3Legacy in certbot-auto @@ -860,43 +857,38 @@ elif [ -f /etc/redhat-release ]; then fi if [ "$RPM_USE_PYTHON_3" = 1 ]; then - Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 - } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" - else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" fi fi LE_PYTHON="$prev_le_python" elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/arch-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/manjaro-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/gentoo-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq FreeBSD ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq Darwin ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then - Bootstrap() { - ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 else DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 fi # We handle this case after determining the normal bootstrap version to allow @@ -1125,7 +1117,9 @@ if [ "$1" = "--le-auto-phase2" ]; then fi if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then - error "Certbot will no longer receive updates." + error "certbot-auto and its Certbot installation will no longer receive updates." + error "You will not receive any bug fixes including those fixing server compatibility" + error "or security problems." error "Please visit https://certbot.eff.org/ to check for other alternatives." "$VENV_BIN/letsencrypt" "$@" exit 0 @@ -1493,18 +1487,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.10.1 \ - --hash=sha256:011ac980fa21b9f29e02c9b8d8b86e8a4bf4670b51b6ad91656e401e9d2d2231 \ - --hash=sha256:0d9ee3fc09e0d03b2d1b1f1c4916e61ecfc6904b4216ddef4e6a5ca1424d9cb7 -acme==1.10.1 \ - --hash=sha256:752d598e54e98ad1e874de53fd50c61044f1b566d6deb790db5676ce9c573546 \ - --hash=sha256:fcbb559aedc96b404edf593e78517dcd7291984d5a37036c3fc77f3c5c122fd8 -certbot-apache==1.10.1 \ - --hash=sha256:f077b4b7f166627ef5e0921fe7cde57700670fc86e9ad9dbdfaf2c573cc0f2fa \ - --hash=sha256:97ed637b4c7b03820db6c69aa90145dc989933351d46a3d62baf6b71674f0a10 -certbot-nginx==1.10.1 \ - --hash=sha256:7c36459021f8a1ec3b6c062e4c4fc866bfaa1dbf26ccd29e043dd6848003be08 \ - --hash=sha256:c0bbeccf85f46b728fd95e6bb8c2649d32d3383d7f47ea4b9c312d12bf04d2f0 +certbot==1.12.0 \ + --hash=sha256:f4bb3da5391e4a28e9a2e52ab54986171c0864feff17eaaaca6729a1d4c433a6 \ + --hash=sha256:5ee738773479bcb7794e43fedd2415acc0969b75bdd2a21f451e3bff9d99df59 +acme==1.12.0 \ + --hash=sha256:ca4ad044429f1b8b670b958e5c7ea38159def9d601f4af2359355993918c3317 \ + --hash=sha256:aa363474d50e9fdda27acb8b1aa7efb26fecc5650e02039a0de3a3f0e696c2f2 +certbot-apache==1.12.0 \ + --hash=sha256:38899f6fa08799de9535795d919acf968f288d7208909baf7733f9a763c15227 \ + --hash=sha256:e5679b40d99bd241f4fcd9fe44b73e6e25ccc969a617131ff6ebc90d562a49f2 +certbot-nginx==1.12.0 \ + --hash=sha256:332cd70067bbcf6db52a002650ffa4844d0bd9780279d662aa6725b43f776c14 \ + --hash=sha256:3fb6a55290d37ad466681a89a85ceca4c4026fdd8702f3010b87a74266a6fe7b UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index c1897074c..aba5f1140 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl/JL3kACgkQTRfJlc2X -dfKJMwf/RXjfg5KScEjWiR+YMAcTVxGl4ITDMNBvmPoqCfrPwIJQewy1k6yQUITr -tMe0tkPneGgGccJreLAuO4+RdmNqm2MKBO3wMW9YZobJxcbMmrtVxyBD2OP4K/lL -oCZvjcN5pLvje6OlMwJ/fQ+zGY8mFUpfKIluxKrqkkO3p6Q+i/wPXF5Gjjb2J/bI -N+TczQJYUkDWAw7Tp4ho3J9xpqIn3zyOc2hI3wQDMC1o9sU5a80Vyc/mEqpE8SQ3 -qOWg9Gdx3DXTWOztcx2IxZtFEkIukPM8iD/Fkr//3XHeIc3+mqRAQdY+w7EopzbP -hLwjHVEJs1EMYq8ntWmMFjZ4+ImFgw== -=Peuv +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAmAZorcACgkQTRfJlc2X +dfI6Ogf+LFASyH9sgTV1k9hs1zbmO3CxyE9QQs1JLXpoKOQ1tKv+v+kpt+lJ005g +rielyRSssXtZSyfLchCSBh6qaEBodoOcz8RS2z7rDnR9jKOJv252Buh2oSa3KPmn +WPjRmB3zVXnhq/XmPKQTnoflUlBg+MtZuZXt0Fvu8rvQB+RY3AUfB5Xs83nxJNj4 +W9qNpZYl0sJWWiydr23bEk35MJSt62sKDvyqIVjUfgDfXHmauOpg0foz2xS6XP8i +Ke66GUKaQ1ap2BTucwVT0hieXiQZpxx1PitUeEOjOH9PUfrAxyFlQ0XQaVlqoBhc +YM3nzJw9yf12b+XCUvMzHyQmDA5vdQ== +=AUGt -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 7f358f805..14e71c615 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.11.0.dev0" +LE_AUTO_VERSION="1.13.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -803,6 +803,7 @@ if [ -f /etc/debian_version ]; then elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/redhat-release ]; then DEPRECATED_OS=1 # Run DeterminePythonVersion to decide on the basis of available Python versions @@ -863,22 +864,31 @@ elif [ -f /etc/redhat-release ]; then LE_PYTHON="$prev_le_python" elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/arch-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/manjaro-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/gentoo-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq FreeBSD ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq Darwin ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 else DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 fi # We handle this case after determining the normal bootstrap version to allow @@ -1107,7 +1117,9 @@ if [ "$1" = "--le-auto-phase2" ]; then fi if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then - error "Certbot will no longer receive updates." + error "certbot-auto and its Certbot installation will no longer receive updates." + error "You will not receive any bug fixes including those fixing server compatibility" + error "or security problems." error "Please visit https://certbot.eff.org/ to check for other alternatives." "$VENV_BIN/letsencrypt" "$@" exit 0 @@ -1475,18 +1487,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.10.1 \ - --hash=sha256:011ac980fa21b9f29e02c9b8d8b86e8a4bf4670b51b6ad91656e401e9d2d2231 \ - --hash=sha256:0d9ee3fc09e0d03b2d1b1f1c4916e61ecfc6904b4216ddef4e6a5ca1424d9cb7 -acme==1.10.1 \ - --hash=sha256:752d598e54e98ad1e874de53fd50c61044f1b566d6deb790db5676ce9c573546 \ - --hash=sha256:fcbb559aedc96b404edf593e78517dcd7291984d5a37036c3fc77f3c5c122fd8 -certbot-apache==1.10.1 \ - --hash=sha256:f077b4b7f166627ef5e0921fe7cde57700670fc86e9ad9dbdfaf2c573cc0f2fa \ - --hash=sha256:97ed637b4c7b03820db6c69aa90145dc989933351d46a3d62baf6b71674f0a10 -certbot-nginx==1.10.1 \ - --hash=sha256:7c36459021f8a1ec3b6c062e4c4fc866bfaa1dbf26ccd29e043dd6848003be08 \ - --hash=sha256:c0bbeccf85f46b728fd95e6bb8c2649d32d3383d7f47ea4b9c312d12bf04d2f0 +certbot==1.12.0 \ + --hash=sha256:f4bb3da5391e4a28e9a2e52ab54986171c0864feff17eaaaca6729a1d4c433a6 \ + --hash=sha256:5ee738773479bcb7794e43fedd2415acc0969b75bdd2a21f451e3bff9d99df59 +acme==1.12.0 \ + --hash=sha256:ca4ad044429f1b8b670b958e5c7ea38159def9d601f4af2359355993918c3317 \ + --hash=sha256:aa363474d50e9fdda27acb8b1aa7efb26fecc5650e02039a0de3a3f0e696c2f2 +certbot-apache==1.12.0 \ + --hash=sha256:38899f6fa08799de9535795d919acf968f288d7208909baf7733f9a763c15227 \ + --hash=sha256:e5679b40d99bd241f4fcd9fe44b73e6e25ccc969a617131ff6ebc90d562a49f2 +certbot-nginx==1.12.0 \ + --hash=sha256:332cd70067bbcf6db52a002650ffa4844d0bd9780279d662aa6725b43f776c14 \ + --hash=sha256:3fb6a55290d37ad466681a89a85ceca4c4026fdd8702f3010b87a74266a6fe7b UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index c701f4a4d..ac143de51 100644 Binary files a/letsencrypt-auto-source/letsencrypt-auto.sig and b/letsencrypt-auto-source/letsencrypt-auto.sig differ diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index bc27469fb..783268571 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -325,6 +325,7 @@ if [ -f /etc/debian_version ]; then elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/redhat-release ]; then DEPRECATED_OS=1 # Run DeterminePythonVersion to decide on the basis of available Python versions @@ -385,22 +386,31 @@ elif [ -f /etc/redhat-release ]; then LE_PYTHON="$prev_le_python" elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/arch-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/manjaro-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/gentoo-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq FreeBSD ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq Darwin ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 else DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 fi # We handle this case after determining the normal bootstrap version to allow @@ -521,7 +531,9 @@ if [ "$1" = "--le-auto-phase2" ]; then fi if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then - error "Certbot will no longer receive updates." + error "certbot-auto and its Certbot installation will no longer receive updates." + error "You will not receive any bug fixes including those fixing server compatibility" + error "or security problems." error "Please visit https://certbot.eff.org/ to check for other alternatives." "$VENV_BIN/letsencrypt" "$@" exit 0 diff --git a/letsencrypt-auto-source/pieces/certbot-requirements.txt b/letsencrypt-auto-source/pieces/certbot-requirements.txt index 4839d1e72..4d4c91a5d 100644 --- a/letsencrypt-auto-source/pieces/certbot-requirements.txt +++ b/letsencrypt-auto-source/pieces/certbot-requirements.txt @@ -1,12 +1,12 @@ -certbot==1.10.1 \ - --hash=sha256:011ac980fa21b9f29e02c9b8d8b86e8a4bf4670b51b6ad91656e401e9d2d2231 \ - --hash=sha256:0d9ee3fc09e0d03b2d1b1f1c4916e61ecfc6904b4216ddef4e6a5ca1424d9cb7 -acme==1.10.1 \ - --hash=sha256:752d598e54e98ad1e874de53fd50c61044f1b566d6deb790db5676ce9c573546 \ - --hash=sha256:fcbb559aedc96b404edf593e78517dcd7291984d5a37036c3fc77f3c5c122fd8 -certbot-apache==1.10.1 \ - --hash=sha256:f077b4b7f166627ef5e0921fe7cde57700670fc86e9ad9dbdfaf2c573cc0f2fa \ - --hash=sha256:97ed637b4c7b03820db6c69aa90145dc989933351d46a3d62baf6b71674f0a10 -certbot-nginx==1.10.1 \ - --hash=sha256:7c36459021f8a1ec3b6c062e4c4fc866bfaa1dbf26ccd29e043dd6848003be08 \ - --hash=sha256:c0bbeccf85f46b728fd95e6bb8c2649d32d3383d7f47ea4b9c312d12bf04d2f0 +certbot==1.12.0 \ + --hash=sha256:f4bb3da5391e4a28e9a2e52ab54986171c0864feff17eaaaca6729a1d4c433a6 \ + --hash=sha256:5ee738773479bcb7794e43fedd2415acc0969b75bdd2a21f451e3bff9d99df59 +acme==1.12.0 \ + --hash=sha256:ca4ad044429f1b8b670b958e5c7ea38159def9d601f4af2359355993918c3317 \ + --hash=sha256:aa363474d50e9fdda27acb8b1aa7efb26fecc5650e02039a0de3a3f0e696c2f2 +certbot-apache==1.12.0 \ + --hash=sha256:38899f6fa08799de9535795d919acf968f288d7208909baf7733f9a763c15227 \ + --hash=sha256:e5679b40d99bd241f4fcd9fe44b73e6e25ccc969a617131ff6ebc90d562a49f2 +certbot-nginx==1.12.0 \ + --hash=sha256:332cd70067bbcf6db52a002650ffa4844d0bd9780279d662aa6725b43f776c14 \ + --hash=sha256:3fb6a55290d37ad466681a89a85ceca4c4026fdd8702f3010b87a74266a6fe7b diff --git a/pytest.ini b/pytest.ini index b7a6928ea..d7fe53494 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,10 +2,6 @@ # settings we want to also change there must be added to the release script # directly. [pytest] -# In general, all warnings are treated as errors. Here are the exceptions: -# 1- decodestring: https://github.com/rthalley/dnspython/issues/338 -# 2- Python 2 deprecation: https://github.com/certbot/certbot/issues/8388 -# (to be removed with Certbot 1.12.0 and its drop of Python 2 support) # Warnings being triggered by our plugins using deprecated features in # acme/certbot should be fixed by having our plugins no longer using the # deprecated code rather than adding them to the list of ignored warnings here. @@ -15,5 +11,3 @@ # we release breaking changes. filterwarnings = error - ignore:decodestring:DeprecationWarning - ignore:Python 2 support will be dropped:PendingDeprecationWarning diff --git a/tests/letstest/auto_targets.yaml b/tests/letstest/auto_targets.yaml index 01d410227..164580e86 100644 --- a/tests/letstest/auto_targets.yaml +++ b/tests/letstest/auto_targets.yaml @@ -57,3 +57,10 @@ targets: type: centos virt: hvm user: centos + #----------------------------------------------------------------------------- + # Amazon Linux + - ami: ami-0ff8a91507f77f867 + name: amazon + type: centos + virt: hvm + user: ec2-user diff --git a/tests/letstest/scripts/set_python_envvars.sh b/tests/letstest/scripts/set_python_envvars.sh deleted file mode 100755 index 668444209..000000000 --- a/tests/letstest/scripts/set_python_envvars.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -# This is a simple script that can be sourced to set Python environment -# variables for use in Certbot's letstest test farm tests. - -# Some distros like Fedora may only have an executable named python3 installed. -if command -v python; then - PYTHON_NAME="python" - VENV_SCRIPT="tools/venv.py" - VENV_PATH="venv" -else - # We could check for "python2" here, however, the addition of "python3" - # only systems is what necessitated this change so checking for "python2" - # isn't necessary. - PYTHON_NAME="python3" - VENV_PATH="venv3" - VENV_SCRIPT="tools/venv3.py" -fi diff --git a/tests/letstest/scripts/test_apache2.sh b/tests/letstest/scripts/test_apache2.sh index 247191610..77dc35f1e 100755 --- a/tests/letstest/scripts/test_apache2.sh +++ b/tests/letstest/scripts/test_apache2.sh @@ -64,7 +64,7 @@ if [ $? -ne 0 ] ; then exit 1 fi -tools/venv3.py -e acme[dev] -e certbot[dev,docs] -e certbot-apache -e certbot-ci +tools/venv.py -e acme[dev] -e certbot[dev,docs] -e certbot-apache -e certbot-ci PEBBLE_LOGS="acme_server.log" PEBBLE_URL="https://localhost:14000/dir" # We configure Pebble to use port 80 for http-01 validation rather than an @@ -73,7 +73,7 @@ PEBBLE_URL="https://localhost:14000/dir" # and closer to the default configuration on various OSes. # 2) As of writing this, Certbot's Apache plugin requires there to be an # existing virtual host for the port used for http-01 validation. -venv3/bin/run_acme_server --http-01-port 80 > "${PEBBLE_LOGS}" 2>&1 & +venv/bin/run_acme_server --http-01-port 80 > "${PEBBLE_LOGS}" 2>&1 & DumpPebbleLogs() { if [ -f "${PEBBLE_LOGS}" ] ; then @@ -96,7 +96,7 @@ if ! curl --insecure "${PEBBLE_URL}" 2>/dev/null; then exit 1 fi -sudo "venv3/bin/certbot" -v --debug --text --agree-tos --no-verify-ssl \ +sudo "venv/bin/certbot" -v --debug --text --agree-tos --no-verify-ssl \ --renew-by-default --redirect --register-unsafely-without-email \ --domain "${PUBLIC_HOSTNAME}" --server "${PEBBLE_URL}" if [ $? -ne 0 ] ; then @@ -113,7 +113,7 @@ elif [ "$OS_TYPE" = "centos" ]; then fi OPENSSL_VERSION=$(strings "$MOD_SSL_LOCATION" | egrep -o -m1 '^OpenSSL ([0-9]\.[^ ]+) ' | tail -c +9) APACHE_VERSION=$(sudo $APACHE_NAME -v | egrep -o 'Apache/([0-9]\.[^ ]+)' | tail -c +8) -"venv3/bin/python" tests/letstest/scripts/test_openssl_version.py "$OPENSSL_VERSION" "$APACHE_VERSION" +"venv/bin/python" tests/letstest/scripts/test_openssl_version.py "$OPENSSL_VERSION" "$APACHE_VERSION" if [ $? -ne 0 ] ; then FAIL=1 fi @@ -121,7 +121,7 @@ fi if [ "$OS_TYPE" = "ubuntu" ] ; then export SERVER="${PEBBLE_URL}" - "venv3/bin/tox" -e apacheconftest + "venv/bin/tox" -e apacheconftest else echo Not running hackish apache tests on $OS_TYPE fi diff --git a/tests/letstest/scripts/test_leauto_upgrades.sh b/tests/letstest/scripts/test_leauto_upgrades.sh index c599623cb..d0b941736 100755 --- a/tests/letstest/scripts/test_leauto_upgrades.sh +++ b/tests/letstest/scripts/test_leauto_upgrades.sh @@ -33,19 +33,22 @@ if ! ./letsencrypt-auto -v --debug --version --no-self-upgrade 2>&1 | tail -n1 | exit 1 fi -# This script sets the environment variables PYTHON_NAME, VENV_PATH, and -# VENV_SCRIPT based on the version of Python available on the system. For -# instance, Fedora uses Python 3 and Python 2 is not installed. -. tests/letstest/scripts/set_python_envvars.sh +if command -v python; then + PYTHON_NAME="python" +else + PYTHON_NAME="python3" +fi # Now that python and openssl have been installed, we can set up a fake server # to provide a new version of letsencrypt-auto. First, we start the server and # directory to be served. MY_TEMP_DIR=$(mktemp -d) PORT_FILE="$MY_TEMP_DIR/port" +LOG_FILE="$MY_TEMP_DIR/log" SERVER_PATH=$("$PYTHON_NAME" tools/readlink.py tools/simple_http_server.py) cd "$MY_TEMP_DIR" -"$PYTHON_NAME" "$SERVER_PATH" 0 > $PORT_FILE & +# We set PYTHONUNBUFFERED to disable buffering of output to LOG_FILE +PYTHONUNBUFFERED=1 "$PYTHON_NAME" "$SERVER_PATH" 0 > $PORT_FILE 2> "$LOG_FILE" & SERVER_PID=$! trap 'kill "$SERVER_PID" && rm -rf "$MY_TEMP_DIR"' EXIT cd ~- @@ -119,3 +122,48 @@ if ! diff letsencrypt-auto letsencrypt-auto-source/letsencrypt-auto ; then echo letsencrypt-auto and letsencrypt-auto-source/letsencrypt-auto differ exit 1 fi + +# Now let's test if letsencrypt-auto still tries to upgrade to a new version. +# Regardless of the OS, versions of the script with development version numbers +# ending in .dev0 will not upgrade. See +# https://github.com/certbot/certbot/blob/bdfb9f19c4086a60ef010d2431768850c26d838a/certbot-auto#L1947-L1948. +# In order to test the process of different OSes setting NO_SELF_UPGRADE as +# part of the script's deprecation, we make use of the fact that +# letsencrypt-auto should still attempt to fetch the version number from PyPI +# even if it has a development version number unless NO_SELF_UPGRADE is set in +# which case all of that logic should be skipped. +# +# First we make a copy of the current server logs. +PREVIOUS_LOG_FILE="$MY_TEMP_DIR/previous-log" +cp "$LOG_FILE" "$PREVIOUS_LOG_FILE" + +# Next we run letsencrypt-auto and make sure there were no problems checking +# for updates, the Certbot install still works, the version number is what +# we expect, and it prints a message about not receiving updates. +if ./letsencrypt-auto -v --debug --version | grep "WARNING: couldn't find Python" ; then + echo "Had problems checking for updates!" + exit 1 +fi +if ! ./letsencrypt-auto -v --debug --version 2>&1 | tail -n1 | grep "^certbot $EXPECTED_VERSION$" ; then + echo unexpected certbot version found + exit 1 +fi +if ! ./letsencrypt-auto -v --debug --version 2>&1 | grep "will no longer receive updates" ; then + echo script did not print warning about not receiving updates! + exit 1 +fi + +# Finally, we check if our local server received more requests. Over time, +# we'll move more and more OSes into this case until it this is the expected +# behavior on all systems. +if [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue; then + if ! diff "$LOG_FILE" "$PREVIOUS_LOG_FILE" ; then + echo our local server received unexpected requests + exit 1 + fi +else + if diff "$LOG_FILE" "$PREVIOUS_LOG_FILE" ; then + echo our local server did not receive the requests we expected + exit 1 + fi +fi diff --git a/tests/letstest/scripts/test_sdists.sh b/tests/letstest/scripts/test_sdists.sh index a038caff6..aa12d5610 100755 --- a/tests/letstest/scripts/test_sdists.sh +++ b/tests/letstest/scripts/test_sdists.sh @@ -3,7 +3,7 @@ cd letsencrypt BOOTSTRAP_SCRIPT="tests/letstest/scripts/bootstrap_os_packages.sh" -VENV_PATH=venv3 +VENV_PATH=venv # install OS packages sudo $BOOTSTRAP_SCRIPT @@ -18,7 +18,7 @@ python3 tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirem # marker that'd normally prevent it from being installed, and this package is # not needed for any OS tested here. sed -i '/enum34/d' requirements.txt -CERTBOT_PIP_NO_BINARY=:all: tools/venv3.py --requirement requirements.txt +CERTBOT_PIP_NO_BINARY=:all: tools/venv.py --requirement requirements.txt . "$VENV_PATH/bin/activate" # pytest is needed to run tests on some of our packages so we install a pinned version here. tools/pip_install.py pytest diff --git a/tests/letstest/scripts/test_tests.sh b/tests/letstest/scripts/test_tests.sh index f07e3b78e..858fc1f18 100755 --- a/tests/letstest/scripts/test_tests.sh +++ b/tests/letstest/scripts/test_tests.sh @@ -9,9 +9,9 @@ LE_AUTO="$REPO_ROOT/letsencrypt-auto-source/letsencrypt-auto" LE_AUTO="$LE_AUTO --debug --no-self-upgrade --non-interactive" MODULES="acme certbot certbot-apache certbot-nginx" PIP_INSTALL="tools/pip_install.py" -VENV_NAME=venv3 +VENV_NAME=venv BOOTSTRAP_SCRIPT="$REPO_ROOT/tests/letstest/scripts/bootstrap_os_packages.sh" -VENV_SCRIPT="tools/venv3.py" +VENV_SCRIPT="tools/venv.py" sudo $BOOTSTRAP_SCRIPT diff --git a/tools/_release.sh b/tools/_release.sh index e17332f30..e9e0e49f0 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -216,8 +216,13 @@ fi # ensure we have the latest built version of leauto letsencrypt-auto-source/build.py -# and that it's signed correctly -tools/offline-sigrequest.sh || true +# Now we have to sign the built version of leauto. +SignLEAuto() { + yubico-piv-tool -a verify-pin --sign -s 9c -i letsencrypt-auto-source/letsencrypt-auto -o letsencrypt-auto-source/letsencrypt-auto.sig +} + +# Loop until letsencrypt-auto is signed correctly. +SignLEAuto || true while ! openssl dgst -sha256 -verify $RELEASE_OPENSSL_PUBKEY -signature \ letsencrypt-auto-source/letsencrypt-auto.sig \ letsencrypt-auto-source/letsencrypt-auto ; do @@ -225,7 +230,7 @@ while ! openssl dgst -sha256 -verify $RELEASE_OPENSSL_PUBKEY -signature \ read -p "Would you like this script to try and sign it again [Y/n]?" response case $response in [yY][eE][sS]|[yY]|"") - tools/offline-sigrequest.sh || true;; + SignLEAuto || true;; *) ;; esac diff --git a/tools/_venv_common.py b/tools/_venv_common.py deleted file mode 100644 index 58c05ed09..000000000 --- a/tools/_venv_common.py +++ /dev/null @@ -1,244 +0,0 @@ -#!/usr/bin/env python -"""Aids in creating a developer virtual environment for Certbot. - -When this module is run as a script, it takes the arguments that should -be passed to pip to install the Certbot packages as command line -arguments. The virtual environment will be created with the name "venv" -in the current working directory and will use the default version of -Python for the virtualenv executable in your PATH. You can change the -name of the virtual environment by setting the environment variable -VENV_NAME. -""" - -from __future__ import print_function - -from distutils.version import LooseVersion -import glob -import os -import re -import shutil -import subprocess -import sys -import time - -REQUIREMENTS = [ - '-e acme[dev]', - '-e certbot[dev,docs]', - '-e certbot-apache', - '-e certbot-dns-cloudflare', - '-e certbot-dns-cloudxns', - '-e certbot-dns-digitalocean', - '-e certbot-dns-dnsimple', - '-e certbot-dns-dnsmadeeasy', - '-e certbot-dns-gehirn', - '-e certbot-dns-google', - '-e certbot-dns-linode', - '-e certbot-dns-luadns', - '-e certbot-dns-nsone', - '-e certbot-dns-ovh', - '-e certbot-dns-rfc2136', - '-e certbot-dns-route53', - '-e certbot-dns-sakuracloud', - '-e certbot-nginx', - '-e certbot-compatibility-test', - '-e certbot-ci', -] - -VERSION_PATTERN = re.compile(r'^(\d+)\.(\d+).*$') - - -class PythonExecutableNotFoundError(Exception): - pass - - -def find_python_executable(python_major): - # type: (int) -> str - """ - Find the relevant python executable that is of the given python major version. - Will test, in decreasing priority order: - - * the current Python interpreter - * 'pythonX' executable in PATH (with X the given major version) if available - * 'python' executable in PATH if available - * Windows Python launcher 'py' executable in PATH if available - - Incompatible python versions for Certbot will be evicted (e.g. Python 3 - versions less than 3.6). - - :param int python_major: the Python major version to target (2 or 3) - :rtype: str - :return: the relevant python executable path - :raise RuntimeError: if no relevant python executable path could be found - """ - python_executable_path = None - - # First try, current python executable - if _check_version('{0}.{1}.{2}'.format( - sys.version_info[0], sys.version_info[1], sys.version_info[2]), python_major): - return sys.executable - - # Second try, with python executables in path - versions_to_test = ['2.7', '2', ''] if python_major == 2 else ['3', ''] - for one_version in versions_to_test: - try: - one_python = 'python{0}'.format(one_version) - output = subprocess.check_output([one_python, '--version'], - universal_newlines=True, stderr=subprocess.STDOUT) - if _check_version(output.strip().split()[1], python_major): - return subprocess.check_output([one_python, '-c', - 'import sys; sys.stdout.write(sys.executable);'], - universal_newlines=True) - except (subprocess.CalledProcessError, OSError): - pass - - # Last try, with Windows Python launcher - try: - env_arg = '-{0}'.format(python_major) - output_version = subprocess.check_output(['py', env_arg, '--version'], - universal_newlines=True, stderr=subprocess.STDOUT) - if _check_version(output_version.strip().split()[1], python_major): - return subprocess.check_output(['py', env_arg, '-c', - 'import sys; sys.stdout.write(sys.executable);'], - universal_newlines=True) - except (subprocess.CalledProcessError, OSError): - pass - - if not python_executable_path: - raise RuntimeError('Error, no compatible Python {0} executable for Certbot could be found.' - .format(python_major)) - - -def _check_version(version_str, major_version): - search = VERSION_PATTERN.search(version_str) - - if not search: - return False - - version = (int(search.group(1)), int(search.group(2))) - - minimal_version_supported = (2, 7) - if major_version == 3: - minimal_version_supported = (3, 6) - - if version >= minimal_version_supported: - return True - - print('Incompatible python version for Certbot found: {0}'.format(version_str)) - return False - - -def subprocess_with_print(cmd, env=None, shell=False): - if env is None: - env = os.environ - print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd) - subprocess.check_call(cmd, env=env, shell=shell) - - -def subprocess_output_with_print(cmd, env=None, shell=False): - if env is None: - env = os.environ - print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd) - return subprocess.check_output(cmd, env=env, shell=shell) - - -def get_venv_python_path(venv_path): - python_linux = os.path.join(venv_path, 'bin/python') - if os.path.isfile(python_linux): - return os.path.abspath(python_linux) - python_windows = os.path.join(venv_path, 'Scripts\\python.exe') - if os.path.isfile(python_windows): - return os.path.abspath(python_windows) - - raise ValueError(( - 'Error, could not find python executable in venv path {0}: is it a valid venv ?' - .format(venv_path))) - - -def prepare_venv_path(venv_name): - """Determines the venv path and prepares it for use. - - This function cleans up any Python eggs in the current working directory - and ensures the venv path is available for use. The path used is the - VENV_NAME environment variable if it is set and venv_name otherwise. If - there is already a directory at the desired path, the existing directory is - renamed by appending a timestamp to the directory name. - - :param str venv_name: The name or path at where the virtual - environment should be created if VENV_NAME isn't set. - - :returns: path where the virtual environment should be created - :rtype: str - - """ - for path in glob.glob('*.egg-info'): - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.remove(path) - - env_venv_name = os.environ.get('VENV_NAME') - if env_venv_name: - print('Creating venv at {0}' - ' as specified in VENV_NAME'.format(env_venv_name)) - venv_name = env_venv_name - - if os.path.isdir(venv_name): - os.rename(venv_name, '{0}.{1}.bak'.format(venv_name, int(time.time()))) - - return venv_name - - -def install_packages(venv_name, pip_args): - """Installs packages in the given venv. - - :param str venv_name: The name or path at where the virtual - environment should be created. - :param pip_args: Command line arguments that should be given to - pip to install packages - :type pip_args: `list` of `str` - - """ - # Using the python executable from venv, we ensure to execute following commands in this venv. - py_venv = get_venv_python_path(venv_name) - subprocess_with_print([py_venv, os.path.abspath('tools/pipstrap.py')]) - # We only use this value during pip install because: - # 1) We're really only adding it for installing cryptography, which happens here, and - # 2) There are issues with calling it along with VIRTUALENV_NO_DOWNLOAD, which applies at the - # steps above, not during pip install. - env_pip_no_binary = os.environ.get('CERTBOT_PIP_NO_BINARY') - if env_pip_no_binary: - # Check OpenSSL version. If it's too low, don't apply the env variable. - openssl_version_string = str(subprocess_output_with_print(['openssl', 'version'])) - matches = re.findall(r'OpenSSL ([^ ]+) ', openssl_version_string) - if not matches: - print('Could not find OpenSSL version, not setting PIP_NO_BINARY.') - else: - openssl_version = matches[0] - - if LooseVersion(openssl_version) >= LooseVersion('1.0.2'): - print('Setting PIP_NO_BINARY to {0}' - ' as specified in CERTBOT_PIP_NO_BINARY'.format(env_pip_no_binary)) - os.environ['PIP_NO_BINARY'] = env_pip_no_binary - else: - print('Not setting PIP_NO_BINARY, as OpenSSL version is too old.') - command = [py_venv, os.path.abspath('tools/pip_install.py')] - command.extend(pip_args) - subprocess_with_print(command) - if 'PIP_NO_BINARY' in os.environ: - del os.environ['PIP_NO_BINARY'] - - if os.path.isdir(os.path.join(venv_name, 'bin')): - # Linux/OSX specific - print('-------------------------------------------------------------------') - print('Please run the following command to activate developer environment:') - print('source {0}/bin/activate'.format(venv_name)) - print('-------------------------------------------------------------------') - elif os.path.isdir(os.path.join(venv_name, 'Scripts')): - # Windows specific - print('---------------------------------------------------------------------------') - print('Please run one of the following commands to activate developer environment:') - print('{0}\\Scripts\\activate.bat (for Batch)'.format(venv_name)) - print('.\\{0}\\Scripts\\Activate.ps1 (for Powershell)'.format(venv_name)) - print('---------------------------------------------------------------------------') - else: - raise ValueError('Error, directory {0} is not a valid venv.'.format(venv_name)) diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index 967596ded..f5140f9c7 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -26,13 +26,7 @@ coverage==4.5.4 decorator==4.4.1 deprecated==1.2.10 dns-lexicon==3.3.17 -# There is no version of dnspython that works on both Python 2 and Python 3.9. -# To work around this, we make use of the fact that subject to other -# constraints, pip will install the newest version of a package while ignoring -# versions that don't support the version of Python being used. The result of -# this is dnspython 2.0.0 is installed in Python 3 while dnspython 1.16.0 is -# installed in Python 2. -dnspython<=2.0.0 +dnspython==2.1.0 docker==4.3.1 docker-compose==1.26.2 docker-pycreds==0.4.0 @@ -91,7 +85,7 @@ pylint==2.4.3 # If pynsist version is upgraded, our NSIS template windows-installer/template.nsi # must be upgraded if necessary using the new built-in one from pynsist. pynacl==1.3.0 -pynsist==2.4 +pynsist==2.6 pytest==3.2.5 pytest-cov==2.5.1 pytest-forked==0.2 @@ -101,7 +95,7 @@ pytest-rerunfailures==4.2 python-dateutil==2.8.1 python-digitalocean==1.11 python-dotenv==0.14.0 -pywin32==227 +pywin32==300 PyYAML==5.3.1 repoze.sphinx.autointerface==0.8 requests-file==1.4.2 diff --git a/tools/offline-sigrequest.sh b/tools/offline-sigrequest.sh deleted file mode 100755 index 6443ae8af..000000000 --- a/tools/offline-sigrequest.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -set -o errexit - -function sayhash { # $1 <-- HASH ; $2 <---SIGFILEBALL - while read -p "Press Enter to read the hash aloud or type 'done': " INP && [ "$INP" = "" ] ; do - if ! `which festival > /dev/null` ; then - echo \`festival\` is not installed! - echo Please install it to read the hash aloud - else - cat $1 | (echo "(Parameter.set 'Duration_Stretch 1.8)"; \ - echo -n '(SayText "'; \ - sha256sum | cut -c1-64 | fold -1 | sed 's/^a$/alpha/; s/^b$/bravo/; s/^c$/charlie/; s/^d$/delta/; s/^e$/echo/; s/^f$/foxtrot/'; \ - echo '")' ) | festival - fi - done - - echo 'Paste in the data from the QR code, then type Ctrl-D:' - cat > $2 -} - -function offlinesign { # $1 <-- INPFILE ; $2 <---SIGFILE - echo HASH FOR SIGNING: - SIGFILEBALL="$2.lzma.base64" - #echo "(place the resulting raw binary signature in $SIGFILEBALL)" - sha256sum $1 - echo metahash for confirmation only $(sha256sum $1 |cut -d' ' -f1 | tr -d '\n' | sha256sum | cut -c1-6) ... - echo - sayhash $1 $SIGFILEBALL -} - -function oncesigned { # $1 <-- INPFILE ; $2 <--SIGFILE - SIGFILEBALL="$2.lzma.base64" - cat $SIGFILEBALL | tr -d '\r' | base64 -d | unlzma -c > $2 || exit 1 - if ! [ -f $2 ] ; then - echo "Failed to find $2"'!' - exit 1 - fi - - if file $2 | grep -qv " data" ; then - echo "WARNING WARNING $2 does not look like a binary signature:" - echo `file $2` - exit 1 - fi -} - -HERE=`dirname $0` -LEAUTO="`realpath $HERE`/../letsencrypt-auto-source/letsencrypt-auto" -SIGFILE="$LEAUTO".sig -offlinesign $LEAUTO $SIGFILE -oncesigned $LEAUTO $SIGFILE diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index 5d1446005..f6528f396 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -1,76 +1,79 @@ -# This file contains the oldest versions of our dependencies we say we require -# in our packages or versions we need to support to maintain compatibility with -# the versions included in the various Linux distros where we are packaged. +# This file contains the oldest versions of our dependencies we're trying to +# support. Usually these version numbers are taken from the packages of our +# dependencies available in popular LTS Linux distros. Keeping compatibility +# with those versions makes it much easier for OS maintainers to update their +# Certbot packages. +# +# When updating these dependencies, we should try to only update them to the +# oldest version of the package that is found in a non-EOL'd version of +# CentOS, Debian, or Ubuntu that has Certbot packages in their OS repositories +# using a version of Python we support. If the distro is EOL'd or using a +# version of Python we don't support, it can be ignored. # CentOS/RHEL 7 EPEL constraints -cffi==1.6.0 +# Some of these constraints may be stricter than necessary because they +# initially referred to the Python 2 packages in CentOS/RHEL 7 with EPEL. +cffi==1.9.1 chardet==2.2.1 -configobj==4.7.2 ipaddress==1.0.16 mock==1.0.1 ndg-httpsclient==0.3.2 ply==3.4 +pyOpenSSL==17.3.0 pyasn1==0.1.9 pycparser==2.14 pyRFC3339==1.0 python-augeas==0.5.0 oauth2client==4.0.0 -six==1.9.0 -# setuptools 0.9.8 is the actual version packaged, but some other dependencies -# in this file require setuptools>=1.0 and there are no relevant changes for us -# between these versions. -setuptools==1.0.0 urllib3==1.10.2 zope.component==4.1.0 zope.event==4.0.3 zope.interface==4.0.5 # Debian Jessie Backports constraints -# Debian Jessie has reached end of life. However: -# When it becomes necessary to upgrade any of these dependencies, you should only update them to the oldest version of the package found -# in a non-EOL'd version of CentOS, Debian, or Ubuntu that has Certbot packages in their OS repositories. -PyICU==1.8 +# Debian Jessie has reached end of life so these dependencies can probably be +# updated as needed or desired. colorama==0.3.2 enum34==1.0.3 html5lib==0.999 -idna==2.0 pbr==1.8.0 pytz==2012rc0 # Debian Buster constraints google-api-python-client==1.5.5 +pyparsing==2.2.0 # Our setup.py constraints apacheconfig==0.3.2 cloudflare==1.5.1 -cryptography==1.2.3 -parsedatetime==1.3 -pyparsing==1.5.5 python-digitalocean==1.11 -requests[security]==2.6.0 +requests==2.6.0 # Ubuntu Xenial constraints +# Ubuntu Xenial only has versions of Python which we do not support available +# so these dependencies can probably be updated as needed or desired. ConfigArgParse==0.10.0 -pyOpenSSL==0.15.1 funcsigs==0.4 zope.hookable==4.0.4 # Ubuntu Bionic constraints. +cryptography==2.1.4 distro==1.0.1 # Lexicon oldest constraint is overridden appropriately on relevant DNS provider plugins # using their local-oldest-requirements.txt dns-lexicon==2.2.1 httplib2==0.9.2 +idna==2.6 +setuptools==39.0.1 +six==1.11.0 + +# Ubuntu Focal constraints +asn1crypto==0.24.0 +configobj==5.0.6 +parsedatetime==2.4 # Plugin constraints # These aren't necessarily the oldest versions we need to support # Tracking at https://github.com/certbot/certbot/issues/6473 boto3==1.4.7 botocore==1.7.41 - -# Old certbot[dev] constraints -# Old versions of certbot[dev] required ipdb and our normally pinned version of -# ipython which ipdb depends on doesn't support Python 2 so we pin an older -# version here to keep tests working while we have Python 2 support. -ipython==5.8.0 -prompt-toolkit==1.0.18 diff --git a/tools/run_oldest_tests.sh b/tools/run_oldest_tests.sh deleted file mode 100755 index 7bf9f2bc5..000000000 --- a/tools/run_oldest_tests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -set -e - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" - -pushd "${DIR}/../" - -function cleanup() { - rm -f "${DOCKERFILE}" - popd -} - -trap cleanup EXIT - -DOCKERFILE=$(mktemp /tmp/Dockerfile.XXXXXX) - -cat << "EOF" >> "${DOCKERFILE}" -FROM ubuntu:16.04 -COPY letsencrypt-auto-source/pieces/dependency-requirements.txt /tmp/letsencrypt-auto-source/pieces/ -COPY tools/ /tmp/tools/ -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - python-dev python-pip python-setuptools \ - gcc libaugeas0 libssl-dev libffi-dev \ - git ca-certificates nginx-light openssl curl \ - && curl -fsSL https://get.docker.com | bash /dev/stdin \ - && python /tmp/tools/pipstrap.py \ - && python /tmp/tools/pip_install.py tox \ - && rm -rf /var/lib/apt/lists/* -EOF - -docker build -f "${DOCKERFILE}" -t oldest-worker . -docker run --rm --network=host -w "${PWD}" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v "${PWD}:${PWD}" -v /tmp:/tmp \ - -e TOXENV -e ACME_SERVER -e PYTEST_ADDOPTS \ - oldest-worker python -m tox diff --git a/tools/venv.py b/tools/venv.py index f99386eff..9f7488008 100755 --- a/tools/venv.py +++ b/tools/venv.py @@ -1,36 +1,261 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Developer virtualenv setup for Certbot client -import os -import sys +"""Aids in creating a developer virtual environment for Certbot. -import _venv_common +When this module is run as a script, it takes the arguments that should +be passed to pip to install the Certbot packages as command line +arguments. If no arguments are provided, all Certbot packages and their +development dependencies are installed. The virtual environment will be +created with the name "venv" in the current working directory. You can +change the name of the virtual environment by setting the environment +variable VENV_NAME. + +""" + +from __future__ import print_function + +from distutils.version import LooseVersion +import glob +import os +import re +import shutil +import subprocess +import sys +import time + +REQUIREMENTS = [ + '-e acme[dev]', + '-e certbot[dev,docs]', + '-e certbot-apache', + '-e certbot-dns-cloudflare', + '-e certbot-dns-cloudxns', + '-e certbot-dns-digitalocean', + '-e certbot-dns-dnsimple', + '-e certbot-dns-dnsmadeeasy', + '-e certbot-dns-gehirn', + '-e certbot-dns-google', + '-e certbot-dns-linode', + '-e certbot-dns-luadns', + '-e certbot-dns-nsone', + '-e certbot-dns-ovh', + '-e certbot-dns-rfc2136', + '-e certbot-dns-route53', + '-e certbot-dns-sakuracloud', + '-e certbot-nginx', + '-e certbot-compatibility-test', + '-e certbot-ci', +] + +VERSION_PATTERN = re.compile(r'^(\d+)\.(\d+).*$') + + +class PythonExecutableNotFoundError(Exception): + pass + + +def find_python_executable() -> str: + """ + Find the relevant python executable that is of the given python major version. + Will test, in decreasing priority order: + + * the current Python interpreter + * 'pythonX' executable in PATH (with X the given major version) if available + * 'python' executable in PATH if available + * Windows Python launcher 'py' executable in PATH if available + + Incompatible python versions for Certbot will be evicted (e.g. Python 3 + versions less than 3.6). + + :rtype: str + :return: the relevant python executable path + :raise RuntimeError: if no relevant python executable path could be found + """ + python_executable_path = None + + # First try, current python executable + if _check_version('{0}.{1}.{2}'.format( + sys.version_info[0], sys.version_info[1], sys.version_info[2])): + return sys.executable + + # Second try, with python executables in path + for one_version in ('3', '',): + try: + one_python = 'python{0}'.format(one_version) + output = subprocess.check_output([one_python, '--version'], + universal_newlines=True, stderr=subprocess.STDOUT) + if _check_version(output.strip().split()[1]): + return subprocess.check_output([one_python, '-c', + 'import sys; sys.stdout.write(sys.executable);'], + universal_newlines=True) + except (subprocess.CalledProcessError, OSError): + pass + + # Last try, with Windows Python launcher + try: + output_version = subprocess.check_output(['py', '-3', '--version'], + universal_newlines=True, stderr=subprocess.STDOUT) + if _check_version(output_version.strip().split()[1]): + return subprocess.check_output(['py', env_arg, '-c', + 'import sys; sys.stdout.write(sys.executable);'], + universal_newlines=True) + except (subprocess.CalledProcessError, OSError): + pass + + if not python_executable_path: + raise RuntimeError('Error, no compatible Python executable for Certbot could be found.') + + +def _check_version(version_str): + search = VERSION_PATTERN.search(version_str) + + if not search: + return False + + version = (int(search.group(1)), int(search.group(2))) + + if version >= (3, 6): + return True + + print('Incompatible python version for Certbot found: {0}'.format(version_str)) + return False + + +def subprocess_with_print(cmd, env=None, shell=False): + if env is None: + env = os.environ + print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd) + subprocess.check_call(cmd, env=env, shell=shell) + + +def subprocess_output_with_print(cmd, env=None, shell=False): + if env is None: + env = os.environ + print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd) + return subprocess.check_output(cmd, env=env, shell=shell) + + +def get_venv_python_path(venv_path): + python_linux = os.path.join(venv_path, 'bin/python') + if os.path.isfile(python_linux): + return os.path.abspath(python_linux) + python_windows = os.path.join(venv_path, 'Scripts\\python.exe') + if os.path.isfile(python_windows): + return os.path.abspath(python_windows) + + raise ValueError(( + 'Error, could not find python executable in venv path {0}: is it a valid venv ?' + .format(venv_path))) + + +def prepare_venv_path(venv_name): + """Determines the venv path and prepares it for use. + + This function cleans up any Python eggs in the current working directory + and ensures the venv path is available for use. The path used is the + VENV_NAME environment variable if it is set and venv_name otherwise. If + there is already a directory at the desired path, the existing directory is + renamed by appending a timestamp to the directory name. + + :param str venv_name: The name or path at where the virtual + environment should be created if VENV_NAME isn't set. + + :returns: path where the virtual environment should be created + :rtype: str + + """ + for path in glob.glob('*.egg-info'): + if os.path.isdir(path): + shutil.rmtree(path) + else: + os.remove(path) + + env_venv_name = os.environ.get('VENV_NAME') + if env_venv_name: + print('Creating venv at {0}' + ' as specified in VENV_NAME'.format(env_venv_name)) + venv_name = env_venv_name + + if os.path.isdir(venv_name): + os.rename(venv_name, '{0}.{1}.bak'.format(venv_name, int(time.time()))) + + return venv_name + + +def install_packages(venv_name, pip_args): + """Installs packages in the given venv. + + :param str venv_name: The name or path at where the virtual + environment should be created. + :param pip_args: Command line arguments that should be given to + pip to install packages + :type pip_args: `list` of `str` + + """ + # Using the python executable from venv, we ensure to execute following commands in this venv. + py_venv = get_venv_python_path(venv_name) + subprocess_with_print([py_venv, os.path.abspath('tools/pipstrap.py')]) + # We only use this value during pip install because: + # 1) We're really only adding it for installing cryptography, which happens here, and + # 2) There are issues with calling it along with VIRTUALENV_NO_DOWNLOAD, which applies at the + # steps above, not during pip install. + env_pip_no_binary = os.environ.get('CERTBOT_PIP_NO_BINARY') + if env_pip_no_binary: + # Check OpenSSL version. If it's too low, don't apply the env variable. + openssl_version_string = str(subprocess_output_with_print(['openssl', 'version'])) + matches = re.findall(r'OpenSSL ([^ ]+) ', openssl_version_string) + if not matches: + print('Could not find OpenSSL version, not setting PIP_NO_BINARY.') + else: + openssl_version = matches[0] + + if LooseVersion(openssl_version) >= LooseVersion('1.0.2'): + print('Setting PIP_NO_BINARY to {0}' + ' as specified in CERTBOT_PIP_NO_BINARY'.format(env_pip_no_binary)) + os.environ['PIP_NO_BINARY'] = env_pip_no_binary + else: + print('Not setting PIP_NO_BINARY, as OpenSSL version is too old.') + command = [py_venv, os.path.abspath('tools/pip_install.py')] + command.extend(pip_args) + subprocess_with_print(command) + if 'PIP_NO_BINARY' in os.environ: + del os.environ['PIP_NO_BINARY'] + + if os.path.isdir(os.path.join(venv_name, 'bin')): + # Linux/OSX specific + print('-------------------------------------------------------------------') + print('Please run the following command to activate developer environment:') + print('source {0}/bin/activate'.format(venv_name)) + print('-------------------------------------------------------------------') + elif os.path.isdir(os.path.join(venv_name, 'Scripts')): + # Windows specific + print('---------------------------------------------------------------------------') + print('Please run one of the following commands to activate developer environment:') + print('{0}\\Scripts\\activate.bat (for Batch)'.format(venv_name)) + print('.\\{0}\\Scripts\\Activate.ps1 (for Powershell)'.format(venv_name)) + print('---------------------------------------------------------------------------') + else: + raise ValueError('Error, directory {0} is not a valid venv.'.format(venv_name)) def create_venv(venv_path): - """Create a Python 2 virtual environment at venv_path. + """Create a Python virtual environment at venv_path. :param str venv_path: path where the venv should be created """ - python2 = _venv_common.find_python_executable(2) - command = [sys.executable, '-m', 'virtualenv', '--python', python2, venv_path] - - environ = os.environ.copy() - environ['VIRTUALENV_NO_DOWNLOAD'] = '1' - _venv_common.subprocess_with_print(command, environ) + python = find_python_executable() + command = [python, '-m', 'venv', venv_path] + subprocess_with_print(command) def main(pip_args=None): - if os.name == 'nt': - raise ValueError('Certbot for Windows is not supported on Python 2.x.') - - venv_path = _venv_common.prepare_venv_path('venv') + venv_path = prepare_venv_path('venv') create_venv(venv_path) if not pip_args: - pip_args = _venv_common.REQUIREMENTS + pip_args = REQUIREMENTS - _venv_common.install_packages(venv_path, pip_args) + install_packages(venv_path, pip_args) if __name__ == '__main__': diff --git a/tools/venv3.py b/tools/venv3.py deleted file mode 100755 index 7ead82bd5..000000000 --- a/tools/venv3.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 -# Developer virtualenv setup for Certbot client -import sys - -import _venv_common - - -def create_venv(venv_path): - """Create a Python 3 virtual environment at venv_path. - - :param str venv_path: path where the venv should be created - - """ - python3 = _venv_common.find_python_executable(3) - command = [python3, '-m', 'venv', venv_path] - _venv_common.subprocess_with_print(command) - - -def main(pip_args=None): - venv_path = _venv_common.prepare_venv_path('venv3') - create_venv(venv_path) - - if not pip_args: - pip_args = _venv_common.REQUIREMENTS + ['-e certbot[dev3]'] - - _venv_common.install_packages(venv_path, pip_args) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/tox.ini b/tox.ini index 212d4ee76..9f63b897c 100644 --- a/tox.ini +++ b/tox.ini @@ -77,49 +77,70 @@ setenv = PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:--numprocesses auto} PYTHONHASHSEED = 0 -[testenv:py27-oldest] +[testenv:oldest] +# Setting basepython allows the tests to fail fast if that version of Python +# isn't available instead of potentially trying to use a newer version of +# Python which is unlikely to work. +basepython = python3.6 commands = {[testenv]commands} setenv = {[testenv]setenv} CERTBOT_OLDEST=1 -[testenv:py27-acme-oldest] +[testenv:acme-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} acme[dev] setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-apache-oldest] +[testenv:apache-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot-apache setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-apache-v2-oldest] +[testenv:apache-v2-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot-apache[dev] setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-certbot-oldest] +[testenv:certbot-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot[dev] setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-dns-oldest] +[testenv:dns-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} {[base]dns_packages} setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-nginx-oldest] +[testenv:nginx-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot-nginx python tests/lock_test.py setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} + +[testenv:external-mock] +commands = + python {toxinidir}/tools/pip_install.py mock + {[base]install_and_test} {[base]all_packages} [testenv:lint] basepython = python3 @@ -128,14 +149,12 @@ basepython = python3 # continue, but tox return code will reflect previous error commands = {[base]install_packages} - {[base]pip_install} certbot[dev3] python -m pylint --reports=n --rcfile=.pylintrc {[base]source_paths} [testenv:mypy] basepython = python3 commands = {[base]install_packages} - {[base]pip_install} certbot[dev3] mypy {[base]source_paths} [testenv:apacheconftest] @@ -238,22 +257,26 @@ commands = passenv = DOCKER_* [testenv:integration-certbot-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]pip_install} certbot {[base]pip_install} certbot-ci pytest certbot-ci/certbot_integration_tests/certbot_tests \ --acme-server={env:ACME_SERVER:pebble} passenv = DOCKER_* -setenv = {[testenv:py27-oldest]setenv} +setenv = {[testenv:oldest]setenv} [testenv:integration-nginx-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]pip_install} certbot-nginx {[base]pip_install} certbot-ci pytest certbot-ci/certbot_integration_tests/nginx_tests \ --acme-server={env:ACME_SERVER:pebble} passenv = DOCKER_* -setenv = {[testenv:py27-oldest]setenv} +setenv = {[testenv:oldest]setenv} [testenv:test-farm-tests-base] changedir = tests/letstest diff --git a/windows-installer/construct.py b/windows-installer/construct.py index 1ce4811ac..0684b3c25 100644 --- a/windows-installer/construct.py +++ b/windows-installer/construct.py @@ -9,10 +9,10 @@ import sys import tempfile import time -PYTHON_VERSION = (3, 7, 4) +PYTHON_VERSION = (3, 8, 6) PYTHON_BITNESS = 32 -PYWIN32_VERSION = 227 # do not forget to edit pywin32 dependency accordingly in setup.py -NSIS_VERSION = '3.04' +PYWIN32_VERSION = 300 # do not forget to edit pywin32 dependency accordingly in setup.py +NSIS_VERSION = '3.06.1' def main(): @@ -98,32 +98,6 @@ def _copy_assets(build_path, repo_path): def _generate_pynsist_config(repo_path, build_path): print('Generate pynsist configuration') - pywin32_paths_file = os.path.join(build_path, 'pywin32_paths.py') - - # Pywin32 uses non-standard folders to hold its packages. We need to instruct pynsist bootstrap - # explicitly to add them into sys.path. This is done with a custom "pywin32_paths.py" that is - # referred in the pynsist configuration as an "extra_preamble". - # Reference example: https://github.com/takluyver/pynsist/tree/master/examples/pywebview - with open(pywin32_paths_file, 'w') as file_h: - file_h.write('''\ -pkgdir = os.path.join(os.path.dirname(installdir), 'pkgs') - -sys.path.extend([ - os.path.join(pkgdir, 'win32'), - os.path.join(pkgdir, 'win32', 'lib'), -]) - -# Preload pywintypes and pythoncom -pwt = os.path.join(pkgdir, 'pywin32_system32', 'pywintypes{0}{1}.dll') -pcom = os.path.join(pkgdir, 'pywin32_system32', 'pythoncom{0}{1}.dll') -import warnings -with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import imp -imp.load_dynamic('pywintypes', pwt) -imp.load_dynamic('pythoncom', pcom) -'''.format(PYTHON_VERSION[0], PYTHON_VERSION[1])) - installer_cfg_path = os.path.join(build_path, 'installer.cfg') certbot_pkg_path = os.path.join(repo_path, 'certbot') @@ -158,7 +132,6 @@ files=run.bat [Command certbot] entry_point=certbot.main:main -extra_preamble=pywin32_paths.py '''.format(certbot_version=certbot_version, installer_suffix='win_amd64' if PYTHON_BITNESS == 64 else 'win32', python_bitness=PYTHON_BITNESS, diff --git a/windows-installer/template.nsi b/windows-installer/template.nsi index 50a03865f..64bceb065 100644 --- a/windows-installer/template.nsi +++ b/windows-installer/template.nsi @@ -1,7 +1,7 @@ -; This NSIS template is based on the built-in one in pynsist 2.3. +; This NSIS template is based on the built-in one in pynsist 2.6. ; Added lines are enclosed within "CERTBOT CUSTOM BEGIN/END" comments. ; If pynsist is upgraded, this template must be updated if necessary using the new built-in one. -; Original file can be found here: https://github.com/takluyver/pynsist/blob/2.4/nsist/pyapp.nsi +; Original file can be found here: https://github.com/takluyver/pynsist/blob/2.6/nsist/pyapp.nsi !define PRODUCT_NAME "[[ib.appname]]" !define PRODUCT_VERSION "[[ib.version]]" @@ -14,9 +14,14 @@ ; Marker file to tell the uninstaller that it's a user installation !define USER_INSTALL_MARKER _user_install_marker - + SetCompressor lzma +!if "${NSIS_PACKEDVERSION}" >= 0x03000000 + Unicode true + ManifestDPIAware true +!endif + ; CERTBOT CUSTOM BEGIN ; Administrator privileges are required to insert a new task in Windows Scheduler. ; Also comment out some options to disable ability to choose AllUsers/CurrentUser install mode. @@ -35,9 +40,10 @@ SetCompressor lzma !define MULTIUSER_INSTALLMODE_FUNCTION correct_prog_files [% endif %] !include MultiUser.nsh +!include FileFunc.nsh [% block modernui %] -; Modern UI installer stuff +; Modern UI installer stuff !include "MUI2.nsh" !define MUI_ABORTWARNING !define MUI_ICON "[[icon]]" @@ -67,6 +73,8 @@ Name "${PRODUCT_NAME} (beta) ${PRODUCT_VERSION}" OutFile "${INSTALLER_NAME}" ShowInstDetails show +Var cmdLineInstallDir + Section -SETTINGS SetOutPath "$INSTDIR" SetOverwrite ifnewer @@ -96,14 +104,14 @@ Section "!${PRODUCT_NAME}" sec_app File "[[ file ]]" [% endfor %] [% endfor %] - + ; Install directories [% for dir, destination in ib.install_dirs %] SetOutPath "[[ pjoin(destination, dir) ]]" File /r "[[dir]]\*.*" [% endfor %] [% endblock install_files %] - + [% block install_shortcuts %] ; Install shortcuts ; The output path becomes the working directory for shortcuts @@ -127,7 +135,6 @@ Section "!${PRODUCT_NAME}" sec_app [% block install_commands %] [% if has_commands %] DetailPrint "Setting up command-line launchers..." - nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_assemble_launchers.py" [[ python ]] "$INSTDIR\bin"' StrCmp $MultiUser.InstallMode CurrentUser 0 AddSysPathSystem ; Add to PATH for current user @@ -139,7 +146,7 @@ Section "!${PRODUCT_NAME}" sec_app AddedSysPath: [% endif %] [% endblock install_commands %] - + ; Byte-compile Python files. DetailPrint "Byte-compiling Python modules..." nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"' @@ -238,12 +245,25 @@ Function .onMouseOverSection [% block mouseover_messages %] StrCmp $0 ${sec_app} "" +2 SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}" - + [% endblock mouseover_messages %] FunctionEnd Function .onInit + ; Multiuser.nsh breaks /D command line parameter. Parse /INSTDIR instead. + ; Cribbing from https://nsis-dev.github.io/NSIS-Forums/html/t-299280.html + ${GetParameters} $0 + ClearErrors + ${GetOptions} '$0' "/INSTDIR=" $1 + IfErrors +2 ; Error means flag not found + StrCpy $cmdLineInstallDir $1 + ClearErrors + !insertmacro MULTIUSER_INIT + + ; If cmd line included /INSTDIR, override the install dir set by MultiUser + StrCmp $cmdLineInstallDir "" +2 + StrCpy $INSTDIR $cmdLineInstallDir FunctionEnd Function un.onInit @@ -257,4 +277,4 @@ Function correct_prog_files StrCmp $MultiUser.InstallMode AllUsers 0 +2 StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}" FunctionEnd -[% endif %] \ No newline at end of file +[% endif %]