diff --git a/.azure-pipelines/INSTALL.md b/.azure-pipelines/INSTALL.md index 9c1e4bff7..1a50bcb0c 100644 --- a/.azure-pipelines/INSTALL.md +++ b/.azure-pipelines/INSTALL.md @@ -69,12 +69,12 @@ Access can be defined for all or only selected repositories, which is nice. ``` - Redirected to Azure DevOps, select the account created in _Having an Azure DevOps account_ section. -- Select the organization, and click "Create a new project" (let's name it the same than the targetted github repo) +- Select the organization, and click "Create a new project" (let's name it the same than the targeted github repo) - The Visibility is public, to profit from 10 parallel jobs ``` !!! ACCESS !!! -Azure Pipelines needs access to the GitHub account (in term of beeing able to check it is valid), and the Resources shared between the GitHub account and Azure Pipelines. +Azure Pipelines needs access to the GitHub account (in term of being able to check it is valid), and the Resources shared between the GitHub account and Azure Pipelines. ``` _Done. We can move to pipelines configuration._ diff --git a/.azure-pipelines/templates/installer-tests.yml b/.azure-pipelines/templates/installer-tests.yml index e3a005334..f1ccd92ed 100644 --- a/.azure-pipelines/templates/installer-tests.yml +++ b/.azure-pipelines/templates/installer-tests.yml @@ -40,7 +40,7 @@ jobs: displayName: Retrieve Windows installer - script: $(Build.SourcesDirectory)\bin\certbot-beta-installer-win32.exe /S displayName: Install Certbot - - powershell: Invoke-WebRequest https://www.python.org/ftp/python/3.8.0/python-3.8.0-amd64-webinstall.exe -OutFile C:\py3-setup.exe + - powershell: Invoke-WebRequest https://www.python.org/ftp/python/3.8.1/python-3.8.1-amd64-webinstall.exe -OutFile C:\py3-setup.exe displayName: Get Python - script: C:\py3-setup.exe /quiet PrependPath=1 InstallAllUsers=1 Include_launcher=1 InstallLauncherAllUsers=1 Include_test=0 Include_doc=0 Include_dev=1 Include_debug=0 Include_tcltk=0 TargetDir=C:\py3 displayName: Install Python diff --git a/.gitignore b/.gitignore index 68762da6b..6dd422187 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ tags \#*# .idea .ropeproject +.vscode # auth --cert-path --chain-path /*.pem diff --git a/.travis.yml b/.travis.yml index 9f18b04ac..9a11c4f7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,11 +59,8 @@ matrix: dist: trusty env: TOXENV='py27-{acme,apache,apache-v2,certbot,dns,nginx}-oldest' <<: *not-on-master - - python: "3.4" - env: TOXENV=py34 - <<: *not-on-master - - python: "3.7" - env: TOXENV=py37 + - python: "3.5" + env: TOXENV=py35 <<: *not-on-master - python: "3.8" env: TOXENV=py38 @@ -163,31 +160,12 @@ matrix: sudo: required services: docker <<: *extended-test-suite - - python: "3.4" - env: TOXENV=py34 - <<: *extended-test-suite - - python: "3.5" - env: TOXENV=py35 - <<: *extended-test-suite - python: "3.6" env: TOXENV=py36 <<: *extended-test-suite - python: "3.7" env: TOXENV=py37 <<: *extended-test-suite - - python: "3.8" - env: TOXENV=py38 - <<: *extended-test-suite - - python: "3.4" - env: ACME_SERVER=boulder-v1 TOXENV=integration - sudo: required - services: docker - <<: *extended-test-suite - - python: "3.4" - env: ACME_SERVER=boulder-v2 TOXENV=integration - sudo: required - services: docker - <<: *extended-test-suite - python: "3.5" env: ACME_SERVER=boulder-v1 TOXENV=integration sudo: required @@ -232,6 +210,10 @@ matrix: env: TOXENV=le_auto_centos6 services: docker <<: *extended-test-suite + - sudo: required + env: TOXENV=le_auto_oraclelinux6 + services: docker + <<: *extended-test-suite - sudo: required env: TOXENV=docker_dev services: docker @@ -243,9 +225,6 @@ matrix: - language: generic env: TOXENV=py27 os: osx - # Using this osx_image is a workaround for - # https://travis-ci.community/t/xcode-8-3-homebrew-outdated-error/3798. - osx_image: xcode10.2 addons: homebrew: packages: @@ -255,9 +234,6 @@ matrix: - language: generic env: TOXENV=py3 os: osx - # Using this osx_image is a workaround for - # https://travis-ci.community/t/xcode-8-3-homebrew-outdated-error/3798. - osx_image: xcode10.2 addons: homebrew: packages: diff --git a/AUTHORS.md b/AUTHORS.md index d24c5be1d..80a24d3be 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -36,6 +36,7 @@ Authors * [Brad Warren](https://github.com/bmw) * [Brandon Kraft](https://github.com/kraftbj) * [Brandon Kreisel](https://github.com/kraftbj) +* [Cameron Steel](https://github.com/Tugzrida) * [Ceesjan Luiten](https://github.com/quinox) * [Chad Whitacre](https://github.com/whit537) * [Chhatoi Pritam Baral](https://github.com/pritambaral) @@ -100,6 +101,7 @@ Authors * [Harlan Lieberman-Berg](https://github.com/hlieberman) * [Henri Salo](https://github.com/fgeek) * [Henry Chen](https://github.com/henrychen95) +* [Hugo van Kemenade](https://github.com/hugovk) * [Ingolf Becker](https://github.com/watercrossing) * [Jaap Eldering](https://github.com/eldering) * [Jacob Hoffman-Andrews](https://github.com/jsha) @@ -124,6 +126,7 @@ Authors * [Jonathan Herlin](https://github.com/Jonher937) * [Jon Walsh](https://github.com/code-tree) * [Joona Hoikkala](https://github.com/joohoi) +* [Josh McCullough](https://github.com/JoshMcCullough) * [Josh Soref](https://github.com/jsoref) * [Joubin Jabbari](https://github.com/joubin) * [Juho Juopperi](https://github.com/jkjuopperi) diff --git a/acme/acme/client.py b/acme/acme/client.py index 527430120..f48ff40b2 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -942,7 +942,7 @@ class ClientNetwork(object): :param messages.RegistrationResource account: Account object. Required if you are planning to use .post() with acme_version=2 for anything other than creating a new account; may be set later after registering. - :param josepy.JWASignature alg: Algoritm to use in signing JWS. + :param josepy.JWASignature alg: Algorithm to use in signing JWS. :param bool verify_ssl: Whether to verify certificates on SSL connections. :param str user_agent: String to send as User-Agent header. :param float timeout: Timeout for requests. diff --git a/acme/acme/messages.py b/acme/acme/messages.py index 96a1ed7c0..e82d12890 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -36,7 +36,7 @@ ERROR_CODES = { ' domain'), 'dns': 'There was a problem with a DNS query during identifier validation', 'dnssec': 'The server could not validate a DNSSEC signed domain', - 'incorrectResponse': 'Response recieved didn\'t match the challenge\'s requirements', + 'incorrectResponse': 'Response received didn\'t match the challenge\'s requirements', # deprecate invalidEmail 'invalidEmail': 'The provided email for a registration was invalid', 'invalidContact': 'The provided contact URI was invalid', @@ -245,13 +245,13 @@ class Directory(jose.JSONDeSerializable): try: return self[name.replace('_', '-')] except KeyError as error: - raise AttributeError(str(error) + ': ' + name) + raise AttributeError(str(error)) def __getitem__(self, name): try: return self._jobj[self._canon_key(name)] except KeyError: - raise KeyError('Directory field not found') + raise KeyError('Directory field "' + self._canon_key(name) + '" not found') def to_partial_json(self): return self._jobj diff --git a/acme/docs/conf.py b/acme/docs/conf.py index 01029a81f..8c1689128 100644 --- a/acme/docs/conf.py +++ b/acme/docs/conf.py @@ -41,7 +41,7 @@ extensions = [ ] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/acme/setup.py b/acme/setup.py index 6da5fe519..458ca083d 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -4,7 +4,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ @@ -61,7 +61,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', @@ -70,7 +70,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-apache/MANIFEST.in b/certbot-apache/MANIFEST.in index fa15504e7..2316983bb 100644 --- a/certbot-apache/MANIFEST.in +++ b/certbot-apache/MANIFEST.in @@ -1,7 +1,6 @@ include LICENSE.txt include README.rst recursive-include tests * -include certbot_apache/_internal/centos-options-ssl-apache.conf include certbot_apache/_internal/options-ssl-apache.conf recursive-include certbot_apache/_internal/augeas_lens *.aug global-exclude __pycache__ diff --git a/certbot-apache/certbot_apache/_internal/centos-options-ssl-apache.conf b/certbot-apache/certbot_apache/_internal/centos-options-ssl-apache.conf deleted file mode 100644 index 56c946a4e..000000000 --- a/certbot-apache/certbot_apache/_internal/centos-options-ssl-apache.conf +++ /dev/null @@ -1,25 +0,0 @@ -# This file contains important security parameters. If you modify this file -# manually, Certbot will be unable to automatically provide future security -# updates. Instead, Certbot will print and log an error message with a path to -# the up-to-date file that you will need to refer to when manually updating -# this file. - -SSLEngine on - -# Intermediate configuration, tweak to your needs -SSLProtocol all -SSLv2 -SSLv3 -SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS -SSLHonorCipherOrder on - -SSLOptions +StrictRequire - -# Add vhost name to log entries: -LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined -LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common - -#CustomLog /var/log/apache2/access.log vhost_combined -#LogLevel warn -#ErrorLog /var/log/apache2/error.log - -# Always ensure Cookies have "Secure" set (JAH 2012/1) -#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4" diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index 7d53fdae5..e9ed1f8ab 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -1946,7 +1946,7 @@ class ApacheConfigurator(common.Installer): ssl_vhost.filep) def _verify_no_matching_http_header(self, ssl_vhost, header_substring): - """Checks to see if an there is an existing Header directive that + """Checks to see if there is an existing Header directive that contains the string header_substring. :param ssl_vhost: vhost to check diff --git a/certbot-apache/certbot_apache/_internal/constants.py b/certbot-apache/certbot_apache/_internal/constants.py index 47e3be856..a37bebac5 100644 --- a/certbot-apache/certbot_apache/_internal/constants.py +++ b/certbot-apache/certbot_apache/_internal/constants.py @@ -24,6 +24,8 @@ ALL_SSL_OPTIONS_HASHES = [ '0fcdc81280cd179a07ec4d29d3595068b9326b455c488de4b09f585d5dafc137', '86cc09ad5415cd6d5f09a947fe2501a9344328b1e8a8b458107ea903e80baa6c', '06675349e457eae856120cdebb564efe546f0b87399f2264baeb41e442c724c7', + '5cc003edd93fb9cd03d40c7686495f8f058f485f75b5e764b789245a386e6daf', + '007cd497a56a3bb8b6a2c1aeb4997789e7e38992f74e44cc5d13a625a738ac73', ] """SHA256 hashes of the contents of previous versions of all versions of MOD_SSL_CONF_SRC""" diff --git a/certbot-apache/certbot_apache/_internal/options-ssl-apache.conf b/certbot-apache/certbot_apache/_internal/options-ssl-apache.conf index 8113ee81e..1a3799628 100644 --- a/certbot-apache/certbot_apache/_internal/options-ssl-apache.conf +++ b/certbot-apache/certbot_apache/_internal/options-ssl-apache.conf @@ -7,20 +7,12 @@ SSLEngine on # Intermediate configuration, tweak to your needs -SSLProtocol all -SSLv2 -SSLv3 -SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS -SSLHonorCipherOrder on -SSLCompression off +SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 +SSLHonorCipherOrder off SSLOptions +StrictRequire # Add vhost name to log entries: LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common - -#CustomLog /var/log/apache2/access.log vhost_combined -#LogLevel warn -#ErrorLog /var/log/apache2/error.log - -# Always ensure Cookies have "Secure" set (JAH 2012/1) -#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4" diff --git a/certbot-apache/certbot_apache/_internal/override_centos.py b/certbot-apache/certbot_apache/_internal/override_centos.py index b3576e083..a3ef2d760 100644 --- a/certbot-apache/certbot_apache/_internal/override_centos.py +++ b/certbot-apache/certbot_apache/_internal/override_centos.py @@ -38,7 +38,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator): handle_sites=False, challenge_location="/etc/httpd/conf.d", MOD_SSL_CONF_SRC=pkg_resources.resource_filename( - "certbot_apache", os.path.join("_internal", "centos-options-ssl-apache.conf")) + "certbot_apache", os.path.join("_internal", "options-ssl-apache.conf")) ) def config_test(self): diff --git a/certbot-apache/certbot_apache/_internal/override_fedora.py b/certbot-apache/certbot_apache/_internal/override_fedora.py index a9607a60f..8197b0dcd 100644 --- a/certbot-apache/certbot_apache/_internal/override_fedora.py +++ b/certbot-apache/certbot_apache/_internal/override_fedora.py @@ -33,7 +33,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): challenge_location="/etc/httpd/conf.d", MOD_SSL_CONF_SRC=pkg_resources.resource_filename( # TODO: eventually newest version of Fedora will need their own config - "certbot_apache", os.path.join("_internal", "centos-options-ssl-apache.conf")) + "certbot_apache", os.path.join("_internal", "options-ssl-apache.conf")) ) def config_test(self): diff --git a/certbot-apache/certbot_apache/_internal/parser.py b/certbot-apache/certbot_apache/_internal/parser.py index dca8cedf4..aae3dc6e4 100644 --- a/certbot-apache/certbot_apache/_internal/parser.py +++ b/certbot-apache/certbot_apache/_internal/parser.py @@ -705,7 +705,7 @@ class ApacheParser(object): split_arg = arg.split("/") for idx, split in enumerate(split_arg): if any(char in ApacheParser.fnmatch_chars for char in split): - # Turn it into a augeas regex + # Turn it into an augeas regex # TODO: Can this instead be an augeas glob instead of regex split_arg[idx] = ("* [label()=~regexp('%s')]" % self.fnmatch_to_re(split)) diff --git a/certbot-apache/local-oldest-requirements.txt b/certbot-apache/local-oldest-requirements.txt index 3fce6f83b..cf61c15a5 100644 --- a/certbot-apache/local-oldest-requirements.txt +++ b/certbot-apache/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index c48b8a336..f1ce5c879 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'mock', 'python-augeas', 'setuptools', @@ -45,7 +45,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -56,7 +56,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf index fb2174af1..abe07dd0c 100644 --- a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf +++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf @@ -26,7 +26,7 @@ Listen 443 # Pass Phrase Dialog: # Configure the pass phrase gathering process. -# The filtering dialog program (`builtin' is a internal +# The filtering dialog program (`builtin' is an internal # terminal dialog) has to provide the pass phrase on stdout. SSLPassPhraseDialog builtin diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf index 579d194ce..eac6143da 100644 --- a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf +++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf @@ -702,7 +702,7 @@ IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t # English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de) # Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja) # Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn) -# Norwegian (no) - Polish (pl) - Portugese (pt) +# Norwegian (no) - Polish (pl) - Portuguese (pt) # Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv) # Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW) # diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf index 6e2502e9a..c90fc780f 100644 --- a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf +++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf @@ -13,7 +13,7 @@ Listen 443 https # Pass Phrase Dialog: # Configure the pass phrase gathering process. -# The filtering dialog program (`builtin' is a internal +# The filtering dialog program (`builtin' is an internal # terminal dialog) has to provide the pass phrase on stdout. SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf index e9fcf4f9b..65baec874 100644 --- a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf +++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf @@ -31,7 +31,7 @@ # Pass Phrase Dialog: # Configure the pass phrase gathering process. - # The filtering dialog program (`builtin' is a internal + # The filtering dialog program (`builtin' is an internal # terminal dialog) has to provide the pass phrase on stdout. SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf index e9fcf4f9b..65baec874 100644 --- a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf +++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf @@ -31,7 +31,7 @@ # Pass Phrase Dialog: # Configure the pass phrase gathering process. - # The filtering dialog program (`builtin' is a internal + # The filtering dialog program (`builtin' is an internal # terminal dialog) has to provide the pass phrase on stdout. SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf index e9fcf4f9b..65baec874 100644 --- a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf +++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf @@ -31,7 +31,7 @@ # Pass Phrase Dialog: # Configure the pass phrase gathering process. - # The filtering dialog program (`builtin' is a internal + # The filtering dialog program (`builtin' is an internal # terminal dialog) has to provide the pass phrase on stdout. SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf index c429bf94c..10cf3fb54 100644 --- a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf +++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf @@ -33,7 +33,7 @@ # English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de) # Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja) # Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn) -# Norwegian (no) - Polish (pl) - Portugese (pt) +# Norwegian (no) - Polish (pl) - Portuguese (pt) # Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv) # Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW) AddLanguage ca .ca diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf index f51de4641..7f3cef423 100644 --- a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf +++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf @@ -43,7 +43,7 @@ SSLRandomSeed connect builtin ## Pass Phrase Dialog: # Configure the pass phrase gathering process. The filtering dialog program -# (`builtin' is a internal terminal dialog) has to provide the pass phrase on +# (`builtin' is an internal terminal dialog) has to provide the pass phrase on # stdout. SSLPassPhraseDialog builtin diff --git a/certbot-auto b/certbot-auto index 24c007e03..2d3f4cfef 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.0.0" +LE_AUTO_VERSION="1.1.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -256,20 +256,28 @@ DeprecationBootstrap() { fi } -MIN_PYTHON_VERSION="2.7" -MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//') +MIN_PYTHON_2_VERSION="2.7" +MIN_PYVER2=$(echo "$MIN_PYTHON_2_VERSION" | sed 's/\.//') +MIN_PYTHON_3_VERSION="3.5" +MIN_PYVER3=$(echo "$MIN_PYTHON_3_VERSION" | sed 's/\.//') # Sets LE_PYTHON to Python version string and PYVER to the first two -# digits of the python version +# digits of the python version. +# MIN_PYVER and MIN_PYTHON_VERSION are also set by this function, and their +# values depend on if we try to use Python 3 or Python 2. DeterminePythonVersion() { # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python # # If no Python is found, PYVER is set to 0. if [ "$USE_PYTHON_3" = 1 ]; then + MIN_PYVER=$MIN_PYVER3 + MIN_PYTHON_VERSION=$MIN_PYTHON_3_VERSION for LE_PYTHON in "$LE_PYTHON" python3; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break done else + MIN_PYVER=$MIN_PYVER2 + MIN_PYTHON_VERSION=$MIN_PYTHON_2_VERSION for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break @@ -285,7 +293,7 @@ DeterminePythonVersion() { fi fi - PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + PYVER=$("$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') if [ "$PYVER" -lt "$MIN_PYVER" ]; then if [ "$1" != "NOCRASH" ]; then error "You have an ancient version of Python entombed in your operating system..." @@ -368,7 +376,9 @@ BootstrapDebCommon() { # Sets TOOL to the name of the package manager # Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG. -# Enables EPEL if applicable and possible. +# Note: this function is called both while selecting the bootstrap scripts and +# during the actual bootstrap. Some things like prompting to user can be done in the latter +# case, but not in the former one. InitializeRPMCommonBase() { if type dnf 2>/dev/null then @@ -388,26 +398,6 @@ InitializeRPMCommonBase() { if [ "$QUIET" = 1 ]; then QUIET_FLAG='--quiet' fi - - if ! $TOOL list *virtualenv >/dev/null 2>&1; then - echo "To use Certbot, packages from the EPEL repository need to be installed." - if ! $TOOL list epel-release >/dev/null 2>&1; then - error "Enable the EPEL repository and try running Certbot again." - exit 1 - fi - if [ "$ASSUME_YES" = 1 ]; then - /bin/echo -n "Enabling the EPEL repository in 3 seconds..." - sleep 1s - /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..." - sleep 1s - /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..." - sleep 1s - fi - if ! $TOOL install $YES_FLAG $QUIET_FLAG epel-release; then - error "Could not enable EPEL. Aborting bootstrap!" - exit 1 - fi - fi } BootstrapRpmCommonBase() { @@ -488,13 +478,91 @@ BootstrapRpmCommon() { BootstrapRpmCommonBase "$python_pkgs" } +# If new packages are installed by BootstrapRpmPython3 below, this version +# number must be increased. +BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION=1 + +# Checks if rh-python36 can be installed. +Python36SclIsAvailable() { + InitializeRPMCommonBase >/dev/null 2>&1; + + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + return 0 + fi + if "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + return 0 + fi + return 1 +} + +# Try to enable rh-python36 from SCL if it is necessary and possible. +EnablePython36SCL() { + if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then + return 0 + fi + if [ ! -f /opt/rh/rh-python36/enable ]; then + return 0 + fi + set +e + if ! . /opt/rh/rh-python36/enable; then + error 'Unable to enable rh-python36!' + exit 1 + fi + set -e +} + +# This bootstrap concerns old RedHat-based distributions that do not ship by default +# with Python 2.7, but only Python 2.6. We bootstrap them by enabling SCL and installing +# Python 3.6. Some of these distributions are: CentOS/RHEL/OL/SL 6. +BootstrapRpmPython3Legacy() { + # Tested with: + # - CentOS 6 + + InitializeRPMCommonBase + + if ! "${TOOL}" list rh-python36 >/dev/null 2>&1; then + echo "To use Certbot on this operating system, packages from the SCL repository need to be installed." + if ! "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + error "Enable the SCL repository and try running Certbot again." + exit 1 + fi + if [ "${ASSUME_YES}" = 1 ]; then + /bin/echo -n "Enabling the SCL repository in 3 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -ne "\e[0K\rEnabling the SCL repository in 2 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -e "\e[0K\rEnabling the SCL repository in 1 second... (Press Ctrl-C to cancel)" + sleep 1s + fi + if ! "${TOOL}" install "${YES_FLAG}" "${QUIET_FLAG}" centos-release-scl; then + error "Could not enable SCL. Aborting bootstrap!" + exit 1 + fi + fi + + # CentOS 6 must use rh-python36 from SCL + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + python_pkgs="rh-python36-python + rh-python36-python-virtualenv + rh-python36-python-devel + " + else + error "No supported Python package available to install. Aborting bootstrap!" + exit 1 + fi + + BootstrapRpmCommonBase "${python_pkgs}" + + # Enable SCL rh-python36 after bootstrapping. + EnablePython36SCL +} + # If new packages are installed by BootstrapRpmPython3 below, this version # number must be increased. BOOTSTRAP_RPM_PYTHON3_VERSION=1 BootstrapRpmPython3() { # Tested with: - # - CentOS 6 # - Fedora 29 InitializeRPMCommonBase @@ -505,12 +573,6 @@ BootstrapRpmPython3() { python3-virtualenv python3-devel " - # EPEL uses python34 - elif $TOOL list python34 >/dev/null 2>&1; then - python_pkgs="python34 - python34-devel - python34-tools - " else error "No supported Python package available to install. Aborting bootstrap!" exit 1 @@ -758,6 +820,11 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` + if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then + # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. + DEPRECATED_OS=1 + fi + # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an # error, RPM_DIST_VERSION is set to "unknown". @@ -769,31 +836,50 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_VERSION=0 fi - # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. - # RHEL 8 also uses python3 by default. - if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 -o "$PYVER" -eq 26 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - else - RPM_USE_PYTHON_3=0 - fi + # Handle legacy RPM distributions + if [ "$PYVER" -eq 26 ]; then + # Check if an automated bootstrap can be achieved on this system. + if ! Python36SclIsAvailable; then + INTERACTIVE_BOOTSTRAP=1 + fi - if [ "$RPM_USE_PYTHON_3" = 1 ]; then Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 + BootstrapMessage "Legacy RedHat-based OSes that will use Python3" + BootstrapRpmPython3Legacy } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" + 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 + EnablePython36SCL else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. + # RHEL 8 also uses python3 by default. + if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + else + RPM_USE_PYTHON_3=0 + 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" @@ -870,6 +956,13 @@ if [ "$NO_BOOTSTRAP" = 1 ]; then unset BOOTSTRAP_VERSION fi +if [ "$DEPRECATED_OS" = 1 ]; then + Bootstrap() { + error "Skipping bootstrap because certbot-auto is deprecated on this system." + } + unset BOOTSTRAP_VERSION +fi + # Sets PREV_BOOTSTRAP_VERSION to the identifier for the bootstrap script used # to install OS dependencies on this system. PREV_BOOTSTRAP_VERSION isn't set # if it is unknown how OS dependencies were installed on this system. @@ -1067,6 +1160,28 @@ if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. shift 1 # the --le-auto-phase2 arg + + if [ "$DEPRECATED_OS" = 1 ]; then + # Phase 2 damage control mode for deprecated OSes. + # In this situation, we bypass any bootstrap or certbot venv setup. + error "Your system is not supported by certbot-auto anymore." + + if [ ! -d "$VENV_PATH" ] && OldVenvExists; then + VENV_BIN="$OLD_VENV_PATH/bin" + fi + + if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then + error "Certbot will no longer receive updates." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + "$VENV_BIN/letsencrypt" "$@" + exit 0 + else + error "Certbot cannot be installed." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + exit 1 + fi + fi + SetPrevBootstrapVersion if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then @@ -1078,8 +1193,15 @@ if [ "$1" = "--le-auto-phase2" ]; then # If the selected Bootstrap function isn't a noop and it differs from the # previously used version if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then - # if non-interactive mode or stdin and stdout are connected to a terminal - if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then + # Check if we can rebootstrap without manual user intervention: this requires that + # certbot-auto is in non-interactive mode AND selected bootstrap does not claim to + # require a manual user intervention. + if [ "$NONINTERACTIVE" = 1 -a "$INTERACTIVE_BOOTSTRAP" != 1 ]; then + CAN_REBOOTSTRAP=1 + fi + # Check if rebootstrap can be done non-interactively and current shell is non-interactive + # (true if stdin and stdout are not attached to a terminal). + if [ \( "$CAN_REBOOTSTRAP" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then if [ -d "$VENV_PATH" ]; then rm -rf "$VENV_PATH" fi @@ -1090,12 +1212,21 @@ if [ "$1" = "--le-auto-phase2" ]; then ln -s "$VENV_PATH" "$OLD_VENV_PATH" fi RerunWithArgs "$@" + # Otherwise bootstrap needs to be done manually by the user. else - error "Skipping upgrade because new OS dependencies may need to be installed." - error - error "To upgrade to a newer version, please run this script again manually so you can" - error "approve changes or with --non-interactive on the command line to automatically" - error "install any required packages." + # If it is because bootstrapping is interactive, --non-interactive will be of no use. + if [ "$INTERACTIVE_BOOTSTRAP" = 1 ]; then + error "Skipping upgrade because new OS dependencies may need to be installed." + error "This requires manual user intervention: please run this script again manually." + # If this is because of the environment (eg. non interactive shell without + # --non-interactive flag set), help the user in that direction. + else + error "Skipping upgrade because new OS dependencies may need to be installed." + error + error "To upgrade to a newer version, please run this script again manually so you can" + error "approve changes or with --non-interactive on the command line to automatically" + error "install any required packages." + fi # Set INSTALLED_VERSION to be the same so we don't update the venv INSTALLED_VERSION="$LE_AUTO_VERSION" # Continue to use OLD_VENV_PATH if the new venv doesn't exist @@ -1372,18 +1503,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.0.0 \ - --hash=sha256:8d074cff89dee002dec1c47cb0da04ea8e0ede8d68838b6d54aa41580d9262df \ - --hash=sha256:86b82d31db19fffffb0d6b218951e2121ef514e3ff659aa042deaf92a33e302a -acme==1.0.0 \ - --hash=sha256:f6972e436e76f7f1e395e81e149f8713ca8462d465b14993bddc53fb18a40644 \ - --hash=sha256:6a08f12f848ce563b50bca421ba9db653df9f82cfefeaf8aba517f046d1386c2 -certbot-apache==1.0.0 \ - --hash=sha256:e591d0cf773ad33ee978f7adb1b69288eac2c8847c643b06e70260e707626f8e \ - --hash=sha256:7335ab5687a0a47d9041d9e13f3a2d67d0e8372da97ab639edb31c14b787cd68 -certbot-nginx==1.0.0 \ - --hash=sha256:ce8a2e51165da7c15bfdc059cd6572d0f368c078f1e1a77633a2773310b2f231 \ - --hash=sha256:63b4ae09d4f1c9ef0a1a2a49c3f651d8a7cb30303ec6f954239e987c5da45dc4 +certbot==1.1.0 \ + --hash=sha256:66a5cab9267349941604c2c98082bfef85877653c023fc324b1c3869fb16add6 \ + --hash=sha256:46e93661a0db53f416c0f5476d8d2e62bc7259b7660dd983453b85df9ef6e8b8 +acme==1.1.0 \ + --hash=sha256:11b9beba706fb8f652c8910d46dd1939d670cac8169f3c66c18c080ed3353e71 \ + --hash=sha256:c305a20eeb9cb02240347703d497891c13d43a47c794fa100d4dbb479a5370d9 +certbot-apache==1.1.0 \ + --hash=sha256:9c847ff223c2e465e241c78d22f97cee77d5e551df608bed06c55f8627f4cbd2 \ + --hash=sha256:05e84dfe96b72582cde97c490977d8e2d33d440c927a320debb4cf287f6fadcc +certbot-nginx==1.1.0 \ + --hash=sha256:bf06fa2f5059f0fdb7d352c8739e1ed0830db4f0d89e812dab4f081bda6ec7d6 \ + --hash=sha256:0a80ecbd2a30f3757c7652cabfff854ca07873b1cf02ebbe1892786c3b3a5874 UNLIKELY_EOF # ------------------------------------------------------------------------- @@ -1617,6 +1748,9 @@ UNLIKELY_EOF say "Installation succeeded." fi + # If you're modifying any of the code after this point in this current `if` block, you + # may need to update the "$DEPRECATED_OS" = 1 case at the beginning of phase 2 as well. + if [ "$INSTALL_ONLY" = 1 ]; then say "Certbot is installed." exit 0 @@ -1828,30 +1962,35 @@ UNLIKELY_EOF error "WARNING: unable to check for updates." fi - LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then - say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" - elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then - say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + # If for any reason REMOTE_VERSION is not set, let's assume certbot-auto is up-to-date, + # and do not go into the self-upgrading process. + if [ -n "$REMOTE_VERSION" ]; then + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then + say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - # Install new copy of certbot-auto. - # TODO: Deal with quotes in pathnames. - say "Replacing certbot-auto..." - # Clone permissions with cp. chmod and chown don't have a --reference - # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: - cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" - cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" - # Using mv rather than cp leaves the old file descriptor pointing to the - # original copy so the shell can continue to read it unmolested. mv across - # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the - # cp is unlikely to fail if the rm doesn't. - mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" - fi # A newer version is available. + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + + # Install new copy of certbot-auto. + # TODO: Deal with quotes in pathnames. + say "Replacing certbot-auto..." + # Clone permissions with cp. chmod and chown don't have a --reference + # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: + cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" + cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" + # Using mv rather than cp leaves the old file descriptor pointing to the + # original copy so the shell can continue to read it unmolested. mv across + # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the + # cp is unlikely to fail if the rm doesn't. + mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" + fi # A newer version is available. + fi fi # Self-upgrading is allowed. RerunWithArgs --le-auto-phase2 "$@" diff --git a/certbot-ci/certbot_integration_tests/conftest.py b/certbot-ci/certbot_integration_tests/conftest.py index 6eb9ee865..bb1d76e57 100644 --- a/certbot-ci/certbot_integration_tests/conftest.py +++ b/certbot-ci/certbot_integration_tests/conftest.py @@ -62,7 +62,7 @@ def _setup_primary_node(config): """ Setup the environment for integration tests. Will: - - check runtime compatiblity (Docker, docker-compose, Nginx) + - check runtime compatibility (Docker, docker-compose, Nginx) - create a temporary workspace and the persistent GIT repositories space - configure and start paralleled ACME CA servers using Docker - transfer ACME CA servers configurations to pytest nodes using env variables diff --git a/certbot-ci/certbot_integration_tests/utils/acme_server.py b/certbot-ci/certbot_integration_tests/utils/acme_server.py index fbf97fef1..5483251e6 100755 --- a/certbot-ci/certbot_integration_tests/utils/acme_server.py +++ b/certbot-ci/certbot_integration_tests/utils/acme_server.py @@ -189,7 +189,7 @@ class ACMEServer(object): print('=> Finished configuring the HTTP proxy.') def _launch_process(self, command, cwd=os.getcwd(), env=None): - """Launch silently an subprocess OS command""" + """Launch silently a subprocess OS command""" if not env: env = os.environ process = subprocess.Popen(command, stdout=self._stdout, stderr=subprocess.STDOUT, cwd=cwd, env=env) diff --git a/certbot-ci/setup.py b/certbot-ci/setup.py index fb82b6ca5..75d2cc96a 100644 --- a/certbot-ci/setup.py +++ b/certbot-ci/setup.py @@ -40,7 +40,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', @@ -49,7 +49,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-compatibility-test/certbot_compatibility_test/validator_test.py b/certbot-compatibility-test/certbot_compatibility_test/validator_test.py index 86edbdb55..235ce0e3c 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/validator_test.py +++ b/certbot-compatibility-test/certbot_compatibility_test/validator_test.py @@ -39,7 +39,7 @@ class ValidatorTest(unittest.TestCase): cert, "test.com", "127.0.0.1")) @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_succesful_redirect(self, mock_get_request): + def test_successful_redirect(self, mock_get_request): mock_get_request.return_value = create_response( 301, {"location": "https://test.com"}) self.assertTrue(self.validator.redirect("test.com")) diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index f26fb0706..c3443e35e 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.1.0.dev0' +version = '1.2.0.dev0' install_requires = [ 'certbot', @@ -28,7 +28,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', @@ -37,7 +37,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py index b08bc0968..11886ea54 100644 --- a/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py +++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py @@ -22,17 +22,40 @@ Credentials Use of this plugin requires a configuration file containing Cloudflare API credentials, obtained from your Cloudflare -`account page `_. This plugin -does not currently support Cloudflare's "API Tokens", so please ensure you use -the "Global API Key" for authentication. +`account page `_. + +Previously, Cloudflare's "Global API Key" was used for authentication, however +this key can access the entire Cloudflare API for all domains in your account, +meaning it could cause a lot of damage if leaked. + +Cloudflare's newer API Tokens can be restricted to specific domains and +operations, and are therefore now the recommended authentication option. + +However, due to some shortcomings in Cloudflare's implementation of Tokens, +Tokens created for Certbot currently require ``Zone:Zone:Read`` and ``Zone:DNS:Edit`` +permissions for **all** zones in your account. While this is not ideal, your Token +will still have fewer permission than the Global key, so it's still worth doing. +Hopefully Cloudflare will improve this in the future. + +Using Cloudflare Tokens also requires at least version 2.3.1 of the ``cloudflare`` +python module. If the version that automatically installed with this plugin is +older than that, and you can't upgrade it on your system, you'll have to stick to +the Global key. .. code-block:: ini - :name: credentials.ini - :caption: Example credentials file: + :name: certbot_cloudflare_token.ini + :caption: Example credentials file using restricted API Token (recommended): + + # Cloudflare API token used by Certbot + dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567 + +.. code-block:: ini + :name: certbot_cloudflare_key.ini + :caption: Example credentials file using Global API Key (not recommended): # Cloudflare API credentials used by Certbot dns_cloudflare_email = cloudflare@example.com - dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567 + dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234 The path to this file can be provided interactively or using the ``--dns-cloudflare-credentials`` command-line argument. Certbot records the path diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py index 0bbdf703a..22124ac04 100644 --- a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py +++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py @@ -4,6 +4,10 @@ import logging import CloudFlare import zope.interface +from acme.magic_typing import Any +from acme.magic_typing import Dict +from acme.magic_typing import List + from certbot import errors from certbot import interfaces from certbot.plugins import dns_common @@ -38,14 +42,35 @@ class Authenticator(dns_common.DNSAuthenticator): return 'This plugin configures a DNS TXT record to respond to a dns-01 challenge using ' + \ 'the Cloudflare API.' + def _validate_credentials(self, credentials): + token = credentials.conf('api-token') + email = credentials.conf('email') + key = credentials.conf('api-key') + if token: + if email or key: + raise errors.PluginError('{}: dns_cloudflare_email and dns_cloudflare_api_key are ' + 'not needed when using an API Token' + .format(credentials.confobj.filename)) + elif email or key: + if not email: + raise errors.PluginError('{}: dns_cloudflare_email is required when using a Global ' + 'API Key. (should be email address associated with ' + 'Cloudflare account)'.format(credentials.confobj.filename)) + if not key: + raise errors.PluginError('{}: dns_cloudflare_api_key is required when using a ' + 'Global API Key. (see {})' + .format(credentials.confobj.filename, ACCOUNT_URL)) + else: + raise errors.PluginError('{}: Either dns_cloudflare_api_token (recommended), or ' + 'dns_cloudflare_email and dns_cloudflare_api_key are required.' + ' (see {})'.format(credentials.confobj.filename, ACCOUNT_URL)) + def _setup_credentials(self): self.credentials = self._configure_credentials( 'credentials', 'Cloudflare credentials INI file', - { - 'email': 'email address associated with Cloudflare account', - 'api-key': 'API key for Cloudflare account, obtained from {0}'.format(ACCOUNT_URL) - } + None, + self._validate_credentials ) def _perform(self, domain, validation_name, validation): @@ -55,6 +80,8 @@ class Authenticator(dns_common.DNSAuthenticator): self._get_cloudflare_client().del_txt_record(domain, validation_name, validation) def _get_cloudflare_client(self): + if self.credentials.conf('api-token'): + return _CloudflareClient(None, self.credentials.conf('api-token')) return _CloudflareClient(self.credentials.conf('email'), self.credentials.conf('api-key')) @@ -88,8 +115,15 @@ class _CloudflareClient(object): logger.debug('Attempting to add record to zone %s: %s', zone_id, data) self.cf.zones.dns_records.post(zone_id, data=data) # zones | pylint: disable=no-member except CloudFlare.exceptions.CloudFlareAPIError as e: + code = int(e) + hint = None + + if code == 9109: + hint = 'Does your API token have "Zone:DNS:Edit" permissions?' + logger.error('Encountered CloudFlareAPIError adding TXT record: %d %s', e, e) - raise errors.PluginError('Error communicating with the Cloudflare API: {0}'.format(e)) + raise errors.PluginError('Error communicating with the Cloudflare API: {0}{1}' + .format(e, ' ({0})'.format(hint) if hint else '')) record_id = self._find_txt_record_id(zone_id, record_name, record_content) logger.debug('Successfully added TXT record with record_id: %s', record_id) @@ -139,6 +173,8 @@ class _CloudflareClient(object): """ zone_name_guesses = dns_common.base_domain_name_guesses(domain) + zones = [] # type: List[Dict[str, Any]] + code = msg = None for zone_name in zone_name_guesses: params = {'name': zone_name, @@ -148,16 +184,26 @@ class _CloudflareClient(object): zones = self.cf.zones.get(params=params) # zones | pylint: disable=no-member except CloudFlare.exceptions.CloudFlareAPIError as e: code = int(e) + msg = str(e) hint = None if code == 6003: - hint = 'Did you copy your entire API key?' + hint = ('Did you copy your entire API token/key? To use Cloudflare tokens, ' + 'you\'ll need the python package cloudflare>=2.3.1.{}' + .format(' This certbot is running cloudflare ' + str(CloudFlare.__version__) + if hasattr(CloudFlare, '__version__') else '')) elif code == 9103: - hint = 'Did you enter the correct email address?' + hint = 'Did you enter the correct email address and Global key?' + elif code == 9109: + hint = 'Did you enter a valid Cloudflare Token?' - raise errors.PluginError('Error determining zone_id: {0} {1}. Please confirm that ' - 'you have supplied valid Cloudflare API credentials.{2}' - .format(code, e, ' ({0})'.format(hint) if hint else '')) + if hint: + raise errors.PluginError('Error determining zone_id: {0} {1}. Please confirm ' + 'that you have supplied valid Cloudflare API credentials. ({2})' + .format(code, msg, hint)) + else: + logger.debug('Unrecognised CloudFlareAPIError while finding zone_id: %d %s. ' + 'Continuing with next zone guess...', e, e) if zones: zone_id = zones[0]['id'] @@ -165,9 +211,10 @@ class _CloudflareClient(object): return zone_id raise errors.PluginError('Unable to determine zone_id for {0} using zone names: {1}. ' - 'Please confirm that the domain name has been entered correctly ' - 'and is already associated with the supplied Cloudflare account.' - .format(domain, zone_name_guesses)) + 'Please confirm that the domain name has been entered correctly ' + 'and is already associated with the supplied Cloudflare account.{2}' + .format(domain, zone_name_guesses, ' The error from Cloudflare was:' + ' {0} {1}'.format(code, msg) if code is not None else '')) def _find_txt_record_id(self, zone_id, record_name, record_content): """ diff --git a/certbot-dns-cloudflare/docs/conf.py b/certbot-dns-cloudflare/docs/conf.py index 488268577..97e54421e 100644 --- a/certbot-dns-cloudflare/docs/conf.py +++ b/certbot-dns-cloudflare/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-cloudflare/local-oldest-requirements.txt b/certbot-dns-cloudflare/local-oldest-requirements.txt index 3fce6f83b..cf61c15a5 100644 --- a/certbot-dns-cloudflare/local-oldest-requirements.txt +++ b/certbot-dns-cloudflare/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index b3fd81223..a3e64f07d 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'cloudflare>=1.5.1', 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py index b24628b0d..d38330191 100644 --- a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py +++ b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py @@ -12,6 +12,9 @@ from certbot.plugins.dns_test_common import DOMAIN from certbot.tests import util as test_util API_ERROR = CloudFlare.exceptions.CloudFlareAPIError(1000, '', '') + +API_TOKEN = 'an-api-token' + API_KEY = 'an-api-key' EMAIL = 'example@example.com' @@ -49,6 +52,50 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic expected = [mock.call.del_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY)] self.assertEqual(expected, self.mock_client.mock_calls) + def test_api_token(self): + dns_test_common.write({"cloudflare_api_token": API_TOKEN}, + self.config.cloudflare_credentials) + self.auth.perform([self.achall]) + + expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)] + self.assertEqual(expected, self.mock_client.mock_calls) + + def test_no_creds(self): + dns_test_common.write({}, self.config.cloudflare_credentials) + self.assertRaises(errors.PluginError, + self.auth.perform, + [self.achall]) + + def test_missing_email_or_key(self): + dns_test_common.write({"cloudflare_api_key": API_KEY}, self.config.cloudflare_credentials) + self.assertRaises(errors.PluginError, + self.auth.perform, + [self.achall]) + + dns_test_common.write({"cloudflare_email": EMAIL}, self.config.cloudflare_credentials) + self.assertRaises(errors.PluginError, + self.auth.perform, + [self.achall]) + + def test_email_or_key_with_token(self): + dns_test_common.write({"cloudflare_api_token": API_TOKEN, "cloudflare_email": EMAIL}, + self.config.cloudflare_credentials) + self.assertRaises(errors.PluginError, + self.auth.perform, + [self.achall]) + + dns_test_common.write({"cloudflare_api_token": API_TOKEN, "cloudflare_api_key": API_KEY}, + self.config.cloudflare_credentials) + self.assertRaises(errors.PluginError, + self.auth.perform, + [self.achall]) + + dns_test_common.write({"cloudflare_api_token": API_TOKEN, "cloudflare_email": EMAIL, + "cloudflare_api_key": API_KEY}, self.config.cloudflare_credentials) + self.assertRaises(errors.PluginError, + self.auth.perform, + [self.achall]) + class CloudflareClientTest(unittest.TestCase): record_name = "foo" @@ -83,7 +130,7 @@ class CloudflareClientTest(unittest.TestCase): def test_add_txt_record_error(self): self.cf.zones.get.return_value = [{'id': self.zone_id}] - self.cf.zones.dns_records.post.side_effect = API_ERROR + self.cf.zones.dns_records.post.side_effect = CloudFlare.exceptions.CloudFlareAPIError(9109, '', '') self.assertRaises( errors.PluginError, @@ -106,6 +153,25 @@ class CloudflareClientTest(unittest.TestCase): self.cloudflare_client.add_txt_record, DOMAIN, self.record_name, self.record_content, self.record_ttl) + def test_add_txt_record_bad_creds(self): + self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(6003, '', '') + self.assertRaises( + errors.PluginError, + self.cloudflare_client.add_txt_record, + DOMAIN, self.record_name, self.record_content, self.record_ttl) + + self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(9103, '', '') + self.assertRaises( + errors.PluginError, + self.cloudflare_client.add_txt_record, + DOMAIN, self.record_name, self.record_content, self.record_ttl) + + self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(9109, '', '') + self.assertRaises( + errors.PluginError, + self.cloudflare_client.add_txt_record, + DOMAIN, self.record_name, self.record_content, self.record_ttl) + def test_del_txt_record(self): self.cf.zones.get.return_value = [{'id': self.zone_id}] self.cf.zones.dns_records.get.return_value = [{'id': self.record_id}] diff --git a/certbot-dns-cloudxns/docs/conf.py b/certbot-dns-cloudxns/docs/conf.py index 16ccd1d62..1fc05c94c 100644 --- a/certbot-dns-cloudxns/docs/conf.py +++ b/certbot-dns-cloudxns/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-cloudxns/local-oldest-requirements.txt b/certbot-dns-cloudxns/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-cloudxns/local-oldest-requirements.txt +++ b/certbot-dns-cloudxns/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 288a6d115..a7a0072c4 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 9c493a220..0741e4cea 100644 --- a/certbot-dns-digitalocean/docs/conf.py +++ b/certbot-dns-digitalocean/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-digitalocean/local-oldest-requirements.txt b/certbot-dns-digitalocean/local-oldest-requirements.txt index 3fce6f83b..cf61c15a5 100644 --- a/certbot-dns-digitalocean/local-oldest-requirements.txt +++ b/certbot-dns-digitalocean/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index ba3190567..fe5243bc5 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'mock', 'python-digitalocean>=1.11', 'setuptools', @@ -45,7 +45,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -56,7 +56,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 b5cb24e2f..99cc93135 100644 --- a/certbot-dns-dnsimple/docs/conf.py +++ b/certbot-dns-dnsimple/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-dnsimple/local-oldest-requirements.txt b/certbot-dns-dnsimple/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-dnsimple/local-oldest-requirements.txt +++ b/certbot-dns-dnsimple/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 5729bd789..e31bc5949 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -5,13 +5,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'mock', 'setuptools', 'zope.interface', @@ -56,7 +56,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -67,7 +67,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 60e0163bd..1f0c57812 100644 --- a/certbot-dns-dnsmadeeasy/docs/conf.py +++ b/certbot-dns-dnsmadeeasy/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt b/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt +++ b/certbot-dns-dnsmadeeasy/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 6fc756389..fceb0b518 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-gehirn/README.rst b/certbot-dns-gehirn/README.rst index 16058eff8..7a825bd7e 100644 --- a/certbot-dns-gehirn/README.rst +++ b/certbot-dns-gehirn/README.rst @@ -1 +1 @@ -Gehirn Infrastracture Service DNS Authenticator plugin for Certbot +Gehirn Infrastructure Service DNS Authenticator plugin for Certbot diff --git a/certbot-dns-gehirn/certbot_dns_gehirn/__init__.py b/certbot-dns-gehirn/certbot_dns_gehirn/__init__.py index db54154ac..fdcb8cd48 100644 --- a/certbot-dns-gehirn/certbot_dns_gehirn/__init__.py +++ b/certbot-dns-gehirn/certbot_dns_gehirn/__init__.py @@ -1,14 +1,14 @@ """ The `~certbot_dns_gehirn.dns_gehirn` plugin automates the process of completing a ``dns-01`` challenge (`~acme.challenges.DNS01`) by creating, and subsequently -removing, TXT records using the Gehirn Infrastracture Service DNS API. +removing, TXT records using the Gehirn Infrastructure Service DNS API. Named Arguments --------------- ======================================== ===================================== -``--dns-gehirn-credentials`` Gehirn Infrastracture Service +``--dns-gehirn-credentials`` Gehirn Infrastructure Service credentials_ INI file. (Required) ``--dns-gehirn-propagation-seconds`` The number of seconds to wait for DNS @@ -22,15 +22,15 @@ Credentials ----------- Use of this plugin requires a configuration file containing -Gehirn Infrastracture Service DNS API credentials, -obtained from your Gehirn Infrastracture Service +Gehirn Infrastructure Service DNS API credentials, +obtained from your Gehirn Infrastructure Service `dashboard `_. .. code-block:: ini :name: credentials.ini :caption: Example credentials file: - # Gehirn Infrastracture Service API credentials used by Certbot + # Gehirn Infrastructure Service API credentials used by Certbot dns_gehirn_api_token = 00000000-0000-0000-0000-000000000000 dns_gehirn_api_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw @@ -40,7 +40,7 @@ to this file for use during renewal, but does not store the file's contents. .. caution:: You should protect these API credentials as you would the password to your - Gehirn Infrastracture Service account. Users who can read this file can use + Gehirn Infrastructure Service account. Users who can read this file can use these credentials to issue arbitrary API calls on your behalf. Users who can cause Certbot to run using these credentials can complete a ``dns-01`` challenge to acquire new certificates or revoke existing certificates for diff --git a/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py b/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py index 18090c95a..76c0ed584 100644 --- a/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py +++ b/certbot-dns-gehirn/certbot_dns_gehirn/_internal/dns_gehirn.py @@ -1,4 +1,4 @@ -"""DNS Authenticator for Gehirn Infrastracture Service DNS.""" +"""DNS Authenticator for Gehirn Infrastructure Service DNS.""" import logging from lexicon.providers import gehirn @@ -15,14 +15,14 @@ DASHBOARD_URL = "https://gis.gehirn.jp/" @zope.interface.implementer(interfaces.IAuthenticator) @zope.interface.provider(interfaces.IPluginFactory) class Authenticator(dns_common.DNSAuthenticator): - """DNS Authenticator for Gehirn Infrastracture Service DNS + """DNS Authenticator for Gehirn Infrastructure Service DNS - This Authenticator uses the Gehirn Infrastracture Service API to fulfill + This Authenticator uses the Gehirn Infrastructure Service API to fulfill a dns-01 challenge. """ description = 'Obtain certificates using a DNS TXT record ' + \ - '(if you are using Gehirn Infrastracture Service for DNS).' + '(if you are using Gehirn Infrastructure Service for DNS).' ttl = 60 def __init__(self, *args, **kwargs): @@ -32,20 +32,20 @@ class Authenticator(dns_common.DNSAuthenticator): @classmethod def add_parser_arguments(cls, add): # pylint: disable=arguments-differ super(Authenticator, cls).add_parser_arguments(add, default_propagation_seconds=30) - add('credentials', help='Gehirn Infrastracture Service credentials file.') + add('credentials', help='Gehirn Infrastructure Service credentials file.') def more_info(self): # pylint: disable=missing-docstring,no-self-use return 'This plugin configures a DNS TXT record to respond to a dns-01 challenge using ' + \ - 'the Gehirn Infrastracture Service API.' + 'the Gehirn Infrastructure Service API.' def _setup_credentials(self): self.credentials = self._configure_credentials( 'credentials', - 'Gehirn Infrastracture Service credentials file', + 'Gehirn Infrastructure Service credentials file', { - 'api-token': 'API token for Gehirn Infrastracture Service ' + \ + 'api-token': 'API token for Gehirn Infrastructure Service ' + \ 'API obtained from {0}'.format(DASHBOARD_URL), - 'api-secret': 'API secret for Gehirn Infrastracture Service ' + \ + 'api-secret': 'API secret for Gehirn Infrastructure Service ' + \ 'API obtained from {0}'.format(DASHBOARD_URL), } ) @@ -66,7 +66,7 @@ class Authenticator(dns_common.DNSAuthenticator): class _GehirnLexiconClient(dns_common_lexicon.LexiconClient): """ - Encapsulates all communication with the Gehirn Infrastracture Service via Lexicon. + Encapsulates all communication with the Gehirn Infrastructure Service via Lexicon. """ def __init__(self, api_token, api_secret, ttl): diff --git a/certbot-dns-gehirn/docs/conf.py b/certbot-dns-gehirn/docs/conf.py index 67aafa3b4..527bc3d55 100644 --- a/certbot-dns-gehirn/docs/conf.py +++ b/certbot-dns-gehirn/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-gehirn/local-oldest-requirements.txt b/certbot-dns-gehirn/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-gehirn/local-oldest-requirements.txt +++ b/certbot-dns-gehirn/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 7c4da556d..974b17d44 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,12 +4,12 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.1.22', 'mock', 'setuptools', @@ -38,12 +38,12 @@ class PyTest(TestCommand): setup( name='certbot-dns-gehirn', version=version, - description="Gehirn Infrastracture Service DNS Authenticator plugin for Certbot", + description="Gehirn Infrastructure Service DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', 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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -54,7 +54,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 8f045cf3f..b2ddcfb34 100644 --- a/certbot-dns-google/docs/conf.py +++ b/certbot-dns-google/docs/conf.py @@ -39,7 +39,7 @@ extensions = ['sphinx.ext.autodoc', 'jsonlexer'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-google/local-oldest-requirements.txt b/certbot-dns-google/local-oldest-requirements.txt index 3fce6f83b..cf61c15a5 100644 --- a/certbot-dns-google/local-oldest-requirements.txt +++ b/certbot-dns-google/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index a0dc1c386..7b5583307 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'google-api-python-client>=1.5.5', 'mock', 'oauth2client>=4.0', @@ -47,7 +47,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -58,7 +58,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 f23d65023..c6d564b7a 100644 --- a/certbot-dns-linode/docs/conf.py +++ b/certbot-dns-linode/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-linode/local-oldest-requirements.txt b/certbot-dns-linode/local-oldest-requirements.txt index 1829f7eb2..a8bd7449a 100644 --- a/certbot-dns-linode/local-oldest-requirements.txt +++ b/certbot-dns-linode/local-oldest-requirements.txt @@ -1,4 +1,4 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 dns-lexicon==2.2.3 diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index f772dc26a..37b5a4921 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,12 +4,12 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.2.3', 'mock', 'setuptools', @@ -43,7 +43,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -54,7 +54,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 899480f66..8e9d49988 100644 --- a/certbot-dns-luadns/docs/conf.py +++ b/certbot-dns-luadns/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-luadns/local-oldest-requirements.txt b/certbot-dns-luadns/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-luadns/local-oldest-requirements.txt +++ b/certbot-dns-luadns/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 18ba8cacc..4d60ca520 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 aec0771a2..5531959ed 100644 --- a/certbot-dns-nsone/docs/conf.py +++ b/certbot-dns-nsone/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-nsone/local-oldest-requirements.txt b/certbot-dns-nsone/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-nsone/local-oldest-requirements.txt +++ b/certbot-dns-nsone/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 3894f01cd..81324dbc2 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 a4985edee..56e24a920 100644 --- a/certbot-dns-ovh/docs/conf.py +++ b/certbot-dns-ovh/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-ovh/local-oldest-requirements.txt b/certbot-dns-ovh/local-oldest-requirements.txt index 2e11550d6..c55e0d570 100644 --- a/certbot-dns-ovh/local-oldest-requirements.txt +++ b/certbot-dns-ovh/local-oldest-requirements.txt @@ -1,4 +1,4 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 dns-lexicon==2.7.14 diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 2fccf17c2..ee7d9fc69 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.7.14', # Correct proxy use on OVH provider 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', '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 ee71c9681..cb4d5addb 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py @@ -129,7 +129,7 @@ class _RFC2136Client(object): rcode = response.rcode() if rcode == dns.rcode.NOERROR: - logger.debug('Successfully added TXT record') + logger.debug('Successfully added TXT record %s', record_name) else: raise errors.PluginError('Received response from server: {0}' .format(dns.rcode.to_text(rcode))) @@ -164,7 +164,7 @@ class _RFC2136Client(object): rcode = response.rcode() if rcode == dns.rcode.NOERROR: - logger.debug('Successfully deleted TXT record') + logger.debug('Successfully deleted TXT record %s', record_name) else: raise errors.PluginError('Received response from server: {0}' .format(dns.rcode.to_text(rcode))) diff --git a/certbot-dns-rfc2136/docs/conf.py b/certbot-dns-rfc2136/docs/conf.py index e4df84594..c0d55078e 100644 --- a/certbot-dns-rfc2136/docs/conf.py +++ b/certbot-dns-rfc2136/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-rfc2136/local-oldest-requirements.txt b/certbot-dns-rfc2136/local-oldest-requirements.txt index 3fce6f83b..cf61c15a5 100644 --- a/certbot-dns-rfc2136/local-oldest-requirements.txt +++ b/certbot-dns-rfc2136/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 47167fa2b..aa2509727 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dnspython', 'mock', 'setuptools', @@ -44,7 +44,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,7 +55,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-route53/docs/conf.py b/certbot-dns-route53/docs/conf.py index cb8aae0b6..c2eb880ac 100644 --- a/certbot-dns-route53/docs/conf.py +++ b/certbot-dns-route53/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-route53/local-oldest-requirements.txt b/certbot-dns-route53/local-oldest-requirements.txt index 3fce6f83b..cf61c15a5 100644 --- a/certbot-dns-route53/local-oldest-requirements.txt +++ b/certbot-dns-route53/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.29.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index b4dcc58c1..df43d90a9 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'boto3', 'mock', 'setuptools', @@ -39,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -50,7 +50,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-dns-sakuracloud/docs/conf.py b/certbot-dns-sakuracloud/docs/conf.py index f973779ab..70a4d7434 100644 --- a/certbot-dns-sakuracloud/docs/conf.py +++ b/certbot-dns-sakuracloud/docs/conf.py @@ -38,7 +38,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot-dns-sakuracloud/local-oldest-requirements.txt b/certbot-dns-sakuracloud/local-oldest-requirements.txt index 67d4cc53b..1307698d4 100644 --- a/certbot-dns-sakuracloud/local-oldest-requirements.txt +++ b/certbot-dns-sakuracloud/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==0.31.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 56c209a90..4d35dc7ac 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,12 +4,12 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'acme>=0.31.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'dns-lexicon>=2.1.23', 'mock', 'setuptools', @@ -43,7 +43,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -54,7 +54,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-old.conf b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-old.conf index 731e38919..a678b0507 100644 --- a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-old.conf +++ b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-old.conf @@ -10,4 +10,4 @@ ssl_session_timeout 1440m; ssl_protocols TLSv1.2; ssl_prefer_server_ciphers off; -ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA"; +ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; diff --git a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls12-only.conf b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls12-only.conf index 33771a189..1933cbc4f 100644 --- a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls12-only.conf +++ b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls12-only.conf @@ -11,4 +11,4 @@ ssl_session_tickets off; ssl_protocols TLSv1.2; ssl_prefer_server_ciphers off; -ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA"; +ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; diff --git a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls13-session-tix-on.conf b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls13-session-tix-on.conf index 91197d2c8..52fdfde24 100644 --- a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls13-session-tix-on.conf +++ b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx-tls13-session-tix-on.conf @@ -10,4 +10,4 @@ ssl_session_timeout 1440m; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; -ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA"; +ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; diff --git a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf index 98b1c4ab9..978e6e8ab 100644 --- a/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf +++ b/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf @@ -11,4 +11,4 @@ ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; -ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA"; +ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; diff --git a/certbot-nginx/local-oldest-requirements.txt b/certbot-nginx/local-oldest-requirements.txt index 37532aabf..cee142934 100644 --- a/certbot-nginx/local-oldest-requirements.txt +++ b/certbot-nginx/local-oldest-requirements.txt @@ -1,3 +1,3 @@ # Remember to update setup.py to match the package versions below. acme[dev]==1.0.0 --e certbot[dev] +certbot[dev]==1.1.0 diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 96bf32d3e..aad736da5 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -4,13 +4,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.1.0.dev0' +version = '1.2.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=1.0.0', - 'certbot>=1.0.0.dev0', + 'certbot>=1.1.0', 'mock', 'PyOpenSSL', 'pyparsing>=1.5.5', # Python3 support; perhaps unnecessary? @@ -42,7 +42,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -53,7 +53,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index f2671a7b4..86d27143c 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,7 +2,27 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). -## 1.1.0 - master +## 1.2.0 - master + +### Added + +* Added support for Cloudflare's limited-scope API Tokens + +### Changed + +* Add directory field to error message when field is missing. +* If MD5 hasher is not available, try it in non-security mode (fix for FIPS systems) -- [#1948](https://github.com/certbot/certbot/issues/1948) +* Disable old SSL versions and ciphersuites and remove `SSLCompression off` setting to follow Mozilla recommendations in Apache. +* Remove ECDHE-RSA-AES128-SHA from NGINX ciphers list now that Windows 2008 R2 and Windows 7 are EOLed +* Support for Python 3.4 has been removed. + +### Fixed + +* Fix collections.abc imports for Python 3.9. + +More details about these changes can be found on our GitHub repo. + +## 1.1.0 - 2020-01-14 ### Added @@ -13,6 +33,15 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). * Removed the fallback introduced with 0.34.0 in `acme` to retry a POST-as-GET request as a GET request when the targeted ACME CA server seems to not support POST-as-GET requests. +* certbot-auto no longer supports architectures other than x86_64 on RHEL 6 + based systems. Existing certbot-auto installations affected by this will + continue to work, but they will no longer receive updates. To install a + newer version of Certbot on these systems, you should update your OS. +* Support for Python 3.4 in Certbot and its ACME library is deprecated and will be + removed in the next release of Certbot. certbot-auto users on x86_64 systems running + RHEL 6 or derivatives will be asked to enable Software Collections (SCL) repository + so Python 3.6 can be installed. certbot-auto can enable the SCL repo for you on CentOS 6 + while users on other RHEL 6 based systems will be asked to do this manually. ### Fixed @@ -223,7 +252,7 @@ More details about these changes can be found on our GitHub repo. ### Added -* dns_rfc2136 plugin now supports explicitly specifing an authorative +* dns_rfc2136 plugin now supports explicitly specifying an authoritative base domain for cases when the automatic method does not work (e.g. Split horizon DNS) @@ -607,7 +636,7 @@ https://github.com/certbot/certbot/milestone/62?closed=1 * Log warning about TLS-SNI deprecation in Certbot * Stop preferring TLS-SNI in the Apache, Nginx, and standalone plugins * OVH DNS plugin now relies on Lexicon>=2.7.14 to support HTTP proxies -* Default time the Linode plugin waits for DNS changes to propogate is now 1200 seconds. +* Default time the Linode plugin waits for DNS changes to propagate is now 1200 seconds. ### Fixed @@ -726,7 +755,7 @@ https://github.com/certbot/certbot/milestone/58?closed=1 increased over time. The max-age value is not increased to a large value until you've successfully managed to renew your certificate. This enhancement can be requested with the --auto-hsts flag. -* New official DNS plugins have been created for Gehirn Infrastracture Service, +* New official DNS plugins have been created for Gehirn Infrastructure Service, Linode, OVH, and Sakura Cloud. These plugins can be found on our Docker Hub page at https://hub.docker.com/u/certbot and on PyPI. * The ability to reuse ACME accounts from Let's Encrypt's ACMEv1 endpoint on diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 71c7e4e87..caae1a041 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '1.1.0.dev0' +__version__ = '1.2.0.dev0' diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py index c4ea6ef35..61f63bda6 100644 --- a/certbot/certbot/_internal/account.py +++ b/certbot/certbot/_internal/account.py @@ -56,11 +56,18 @@ class Account(object): tz=pytz.UTC).replace(microsecond=0), creation_host=socket.getfqdn()) if meta is None else meta - self.id = hashlib.md5( - self.key.key.public_key().public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo) - ).hexdigest() + # try MD5, else use MD5 in non-security mode (e.g. for FIPS systems / RHEL) + try: + hasher = hashlib.md5() + except ValueError: + hasher = hashlib.new('md5', usedforsecurity=False) # type: ignore + + hasher.update(self.key.key.public_key().public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo) + ) + + self.id = hasher.hexdigest() # Implementation note: Email? Multiple accounts can have the # same email address. Registration URI? Assigned by the # server, not guaranteed to be stable over time, nor diff --git a/certbot/certbot/_internal/cli.py b/certbot/certbot/_internal/cli.py index fb3010a4e..d5d498b4d 100644 --- a/certbot/certbot/_internal/cli.py +++ b/certbot/certbot/_internal/cli.py @@ -92,8 +92,8 @@ obtain, install, and renew certificates: manage certificates: certificates Display information about certificates you have from Certbot - revoke Revoke a certificate (supply --cert-path or --cert-name) - delete Delete a certificate + revoke Revoke a certificate (supply --cert-name or --cert-path) + delete Delete a certificate (supply --cert-name) manage your account: register Create an ACME account @@ -1414,7 +1414,7 @@ def _plugins_parsing(helpful, plugins): helpful.add(["plugins", "certonly"], "--dns-gehirn", action="store_true", default=flag_default("dns_gehirn"), help=("Obtain certificates using a DNS TXT record " - "(if you are using Gehirn Infrastracture Service for DNS).")) + "(if you are using Gehirn Infrastructure Service for DNS).")) helpful.add(["plugins", "certonly"], "--dns-google", action="store_true", default=flag_default("dns_google"), help=("Obtain certificates using a DNS TXT record (if you are " diff --git a/certbot/certbot/_internal/ocsp.py b/certbot/certbot/_internal/ocsp.py index 65a6d5c17..2f6543e5d 100644 --- a/certbot/certbot/_internal/ocsp.py +++ b/certbot/certbot/_internal/ocsp.py @@ -192,7 +192,7 @@ def _check_ocsp_cryptography(cert_path, chain_path, url): def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert, cert_path): - """Verify that the OCSP is valid for serveral criterias""" + """Verify that the OCSP is valid for serveral criteria""" # Assert OCSP response corresponds to the certificate we are talking about if response_ocsp.serial_number != request_ocsp.serial_number: raise AssertionError('the certificate in response does not correspond ' diff --git a/certbot/certbot/_internal/plugins/disco.py b/certbot/certbot/_internal/plugins/disco.py index 360597474..d7d6390f7 100644 --- a/certbot/certbot/_internal/plugins/disco.py +++ b/certbot/certbot/_internal/plugins/disco.py @@ -13,6 +13,12 @@ from certbot import errors from certbot import interfaces from certbot._internal import constants +try: + # Python 3.3+ + from collections.abc import Mapping +except ImportError: # pragma: no cover + from collections import Mapping + logger = logging.getLogger(__name__) @@ -178,7 +184,7 @@ class PluginEntryPoint(object): return "\n".join(lines) -class PluginsRegistry(collections.Mapping): +class PluginsRegistry(Mapping): """Plugins registry.""" def __init__(self, plugins): diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py index 0426b2e2d..930f6c1a9 100644 --- a/certbot/certbot/_internal/renewal.py +++ b/certbot/certbot/_internal/renewal.py @@ -192,7 +192,7 @@ def _restore_pref_challs(unused_name, value): :returns: converted option value to be stored in the runtime config :rtype: `list` of `str` - :raises errors.Error: if value can't be converted to an bool + :raises errors.Error: if value can't be converted to a bool """ # If pref_challs has only one element, configobj saves the value @@ -203,7 +203,7 @@ def _restore_pref_challs(unused_name, value): def _restore_bool(name, value): - """Restores an boolean key-value pair from a renewal config file. + """Restores a boolean key-value pair from a renewal config file. :param str name: option name :param str value: option value @@ -211,7 +211,7 @@ def _restore_bool(name, value): :returns: converted option value to be stored in the runtime config :rtype: bool - :raises errors.Error: if value can't be converted to an bool + :raises errors.Error: if value can't be converted to a bool """ lowercase_value = value.lower() @@ -244,7 +244,7 @@ def _restore_int(name, value): def _restore_str(unused_name, value): - """Restores an string key-value pair from a renewal config file. + """Restores a string key-value pair from a renewal config file. :param str unused_name: option name :param str value: option value diff --git a/certbot/certbot/compat/filesystem.py b/certbot/certbot/compat/filesystem.py index ba4a155e8..65bb53f38 100644 --- a/certbot/certbot/compat/filesystem.py +++ b/certbot/certbot/compat/filesystem.py @@ -263,7 +263,7 @@ def replace(src, dst): :param str dst: The new file path. """ if hasattr(os, 'replace'): - # Use replace if possible. On Windows, only Python >= 3.4 is supported + # Use replace if possible. On Windows, only Python >= 3.5 is supported # so we can assume that os.replace() is always available for this platform. getattr(os, 'replace')(src, dst) else: @@ -541,7 +541,7 @@ def _generate_windows_flags(rights_desc): # write access on Linux: for Windows, FILE_GENERIC_WRITE does not include delete, move or # rename. This is something that requires ntsecuritycon.FILE_ALL_ACCESS. # So to reproduce the write right as POSIX, we will apply ntsecuritycon.FILE_ALL_ACCESS - # substracted of the rights corresponding to POSIX read and POSIX execute. + # subtracted of the rights corresponding to POSIX read and POSIX execute. # # Finally, having read + write + execute gives a ntsecuritycon.FILE_ALL_ACCESS, # so a "Full Control" on the file. diff --git a/certbot/certbot/display/ops.py b/certbot/certbot/display/ops.py index 92b09d6a1..eab9d251d 100644 --- a/certbot/certbot/display/ops.py +++ b/certbot/certbot/display/ops.py @@ -340,7 +340,7 @@ def validated_input(validator, *args, **kwargs): """Like `~certbot.interfaces.IDisplay.input`, but with validation. :param callable validator: A method which will be called on the - supplied input. If the method raises a `errors.Error`, its + supplied input. If the method raises an `errors.Error`, its text will be displayed and the user will be re-prompted. :param list `*args`: Arguments to be passed to `~certbot.interfaces.IDisplay.input`. :param dict `**kwargs`: Arguments to be passed to `~certbot.interfaces.IDisplay.input`. @@ -355,7 +355,7 @@ def validated_directory(validator, *args, **kwargs): """Like `~certbot.interfaces.IDisplay.directory_select`, but with validation. :param callable validator: A method which will be called on the - supplied input. If the method raises a `errors.Error`, its + supplied input. If the method raises an `errors.Error`, its text will be displayed and the user will be re-prompted. :param list `*args`: Arguments to be passed to `~certbot.interfaces.IDisplay.directory_select`. :param dict `**kwargs`: Arguments to be passed to diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt index b46206b87..51967eb76 100644 --- a/certbot/docs/cli-help.txt +++ b/certbot/docs/cli-help.txt @@ -24,8 +24,8 @@ obtain, install, and renew certificates: manage certificates: certificates Display information about certificates you have from Certbot - revoke Revoke a certificate (supply --cert-path or --cert-name) - delete Delete a certificate + revoke Revoke a certificate (supply --cert-name or --cert-path) + delete Delete a certificate (supply --cert-name) manage your account: register Create an ACME account @@ -113,7 +113,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.0.0 (certbot(-auto); + "". (default: CertbotACMEClient/1.1.0 (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the user agent are: --duplicate, @@ -451,7 +451,7 @@ plugins: --dns-dnsmadeeasy Obtain certificates using a DNS TXT record (if you are using DNS Made Easy for DNS). (default: False) --dns-gehirn Obtain certificates using a DNS TXT record (if you are - using Gehirn Infrastracture Service for DNS). + using Gehirn Infrastructure Service for DNS). (default: False) --dns-google Obtain certificates using a DNS TXT record (if you are using Google Cloud DNS). (default: False) @@ -560,14 +560,14 @@ dns-dnsmadeeasy: dns-gehirn: Obtain certificates using a DNS TXT record (if you are using Gehirn - Infrastracture Service for DNS). + Infrastructure Service for DNS). --dns-gehirn-propagation-seconds DNS_GEHIRN_PROPAGATION_SECONDS The number of seconds to wait for DNS to propagate before asking the ACME server to verify the DNS record. (default: 30) --dns-gehirn-credentials DNS_GEHIRN_CREDENTIALS - Gehirn Infrastracture Service credentials file. + Gehirn Infrastructure Service credentials file. (default: None) dns-google: diff --git a/certbot/docs/compatibility.rst b/certbot/docs/compatibility.rst new file mode 100644 index 000000000..a511f36a2 --- /dev/null +++ b/certbot/docs/compatibility.rst @@ -0,0 +1,39 @@ +======================= +Backwards Compatibility +======================= + +All Certbot components including `acme `_, +Certbot, and :ref:`non-third party plugins ` follow `Semantic +Versioning `_ both for its Python :doc:`API ` and for the +application itself. This means that we will not change behavior in a backwards +incompatible way except in a new major version of the project. + +.. note:: None of this applies to the behavior of Certbot distribution + mechanisms such as :ref:`certbot-auto ` or OS packages whose + behavior may change at any time. Semantic versioning only applies to the + common Certbot components that are installed by various distribution + methods. + +For Certbot as an application, the command line interface and non-interactive +behavior can be considered stable with two exceptions. The first is that no +aspects of Certbot's console or log output should be considered stable and it +may change at any time. The second is that Certbot's behavior should only be +considered stable with certain files but not all. Files with which users should +expect Certbot to maintain its current behavior with are: + +* ``/etc/letsencrypt/live//{cert,chain,fullchain,privkey}.pem`` where + ```` is the name given to ``--cert-name``. If ``--cert-name`` is not + set by the user, it is the first domain given to ``--domains``. +* :ref:`CLI configuration files ` +* Hook directories in ``/etc/letsencrypt/renewal-hooks`` + +Certbot's behavior with other files may change at any point. + +Another area where Certbot should not be considered stable is its behavior when +not run in non-interactive mode which also may change at any point. + +In general, if we're making a change that we expect will break some users, we +will bump the major version and will have warned about it in a prior release +when possible. For our Python API, we will issue warnings using Python's +warning module. For application level changes, we will print and log warning +messages. diff --git a/certbot/docs/conf.py b/certbot/docs/conf.py index 6b7c1c2c0..1e57bc224 100644 --- a/certbot/docs/conf.py +++ b/certbot/docs/conf.py @@ -52,7 +52,7 @@ if sphinx.version_info >= (1, 6): extensions.append('sphinx.ext.imgconverter') autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/certbot/docs/contributing.rst b/certbot/docs/contributing.rst index e1289c849..4ac266ed8 100644 --- a/certbot/docs/contributing.rst +++ b/certbot/docs/contributing.rst @@ -583,7 +583,7 @@ OS-level dependencies can be installed like so: In general... * ``sudo`` is required as a suggested way of running privileged process -* `Python`_ 2.7 or 3.4+ is required +* `Python`_ 2.7 or 3.5+ is required * `Augeas`_ is required for the Python bindings * ``virtualenv`` is used for managing other Python library dependencies diff --git a/certbot/docs/index.rst b/certbot/docs/index.rst index 17cde1adf..a7fc75c5b 100644 --- a/certbot/docs/index.rst +++ b/certbot/docs/index.rst @@ -10,6 +10,7 @@ Welcome to the Certbot documentation! using contributing packaging + compatibility resources .. toctree:: diff --git a/certbot/docs/install.rst b/certbot/docs/install.rst index d21242367..11994776c 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.4+ running on a UNIX-like operating +Certbot currently requires Python 2.7 or 3.5+ 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 diff --git a/certbot/setup.py b/certbot/setup.py index 0026ef8e9..d19327e5e 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -88,7 +88,6 @@ dev3_extras = [ 'astroid', 'mypy', 'pylint', - 'typing', # for python3.4 ] docs_extras = [ @@ -124,7 +123,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', @@ -136,7 +135,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index ae061de65..3ff09a83f 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -579,7 +579,7 @@ class AtexitRegisterTest(unittest.TestCase): with mock.patch('certbot.util.atexit') as mock_atexit: self._call(self.func, *self.args, **self.kwargs) - # _INITAL_PID must be mocked when calling atexit_func + # _INITIAL_PID must be mocked when calling atexit_func self.assertTrue(mock_atexit.register.called) args, kwargs = mock_atexit.register.call_args atexit_func = args[0] diff --git a/letsencrypt-auto b/letsencrypt-auto index 24c007e03..2d3f4cfef 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.0.0" +LE_AUTO_VERSION="1.1.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -256,20 +256,28 @@ DeprecationBootstrap() { fi } -MIN_PYTHON_VERSION="2.7" -MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//') +MIN_PYTHON_2_VERSION="2.7" +MIN_PYVER2=$(echo "$MIN_PYTHON_2_VERSION" | sed 's/\.//') +MIN_PYTHON_3_VERSION="3.5" +MIN_PYVER3=$(echo "$MIN_PYTHON_3_VERSION" | sed 's/\.//') # Sets LE_PYTHON to Python version string and PYVER to the first two -# digits of the python version +# digits of the python version. +# MIN_PYVER and MIN_PYTHON_VERSION are also set by this function, and their +# values depend on if we try to use Python 3 or Python 2. DeterminePythonVersion() { # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python # # If no Python is found, PYVER is set to 0. if [ "$USE_PYTHON_3" = 1 ]; then + MIN_PYVER=$MIN_PYVER3 + MIN_PYTHON_VERSION=$MIN_PYTHON_3_VERSION for LE_PYTHON in "$LE_PYTHON" python3; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break done else + MIN_PYVER=$MIN_PYVER2 + MIN_PYTHON_VERSION=$MIN_PYTHON_2_VERSION for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break @@ -285,7 +293,7 @@ DeterminePythonVersion() { fi fi - PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + PYVER=$("$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') if [ "$PYVER" -lt "$MIN_PYVER" ]; then if [ "$1" != "NOCRASH" ]; then error "You have an ancient version of Python entombed in your operating system..." @@ -368,7 +376,9 @@ BootstrapDebCommon() { # Sets TOOL to the name of the package manager # Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG. -# Enables EPEL if applicable and possible. +# Note: this function is called both while selecting the bootstrap scripts and +# during the actual bootstrap. Some things like prompting to user can be done in the latter +# case, but not in the former one. InitializeRPMCommonBase() { if type dnf 2>/dev/null then @@ -388,26 +398,6 @@ InitializeRPMCommonBase() { if [ "$QUIET" = 1 ]; then QUIET_FLAG='--quiet' fi - - if ! $TOOL list *virtualenv >/dev/null 2>&1; then - echo "To use Certbot, packages from the EPEL repository need to be installed." - if ! $TOOL list epel-release >/dev/null 2>&1; then - error "Enable the EPEL repository and try running Certbot again." - exit 1 - fi - if [ "$ASSUME_YES" = 1 ]; then - /bin/echo -n "Enabling the EPEL repository in 3 seconds..." - sleep 1s - /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..." - sleep 1s - /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..." - sleep 1s - fi - if ! $TOOL install $YES_FLAG $QUIET_FLAG epel-release; then - error "Could not enable EPEL. Aborting bootstrap!" - exit 1 - fi - fi } BootstrapRpmCommonBase() { @@ -488,13 +478,91 @@ BootstrapRpmCommon() { BootstrapRpmCommonBase "$python_pkgs" } +# If new packages are installed by BootstrapRpmPython3 below, this version +# number must be increased. +BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION=1 + +# Checks if rh-python36 can be installed. +Python36SclIsAvailable() { + InitializeRPMCommonBase >/dev/null 2>&1; + + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + return 0 + fi + if "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + return 0 + fi + return 1 +} + +# Try to enable rh-python36 from SCL if it is necessary and possible. +EnablePython36SCL() { + if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then + return 0 + fi + if [ ! -f /opt/rh/rh-python36/enable ]; then + return 0 + fi + set +e + if ! . /opt/rh/rh-python36/enable; then + error 'Unable to enable rh-python36!' + exit 1 + fi + set -e +} + +# This bootstrap concerns old RedHat-based distributions that do not ship by default +# with Python 2.7, but only Python 2.6. We bootstrap them by enabling SCL and installing +# Python 3.6. Some of these distributions are: CentOS/RHEL/OL/SL 6. +BootstrapRpmPython3Legacy() { + # Tested with: + # - CentOS 6 + + InitializeRPMCommonBase + + if ! "${TOOL}" list rh-python36 >/dev/null 2>&1; then + echo "To use Certbot on this operating system, packages from the SCL repository need to be installed." + if ! "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + error "Enable the SCL repository and try running Certbot again." + exit 1 + fi + if [ "${ASSUME_YES}" = 1 ]; then + /bin/echo -n "Enabling the SCL repository in 3 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -ne "\e[0K\rEnabling the SCL repository in 2 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -e "\e[0K\rEnabling the SCL repository in 1 second... (Press Ctrl-C to cancel)" + sleep 1s + fi + if ! "${TOOL}" install "${YES_FLAG}" "${QUIET_FLAG}" centos-release-scl; then + error "Could not enable SCL. Aborting bootstrap!" + exit 1 + fi + fi + + # CentOS 6 must use rh-python36 from SCL + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + python_pkgs="rh-python36-python + rh-python36-python-virtualenv + rh-python36-python-devel + " + else + error "No supported Python package available to install. Aborting bootstrap!" + exit 1 + fi + + BootstrapRpmCommonBase "${python_pkgs}" + + # Enable SCL rh-python36 after bootstrapping. + EnablePython36SCL +} + # If new packages are installed by BootstrapRpmPython3 below, this version # number must be increased. BOOTSTRAP_RPM_PYTHON3_VERSION=1 BootstrapRpmPython3() { # Tested with: - # - CentOS 6 # - Fedora 29 InitializeRPMCommonBase @@ -505,12 +573,6 @@ BootstrapRpmPython3() { python3-virtualenv python3-devel " - # EPEL uses python34 - elif $TOOL list python34 >/dev/null 2>&1; then - python_pkgs="python34 - python34-devel - python34-tools - " else error "No supported Python package available to install. Aborting bootstrap!" exit 1 @@ -758,6 +820,11 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` + if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then + # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. + DEPRECATED_OS=1 + fi + # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an # error, RPM_DIST_VERSION is set to "unknown". @@ -769,31 +836,50 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_VERSION=0 fi - # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. - # RHEL 8 also uses python3 by default. - if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 -o "$PYVER" -eq 26 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - else - RPM_USE_PYTHON_3=0 - fi + # Handle legacy RPM distributions + if [ "$PYVER" -eq 26 ]; then + # Check if an automated bootstrap can be achieved on this system. + if ! Python36SclIsAvailable; then + INTERACTIVE_BOOTSTRAP=1 + fi - if [ "$RPM_USE_PYTHON_3" = 1 ]; then Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 + BootstrapMessage "Legacy RedHat-based OSes that will use Python3" + BootstrapRpmPython3Legacy } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" + 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 + EnablePython36SCL else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. + # RHEL 8 also uses python3 by default. + if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + else + RPM_USE_PYTHON_3=0 + 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" @@ -870,6 +956,13 @@ if [ "$NO_BOOTSTRAP" = 1 ]; then unset BOOTSTRAP_VERSION fi +if [ "$DEPRECATED_OS" = 1 ]; then + Bootstrap() { + error "Skipping bootstrap because certbot-auto is deprecated on this system." + } + unset BOOTSTRAP_VERSION +fi + # Sets PREV_BOOTSTRAP_VERSION to the identifier for the bootstrap script used # to install OS dependencies on this system. PREV_BOOTSTRAP_VERSION isn't set # if it is unknown how OS dependencies were installed on this system. @@ -1067,6 +1160,28 @@ if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. shift 1 # the --le-auto-phase2 arg + + if [ "$DEPRECATED_OS" = 1 ]; then + # Phase 2 damage control mode for deprecated OSes. + # In this situation, we bypass any bootstrap or certbot venv setup. + error "Your system is not supported by certbot-auto anymore." + + if [ ! -d "$VENV_PATH" ] && OldVenvExists; then + VENV_BIN="$OLD_VENV_PATH/bin" + fi + + if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then + error "Certbot will no longer receive updates." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + "$VENV_BIN/letsencrypt" "$@" + exit 0 + else + error "Certbot cannot be installed." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + exit 1 + fi + fi + SetPrevBootstrapVersion if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then @@ -1078,8 +1193,15 @@ if [ "$1" = "--le-auto-phase2" ]; then # If the selected Bootstrap function isn't a noop and it differs from the # previously used version if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then - # if non-interactive mode or stdin and stdout are connected to a terminal - if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then + # Check if we can rebootstrap without manual user intervention: this requires that + # certbot-auto is in non-interactive mode AND selected bootstrap does not claim to + # require a manual user intervention. + if [ "$NONINTERACTIVE" = 1 -a "$INTERACTIVE_BOOTSTRAP" != 1 ]; then + CAN_REBOOTSTRAP=1 + fi + # Check if rebootstrap can be done non-interactively and current shell is non-interactive + # (true if stdin and stdout are not attached to a terminal). + if [ \( "$CAN_REBOOTSTRAP" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then if [ -d "$VENV_PATH" ]; then rm -rf "$VENV_PATH" fi @@ -1090,12 +1212,21 @@ if [ "$1" = "--le-auto-phase2" ]; then ln -s "$VENV_PATH" "$OLD_VENV_PATH" fi RerunWithArgs "$@" + # Otherwise bootstrap needs to be done manually by the user. else - error "Skipping upgrade because new OS dependencies may need to be installed." - error - error "To upgrade to a newer version, please run this script again manually so you can" - error "approve changes or with --non-interactive on the command line to automatically" - error "install any required packages." + # If it is because bootstrapping is interactive, --non-interactive will be of no use. + if [ "$INTERACTIVE_BOOTSTRAP" = 1 ]; then + error "Skipping upgrade because new OS dependencies may need to be installed." + error "This requires manual user intervention: please run this script again manually." + # If this is because of the environment (eg. non interactive shell without + # --non-interactive flag set), help the user in that direction. + else + error "Skipping upgrade because new OS dependencies may need to be installed." + error + error "To upgrade to a newer version, please run this script again manually so you can" + error "approve changes or with --non-interactive on the command line to automatically" + error "install any required packages." + fi # Set INSTALLED_VERSION to be the same so we don't update the venv INSTALLED_VERSION="$LE_AUTO_VERSION" # Continue to use OLD_VENV_PATH if the new venv doesn't exist @@ -1372,18 +1503,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.0.0 \ - --hash=sha256:8d074cff89dee002dec1c47cb0da04ea8e0ede8d68838b6d54aa41580d9262df \ - --hash=sha256:86b82d31db19fffffb0d6b218951e2121ef514e3ff659aa042deaf92a33e302a -acme==1.0.0 \ - --hash=sha256:f6972e436e76f7f1e395e81e149f8713ca8462d465b14993bddc53fb18a40644 \ - --hash=sha256:6a08f12f848ce563b50bca421ba9db653df9f82cfefeaf8aba517f046d1386c2 -certbot-apache==1.0.0 \ - --hash=sha256:e591d0cf773ad33ee978f7adb1b69288eac2c8847c643b06e70260e707626f8e \ - --hash=sha256:7335ab5687a0a47d9041d9e13f3a2d67d0e8372da97ab639edb31c14b787cd68 -certbot-nginx==1.0.0 \ - --hash=sha256:ce8a2e51165da7c15bfdc059cd6572d0f368c078f1e1a77633a2773310b2f231 \ - --hash=sha256:63b4ae09d4f1c9ef0a1a2a49c3f651d8a7cb30303ec6f954239e987c5da45dc4 +certbot==1.1.0 \ + --hash=sha256:66a5cab9267349941604c2c98082bfef85877653c023fc324b1c3869fb16add6 \ + --hash=sha256:46e93661a0db53f416c0f5476d8d2e62bc7259b7660dd983453b85df9ef6e8b8 +acme==1.1.0 \ + --hash=sha256:11b9beba706fb8f652c8910d46dd1939d670cac8169f3c66c18c080ed3353e71 \ + --hash=sha256:c305a20eeb9cb02240347703d497891c13d43a47c794fa100d4dbb479a5370d9 +certbot-apache==1.1.0 \ + --hash=sha256:9c847ff223c2e465e241c78d22f97cee77d5e551df608bed06c55f8627f4cbd2 \ + --hash=sha256:05e84dfe96b72582cde97c490977d8e2d33d440c927a320debb4cf287f6fadcc +certbot-nginx==1.1.0 \ + --hash=sha256:bf06fa2f5059f0fdb7d352c8739e1ed0830db4f0d89e812dab4f081bda6ec7d6 \ + --hash=sha256:0a80ecbd2a30f3757c7652cabfff854ca07873b1cf02ebbe1892786c3b3a5874 UNLIKELY_EOF # ------------------------------------------------------------------------- @@ -1617,6 +1748,9 @@ UNLIKELY_EOF say "Installation succeeded." fi + # If you're modifying any of the code after this point in this current `if` block, you + # may need to update the "$DEPRECATED_OS" = 1 case at the beginning of phase 2 as well. + if [ "$INSTALL_ONLY" = 1 ]; then say "Certbot is installed." exit 0 @@ -1828,30 +1962,35 @@ UNLIKELY_EOF error "WARNING: unable to check for updates." fi - LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then - say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" - elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then - say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + # If for any reason REMOTE_VERSION is not set, let's assume certbot-auto is up-to-date, + # and do not go into the self-upgrading process. + if [ -n "$REMOTE_VERSION" ]; then + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then + say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - # Install new copy of certbot-auto. - # TODO: Deal with quotes in pathnames. - say "Replacing certbot-auto..." - # Clone permissions with cp. chmod and chown don't have a --reference - # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: - cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" - cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" - # Using mv rather than cp leaves the old file descriptor pointing to the - # original copy so the shell can continue to read it unmolested. mv across - # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the - # cp is unlikely to fail if the rm doesn't. - mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" - fi # A newer version is available. + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + + # Install new copy of certbot-auto. + # TODO: Deal with quotes in pathnames. + say "Replacing certbot-auto..." + # Clone permissions with cp. chmod and chown don't have a --reference + # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: + cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" + cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" + # Using mv rather than cp leaves the old file descriptor pointing to the + # original copy so the shell can continue to read it unmolested. mv across + # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the + # cp is unlikely to fail if the rm doesn't. + mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" + fi # A newer version is available. + fi fi # Self-upgrading is allowed. RerunWithArgs --le-auto-phase2 "$@" diff --git a/letsencrypt-auto-source/Dockerfile.centos6 b/letsencrypt-auto-source/Dockerfile.centos6 deleted file mode 100644 index 09aa52dcd..000000000 --- a/letsencrypt-auto-source/Dockerfile.centos6 +++ /dev/null @@ -1,37 +0,0 @@ -# For running tests, build a docker image with a passwordless sudo and a trust -# store we can manipulate. - -FROM centos:6 - -RUN yum install -y epel-release - -# Install pip and sudo: -RUN yum install -y python-pip sudo -# Update to a stable and tested version of pip. -# We do not use pipstrap here because it no longer supports Python 2.6. -RUN pip install pip==9.0.1 setuptools==29.0.1 wheel==0.29.0 -# Pin pytest version for increased stability -RUN pip install pytest==3.2.5 six==1.10.0 - -# Add an unprivileged user: -RUN useradd --create-home --home-dir /home/lea --shell /bin/bash --groups wheel --uid 1000 lea - -# Let that user sudo: -RUN sed -i.bkp -e \ - 's/# %wheel\(NOPASSWD: ALL\)\?/%wheel/g' \ - /etc/sudoers - -RUN mkdir -p /home/lea/certbot - -# Install fake testing CA: -COPY ./tests/certs/ca/my-root-ca.crt.pem /usr/local/share/ca-certificates/ -RUN update-ca-trust - -# Copy code: -COPY . /home/lea/certbot/letsencrypt-auto-source - -USER lea -WORKDIR /home/lea - -RUN sudo chmod +x certbot/letsencrypt-auto-source/tests/centos6_tests.sh -CMD sudo certbot/letsencrypt-auto-source/tests/centos6_tests.sh diff --git a/letsencrypt-auto-source/Dockerfile.redhat6 b/letsencrypt-auto-source/Dockerfile.redhat6 new file mode 100644 index 000000000..66f21bc14 --- /dev/null +++ b/letsencrypt-auto-source/Dockerfile.redhat6 @@ -0,0 +1,54 @@ +# For running tests, build a docker image with a passwordless sudo and a trust +# store we can manipulate. + +ARG REDHAT_DIST_FLAVOR +FROM ${REDHAT_DIST_FLAVOR}:6 + +ARG REDHAT_DIST_FLAVOR + +RUN curl -O https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm \ + && rpm -ivh epel-release-latest-6.noarch.rpm + +# Install pip and sudo: +RUN yum install -y python-pip sudo +# Update to a stable and tested version of pip. +# We do not use pipstrap here because it no longer supports Python 2.6. +RUN pip install pip==9.0.1 setuptools==29.0.1 wheel==0.29.0 +# Pin pytest version for increased stability +RUN pip install pytest==3.2.5 six==1.10.0 + +# Add an unprivileged user: +RUN useradd --create-home --home-dir /home/lea --shell /bin/bash --groups wheel --uid 1000 lea + +# Let that user sudo: +RUN sed -i.bkp -e \ + 's/# %wheel\(NOPASSWD: ALL\)\?/%wheel/g' \ + /etc/sudoers + +RUN mkdir -p /home/lea/certbot + +# Install fake testing CA: +COPY ./tests/certs/ca/my-root-ca.crt.pem /usr/local/share/ca-certificates/ +RUN update-ca-trust + +# Copy current letsencrypt-auto: +COPY . /home/lea/certbot/letsencrypt-auto-source + +# Tweak uname binary for tests on fake 32bits +COPY tests/uname_wrapper.sh /bin +RUN mv /bin/uname /bin/uname_orig \ + && mv /bin/uname_wrapper.sh /bin/uname \ + && chmod +x /bin/uname + +# Fetch previous letsencrypt-auto that was installing python 3.4 +RUN curl https://raw.githubusercontent.com/certbot/certbot/v0.38.0/letsencrypt-auto-source/letsencrypt-auto \ + -o /home/lea/certbot/letsencrypt-auto-source/letsencrypt-auto_py_34 \ + && chmod +x /home/lea/certbot/letsencrypt-auto-source/letsencrypt-auto_py_34 + +RUN cp /home/lea/certbot/letsencrypt-auto-source/tests/${REDHAT_DIST_FLAVOR}6_tests.sh /home/lea/certbot/letsencrypt-auto-source/tests/redhat6_tests.sh \ + && chmod +x /home/lea/certbot/letsencrypt-auto-source/tests/redhat6_tests.sh + +USER lea +WORKDIR /home/lea + +CMD ["sudo", "certbot/letsencrypt-auto-source/tests/redhat6_tests.sh"] diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index aea28117c..1a030eb47 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl3mmvMACgkQTRfJlc2X -dfKUbQf/aW8ZWRH36WhTHmZjJmBumSUYclFdDAR4c6Ym+MBTeYT0iQq/dqfqTklB -7jPHTcxWbyMJCjOqtMEDRt+aVF0A91OA1bSRt1MJCm7o8Oa1h4XVVPL2UZYCPNlu -46UEBGDOkd6DlrRvD0X2BrQ4EsktLe1d+EoDbDPebwfip9OYnEYMD7EQB9O3N8eo -aYRkaSJMc2HalI5u0oLEhnZGucNw6K7uvuW0LkwmRWpN8Lc8e9ELZ3FOCE6qD9yh -giAkvZNklwhAxkk9spFkEilvEOPVtKgiSS6jZIL5G1NlAhp8n6+vhatY5Aotw8nO -QrqmPvzBd+2Gy2nrrGuSMC146m0x/g== -=3A0n +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl4eDcYACgkQTRfJlc2X +dfIAiQgAufTpgNvnHKoLQLwWf3GbjLQYWc3w1zRbGUMjghS/rS1yuf7RE/IPItET +ocIuIE36ogjvgnRuI0OOu3yJ+jxe41u3ToPb0ehNhINd+3rXsDhzwJDPjFdOiq98 +NoW9wQE9AHSfKEEVprckuZe2XmNLsYbBfa9THFULYIlnqAewtercXXx0eKaMG9+d +aRaD+LZXANx7IV6XnI9jfdKRuldHDvYp1TdvrRWBAVHid8j44c3P0pSvzf0YKGbx +xIty/w0zQFIWCfqPdK7/R2EHbEyR0SdI00a1Va1x7P8JGf7kDyLXl+Y9Yth7/uHA +osivJCpSrtAEbvMXojnL7u7kq3b37Q== +=Une9 -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 2f48751f2..9d2013cd1 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.1.0.dev0" +LE_AUTO_VERSION="1.2.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -256,20 +256,28 @@ DeprecationBootstrap() { fi } -MIN_PYTHON_VERSION="2.7" -MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//') +MIN_PYTHON_2_VERSION="2.7" +MIN_PYVER2=$(echo "$MIN_PYTHON_2_VERSION" | sed 's/\.//') +MIN_PYTHON_3_VERSION="3.5" +MIN_PYVER3=$(echo "$MIN_PYTHON_3_VERSION" | sed 's/\.//') # Sets LE_PYTHON to Python version string and PYVER to the first two -# digits of the python version +# digits of the python version. +# MIN_PYVER and MIN_PYTHON_VERSION are also set by this function, and their +# values depend on if we try to use Python 3 or Python 2. DeterminePythonVersion() { # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python # # If no Python is found, PYVER is set to 0. if [ "$USE_PYTHON_3" = 1 ]; then + MIN_PYVER=$MIN_PYVER3 + MIN_PYTHON_VERSION=$MIN_PYTHON_3_VERSION for LE_PYTHON in "$LE_PYTHON" python3; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break done else + MIN_PYVER=$MIN_PYVER2 + MIN_PYTHON_VERSION=$MIN_PYTHON_2_VERSION for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break @@ -285,7 +293,7 @@ DeterminePythonVersion() { fi fi - PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + PYVER=$("$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') if [ "$PYVER" -lt "$MIN_PYVER" ]; then if [ "$1" != "NOCRASH" ]; then error "You have an ancient version of Python entombed in your operating system..." @@ -368,7 +376,9 @@ BootstrapDebCommon() { # Sets TOOL to the name of the package manager # Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG. -# Enables EPEL if applicable and possible. +# Note: this function is called both while selecting the bootstrap scripts and +# during the actual bootstrap. Some things like prompting to user can be done in the latter +# case, but not in the former one. InitializeRPMCommonBase() { if type dnf 2>/dev/null then @@ -388,26 +398,6 @@ InitializeRPMCommonBase() { if [ "$QUIET" = 1 ]; then QUIET_FLAG='--quiet' fi - - if ! $TOOL list *virtualenv >/dev/null 2>&1; then - echo "To use Certbot, packages from the EPEL repository need to be installed." - if ! $TOOL list epel-release >/dev/null 2>&1; then - error "Enable the EPEL repository and try running Certbot again." - exit 1 - fi - if [ "$ASSUME_YES" = 1 ]; then - /bin/echo -n "Enabling the EPEL repository in 3 seconds..." - sleep 1s - /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..." - sleep 1s - /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..." - sleep 1s - fi - if ! $TOOL install $YES_FLAG $QUIET_FLAG epel-release; then - error "Could not enable EPEL. Aborting bootstrap!" - exit 1 - fi - fi } BootstrapRpmCommonBase() { @@ -488,13 +478,91 @@ BootstrapRpmCommon() { BootstrapRpmCommonBase "$python_pkgs" } +# If new packages are installed by BootstrapRpmPython3 below, this version +# number must be increased. +BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION=1 + +# Checks if rh-python36 can be installed. +Python36SclIsAvailable() { + InitializeRPMCommonBase >/dev/null 2>&1; + + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + return 0 + fi + if "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + return 0 + fi + return 1 +} + +# Try to enable rh-python36 from SCL if it is necessary and possible. +EnablePython36SCL() { + if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then + return 0 + fi + if [ ! -f /opt/rh/rh-python36/enable ]; then + return 0 + fi + set +e + if ! . /opt/rh/rh-python36/enable; then + error 'Unable to enable rh-python36!' + exit 1 + fi + set -e +} + +# This bootstrap concerns old RedHat-based distributions that do not ship by default +# with Python 2.7, but only Python 2.6. We bootstrap them by enabling SCL and installing +# Python 3.6. Some of these distributions are: CentOS/RHEL/OL/SL 6. +BootstrapRpmPython3Legacy() { + # Tested with: + # - CentOS 6 + + InitializeRPMCommonBase + + if ! "${TOOL}" list rh-python36 >/dev/null 2>&1; then + echo "To use Certbot on this operating system, packages from the SCL repository need to be installed." + if ! "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + error "Enable the SCL repository and try running Certbot again." + exit 1 + fi + if [ "${ASSUME_YES}" = 1 ]; then + /bin/echo -n "Enabling the SCL repository in 3 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -ne "\e[0K\rEnabling the SCL repository in 2 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -e "\e[0K\rEnabling the SCL repository in 1 second... (Press Ctrl-C to cancel)" + sleep 1s + fi + if ! "${TOOL}" install "${YES_FLAG}" "${QUIET_FLAG}" centos-release-scl; then + error "Could not enable SCL. Aborting bootstrap!" + exit 1 + fi + fi + + # CentOS 6 must use rh-python36 from SCL + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + python_pkgs="rh-python36-python + rh-python36-python-virtualenv + rh-python36-python-devel + " + else + error "No supported Python package available to install. Aborting bootstrap!" + exit 1 + fi + + BootstrapRpmCommonBase "${python_pkgs}" + + # Enable SCL rh-python36 after bootstrapping. + EnablePython36SCL +} + # If new packages are installed by BootstrapRpmPython3 below, this version # number must be increased. BOOTSTRAP_RPM_PYTHON3_VERSION=1 BootstrapRpmPython3() { # Tested with: - # - CentOS 6 # - Fedora 29 InitializeRPMCommonBase @@ -505,12 +573,6 @@ BootstrapRpmPython3() { python3-virtualenv python3-devel " - # EPEL uses python34 - elif $TOOL list python34 >/dev/null 2>&1; then - python_pkgs="python34 - python34-devel - python34-tools - " else error "No supported Python package available to install. Aborting bootstrap!" exit 1 @@ -758,6 +820,11 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` + if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then + # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. + DEPRECATED_OS=1 + fi + # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an # error, RPM_DIST_VERSION is set to "unknown". @@ -769,31 +836,50 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_VERSION=0 fi - # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. - # RHEL 8 also uses python3 by default. - if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 -o "$PYVER" -eq 26 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - else - RPM_USE_PYTHON_3=0 - fi + # Handle legacy RPM distributions + if [ "$PYVER" -eq 26 ]; then + # Check if an automated bootstrap can be achieved on this system. + if ! Python36SclIsAvailable; then + INTERACTIVE_BOOTSTRAP=1 + fi - if [ "$RPM_USE_PYTHON_3" = 1 ]; then Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 + BootstrapMessage "Legacy RedHat-based OSes that will use Python3" + BootstrapRpmPython3Legacy } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" + 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 + EnablePython36SCL else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. + # RHEL 8 also uses python3 by default. + if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + else + RPM_USE_PYTHON_3=0 + 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" @@ -870,6 +956,13 @@ if [ "$NO_BOOTSTRAP" = 1 ]; then unset BOOTSTRAP_VERSION fi +if [ "$DEPRECATED_OS" = 1 ]; then + Bootstrap() { + error "Skipping bootstrap because certbot-auto is deprecated on this system." + } + unset BOOTSTRAP_VERSION +fi + # Sets PREV_BOOTSTRAP_VERSION to the identifier for the bootstrap script used # to install OS dependencies on this system. PREV_BOOTSTRAP_VERSION isn't set # if it is unknown how OS dependencies were installed on this system. @@ -1067,6 +1160,28 @@ if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. shift 1 # the --le-auto-phase2 arg + + if [ "$DEPRECATED_OS" = 1 ]; then + # Phase 2 damage control mode for deprecated OSes. + # In this situation, we bypass any bootstrap or certbot venv setup. + error "Your system is not supported by certbot-auto anymore." + + if [ ! -d "$VENV_PATH" ] && OldVenvExists; then + VENV_BIN="$OLD_VENV_PATH/bin" + fi + + if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then + error "Certbot will no longer receive updates." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + "$VENV_BIN/letsencrypt" "$@" + exit 0 + else + error "Certbot cannot be installed." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + exit 1 + fi + fi + SetPrevBootstrapVersion if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then @@ -1078,8 +1193,15 @@ if [ "$1" = "--le-auto-phase2" ]; then # If the selected Bootstrap function isn't a noop and it differs from the # previously used version if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then - # if non-interactive mode or stdin and stdout are connected to a terminal - if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then + # Check if we can rebootstrap without manual user intervention: this requires that + # certbot-auto is in non-interactive mode AND selected bootstrap does not claim to + # require a manual user intervention. + if [ "$NONINTERACTIVE" = 1 -a "$INTERACTIVE_BOOTSTRAP" != 1 ]; then + CAN_REBOOTSTRAP=1 + fi + # Check if rebootstrap can be done non-interactively and current shell is non-interactive + # (true if stdin and stdout are not attached to a terminal). + if [ \( "$CAN_REBOOTSTRAP" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then if [ -d "$VENV_PATH" ]; then rm -rf "$VENV_PATH" fi @@ -1090,12 +1212,21 @@ if [ "$1" = "--le-auto-phase2" ]; then ln -s "$VENV_PATH" "$OLD_VENV_PATH" fi RerunWithArgs "$@" + # Otherwise bootstrap needs to be done manually by the user. else - error "Skipping upgrade because new OS dependencies may need to be installed." - error - error "To upgrade to a newer version, please run this script again manually so you can" - error "approve changes or with --non-interactive on the command line to automatically" - error "install any required packages." + # If it is because bootstrapping is interactive, --non-interactive will be of no use. + if [ "$INTERACTIVE_BOOTSTRAP" = 1 ]; then + error "Skipping upgrade because new OS dependencies may need to be installed." + error "This requires manual user intervention: please run this script again manually." + # If this is because of the environment (eg. non interactive shell without + # --non-interactive flag set), help the user in that direction. + else + error "Skipping upgrade because new OS dependencies may need to be installed." + error + error "To upgrade to a newer version, please run this script again manually so you can" + error "approve changes or with --non-interactive on the command line to automatically" + error "install any required packages." + fi # Set INSTALLED_VERSION to be the same so we don't update the venv INSTALLED_VERSION="$LE_AUTO_VERSION" # Continue to use OLD_VENV_PATH if the new venv doesn't exist @@ -1143,11 +1274,11 @@ if [ "$1" = "--le-auto-phase2" ]; then # pip install hashin # hashin -r dependency-requirements.txt cryptography==1.5.2 # ``` -ConfigArgParse==0.14.0 \ - --hash=sha256:2e2efe2be3f90577aca9415e32cb629aa2ecd92078adbe27b53a03e53ff12e91 -certifi==2019.9.11 \ - --hash=sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50 \ - --hash=sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef +ConfigArgParse==1.0 \ + --hash=sha256:bf378245bc9cdc403a527e5b7406b991680c2a530e7e81af747880b54eb57133 +certifi==2019.11.28 \ + --hash=sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3 \ + --hash=sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f cffi==1.13.2 \ --hash=sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42 \ --hash=sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04 \ @@ -1220,8 +1351,6 @@ enum34==1.1.6 \ funcsigs==1.0.2 \ --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \ --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50 -future==0.18.2 \ - --hash=sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d idna==2.8 \ --hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \ --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c @@ -1234,40 +1363,40 @@ josepy==1.2.0 \ mock==1.3.0 \ --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6 \ --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb -parsedatetime==2.4 \ - --hash=sha256:3d817c58fb9570d1eec1dd46fa9448cd644eeed4fb612684b02dfda3a79cb84b \ - --hash=sha256:9ee3529454bf35c40a77115f5a596771e59e1aee8c53306f346c461b8e913094 -pbr==5.4.3 \ - --hash=sha256:2c8e420cd4ed4cec4e7999ee47409e876af575d4c35a45840d59e8b5f3155ab8 \ - --hash=sha256:b32c8ccaac7b1a20c0ce00ce317642e6cf231cf038f9875e0280e28af5bf7ac9 -pyOpenSSL==19.0.0 \ - --hash=sha256:aeca66338f6de19d1aa46ed634c3b9ae519a64b458f8468aec688e7e3c20f200 \ - --hash=sha256:c727930ad54b10fc157015014b666f2d8b41f70c0d03e83ab67624fd3dd5d1e6 +parsedatetime==2.5 \ + --hash=sha256:3b835fc54e472c17ef447be37458b400e3fefdf14bb1ffdedb5d2c853acf4ba1 \ + --hash=sha256:d2e9ddb1e463de871d32088a3f3cea3dc8282b1b2800e081bd0ef86900451667 +pbr==5.4.4 \ + --hash=sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b \ + --hash=sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488 +pyOpenSSL==19.1.0 \ + --hash=sha256:621880965a720b8ece2f1b2f54ea2071966ab00e2970ad2ce11d596102063504 \ + --hash=sha256:9a24494b2602aaf402be5c9e30a0b82d4a5c67528fe8fb475e3f3bc00dd69507 pyRFC3339==1.1 \ --hash=sha256:67196cb83b470709c580bb4738b83165e67c6cc60e1f2e4f286cfcb402a926f4 \ --hash=sha256:81b8cbe1519cdb79bed04910dd6fa4e181faf8c88dff1e1b987b5f7ab23a5b1a pycparser==2.19 \ --hash=sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 -pyparsing==2.4.5 \ - --hash=sha256:20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f \ - --hash=sha256:4ca62001be367f01bd3e92ecbb79070272a9d4964dce6a48a82ff0b8bc7e683a +pyparsing==2.4.6 \ + --hash=sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f \ + --hash=sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec python-augeas==0.5.0 \ --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 pytz==2019.3 \ --hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \ --hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be -requests==2.21.0 \ - --hash=sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e \ - --hash=sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b +requests==2.22.0 \ + --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 \ + --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 requests-toolbelt==0.9.1 \ --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f \ --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 -six==1.13.0 \ - --hash=sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd \ - --hash=sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66 -urllib3==1.24.3 \ - --hash=sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4 \ - --hash=sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb +six==1.14.0 \ + --hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \ + --hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c +urllib3==1.25.8 \ + --hash=sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc \ + --hash=sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc zope.component==4.6 \ --hash=sha256:ec2afc5bbe611dcace98bb39822c122d44743d635dafc7315b9aef25097db9e6 zope.deferredimport==4.3.1 \ @@ -1279,47 +1408,86 @@ zope.deprecation==4.4.0 \ zope.event==4.4 \ --hash=sha256:69c27debad9bdacd9ce9b735dad382142281ac770c4a432b533d6d65c4614bcf \ --hash=sha256:d8e97d165fd5a0997b45f5303ae11ea3338becfe68c401dd88ffd2113fe5cae7 -zope.hookable==4.2.0 \ - --hash=sha256:22886e421234e7e8cedc21202e1d0ab59960e40a47dd7240e9659a2d82c51370 \ - --hash=sha256:39912f446e45b4e1f1951b5ffa2d5c8b074d25727ec51855ae9eab5408f105ab \ - --hash=sha256:3adb7ea0871dbc56b78f62c4f5c024851fc74299f4f2a95f913025b076cde220 \ - --hash=sha256:3d7c4b96341c02553d8b8d71065a9366ef67e6c6feca714f269894646bb8268b \ - --hash=sha256:4e826a11a529ed0464ffcecf34b0b7bd1b4928dd5848c5c61bedd7833e8f4801 \ - --hash=sha256:700d68cc30728de1c4c62088a981c6daeaefdf20a0d81995d2c0b7f442c5f88c \ - --hash=sha256:77c82a430cedfbf508d1aa406b2f437363c24fa90c73f577ead0fb5295749b83 \ - --hash=sha256:c1df3929a3666fc5a0c80d60a0c1e6f6ef97c7f6ed2f1b7cf49f3e6f3d4dde15 \ - --hash=sha256:dba8b2dd2cd41cb5f37bfa3f3d82721b8ae10e492944e48ddd90a439227f2893 \ - --hash=sha256:f492540305b15b5591bd7195d61f28946bb071de071cee5d68b6b8414da90fd2 -zope.interface==4.6.0 \ - --hash=sha256:086707e0f413ff8800d9c4bc26e174f7ee4c9c8b0302fbad68d083071822316c \ - --hash=sha256:1157b1ec2a1f5bf45668421e3955c60c610e31913cc695b407a574efdbae1f7b \ - --hash=sha256:11ebddf765bff3bbe8dbce10c86884d87f90ed66ee410a7e6c392086e2c63d02 \ - --hash=sha256:14b242d53f6f35c2d07aa2c0e13ccb710392bcd203e1b82a1828d216f6f6b11f \ - --hash=sha256:1b3d0dcabc7c90b470e59e38a9acaa361be43b3a6ea644c0063951964717f0e5 \ - --hash=sha256:20a12ab46a7e72b89ce0671e7d7a6c3c1ca2c2766ac98112f78c5bddaa6e4375 \ - --hash=sha256:298f82c0ab1b182bd1f34f347ea97dde0fffb9ecf850ecf7f8904b8442a07487 \ - --hash=sha256:2f6175722da6f23dbfc76c26c241b67b020e1e83ec7fe93c9e5d3dd18667ada2 \ - --hash=sha256:3b877de633a0f6d81b600624ff9137312d8b1d0f517064dfc39999352ab659f0 \ - --hash=sha256:4265681e77f5ac5bac0905812b828c9fe1ce80c6f3e3f8574acfb5643aeabc5b \ - --hash=sha256:550695c4e7313555549aa1cdb978dc9413d61307531f123558e438871a883d63 \ - --hash=sha256:5f4d42baed3a14c290a078e2696c5f565501abde1b2f3f1a1c0a94fbf6fbcc39 \ - --hash=sha256:62dd71dbed8cc6a18379700701d959307823b3b2451bdc018594c48956ace745 \ - --hash=sha256:7040547e5b882349c0a2cc9b50674b1745db551f330746af434aad4f09fba2cc \ - --hash=sha256:7e099fde2cce8b29434684f82977db4e24f0efa8b0508179fce1602d103296a2 \ - --hash=sha256:7e5c9a5012b2b33e87980cee7d1c82412b2ebabcb5862d53413ba1a2cfde23aa \ - --hash=sha256:81295629128f929e73be4ccfdd943a0906e5fe3cdb0d43ff1e5144d16fbb52b1 \ - --hash=sha256:95cc574b0b83b85be9917d37cd2fad0ce5a0d21b024e1a5804d044aabea636fc \ - --hash=sha256:968d5c5702da15c5bf8e4a6e4b67a4d92164e334e9c0b6acf080106678230b98 \ - --hash=sha256:9e998ba87df77a85c7bed53240a7257afe51a07ee6bc3445a0bf841886da0b97 \ - --hash=sha256:a0c39e2535a7e9c195af956610dba5a1073071d2d85e9d2e5d789463f63e52ab \ - --hash=sha256:a15e75d284178afe529a536b0e8b28b7e107ef39626a7809b4ee64ff3abc9127 \ - --hash=sha256:a6a6ff82f5f9b9702478035d8f6fb6903885653bff7ec3a1e011edc9b1a7168d \ - --hash=sha256:b639f72b95389620c1f881d94739c614d385406ab1d6926a9ffe1c8abbea23fe \ - --hash=sha256:bad44274b151d46619a7567010f7cde23a908c6faa84b97598fd2f474a0c6891 \ - --hash=sha256:bbcef00d09a30948756c5968863316c949d9cedbc7aabac5e8f0ffbdb632e5f1 \ - --hash=sha256:d788a3999014ddf416f2dc454efa4a5dbeda657c6aba031cf363741273804c6b \ - --hash=sha256:eed88ae03e1ef3a75a0e96a55a99d7937ed03e53d0cffc2451c208db445a2966 \ - --hash=sha256:f99451f3a579e73b5dd58b1b08d1179791d49084371d9a47baad3b22417f0317 +zope.hookable==5.0.0 \ + --hash=sha256:0992a0dd692003c09fb958e1480cebd1a28f2ef32faa4857d864f3ca8e9d6952 \ + --hash=sha256:0f325838dbac827a1e2ed5d482c1f2656b6844dc96aa098f7727e76395fcd694 \ + --hash=sha256:22a317ba00f61bac99eac1a5e330be7cb8c316275a21269ec58aa396b602af0c \ + --hash=sha256:25531cb5e7b35e8a6d1d6eddef624b9a22ce5dcf8f4448ef0f165acfa8c3fc21 \ + --hash=sha256:30890892652766fc80d11f078aca9a5b8150bef6b88aba23799581a53515c404 \ + --hash=sha256:342d682d93937e5b8c232baffb32a87d5eee605d44f74566657c64a239b7f342 \ + --hash=sha256:46b2fddf1f5aeb526e02b91f7e62afbb9fff4ffd7aafc97cdb00a0d717641567 \ + --hash=sha256:523318ff96df9b8d378d997c00c5d4cbfbff68dc48ff5ee5addabdb697d27528 \ + --hash=sha256:53aa02eb8921d4e667c69d76adeed8fe426e43870c101cb08dcd2f3468aff742 \ + --hash=sha256:62e79e8fdde087cb20822d7874758f5acbedbffaf3c0fbe06309eb8a41ee4e06 \ + --hash=sha256:74bf2f757f7385b56dc3548adae508d8b3ef952d600b4b12b88f7d1706b05dcc \ + --hash=sha256:751ee9d89eb96e00c1d7048da9725ce392a708ed43406416dc5ed61e4d199764 \ + --hash=sha256:7b83bc341e682771fe810b360cd5d9c886a948976aea4b979ff214e10b8b523b \ + --hash=sha256:81eeeb27dbb0ddaed8070daee529f0d1bfe4f74c7351cce2aaca3ea287c4cc32 \ + --hash=sha256:856509191e16930335af4d773c0fc31a17bae8991eb6f167a09d5eddf25b56cc \ + --hash=sha256:8853e81fd07b18fa9193b19e070dc0557848d9945b1d2dac3b7782543458c87d \ + --hash=sha256:94506a732da2832029aecdfe6ea07eb1b70ee06d802fff34e1b3618fe7cdf026 \ + --hash=sha256:95ad874a8cc94e786969215d660143817f745225579bfe318c4676e218d3147c \ + --hash=sha256:9758ec9174966ffe5c499b6c3d149f80aa0a9238020006a2b87c6af5963fcf48 \ + --hash=sha256:a169823e331da939aa7178fc152e65699aeb78957e46c6f80ccb50ee4c3616c2 \ + --hash=sha256:a67878a798f6ca292729a28c2226592b3d000dc6ee7825d31887b553686c7ac7 \ + --hash=sha256:a9a6d9eb2319a09905670810e2de971d6c49013843700b4975e2fc0afe96c8db \ + --hash=sha256:b3e118b58a3d2301960e6f5f25736d92f6b9f861728d3b8c26d69f54d8a157d2 \ + --hash=sha256:ca6705c2a1fb5059a4efbe9f5426be4cdf71b3c9564816916fc7aa7902f19ede \ + --hash=sha256:cf711527c9d4ae72085f137caffb4be74fc007ffb17cd103628c7d5ba17e205f \ + --hash=sha256:d087602a6845ebe9d5a1c5a949fedde2c45f372d77fbce4f7fe44b68b28a1d03 \ + --hash=sha256:d1080e1074ddf75ad6662a9b34626650759c19a9093e1a32a503d37e48da135b \ + --hash=sha256:db9c60368aff2b7e6c47115f3ad9bd6e96aa298b12ed5f8cb13f5673b30be565 \ + --hash=sha256:dbeb127a04473f5a989169eb400b67beb921c749599b77650941c21fe39cb8d9 \ + --hash=sha256:dca336ca3682d869d291d7cd18284f6ff6876e4244eb1821430323056b000e2c \ + --hash=sha256:dd69a9be95346d10c853b6233fcafe3c0315b89424b378f2ad45170d8e161568 \ + --hash=sha256:dd79f8fae5894f1ee0a0042214685f2d039341250c994b825c10a4cd075d80f6 \ + --hash=sha256:e647d850aa1286d98910133cee12bd87c354f7b7bb3f3cd816a62ba7fa2f7007 \ + --hash=sha256:f37a210b5c04b2d4e4bac494ab15b70196f219a1e1649ddca78560757d4278fb \ + --hash=sha256:f67820b6d33a705dc3c1c457156e51686f7b350ff57f2112e1a9a4dad38ec268 \ + --hash=sha256:f68969978ccf0e6123902f7365aae5b7a9e99169d4b9105c47cf28e788116894 \ + --hash=sha256:f717a0b34460ae1ac0064e91b267c0588ac2c098ffd695992e72cd5462d97a67 \ + --hash=sha256:f9d58ccec8684ca276d5a4e7b0dfacca028336300a8f715d616d9f0ce9ae8096 \ + --hash=sha256:fcc3513a54e656067cbf7b98bab0d6b9534b9eabc666d1f78aad6acdf0962736 +zope.interface==4.7.1 \ + --hash=sha256:048b16ac882a05bc7ef534e8b9f15c9d7a6c190e24e8938a19b7617af4ed854a \ + --hash=sha256:05816cf8e7407cf62f2ec95c0a5d69ec4fa5741d9ccd10db9f21691916a9a098 \ + --hash=sha256:065d6a1ac89d35445168813bed45048ed4e67a4cdfc5a68fdb626a770378869f \ + --hash=sha256:14157421f4121a57625002cc4f48ac7521ea238d697c4a4459a884b62132b977 \ + --hash=sha256:18dc895945694f397a0be86be760ff664b790f95d8e7752d5bab80284ff9105d \ + --hash=sha256:1962c9f838bd6ae4075d0014f72697510daefc7e1c7e48b2607df0b6e157989c \ + --hash=sha256:1a67408cacd198c7e6274a19920bb4568d56459e659e23c4915528686ac1763a \ + --hash=sha256:21bf781076dd616bd07cf0223f79d61ab4f45176076f90bc2890e18c48195da4 \ + --hash=sha256:21c0a5d98650aebb84efa16ce2c8df1a46bdc4fe8a9e33237d0ca0b23f416ead \ + --hash=sha256:23cfeea25d1e42ff3bf4f9a0c31e9d5950aa9e7c4b12f0c4bd086f378f7b7a71 \ + --hash=sha256:24b6fce1fb71abf9f4093e3259084efcc0ef479f89356757780685bd2b06ef37 \ + --hash=sha256:24f84ce24eb6b5fcdcb38ad9761524f1ae96f7126abb5e597f8a3973d9921409 \ + --hash=sha256:25e0ef4a824017809d6d8b0ce4ab3288594ba283e4d4f94d8cfb81d73ed65114 \ + --hash=sha256:2e8fdd625e9aba31228e7ddbc36bad5c38dc3ee99a86aa420f89a290bd987ce9 \ + --hash=sha256:2f3bc2f49b67b1bea82b942d25bc958d4f4ea6709b411cb2b6b9718adf7914ce \ + --hash=sha256:35d24be9d04d50da3a6f4d61de028c1dd087045385a0ff374d93ef85af61b584 \ + --hash=sha256:35dbe4e8c73003dff40dfaeb15902910a4360699375e7b47d3c909a83ff27cd0 \ + --hash=sha256:3dfce831b824ab5cf446ed0c350b793ac6fa5fe33b984305cb4c966a86a8fb79 \ + --hash=sha256:3f7866365df5a36a7b8de8056cd1c605648f56f9a226d918ed84c85d25e8d55f \ + --hash=sha256:455cc8c01de3bac6f9c223967cea41f4449f58b4c2e724ec8177382ddd183ab4 \ + --hash=sha256:4bb937e998be9d5e345f486693e477ba79e4344674484001a0b646be1d530487 \ + --hash=sha256:52303a20902ca0888dfb83230ca3ee6fbe63c0ad1dd60aa0bba7958ccff454d8 \ + --hash=sha256:6e0a897d4e09859cc80c6a16a29697406ead752292ace17f1805126a4f63c838 \ + --hash=sha256:6e1816e7c10966330d77af45f77501f9a68818c065dec0ad11d22b50a0e212e7 \ + --hash=sha256:73b5921c5c6ce3358c836461b5470bf675601c96d5e5d8f2a446951470614f67 \ + --hash=sha256:8093cd45cdb5f6c8591cfd1af03d32b32965b0f79b94684cd0c9afdf841982bb \ + --hash=sha256:864b4a94b60db301899cf373579fd9ef92edddbf0fb2cd5ae99f53ef423ccc56 \ + --hash=sha256:8a27b4d3ea9c6d086ce8e7cdb3e8d319b6752e2a03238a388ccc83ccbe165f50 \ + --hash=sha256:91b847969d4784abd855165a2d163f72ac1e58e6dce09a5e46c20e58f19cc96d \ + --hash=sha256:b47b1028be4758c3167e474884ccc079b94835f058984b15c145966c4df64d27 \ + --hash=sha256:b68814a322835d8ad671b7acc23a3b2acecba527bb14f4b53fc925f8a27e44d8 \ + --hash=sha256:bcb50a032c3b6ec7fb281b3a83d2b31ab5246c5b119588725b1350d3a1d9f6a3 \ + --hash=sha256:c56db7d10b25ce8918b6aec6b08ac401842b47e6c136773bfb3b590753f7fb67 \ + --hash=sha256:c94b77a13d4f47883e4f97f9fa00f5feadd38af3e6b3c7be45cfdb0a14c7149b \ + --hash=sha256:db381f6fdaef483ad435f778086ccc4890120aff8df2ba5cfeeac24d280b3145 \ + --hash=sha256:e6487d01c8b7ed86af30ea141fcc4f93f8a7dde26f94177c1ad637c353bd5c07 \ + --hash=sha256:e86923fa728dfba39c5bb6046a450bd4eec8ad949ac404eca728cfce320d1732 \ + --hash=sha256:f6ca36dc1e9eeb46d779869c60001b3065fb670b5775c51421c099ea2a77c3c9 \ + --hash=sha256:fb62f2cbe790a50d95593fb40e8cca261c31a2f5637455ea39440d6457c2ba25 zope.proxy==4.3.3 \ --hash=sha256:04646ac04ffa9c8e32fb2b5c3cd42995b2548ea14251f3c21ca704afae88e42c \ --hash=sha256:07b6bceea232559d24358832f1cd2ed344bbf05ca83855a5b9698b5f23c5ed60 \ @@ -1372,18 +1540,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.0.0 \ - --hash=sha256:8d074cff89dee002dec1c47cb0da04ea8e0ede8d68838b6d54aa41580d9262df \ - --hash=sha256:86b82d31db19fffffb0d6b218951e2121ef514e3ff659aa042deaf92a33e302a -acme==1.0.0 \ - --hash=sha256:f6972e436e76f7f1e395e81e149f8713ca8462d465b14993bddc53fb18a40644 \ - --hash=sha256:6a08f12f848ce563b50bca421ba9db653df9f82cfefeaf8aba517f046d1386c2 -certbot-apache==1.0.0 \ - --hash=sha256:e591d0cf773ad33ee978f7adb1b69288eac2c8847c643b06e70260e707626f8e \ - --hash=sha256:7335ab5687a0a47d9041d9e13f3a2d67d0e8372da97ab639edb31c14b787cd68 -certbot-nginx==1.0.0 \ - --hash=sha256:ce8a2e51165da7c15bfdc059cd6572d0f368c078f1e1a77633a2773310b2f231 \ - --hash=sha256:63b4ae09d4f1c9ef0a1a2a49c3f651d8a7cb30303ec6f954239e987c5da45dc4 +certbot==1.1.0 \ + --hash=sha256:66a5cab9267349941604c2c98082bfef85877653c023fc324b1c3869fb16add6 \ + --hash=sha256:46e93661a0db53f416c0f5476d8d2e62bc7259b7660dd983453b85df9ef6e8b8 +acme==1.1.0 \ + --hash=sha256:11b9beba706fb8f652c8910d46dd1939d670cac8169f3c66c18c080ed3353e71 \ + --hash=sha256:c305a20eeb9cb02240347703d497891c13d43a47c794fa100d4dbb479a5370d9 +certbot-apache==1.1.0 \ + --hash=sha256:9c847ff223c2e465e241c78d22f97cee77d5e551df608bed06c55f8627f4cbd2 \ + --hash=sha256:05e84dfe96b72582cde97c490977d8e2d33d440c927a320debb4cf287f6fadcc +certbot-nginx==1.1.0 \ + --hash=sha256:bf06fa2f5059f0fdb7d352c8739e1ed0830db4f0d89e812dab4f081bda6ec7d6 \ + --hash=sha256:0a80ecbd2a30f3757c7652cabfff854ca07873b1cf02ebbe1892786c3b3a5874 UNLIKELY_EOF # ------------------------------------------------------------------------- @@ -1617,6 +1785,9 @@ UNLIKELY_EOF say "Installation succeeded." fi + # If you're modifying any of the code after this point in this current `if` block, you + # may need to update the "$DEPRECATED_OS" = 1 case at the beginning of phase 2 as well. + if [ "$INSTALL_ONLY" = 1 ]; then say "Certbot is installed." exit 0 @@ -1828,30 +1999,35 @@ UNLIKELY_EOF error "WARNING: unable to check for updates." fi - LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then - say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" - elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then - say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + # If for any reason REMOTE_VERSION is not set, let's assume certbot-auto is up-to-date, + # and do not go into the self-upgrading process. + if [ -n "$REMOTE_VERSION" ]; then + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then + say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - # Install new copy of certbot-auto. - # TODO: Deal with quotes in pathnames. - say "Replacing certbot-auto..." - # Clone permissions with cp. chmod and chown don't have a --reference - # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: - cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" - cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" - # Using mv rather than cp leaves the old file descriptor pointing to the - # original copy so the shell can continue to read it unmolested. mv across - # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the - # cp is unlikely to fail if the rm doesn't. - mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" - fi # A newer version is available. + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + + # Install new copy of certbot-auto. + # TODO: Deal with quotes in pathnames. + say "Replacing certbot-auto..." + # Clone permissions with cp. chmod and chown don't have a --reference + # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: + cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" + cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" + # Using mv rather than cp leaves the old file descriptor pointing to the + # original copy so the shell can continue to read it unmolested. mv across + # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the + # cp is unlikely to fail if the rm doesn't. + mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" + fi # A newer version is available. + fi fi # Self-upgrading is allowed. RerunWithArgs --le-auto-phase2 "$@" diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index 705f30e3f..bae77d59b 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 31c5bb134..53e57a498 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -256,20 +256,28 @@ DeprecationBootstrap() { fi } -MIN_PYTHON_VERSION="2.7" -MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//') +MIN_PYTHON_2_VERSION="2.7" +MIN_PYVER2=$(echo "$MIN_PYTHON_2_VERSION" | sed 's/\.//') +MIN_PYTHON_3_VERSION="3.5" +MIN_PYVER3=$(echo "$MIN_PYTHON_3_VERSION" | sed 's/\.//') # Sets LE_PYTHON to Python version string and PYVER to the first two -# digits of the python version +# digits of the python version. +# MIN_PYVER and MIN_PYTHON_VERSION are also set by this function, and their +# values depend on if we try to use Python 3 or Python 2. DeterminePythonVersion() { # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python # # If no Python is found, PYVER is set to 0. if [ "$USE_PYTHON_3" = 1 ]; then + MIN_PYVER=$MIN_PYVER3 + MIN_PYTHON_VERSION=$MIN_PYTHON_3_VERSION for LE_PYTHON in "$LE_PYTHON" python3; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break done else + MIN_PYVER=$MIN_PYVER2 + MIN_PYTHON_VERSION=$MIN_PYTHON_2_VERSION for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do # Break (while keeping the LE_PYTHON value) if found. $EXISTS "$LE_PYTHON" > /dev/null && break @@ -285,7 +293,7 @@ DeterminePythonVersion() { fi fi - PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + PYVER=$("$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') if [ "$PYVER" -lt "$MIN_PYVER" ]; then if [ "$1" != "NOCRASH" ]; then error "You have an ancient version of Python entombed in your operating system..." @@ -298,6 +306,7 @@ DeterminePythonVersion() { {{ bootstrappers/deb_common.sh }} {{ bootstrappers/rpm_common_base.sh }} {{ bootstrappers/rpm_common.sh }} +{{ bootstrappers/rpm_python3_legacy.sh }} {{ bootstrappers/rpm_python3.sh }} {{ bootstrappers/suse_common.sh }} {{ bootstrappers/arch_common.sh }} @@ -333,6 +342,11 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` + if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then + # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. + DEPRECATED_OS=1 + fi + # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an # error, RPM_DIST_VERSION is set to "unknown". @@ -344,31 +358,50 @@ elif [ -f /etc/redhat-release ]; then RPM_DIST_VERSION=0 fi - # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. - # RHEL 8 also uses python3 by default. - if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 -o "$PYVER" -eq 26 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - else - RPM_USE_PYTHON_3=0 - fi + # Handle legacy RPM distributions + if [ "$PYVER" -eq 26 ]; then + # Check if an automated bootstrap can be achieved on this system. + if ! Python36SclIsAvailable; then + INTERACTIVE_BOOTSTRAP=1 + fi - if [ "$RPM_USE_PYTHON_3" = 1 ]; then Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 + BootstrapMessage "Legacy RedHat-based OSes that will use Python3" + BootstrapRpmPython3Legacy } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" + 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 + EnablePython36SCL else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. + # RHEL 8 also uses python3 by default. + if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then + RPM_USE_PYTHON_3=1 + else + RPM_USE_PYTHON_3=0 + 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" @@ -445,6 +478,13 @@ if [ "$NO_BOOTSTRAP" = 1 ]; then unset BOOTSTRAP_VERSION fi +if [ "$DEPRECATED_OS" = 1 ]; then + Bootstrap() { + error "Skipping bootstrap because certbot-auto is deprecated on this system." + } + unset BOOTSTRAP_VERSION +fi + # Sets PREV_BOOTSTRAP_VERSION to the identifier for the bootstrap script used # to install OS dependencies on this system. PREV_BOOTSTRAP_VERSION isn't set # if it is unknown how OS dependencies were installed on this system. @@ -534,6 +574,28 @@ if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. shift 1 # the --le-auto-phase2 arg + + if [ "$DEPRECATED_OS" = 1 ]; then + # Phase 2 damage control mode for deprecated OSes. + # In this situation, we bypass any bootstrap or certbot venv setup. + error "Your system is not supported by certbot-auto anymore." + + if [ ! -d "$VENV_PATH" ] && OldVenvExists; then + VENV_BIN="$OLD_VENV_PATH/bin" + fi + + if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then + error "Certbot will no longer receive updates." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + "$VENV_BIN/letsencrypt" "$@" + exit 0 + else + error "Certbot cannot be installed." + error "Please visit https://certbot.eff.org/ to check for other alternatives." + exit 1 + fi + fi + SetPrevBootstrapVersion if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then @@ -545,8 +607,15 @@ if [ "$1" = "--le-auto-phase2" ]; then # If the selected Bootstrap function isn't a noop and it differs from the # previously used version if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then - # if non-interactive mode or stdin and stdout are connected to a terminal - if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then + # Check if we can rebootstrap without manual user intervention: this requires that + # certbot-auto is in non-interactive mode AND selected bootstrap does not claim to + # require a manual user intervention. + if [ "$NONINTERACTIVE" = 1 -a "$INTERACTIVE_BOOTSTRAP" != 1 ]; then + CAN_REBOOTSTRAP=1 + fi + # Check if rebootstrap can be done non-interactively and current shell is non-interactive + # (true if stdin and stdout are not attached to a terminal). + if [ \( "$CAN_REBOOTSTRAP" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then if [ -d "$VENV_PATH" ]; then rm -rf "$VENV_PATH" fi @@ -557,12 +626,21 @@ if [ "$1" = "--le-auto-phase2" ]; then ln -s "$VENV_PATH" "$OLD_VENV_PATH" fi RerunWithArgs "$@" + # Otherwise bootstrap needs to be done manually by the user. else - error "Skipping upgrade because new OS dependencies may need to be installed." - error - error "To upgrade to a newer version, please run this script again manually so you can" - error "approve changes or with --non-interactive on the command line to automatically" - error "install any required packages." + # If it is because bootstrapping is interactive, --non-interactive will be of no use. + if [ "$INTERACTIVE_BOOTSTRAP" = 1 ]; then + error "Skipping upgrade because new OS dependencies may need to be installed." + error "This requires manual user intervention: please run this script again manually." + # If this is because of the environment (eg. non interactive shell without + # --non-interactive flag set), help the user in that direction. + else + error "Skipping upgrade because new OS dependencies may need to be installed." + error + error "To upgrade to a newer version, please run this script again manually so you can" + error "approve changes or with --non-interactive on the command line to automatically" + error "install any required packages." + fi # Set INSTALLED_VERSION to be the same so we don't update the venv INSTALLED_VERSION="$LE_AUTO_VERSION" # Continue to use OLD_VENV_PATH if the new venv doesn't exist @@ -657,6 +735,9 @@ UNLIKELY_EOF say "Installation succeeded." fi + # If you're modifying any of the code after this point in this current `if` block, you + # may need to update the "$DEPRECATED_OS" = 1 case at the beginning of phase 2 as well. + if [ "$INSTALL_ONLY" = 1 ]; then say "Certbot is installed." exit 0 @@ -720,30 +801,35 @@ UNLIKELY_EOF error "WARNING: unable to check for updates." fi - LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then - say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" - elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then - say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + # If for any reason REMOTE_VERSION is not set, let's assume certbot-auto is up-to-date, + # and do not go into the self-upgrading process. + if [ -n "$REMOTE_VERSION" ]; then + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then + say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - # Install new copy of certbot-auto. - # TODO: Deal with quotes in pathnames. - say "Replacing certbot-auto..." - # Clone permissions with cp. chmod and chown don't have a --reference - # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: - cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" - cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" - # Using mv rather than cp leaves the old file descriptor pointing to the - # original copy so the shell can continue to read it unmolested. mv across - # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the - # cp is unlikely to fail if the rm doesn't. - mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" - fi # A newer version is available. + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + + # Install new copy of certbot-auto. + # TODO: Deal with quotes in pathnames. + say "Replacing certbot-auto..." + # Clone permissions with cp. chmod and chown don't have a --reference + # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: + cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" + cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" + # Using mv rather than cp leaves the old file descriptor pointing to the + # original copy so the shell can continue to read it unmolested. mv across + # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the + # cp is unlikely to fail if the rm doesn't. + mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" + fi # A newer version is available. + fi fi # Self-upgrading is allowed. RerunWithArgs --le-auto-phase2 "$@" diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh index 326ad8b3f..2b00b199b 100644 --- a/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh +++ b/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh @@ -3,7 +3,9 @@ # Sets TOOL to the name of the package manager # Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG. -# Enables EPEL if applicable and possible. +# Note: this function is called both while selecting the bootstrap scripts and +# during the actual bootstrap. Some things like prompting to user can be done in the latter +# case, but not in the former one. InitializeRPMCommonBase() { if type dnf 2>/dev/null then @@ -23,26 +25,6 @@ InitializeRPMCommonBase() { if [ "$QUIET" = 1 ]; then QUIET_FLAG='--quiet' fi - - if ! $TOOL list *virtualenv >/dev/null 2>&1; then - echo "To use Certbot, packages from the EPEL repository need to be installed." - if ! $TOOL list epel-release >/dev/null 2>&1; then - error "Enable the EPEL repository and try running Certbot again." - exit 1 - fi - if [ "$ASSUME_YES" = 1 ]; then - /bin/echo -n "Enabling the EPEL repository in 3 seconds..." - sleep 1s - /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..." - sleep 1s - /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..." - sleep 1s - fi - if ! $TOOL install $YES_FLAG $QUIET_FLAG epel-release; then - error "Could not enable EPEL. Aborting bootstrap!" - exit 1 - fi - fi } BootstrapRpmCommonBase() { diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh index f33b07ca9..ac0553db5 100644 --- a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh +++ b/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh @@ -4,7 +4,6 @@ BOOTSTRAP_RPM_PYTHON3_VERSION=1 BootstrapRpmPython3() { # Tested with: - # - CentOS 6 # - Fedora 29 InitializeRPMCommonBase @@ -15,12 +14,6 @@ BootstrapRpmPython3() { python3-virtualenv python3-devel " - # EPEL uses python34 - elif $TOOL list python34 >/dev/null 2>&1; then - python_pkgs="python34 - python34-devel - python34-tools - " else error "No supported Python package available to install. Aborting bootstrap!" exit 1 diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh new file mode 100644 index 000000000..febfc7a83 --- /dev/null +++ b/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh @@ -0,0 +1,78 @@ +# If new packages are installed by BootstrapRpmPython3 below, this version +# number must be increased. +BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION=1 + +# Checks if rh-python36 can be installed. +Python36SclIsAvailable() { + InitializeRPMCommonBase >/dev/null 2>&1; + + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + return 0 + fi + if "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + return 0 + fi + return 1 +} + +# Try to enable rh-python36 from SCL if it is necessary and possible. +EnablePython36SCL() { + if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then + return 0 + fi + if [ ! -f /opt/rh/rh-python36/enable ]; then + return 0 + fi + set +e + if ! . /opt/rh/rh-python36/enable; then + error 'Unable to enable rh-python36!' + exit 1 + fi + set -e +} + +# This bootstrap concerns old RedHat-based distributions that do not ship by default +# with Python 2.7, but only Python 2.6. We bootstrap them by enabling SCL and installing +# Python 3.6. Some of these distributions are: CentOS/RHEL/OL/SL 6. +BootstrapRpmPython3Legacy() { + # Tested with: + # - CentOS 6 + + InitializeRPMCommonBase + + if ! "${TOOL}" list rh-python36 >/dev/null 2>&1; then + echo "To use Certbot on this operating system, packages from the SCL repository need to be installed." + if ! "${TOOL}" list centos-release-scl >/dev/null 2>&1; then + error "Enable the SCL repository and try running Certbot again." + exit 1 + fi + if [ "${ASSUME_YES}" = 1 ]; then + /bin/echo -n "Enabling the SCL repository in 3 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -ne "\e[0K\rEnabling the SCL repository in 2 seconds... (Press Ctrl-C to cancel)" + sleep 1s + /bin/echo -e "\e[0K\rEnabling the SCL repository in 1 second... (Press Ctrl-C to cancel)" + sleep 1s + fi + if ! "${TOOL}" install "${YES_FLAG}" "${QUIET_FLAG}" centos-release-scl; then + error "Could not enable SCL. Aborting bootstrap!" + exit 1 + fi + fi + + # CentOS 6 must use rh-python36 from SCL + if "${TOOL}" list rh-python36 >/dev/null 2>&1; then + python_pkgs="rh-python36-python + rh-python36-python-virtualenv + rh-python36-python-devel + " + else + error "No supported Python package available to install. Aborting bootstrap!" + exit 1 + fi + + BootstrapRpmCommonBase "${python_pkgs}" + + # Enable SCL rh-python36 after bootstrapping. + EnablePython36SCL +} diff --git a/letsencrypt-auto-source/pieces/certbot-requirements.txt b/letsencrypt-auto-source/pieces/certbot-requirements.txt index d4bdfd49e..67a33390b 100644 --- a/letsencrypt-auto-source/pieces/certbot-requirements.txt +++ b/letsencrypt-auto-source/pieces/certbot-requirements.txt @@ -1,12 +1,12 @@ -certbot==1.0.0 \ - --hash=sha256:8d074cff89dee002dec1c47cb0da04ea8e0ede8d68838b6d54aa41580d9262df \ - --hash=sha256:86b82d31db19fffffb0d6b218951e2121ef514e3ff659aa042deaf92a33e302a -acme==1.0.0 \ - --hash=sha256:f6972e436e76f7f1e395e81e149f8713ca8462d465b14993bddc53fb18a40644 \ - --hash=sha256:6a08f12f848ce563b50bca421ba9db653df9f82cfefeaf8aba517f046d1386c2 -certbot-apache==1.0.0 \ - --hash=sha256:e591d0cf773ad33ee978f7adb1b69288eac2c8847c643b06e70260e707626f8e \ - --hash=sha256:7335ab5687a0a47d9041d9e13f3a2d67d0e8372da97ab639edb31c14b787cd68 -certbot-nginx==1.0.0 \ - --hash=sha256:ce8a2e51165da7c15bfdc059cd6572d0f368c078f1e1a77633a2773310b2f231 \ - --hash=sha256:63b4ae09d4f1c9ef0a1a2a49c3f651d8a7cb30303ec6f954239e987c5da45dc4 +certbot==1.1.0 \ + --hash=sha256:66a5cab9267349941604c2c98082bfef85877653c023fc324b1c3869fb16add6 \ + --hash=sha256:46e93661a0db53f416c0f5476d8d2e62bc7259b7660dd983453b85df9ef6e8b8 +acme==1.1.0 \ + --hash=sha256:11b9beba706fb8f652c8910d46dd1939d670cac8169f3c66c18c080ed3353e71 \ + --hash=sha256:c305a20eeb9cb02240347703d497891c13d43a47c794fa100d4dbb479a5370d9 +certbot-apache==1.1.0 \ + --hash=sha256:9c847ff223c2e465e241c78d22f97cee77d5e551df608bed06c55f8627f4cbd2 \ + --hash=sha256:05e84dfe96b72582cde97c490977d8e2d33d440c927a320debb4cf287f6fadcc +certbot-nginx==1.1.0 \ + --hash=sha256:bf06fa2f5059f0fdb7d352c8739e1ed0830db4f0d89e812dab4f081bda6ec7d6 \ + --hash=sha256:0a80ecbd2a30f3757c7652cabfff854ca07873b1cf02ebbe1892786c3b3a5874 diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index 034fae46d..eec5a9946 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -9,11 +9,11 @@ # pip install hashin # hashin -r dependency-requirements.txt cryptography==1.5.2 # ``` -ConfigArgParse==0.14.0 \ - --hash=sha256:2e2efe2be3f90577aca9415e32cb629aa2ecd92078adbe27b53a03e53ff12e91 -certifi==2019.9.11 \ - --hash=sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50 \ - --hash=sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef +ConfigArgParse==1.0 \ + --hash=sha256:bf378245bc9cdc403a527e5b7406b991680c2a530e7e81af747880b54eb57133 +certifi==2019.11.28 \ + --hash=sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3 \ + --hash=sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f cffi==1.13.2 \ --hash=sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42 \ --hash=sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04 \ @@ -86,8 +86,6 @@ enum34==1.1.6 \ funcsigs==1.0.2 \ --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \ --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50 -future==0.18.2 \ - --hash=sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d idna==2.8 \ --hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \ --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c @@ -100,40 +98,40 @@ josepy==1.2.0 \ mock==1.3.0 \ --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6 \ --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb -parsedatetime==2.4 \ - --hash=sha256:3d817c58fb9570d1eec1dd46fa9448cd644eeed4fb612684b02dfda3a79cb84b \ - --hash=sha256:9ee3529454bf35c40a77115f5a596771e59e1aee8c53306f346c461b8e913094 -pbr==5.4.3 \ - --hash=sha256:2c8e420cd4ed4cec4e7999ee47409e876af575d4c35a45840d59e8b5f3155ab8 \ - --hash=sha256:b32c8ccaac7b1a20c0ce00ce317642e6cf231cf038f9875e0280e28af5bf7ac9 -pyOpenSSL==19.0.0 \ - --hash=sha256:aeca66338f6de19d1aa46ed634c3b9ae519a64b458f8468aec688e7e3c20f200 \ - --hash=sha256:c727930ad54b10fc157015014b666f2d8b41f70c0d03e83ab67624fd3dd5d1e6 +parsedatetime==2.5 \ + --hash=sha256:3b835fc54e472c17ef447be37458b400e3fefdf14bb1ffdedb5d2c853acf4ba1 \ + --hash=sha256:d2e9ddb1e463de871d32088a3f3cea3dc8282b1b2800e081bd0ef86900451667 +pbr==5.4.4 \ + --hash=sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b \ + --hash=sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488 +pyOpenSSL==19.1.0 \ + --hash=sha256:621880965a720b8ece2f1b2f54ea2071966ab00e2970ad2ce11d596102063504 \ + --hash=sha256:9a24494b2602aaf402be5c9e30a0b82d4a5c67528fe8fb475e3f3bc00dd69507 pyRFC3339==1.1 \ --hash=sha256:67196cb83b470709c580bb4738b83165e67c6cc60e1f2e4f286cfcb402a926f4 \ --hash=sha256:81b8cbe1519cdb79bed04910dd6fa4e181faf8c88dff1e1b987b5f7ab23a5b1a pycparser==2.19 \ --hash=sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 -pyparsing==2.4.5 \ - --hash=sha256:20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f \ - --hash=sha256:4ca62001be367f01bd3e92ecbb79070272a9d4964dce6a48a82ff0b8bc7e683a +pyparsing==2.4.6 \ + --hash=sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f \ + --hash=sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec python-augeas==0.5.0 \ --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 pytz==2019.3 \ --hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \ --hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be -requests==2.21.0 \ - --hash=sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e \ - --hash=sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b +requests==2.22.0 \ + --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 \ + --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 requests-toolbelt==0.9.1 \ --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f \ --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 -six==1.13.0 \ - --hash=sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd \ - --hash=sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66 -urllib3==1.24.3 \ - --hash=sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4 \ - --hash=sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb +six==1.14.0 \ + --hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \ + --hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c +urllib3==1.25.8 \ + --hash=sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc \ + --hash=sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc zope.component==4.6 \ --hash=sha256:ec2afc5bbe611dcace98bb39822c122d44743d635dafc7315b9aef25097db9e6 zope.deferredimport==4.3.1 \ @@ -145,47 +143,86 @@ zope.deprecation==4.4.0 \ zope.event==4.4 \ --hash=sha256:69c27debad9bdacd9ce9b735dad382142281ac770c4a432b533d6d65c4614bcf \ --hash=sha256:d8e97d165fd5a0997b45f5303ae11ea3338becfe68c401dd88ffd2113fe5cae7 -zope.hookable==4.2.0 \ - --hash=sha256:22886e421234e7e8cedc21202e1d0ab59960e40a47dd7240e9659a2d82c51370 \ - --hash=sha256:39912f446e45b4e1f1951b5ffa2d5c8b074d25727ec51855ae9eab5408f105ab \ - --hash=sha256:3adb7ea0871dbc56b78f62c4f5c024851fc74299f4f2a95f913025b076cde220 \ - --hash=sha256:3d7c4b96341c02553d8b8d71065a9366ef67e6c6feca714f269894646bb8268b \ - --hash=sha256:4e826a11a529ed0464ffcecf34b0b7bd1b4928dd5848c5c61bedd7833e8f4801 \ - --hash=sha256:700d68cc30728de1c4c62088a981c6daeaefdf20a0d81995d2c0b7f442c5f88c \ - --hash=sha256:77c82a430cedfbf508d1aa406b2f437363c24fa90c73f577ead0fb5295749b83 \ - --hash=sha256:c1df3929a3666fc5a0c80d60a0c1e6f6ef97c7f6ed2f1b7cf49f3e6f3d4dde15 \ - --hash=sha256:dba8b2dd2cd41cb5f37bfa3f3d82721b8ae10e492944e48ddd90a439227f2893 \ - --hash=sha256:f492540305b15b5591bd7195d61f28946bb071de071cee5d68b6b8414da90fd2 -zope.interface==4.6.0 \ - --hash=sha256:086707e0f413ff8800d9c4bc26e174f7ee4c9c8b0302fbad68d083071822316c \ - --hash=sha256:1157b1ec2a1f5bf45668421e3955c60c610e31913cc695b407a574efdbae1f7b \ - --hash=sha256:11ebddf765bff3bbe8dbce10c86884d87f90ed66ee410a7e6c392086e2c63d02 \ - --hash=sha256:14b242d53f6f35c2d07aa2c0e13ccb710392bcd203e1b82a1828d216f6f6b11f \ - --hash=sha256:1b3d0dcabc7c90b470e59e38a9acaa361be43b3a6ea644c0063951964717f0e5 \ - --hash=sha256:20a12ab46a7e72b89ce0671e7d7a6c3c1ca2c2766ac98112f78c5bddaa6e4375 \ - --hash=sha256:298f82c0ab1b182bd1f34f347ea97dde0fffb9ecf850ecf7f8904b8442a07487 \ - --hash=sha256:2f6175722da6f23dbfc76c26c241b67b020e1e83ec7fe93c9e5d3dd18667ada2 \ - --hash=sha256:3b877de633a0f6d81b600624ff9137312d8b1d0f517064dfc39999352ab659f0 \ - --hash=sha256:4265681e77f5ac5bac0905812b828c9fe1ce80c6f3e3f8574acfb5643aeabc5b \ - --hash=sha256:550695c4e7313555549aa1cdb978dc9413d61307531f123558e438871a883d63 \ - --hash=sha256:5f4d42baed3a14c290a078e2696c5f565501abde1b2f3f1a1c0a94fbf6fbcc39 \ - --hash=sha256:62dd71dbed8cc6a18379700701d959307823b3b2451bdc018594c48956ace745 \ - --hash=sha256:7040547e5b882349c0a2cc9b50674b1745db551f330746af434aad4f09fba2cc \ - --hash=sha256:7e099fde2cce8b29434684f82977db4e24f0efa8b0508179fce1602d103296a2 \ - --hash=sha256:7e5c9a5012b2b33e87980cee7d1c82412b2ebabcb5862d53413ba1a2cfde23aa \ - --hash=sha256:81295629128f929e73be4ccfdd943a0906e5fe3cdb0d43ff1e5144d16fbb52b1 \ - --hash=sha256:95cc574b0b83b85be9917d37cd2fad0ce5a0d21b024e1a5804d044aabea636fc \ - --hash=sha256:968d5c5702da15c5bf8e4a6e4b67a4d92164e334e9c0b6acf080106678230b98 \ - --hash=sha256:9e998ba87df77a85c7bed53240a7257afe51a07ee6bc3445a0bf841886da0b97 \ - --hash=sha256:a0c39e2535a7e9c195af956610dba5a1073071d2d85e9d2e5d789463f63e52ab \ - --hash=sha256:a15e75d284178afe529a536b0e8b28b7e107ef39626a7809b4ee64ff3abc9127 \ - --hash=sha256:a6a6ff82f5f9b9702478035d8f6fb6903885653bff7ec3a1e011edc9b1a7168d \ - --hash=sha256:b639f72b95389620c1f881d94739c614d385406ab1d6926a9ffe1c8abbea23fe \ - --hash=sha256:bad44274b151d46619a7567010f7cde23a908c6faa84b97598fd2f474a0c6891 \ - --hash=sha256:bbcef00d09a30948756c5968863316c949d9cedbc7aabac5e8f0ffbdb632e5f1 \ - --hash=sha256:d788a3999014ddf416f2dc454efa4a5dbeda657c6aba031cf363741273804c6b \ - --hash=sha256:eed88ae03e1ef3a75a0e96a55a99d7937ed03e53d0cffc2451c208db445a2966 \ - --hash=sha256:f99451f3a579e73b5dd58b1b08d1179791d49084371d9a47baad3b22417f0317 +zope.hookable==5.0.0 \ + --hash=sha256:0992a0dd692003c09fb958e1480cebd1a28f2ef32faa4857d864f3ca8e9d6952 \ + --hash=sha256:0f325838dbac827a1e2ed5d482c1f2656b6844dc96aa098f7727e76395fcd694 \ + --hash=sha256:22a317ba00f61bac99eac1a5e330be7cb8c316275a21269ec58aa396b602af0c \ + --hash=sha256:25531cb5e7b35e8a6d1d6eddef624b9a22ce5dcf8f4448ef0f165acfa8c3fc21 \ + --hash=sha256:30890892652766fc80d11f078aca9a5b8150bef6b88aba23799581a53515c404 \ + --hash=sha256:342d682d93937e5b8c232baffb32a87d5eee605d44f74566657c64a239b7f342 \ + --hash=sha256:46b2fddf1f5aeb526e02b91f7e62afbb9fff4ffd7aafc97cdb00a0d717641567 \ + --hash=sha256:523318ff96df9b8d378d997c00c5d4cbfbff68dc48ff5ee5addabdb697d27528 \ + --hash=sha256:53aa02eb8921d4e667c69d76adeed8fe426e43870c101cb08dcd2f3468aff742 \ + --hash=sha256:62e79e8fdde087cb20822d7874758f5acbedbffaf3c0fbe06309eb8a41ee4e06 \ + --hash=sha256:74bf2f757f7385b56dc3548adae508d8b3ef952d600b4b12b88f7d1706b05dcc \ + --hash=sha256:751ee9d89eb96e00c1d7048da9725ce392a708ed43406416dc5ed61e4d199764 \ + --hash=sha256:7b83bc341e682771fe810b360cd5d9c886a948976aea4b979ff214e10b8b523b \ + --hash=sha256:81eeeb27dbb0ddaed8070daee529f0d1bfe4f74c7351cce2aaca3ea287c4cc32 \ + --hash=sha256:856509191e16930335af4d773c0fc31a17bae8991eb6f167a09d5eddf25b56cc \ + --hash=sha256:8853e81fd07b18fa9193b19e070dc0557848d9945b1d2dac3b7782543458c87d \ + --hash=sha256:94506a732da2832029aecdfe6ea07eb1b70ee06d802fff34e1b3618fe7cdf026 \ + --hash=sha256:95ad874a8cc94e786969215d660143817f745225579bfe318c4676e218d3147c \ + --hash=sha256:9758ec9174966ffe5c499b6c3d149f80aa0a9238020006a2b87c6af5963fcf48 \ + --hash=sha256:a169823e331da939aa7178fc152e65699aeb78957e46c6f80ccb50ee4c3616c2 \ + --hash=sha256:a67878a798f6ca292729a28c2226592b3d000dc6ee7825d31887b553686c7ac7 \ + --hash=sha256:a9a6d9eb2319a09905670810e2de971d6c49013843700b4975e2fc0afe96c8db \ + --hash=sha256:b3e118b58a3d2301960e6f5f25736d92f6b9f861728d3b8c26d69f54d8a157d2 \ + --hash=sha256:ca6705c2a1fb5059a4efbe9f5426be4cdf71b3c9564816916fc7aa7902f19ede \ + --hash=sha256:cf711527c9d4ae72085f137caffb4be74fc007ffb17cd103628c7d5ba17e205f \ + --hash=sha256:d087602a6845ebe9d5a1c5a949fedde2c45f372d77fbce4f7fe44b68b28a1d03 \ + --hash=sha256:d1080e1074ddf75ad6662a9b34626650759c19a9093e1a32a503d37e48da135b \ + --hash=sha256:db9c60368aff2b7e6c47115f3ad9bd6e96aa298b12ed5f8cb13f5673b30be565 \ + --hash=sha256:dbeb127a04473f5a989169eb400b67beb921c749599b77650941c21fe39cb8d9 \ + --hash=sha256:dca336ca3682d869d291d7cd18284f6ff6876e4244eb1821430323056b000e2c \ + --hash=sha256:dd69a9be95346d10c853b6233fcafe3c0315b89424b378f2ad45170d8e161568 \ + --hash=sha256:dd79f8fae5894f1ee0a0042214685f2d039341250c994b825c10a4cd075d80f6 \ + --hash=sha256:e647d850aa1286d98910133cee12bd87c354f7b7bb3f3cd816a62ba7fa2f7007 \ + --hash=sha256:f37a210b5c04b2d4e4bac494ab15b70196f219a1e1649ddca78560757d4278fb \ + --hash=sha256:f67820b6d33a705dc3c1c457156e51686f7b350ff57f2112e1a9a4dad38ec268 \ + --hash=sha256:f68969978ccf0e6123902f7365aae5b7a9e99169d4b9105c47cf28e788116894 \ + --hash=sha256:f717a0b34460ae1ac0064e91b267c0588ac2c098ffd695992e72cd5462d97a67 \ + --hash=sha256:f9d58ccec8684ca276d5a4e7b0dfacca028336300a8f715d616d9f0ce9ae8096 \ + --hash=sha256:fcc3513a54e656067cbf7b98bab0d6b9534b9eabc666d1f78aad6acdf0962736 +zope.interface==4.7.1 \ + --hash=sha256:048b16ac882a05bc7ef534e8b9f15c9d7a6c190e24e8938a19b7617af4ed854a \ + --hash=sha256:05816cf8e7407cf62f2ec95c0a5d69ec4fa5741d9ccd10db9f21691916a9a098 \ + --hash=sha256:065d6a1ac89d35445168813bed45048ed4e67a4cdfc5a68fdb626a770378869f \ + --hash=sha256:14157421f4121a57625002cc4f48ac7521ea238d697c4a4459a884b62132b977 \ + --hash=sha256:18dc895945694f397a0be86be760ff664b790f95d8e7752d5bab80284ff9105d \ + --hash=sha256:1962c9f838bd6ae4075d0014f72697510daefc7e1c7e48b2607df0b6e157989c \ + --hash=sha256:1a67408cacd198c7e6274a19920bb4568d56459e659e23c4915528686ac1763a \ + --hash=sha256:21bf781076dd616bd07cf0223f79d61ab4f45176076f90bc2890e18c48195da4 \ + --hash=sha256:21c0a5d98650aebb84efa16ce2c8df1a46bdc4fe8a9e33237d0ca0b23f416ead \ + --hash=sha256:23cfeea25d1e42ff3bf4f9a0c31e9d5950aa9e7c4b12f0c4bd086f378f7b7a71 \ + --hash=sha256:24b6fce1fb71abf9f4093e3259084efcc0ef479f89356757780685bd2b06ef37 \ + --hash=sha256:24f84ce24eb6b5fcdcb38ad9761524f1ae96f7126abb5e597f8a3973d9921409 \ + --hash=sha256:25e0ef4a824017809d6d8b0ce4ab3288594ba283e4d4f94d8cfb81d73ed65114 \ + --hash=sha256:2e8fdd625e9aba31228e7ddbc36bad5c38dc3ee99a86aa420f89a290bd987ce9 \ + --hash=sha256:2f3bc2f49b67b1bea82b942d25bc958d4f4ea6709b411cb2b6b9718adf7914ce \ + --hash=sha256:35d24be9d04d50da3a6f4d61de028c1dd087045385a0ff374d93ef85af61b584 \ + --hash=sha256:35dbe4e8c73003dff40dfaeb15902910a4360699375e7b47d3c909a83ff27cd0 \ + --hash=sha256:3dfce831b824ab5cf446ed0c350b793ac6fa5fe33b984305cb4c966a86a8fb79 \ + --hash=sha256:3f7866365df5a36a7b8de8056cd1c605648f56f9a226d918ed84c85d25e8d55f \ + --hash=sha256:455cc8c01de3bac6f9c223967cea41f4449f58b4c2e724ec8177382ddd183ab4 \ + --hash=sha256:4bb937e998be9d5e345f486693e477ba79e4344674484001a0b646be1d530487 \ + --hash=sha256:52303a20902ca0888dfb83230ca3ee6fbe63c0ad1dd60aa0bba7958ccff454d8 \ + --hash=sha256:6e0a897d4e09859cc80c6a16a29697406ead752292ace17f1805126a4f63c838 \ + --hash=sha256:6e1816e7c10966330d77af45f77501f9a68818c065dec0ad11d22b50a0e212e7 \ + --hash=sha256:73b5921c5c6ce3358c836461b5470bf675601c96d5e5d8f2a446951470614f67 \ + --hash=sha256:8093cd45cdb5f6c8591cfd1af03d32b32965b0f79b94684cd0c9afdf841982bb \ + --hash=sha256:864b4a94b60db301899cf373579fd9ef92edddbf0fb2cd5ae99f53ef423ccc56 \ + --hash=sha256:8a27b4d3ea9c6d086ce8e7cdb3e8d319b6752e2a03238a388ccc83ccbe165f50 \ + --hash=sha256:91b847969d4784abd855165a2d163f72ac1e58e6dce09a5e46c20e58f19cc96d \ + --hash=sha256:b47b1028be4758c3167e474884ccc079b94835f058984b15c145966c4df64d27 \ + --hash=sha256:b68814a322835d8ad671b7acc23a3b2acecba527bb14f4b53fc925f8a27e44d8 \ + --hash=sha256:bcb50a032c3b6ec7fb281b3a83d2b31ab5246c5b119588725b1350d3a1d9f6a3 \ + --hash=sha256:c56db7d10b25ce8918b6aec6b08ac401842b47e6c136773bfb3b590753f7fb67 \ + --hash=sha256:c94b77a13d4f47883e4f97f9fa00f5feadd38af3e6b3c7be45cfdb0a14c7149b \ + --hash=sha256:db381f6fdaef483ad435f778086ccc4890120aff8df2ba5cfeeac24d280b3145 \ + --hash=sha256:e6487d01c8b7ed86af30ea141fcc4f93f8a7dde26f94177c1ad637c353bd5c07 \ + --hash=sha256:e86923fa728dfba39c5bb6046a450bd4eec8ad949ac404eca728cfce320d1732 \ + --hash=sha256:f6ca36dc1e9eeb46d779869c60001b3065fb670b5775c51421c099ea2a77c3c9 \ + --hash=sha256:fb62f2cbe790a50d95593fb40e8cca261c31a2f5637455ea39440d6457c2ba25 zope.proxy==4.3.3 \ --hash=sha256:04646ac04ffa9c8e32fb2b5c3cd42995b2548ea14251f3c21ca704afae88e42c \ --hash=sha256:07b6bceea232559d24358832f1cd2ed344bbf05ca83855a5b9698b5f23c5ed60 \ diff --git a/letsencrypt-auto-source/rebuild_dependencies.py b/letsencrypt-auto-source/rebuild_dependencies.py index a79bdd8aa..6d1ec15ff 100755 --- a/letsencrypt-auto-source/rebuild_dependencies.py +++ b/letsencrypt-auto-source/rebuild_dependencies.py @@ -46,12 +46,6 @@ AUTHORITATIVE_CONSTRAINTS = { # certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456. # TODO: hashin seems to overwrite environment markers in dependencies. This needs to be fixed. 'enum34': '1.1.6 ; python_version < \'3.4\'', - # Newer versions of the packages below dropped support for python 3.4. Once - # Certbot does as well, we should unpin these dependencies. - 'requests': '2.21.0', - 'ConfigArgParse': '0.14.0', - 'zope.hookable': '4.2.0', - 'zope.interface': '4.6.0', } @@ -63,7 +57,7 @@ CERTBOT_REPO_PATH = dirname(dirname(abspath(__file__))) # - then this venv is used to consistently construct an empty new venv # - once pipstraped, this new venv pip-installs certbot runtime (including apache/nginx), # without pinned dependencies, and respecting input authoritative requirements -# - `certbot plugins` is called to check we have an healthy environment +# - `certbot plugins` is called to check we have a healthy environment # - finally current set of dependencies is extracted out of the docker using pip freeze SCRIPT = r"""#!/bin/sh set -e diff --git a/letsencrypt-auto-source/tests/centos6_tests.sh b/letsencrypt-auto-source/tests/centos6_tests.sh index 2c6dcf734..8bdffec87 100644 --- a/letsencrypt-auto-source/tests/centos6_tests.sh +++ b/letsencrypt-auto-source/tests/centos6_tests.sh @@ -1,81 +1,173 @@ #!/bin/bash +set -e # Start by making sure your system is up-to-date: -yum update -y > /dev/null -yum install -y centos-release-scl > /dev/null -yum install -y python27 > /dev/null 2> /dev/null +yum update -y >/dev/null +yum install -y centos-release-scl >/dev/null +yum install -y python27 >/dev/null 2>/dev/null +LE_AUTO_PY_34="certbot/letsencrypt-auto-source/letsencrypt-auto_py_34" LE_AUTO="certbot/letsencrypt-auto-source/letsencrypt-auto" +# Last version of certbot-auto that was bootstraping Python 3.4 for CentOS 6 users +INITIAL_CERTBOT_VERSION_PY34="certbot 0.38.0" + # we're going to modify env variables, so do this in a subshell ( -source /opt/rh/python27/enable - -# ensure python 3 isn't installed -python3 --version 2> /dev/null -RESULT=$? -if [ $RESULT -eq 0 ]; then - error "Python3 is already installed." +# ensure CentOS6 32bits is not supported anymore, and so certbot is not installed +export UNAME_FAKE_32BITS=true +if ! "$LE_AUTO" 2>&1 | grep -q "Certbot cannot be installed."; then + echo "ERROR: certbot-auto installed certbot on 32-bit CentOS." exit 1 fi +) -# ensure python2.7 is available -python2.7 --version 2> /dev/null -RESULT=$? -if [ $RESULT -ne 0 ]; then - error "Python3 is not available." - exit 1 -fi +echo "PASSED: On CentOS 6 32 bits, certbot-auto refused to install certbot." -# bootstrap, but don't install python 3. -"$LE_AUTO" --no-self-upgrade -n > /dev/null 2> /dev/null +# we're going to modify env variables, so do this in a subshell +( + . /opt/rh/python27/enable -# ensure python 3 isn't installed -python3 --version 2> /dev/null -RESULT=$? -if [ $RESULT -eq 0 ]; then - error "letsencrypt-auto installed Python3 even though Python2.7 is present." - exit 1 -fi + # ensure python 3 isn't installed + if python3 --version 2> /dev/null; then + echo "ERROR: Python3 is already installed." + exit 1 + fi -echo "" -echo "PASSED: Did not upgrade to Python3 when Python2.7 is present." + # ensure python2.7 is available + if ! python2.7 --version 2> /dev/null; then + echo "ERROR: Python2.7 is not available." + exit 1 + fi + + # bootstrap, but don't install python 3. + "$LE_AUTO" --no-self-upgrade -n --version > /dev/null 2> /dev/null + + # ensure python 3 isn't installed + if python3 --version 2> /dev/null; then + echo "ERROR: letsencrypt-auto installed Python3 even though Python2.7 is present." + exit 1 + fi + + echo "PASSED: Did not upgrade to Python3 when Python2.7 is present." ) # ensure python2.7 isn't available -python2.7 --version 2> /dev/null -RESULT=$? -if [ $RESULT -eq 0 ]; then - error "Python2.7 is still available." +if python2.7 --version 2> /dev/null; then + echo "ERROR: Python2.7 is still available." exit 1 fi # Skip self upgrade due to Python 3 not being available. if ! "$LE_AUTO" 2>&1 | grep -q "WARNING: couldn't find Python"; then - echo "Python upgrade failure warning not printed!" + echo "ERROR: Python upgrade failure warning not printed!" exit 1 fi -# bootstrap, this time installing python3 -"$LE_AUTO" --no-self-upgrade -n > /dev/null 2> /dev/null +# bootstrap from the old letsencrypt-auto, this time installing python3.4 +"$LE_AUTO_PY_34" --no-self-upgrade -n --version >/dev/null 2>/dev/null -# ensure python 3 is installed -python3 --version > /dev/null -RESULT=$? -if [ $RESULT -ne 0 ]; then - error "letsencrypt-auto failed to install Python3 when only Python2.6 is present." +# ensure python 3.4 is installed +if ! python3.4 --version >/dev/null 2>/dev/null; then + echo "ERROR: letsencrypt-auto failed to install Python3.4 using letsencrypt-auto < 0.37.0 when only Python2.6 is present." exit 1 fi -echo "PASSED: Successfully upgraded to Python3 when only Python2.6 is present." -echo "" +echo "PASSED: Successfully upgraded to Python3.4 using letsencrypt-auto < 0.37.0 when only Python2.6 is present." -export VENV_PATH=$(mktemp -d) -"$LE_AUTO" -n --no-bootstrap --no-self-upgrade --version >/dev/null 2>&1 -if [ "$($VENV_PATH/bin/python -V 2>&1 | cut -d" " -f2 | cut -d. -f1)" != 3 ]; then - echo "Python 3 wasn't used with --no-bootstrap!" +# As "certbot-auto" (so without implicit --non-interactive flag set), check that the script +# refuses to install SCL Python 3.6 when run in a non interactive shell (simulated here +# using | tee /dev/null) if --non-interactive flag is not provided. +cp "$LE_AUTO" /tmp/certbot-auto +# NB: Readline has an issue on all Python versions for CentOS 6, making `certbot --version` +# output an unprintable ASCII character on a new line at the end. +# So we take the second last line of the output. +version=$(/tmp/certbot-auto --version 2>/dev/null | tee /dev/null | tail -2 | head -1) + +if [ "$version" != "$INITIAL_CERTBOT_VERSION_PY34" ]; then + echo "ERROR: certbot-auto upgraded certbot in a non-interactive shell with --non-interactive flag not set." exit 1 fi -unset VENV_PATH + +echo "PASSED: certbot-auto did not upgrade certbot in a non-interactive shell with --non-interactive flag not set." + +if [ -f /opt/rh/rh-python36/enable ]; then + echo "ERROR: certbot-auto installed Python3.6 in a non-interactive shell with --non-interactive flag not set." + exit 1 +fi + +echo "PASSED: certbot-auto did not install Python3.6 in a non-interactive shell with --non-interactive flag not set." + +# now bootstrap from current letsencrypt-auto, that will install python3.6 from SCL +"$LE_AUTO" --no-self-upgrade -n --version >/dev/null 2>/dev/null + +# Following test is executed in a subshell, to not leak any environment variable +( + # enable SCL rh-python36 + . /opt/rh/rh-python36/enable + + # ensure python 3.6 is installed + if ! python3.6 --version >/dev/null 2>/dev/null; then + echo "ERROR: letsencrypt-auto failed to install Python3.6 using current letsencrypt-auto when only Python2.6/Python3.4 are present." + exit 1 + fi + + echo "PASSED: Successfully upgraded to Python3.6 using current letsencrypt-auto when only Python2.6/Python3.4 are present." +) + +# Following test is executed in a subshell, to not leak any environment variable +( + export VENV_PATH=$(mktemp -d) + "$LE_AUTO" -n --no-bootstrap --no-self-upgrade --version >/dev/null 2>&1 + if [ "$($VENV_PATH/bin/python -V 2>&1 | cut -d" " -f2 | cut -d. -f1-2)" != "3.6" ]; then + echo "ERROR: Python 3.6 wasn't used with --no-bootstrap!" + exit 1 + fi +) + +# Following test is executed in a subshell, to not leak any environment variable +( + # enable SCL rh-python36 + . /opt/rh/rh-python36/enable + + # ensure everything works fine with certbot-auto bootstrap when python 3.6 is already enabled + export VENV_PATH=$(mktemp -d) + if ! "$LE_AUTO" --no-self-upgrade -n --version >/dev/null 2>/dev/null; then + echo "ERROR: Certbot-auto broke when Python 3.6 SCL is already enabled." + exit 1 + fi +) + +# we're going to modify env variables, so do this in a subshell +( + # ensure CentOS6 32bits is not supported anymore, and so certbot + # is not upgraded nor reinstalled. + export UNAME_FAKE_32BITS=true + OUTPUT=$("$LE_AUTO" --version 2>&1) + if ! echo "$OUTPUT" | grep -q "Certbot will no longer receive updates."; then + echo "ERROR: certbot-auto failed to run or upgraded pre-existing Certbot instance on 32-bit CentOS 6." + exit 1 + fi + if ! "$LE_AUTO" --install-only 2>&1 | grep -q "Certbot cannot be installed."; then + echo "ERROR: certbot-auto reinstalled Certbot on 32-bit CentOS 6." + exit 1 + fi +) + +# we're going to modify env variables, so do this in a subshell +( + # Prepare a certbot installation in the old venv path + rm -rf /opt/eff.org + VENV_PATH=~/.local/share/letsencrypt "$LE_AUTO" --install-only > /dev/null 2> /dev/null + # fake 32 bits mode + export UNAME_FAKE_32BITS=true + OUTPUT=$("$LE_AUTO" --version 2>&1) + if ! echo "$OUTPUT" | grep -q "Certbot will no longer receive updates."; then + echo "ERROR: certbot-auto failed to run or upgraded pre-existing Certbot instance in the old venv path on 32-bit CentOS 6." + exit 1 + fi +) + +echo "PASSED: certbot-auto refused to install/upgrade certbot on 32-bit CentOS 6." # test using python3 pytest -v -s certbot/letsencrypt-auto-source/tests diff --git a/letsencrypt-auto-source/tests/oraclelinux6_tests.sh b/letsencrypt-auto-source/tests/oraclelinux6_tests.sh new file mode 100644 index 000000000..f3fd952f3 --- /dev/null +++ b/letsencrypt-auto-source/tests/oraclelinux6_tests.sh @@ -0,0 +1,85 @@ +#!/bin/bash +set -eo pipefail +# Start by making sure your system is up-to-date: +yum update -y >/dev/null + +LE_AUTO_PY_34="certbot/letsencrypt-auto-source/letsencrypt-auto_py_34" +LE_AUTO="certbot/letsencrypt-auto-source/letsencrypt-auto" + +# Apply installation instructions from official documentation: +# https://certbot.eff.org/lets-encrypt/centosrhel6-other +cp "$LE_AUTO" /usr/local/bin/certbot-auto +chown root /usr/local/bin/certbot-auto +chmod 0755 /usr/local/bin/certbot-auto +LE_AUTO=/usr/local/bin/certbot-auto + +# Last version of certbot-auto that was bootstraping Python 3.4 for CentOS 6 users +INITIAL_CERTBOT_VERSION_PY34="certbot 0.38.0" + +# Check bootstrap from current certbot-auto will fail, because SCL is not enabled. +set +o pipefail +if ! "$LE_AUTO" -n 2>&1 | grep -q "Enable the SCL repository and try running Certbot again."; then + echo "ERROR: Bootstrap was not aborted although SCL was not installed!" + exit 1 +fi +set -o pipefail + +echo "PASSED: Bootstrap was aborted since SCL was not installed." + +# Bootstrap from the old letsencrypt-auto, Python 3.4 will be installed from EPEL. +"$LE_AUTO_PY_34" --no-self-upgrade -n --install-only >/dev/null 2>/dev/null + +# Ensure Python 3.4 is installed +if ! command -v python3.4 &>/dev/null; then + echo "ERROR: old letsencrypt-auto failed to install Python3.4 using letsencrypt-auto < 0.37.0 when only Python2.6 is present." + exit 1 +fi + +echo "PASSED: Bootstrap from old letsencrypt-auto succeeded and installed Python 3.4" + +# Expect certbot-auto to skip rebootstrapping with a warning since SCL is not installed. +if ! "$LE_AUTO" --non-interactive --version 2>&1 | grep -q "This requires manual user intervention"; then + echo "FAILED: Script certbot-auto did not print a warning about needing manual intervention!" + exit 1 +fi + +echo "PASSED: Script certbot-auto did not rebootstrap." + +# NB: Readline has an issue on all Python versions for OL 6, making `certbot --version` +# output an unprintable ASCII character on a new line at the end. +# So we take the second last line of the output. +version=$($LE_AUTO --version 2>/dev/null | tail -2 | head -1) + +if [ "$version" != "$INITIAL_CERTBOT_VERSION_PY34" ]; then + echo "ERROR: Script certbot-auto upgraded certbot in a non-interactive shell while SCL was not enabled." + exit 1 +fi + +echo "PASSED: Script certbot-auto did not upgrade certbot but started it successfully while SCL was not enabled." + +# Enable SCL +yum install -y oracle-softwarecollection-release-el6 >/dev/null + +# Expect certbot-auto to bootstrap successfully since SCL is available. +"$LE_AUTO" -n --version &>/dev/null + +if [ "$(/opt/eff.org/certbot/venv/bin/python -V 2>&1 | cut -d" " -f2 | cut -d. -f1-2)" != "3.6" ]; then + echo "ERROR: Script certbot-auto failed to bootstrap and install Python 3.6 while SCL is available." + exit 1 +fi + +if ! /opt/eff.org/certbot/venv/bin/certbot --version > /dev/null 2> /dev/null; then + echo "ERROR: Script certbot-auto did not install certbot correctly while SCL is enabled." + exit 1 +fi + +echo "PASSED: Script certbot-auto correctly bootstraped Certbot using rh-python36 when SCL is available." + +# Expect certbot-auto will be totally silent now that everything has been correctly boostraped. +OUTPUT_LEN=$("$LE_AUTO" --install-only --no-self-upgrade --quiet 2>&1 | wc -c) +if [ "$OUTPUT_LEN" != 0 ]; then + echo certbot-auto produced unexpected output! + exit 1 +fi + +echo "PASSED: Script certbot-auto did not print anything in quiet mode." diff --git a/letsencrypt-auto-source/tests/uname_wrapper.sh b/letsencrypt-auto-source/tests/uname_wrapper.sh new file mode 100644 index 000000000..df1f568c6 --- /dev/null +++ b/letsencrypt-auto-source/tests/uname_wrapper.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e + +uname_output=$(/bin/uname_orig "$@") + +if [ "$UNAME_FAKE_32BITS" = true ]; then + uname_output="${uname_output//x86_64/i686}" +fi + +echo "$uname_output" diff --git a/letshelp-certbot/docs/conf.py b/letshelp-certbot/docs/conf.py index fcff25d55..fc482a348 100644 --- a/letshelp-certbot/docs/conf.py +++ b/letshelp-certbot/docs/conf.py @@ -40,7 +40,7 @@ extensions = [ ] autodoc_member_order = 'bysource' -autodoc_default_flags = ['show-inheritance', 'private-members'] +autodoc_default_flags = ['show-inheritance'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/letshelp-certbot/setup.py b/letshelp-certbot/setup.py index af992de16..448c145ce 100644 --- a/letshelp-certbot/setup.py +++ b/letshelp-certbot/setup.py @@ -21,7 +21,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.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: System Administrators', @@ -31,7 +31,6 @@ setup( 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/linter_plugin.py b/linter_plugin.py index 6be8c2414..1754b1a2a 100644 --- a/linter_plugin.py +++ b/linter_plugin.py @@ -16,7 +16,7 @@ WHITELIST_PACKAGES = ['acme', 'certbot_compatibility_test', 'letshelp_certbot', class ForbidStandardOsModule(BaseChecker): """ This checker ensures that standard os module (and submodules) is not imported by certbot - modules. Otherwise a 'os-module-forbidden' error will be registered for the faulty lines. + modules. Otherwise an 'os-module-forbidden' error will be registered for the faulty lines. """ __implements__ = IAstroidChecker diff --git a/pytest.ini b/pytest.ini index 6c2404056..e09813e52 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,15 +4,6 @@ [pytest] # In general, all warnings are treated as errors. Here are the exceptions: # 1- decodestring: https://github.com/rthalley/dnspython/issues/338 -# 2- ignore our own TLS-SNI-01 warning -# 3- ignore warn for importing abstract classes from collections instead of collections.abc, -# too much third party dependencies are still relying on this behavior, -# but it should be corrected to allow Certbot compatiblity with Python >= 3.8 -# 4- ipdb uses deprecated functionality of IPython. See -# https://github.com/gotcha/ipdb/issues/144. filterwarnings = error ignore:decodestring:DeprecationWarning - ignore:.*collections\.abc:DeprecationWarning - ignore:The `color_scheme` argument is deprecated:DeprecationWarning:IPython.* - ignore:.*get_systemd_os_info:DeprecationWarning diff --git a/tests/letstest/scripts/test_leauto_upgrades.sh b/tests/letstest/scripts/test_leauto_upgrades.sh index 541f54f6b..fc7632793 100755 --- a/tests/letstest/scripts/test_leauto_upgrades.sh +++ b/tests/letstest/scripts/test_leauto_upgrades.sh @@ -117,6 +117,8 @@ if ! diff letsencrypt-auto letsencrypt-auto-source/letsencrypt-auto ; then fi if [ "$RUN_RHEL6_TESTS" = 1 ]; then + # Add the SCL python release to PATH in order to resolve python3 command + PATH="/opt/rh/rh-python36/root/usr/bin:$PATH" if ! command -v python3; then echo "Python3 wasn't properly installed" exit 1 diff --git a/tests/letstest/scripts/test_sdists.sh b/tests/letstest/scripts/test_sdists.sh index dc024c567..204f55d55 100755 --- a/tests/letstest/scripts/test_sdists.sh +++ b/tests/letstest/scripts/test_sdists.sh @@ -1,8 +1,21 @@ #!/bin/sh -xe cd letsencrypt + +# If we're on a RHEL 6 based system, we can be confident Python is already +# installed because the package manager is written in Python. +if command -v python && [ $(python -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') -eq 26 ]; then + # RHEL/CentOS 6 will need a special treatment, so we need to detect that environment + RUN_RHEL6_TESTS=1 +fi + letsencrypt-auto-source/letsencrypt-auto --install-only -n --debug +if [ "$RUN_RHEL6_TESTS" = 1 ]; then + # Enable the SCL Python 3.6 installed by letsencrypt-auto bootstrap + PATH="/opt/rh/rh-python36/root/usr/bin:$PATH" +fi + PLUGINS="certbot-apache certbot-nginx" PYTHON_MAJOR_VERSION=$(/opt/eff.org/certbot/venv/bin/python --version 2>&1 | cut -d" " -f 2 | cut -d. -f1) TEMP_DIR=$(mktemp -d) diff --git a/tools/_release.sh b/tools/_release.sh index 89f2a3737..1819adad2 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -7,6 +7,24 @@ if [ "$RELEASE_DIR" = "" ]; then exit 1 fi +ExitWarning() { + exit_status="$?" + if [ "$exit_status" != 0 ]; then + # Don't print each command before executing it because it will disrupt + # the desired output. + set +x + echo '******************************' + echo '* *' + echo '* THE RELEASE SCRIPT FAILED! *' + echo '* *' + echo '******************************' + set -x + fi + exit "$exit_status" +} + +trap ExitWarning EXIT + version="$1" echo Releasing production version "$version"... nextversion="$2" @@ -67,7 +85,6 @@ git checkout "$RELEASE_BRANCH" # Update changelog sed -i "s/master/$(date +'%Y-%m-%d')/" certbot/CHANGELOG.md git add certbot/CHANGELOG.md -git diff --cached git commit -m "Update changelog for $version release" for pkg_dir in $SUBPKGS certbot-compatibility-test @@ -230,7 +247,6 @@ cp -p letsencrypt-auto-source/letsencrypt-auto certbot-auto cp -p letsencrypt-auto-source/letsencrypt-auto letsencrypt-auto git add certbot-auto letsencrypt-auto letsencrypt-auto-source certbot/docs/cli-help.txt -git diff --cached while ! git commit --gpg-sign="$RELEASE_GPG_KEY" -m "Release $version"; do echo "Unable to sign the release commit using git." echo "You may have to configure git to use gpg2 by running:" @@ -258,7 +274,6 @@ $body $footer" > certbot/CHANGELOG.md git add certbot/CHANGELOG.md -git diff --cached git commit -m "Add contents to certbot/CHANGELOG.md for next version" echo "New root: $root" @@ -273,6 +288,5 @@ if [ "$RELEASE_BRANCH" = candidate-"$version" ] ; then SetVersion "$nextversion".dev0 letsencrypt-auto-source/build.py git add letsencrypt-auto-source/letsencrypt-auto - git diff git commit -m "Bump version to $nextversion" fi diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index 94a59a6dd..7d2013c7a 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -14,38 +14,38 @@ backports.functools-lru-cache==1.5 backports.shutil-get-terminal-size==1.0.0 backports.ssl-match-hostname==3.7.0.1 bcrypt==3.1.6 -boto3==1.9.36 -botocore==1.12.36 +boto3==1.11.7 +botocore==1.14.7 cached-property==1.5.1 -cloudflare==1.5.1 +cloudflare==2.3.1 codecov==2.0.15 configparser==3.7.4 contextlib2==0.6.0.post1 coverage==4.5.4 -decorator==4.1.2 -dns-lexicon==3.2.1 +decorator==4.4.1 +dns-lexicon==3.3.17 dnspython==1.15.0 docker==3.7.2 docker-compose==1.25.0 docker-pycreds==0.4.0 dockerpty==0.4.1 docopt==0.6.2 -docutils==0.12 +docutils==0.15.2 execnet==1.5.0 functools32==3.2.3.post2 future==0.16.0 -futures==3.1.1 +futures==3.3.0 filelock==3.0.12 google-api-python-client==1.5.5 httplib2==0.10.3 imagesize==0.7.1 importlib-metadata==0.23 -ipdb==0.10.2 -ipython==5.5.0 +ipdb==0.12.3 +ipython==5.8.0 ipython-genutils==0.2.0 isort==4.3.21 Jinja2==2.9.6 -jmespath==0.9.3 +jmespath==0.9.4 josepy==1.1.0 jsonschema==2.6.0 lazy-object-proxy==1.4.3 @@ -60,13 +60,13 @@ ndg-httpsclient==0.3.2 oauth2client==4.0.0 packaging==19.2 paramiko==2.4.2 -pathlib2==2.3.0 +pathlib2==2.3.5 pexpect==4.7.0 -pickleshare==0.7.4 +pickleshare==0.7.5 pkginfo==1.4.2 pluggy==0.13.0 ply==3.4 -prompt-toolkit==1.0.15 +prompt-toolkit==1.0.18 ptyprocess==0.6.0 py==1.8.0 pyasn1==0.1.9 @@ -83,7 +83,7 @@ pytest-forked==0.2 pytest-xdist==1.22.5 pytest-sugar==0.9.2 pytest-rerunfailures==4.2 -python-dateutil==2.6.1 +python-dateutil==2.8.1 python-digitalocean==1.11 pywin32==227 PyYAML==3.13 @@ -91,8 +91,8 @@ repoze.sphinx.autointerface==0.8 requests-file==1.4.2 requests-toolbelt==0.8.0 rsa==3.4.2 -s3transfer==0.1.11 -scandir==1.6 +s3transfer==0.3.1 +scandir==1.10.0 simplegeneric==0.8.1 singledispatch==3.4.0.3 snowballstemmer==1.2.1 @@ -104,13 +104,13 @@ tldextract==2.2.0 toml==0.10.0 tox==3.14.0 tqdm==4.19.4 -traitlets==4.3.2 +traitlets==4.3.3 twine==1.11.0 typed-ast==1.4.0 typing==3.6.4 uritemplate==3.0.0 virtualenv==16.6.2 -wcwidth==0.1.7 +wcwidth==0.1.8 websocket-client==0.56.0 wrapt==1.11.2 zipp==0.6.0 diff --git a/tools/sphinx-quickstart.sh b/tools/sphinx-quickstart.sh index 72dc9e200..35a7f7fad 100755 --- a/tools/sphinx-quickstart.sh +++ b/tools/sphinx-quickstart.sh @@ -14,7 +14,7 @@ sed -i -e "s|\# import os|import os|" conf.py sed -i -e "s|\# needs_sphinx = '1.0'|needs_sphinx = '1.0'|" conf.py sed -i -e "s|intersphinx_mapping = {'https://docs.python.org/': None}|intersphinx_mapping = {\n 'python': ('https://docs.python.org/', None),\n 'acme': ('https://acme-python.readthedocs.org/en/latest/', None),\n 'certbot': ('https://certbot.eff.org/docs/', None),\n}|" conf.py sed -i -e "s|html_theme = 'alabaster'|\n# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs\n# on_rtd is whether we are on readthedocs.org\non_rtd = os.environ.get('READTHEDOCS', None) == 'True'\nif not on_rtd: # only import and set the theme if we're building docs locally\n import sphinx_rtd_theme\n html_theme = 'sphinx_rtd_theme'\n html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\n# otherwise, readthedocs.org uses their theme by default, so no need to specify it|" conf.py -sed -i -e "s|# Add any paths that contain templates here, relative to this directory.|autodoc_member_order = 'bysource'\nautodoc_default_flags = ['show-inheritance', 'private-members']\n\n# Add any paths that contain templates here, relative to this directory.|" conf.py +sed -i -e "s|# Add any paths that contain templates here, relative to this directory.|autodoc_member_order = 'bysource'\nautodoc_default_flags = ['show-inheritance']\n\n# Add any paths that contain templates here, relative to this directory.|" conf.py sed -i -e "s|# The name of the Pygments (syntax highlighting) style to use.|default_role = 'py:obj'\n\n# The name of the Pygments (syntax highlighting) style to use.|" conf.py echo "/_build/" >> .gitignore echo "================= diff --git a/tox.ini b/tox.ini index 31a8a8578..d76ed3ef1 100644 --- a/tox.ini +++ b/tox.ini @@ -213,7 +213,17 @@ passenv = DOCKER_* # At the moment, this tests under Python 2.6 only, as only that version is # readily available on the CentOS 6 Docker image. commands = - docker build -f letsencrypt-auto-source/Dockerfile.centos6 -t lea letsencrypt-auto-source + docker build -f letsencrypt-auto-source/Dockerfile.redhat6 --build-arg REDHAT_DIST_FLAVOR=centos -t lea letsencrypt-auto-source + docker run --rm -t -i lea +whitelist_externals = + docker +passenv = DOCKER_* + +[testenv:le_auto_oraclelinux6] +# At the moment, this tests under Python 2.6 only, as only that version is +# readily available on the Oracle Linux 6 Docker image. +commands = + docker build -f letsencrypt-auto-source/Dockerfile.redhat6 --build-arg REDHAT_DIST_FLAVOR=oraclelinux -t lea letsencrypt-auto-source docker run --rm -t -i lea whitelist_externals = docker diff --git a/windows-installer/construct.py b/windows-installer/construct.py index 77ca67e65..f0724f5f4 100644 --- a/windows-installer/construct.py +++ b/windows-installer/construct.py @@ -56,7 +56,7 @@ def _prepare_build_tools(venv_path, venv_python, repo_path): subprocess.check_call([sys.executable, '-m', 'venv', venv_path]) subprocess.check_call([venv_python, os.path.join(repo_path, 'letsencrypt-auto-source', 'pieces', 'pipstrap.py')]) subprocess.check_call([venv_python, os.path.join(repo_path, 'tools', 'pip_install.py'), 'pynsist']) - subprocess.check_call(['choco', 'upgrade', '-y', 'nsis', '--version', NSIS_VERSION]) + subprocess.check_call(['choco', 'upgrade', '--allow-downgrade', '-y', 'nsis', '--version', NSIS_VERSION]) @contextlib.contextmanager