diff --git a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml index 3fda78618..48fcae18f 100644 --- a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml @@ -22,15 +22,19 @@ jobs: TOXENV: py37 CERTBOT_NO_PIN: 1 linux-boulder-v1-integration-certbot-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-certbot-oldest ACME_SERVER: boulder-v1 linux-boulder-v2-integration-certbot-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-certbot-oldest ACME_SERVER: boulder-v2 linux-boulder-v1-integration-nginx-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-nginx-oldest ACME_SERVER: boulder-v1 linux-boulder-v2-integration-nginx-oldest: + PYTHON_VERSION: 3.6 TOXENV: integration-nginx-oldest ACME_SERVER: boulder-v2 linux-boulder-v1-py36-integration: diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index aba4a7100..3ff00b21a 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -26,10 +26,12 @@ jobs: TOXENV: integration-certbot linux-oldest-tests-1: IMAGE_NAME: ubuntu-18.04 - TOXENV: py27-{acme,apache,apache-v2,certbot}-oldest + PYTHON_VERSION: 3.6 + TOXENV: '{acme,apache,apache-v2,certbot}-oldest' linux-oldest-tests-2: IMAGE_NAME: ubuntu-18.04 - TOXENV: py27-{dns,nginx}-oldest + PYTHON_VERSION: 3.6 + TOXENV: '{dns,nginx}-oldest' linux-py36: IMAGE_NAME: ubuntu-18.04 PYTHON_VERSION: 3.6 diff --git a/.azure-pipelines/templates/steps/tox-steps.yml b/.azure-pipelines/templates/steps/tox-steps.yml index a9f78d36b..ecf3d6032 100644 --- a/.azure-pipelines/templates/steps/tox-steps.yml +++ b/.azure-pipelines/templates/steps/tox-steps.yml @@ -45,11 +45,7 @@ steps: export TARGET_BRANCH="`echo "${BUILD_SOURCEBRANCH}" | sed -E 's!refs/(heads|tags)/!!g'`" [ -z "${SYSTEM_PULLREQUEST_TARGETBRANCH}" ] || export TARGET_BRANCH="${SYSTEM_PULLREQUEST_TARGETBRANCH}" env - if [[ "${TOXENV}" == *"oldest"* ]]; then - tools/run_oldest_tests.sh - else - python -m tox - fi + python -m tox env: AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) diff --git a/AUTHORS.md b/AUTHORS.md index ff5c61613..cb60bfd87 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1,6 +1,7 @@ Authors ======= +* [Aaron Gable](https://github.com/aarongable) * [Aaron Zirbes](https://github.com/aaronzirbes) * Aaron Zuehlke * Ada Lovelace @@ -60,6 +61,7 @@ Authors * [DanCld](https://github.com/DanCld) * [Daniel Albers](https://github.com/AID) * [Daniel Aleksandersen](https://github.com/da2x) +* [Daniel Almasi](https://github.com/almasen) * [Daniel Convissor](https://github.com/convissor) * [Daniel "Drex" Drexler](https://github.com/aeturnum) * [Daniel Huang](https://github.com/dhuang) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index cabc7f4d1..4b58db328 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -166,7 +166,7 @@ def probe_sni(name, host, port=443, timeout=300, # pylint: disable=too-many-argu " from {0}:{1}".format( source_address[0], source_address[1] - ) if socket_kwargs else "" + ) if any(source_address) else "" ) socket_tuple = (host, port) # type: Tuple[str, int] sock = socket.create_connection(socket_tuple, **socket_kwargs) # type: ignore diff --git a/acme/setup.py b/acme/setup.py index 7f7375b2c..056b00107 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -9,21 +9,18 @@ version = '1.12.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ - # load_pem_private/public_key (>=0.6) - # rsa_recover_prime_factors (>=0.8) - 'cryptography>=1.2.3', + 'cryptography>=2.1.4', # formerly known as acme.jose: # 1.1.0+ is required to avoid the warnings described at # https://github.com/certbot/josepy/issues/13. 'josepy>=1.1.0', - # Connection.set_tlsext_host_name (>=0.13) + matching Xenial requirements (>=0.15.1) - 'PyOpenSSL>=0.15.1', + 'PyOpenSSL>=17.3.0', 'pyrfc3339', 'pytz', 'requests[security]>=2.6.0', # security extras added in 2.4.1 'requests-toolbelt>=0.3.0', - 'setuptools', - 'six>=1.9.0', # needed for python_2_unicode_compatible + 'setuptools>=39.0.1', + 'six>=1.11.0', ] setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) diff --git a/certbot-apache/certbot_apache/_internal/override_suse.py b/certbot-apache/certbot_apache/_internal/override_suse.py index eee9b0b64..afce98dfa 100644 --- a/certbot-apache/certbot_apache/_internal/override_suse.py +++ b/certbot-apache/certbot_apache/_internal/override_suse.py @@ -14,10 +14,10 @@ class OpenSUSEConfigurator(configurator.ApacheConfigurator): vhost_root="/etc/apache2/vhosts.d", vhost_files="*.conf", logs_root="/var/log/apache2", - ctl="apache2ctl", - version_cmd=['apache2ctl', '-v'], - restart_cmd=['apache2ctl', 'graceful'], - conftest_cmd=['apache2ctl', 'configtest'], + ctl="apachectl", + version_cmd=['apachectl', '-v'], + restart_cmd=['apachectl', 'graceful'], + conftest_cmd=['apachectl', 'configtest'], enmod="a2enmod", dismod="a2dismod", le_vhost_ext="-le-ssl.conf", diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 343f6e850..bebca6b25 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -13,7 +13,7 @@ install_requires = [ 'acme>=0.29.0', 'certbot>=1.6.0', 'python-augeas', - 'setuptools', + 'setuptools>=39.0.1', 'zope.component', 'zope.interface', ] diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 546f96305..2d3d93669 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -9,7 +9,7 @@ import shutil import subprocess import time -from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, SECP384R1 +from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, SECP384R1, SECP521R1 from cryptography.x509 import NameOID import pytest @@ -148,6 +148,17 @@ def test_certonly(context): """Test the certonly verb on certbot.""" context.certbot(['certonly', '--cert-name', 'newname', '-d', context.get_domain('newname')]) + assert_cert_count_for_lineage(context.config_dir, 'newname', 1) + + +def test_certonly_webroot(context): + """Test the certonly verb with webroot plugin""" + with misc.create_http_server(context.http_01_port) as webroot: + certname = context.get_domain('webroot') + context.certbot(['certonly', '-a', 'webroot', '--webroot-path', webroot, '-d', certname]) + + assert_cert_count_for_lineage(context.config_dir, certname, 1) + def test_auth_and_install_with_csr(context): """Test certificate issuance and install using an existing CSR.""" @@ -476,6 +487,28 @@ def test_default_curve_type(context): assert_elliptic_key(key1, SECP256R1) +@pytest.mark.parametrize('curve,curve_cls,skip_servers', [ + # Curve name, Curve class, ACME servers to skip + ('secp256r1', SECP256R1, []), + ('secp384r1', SECP384R1, []), + ('secp521r1', SECP521R1, ['boulder-v1', 'boulder-v2'])] +) +def test_ecdsa_curves(context, curve, curve_cls, skip_servers): + """Test issuance for each supported ECDSA curve""" + if context.acme_server in skip_servers: + pytest.skip('ACME server {} does not support ECDSA curve {}' + .format(context.acme_server, curve)) + + domain = context.get_domain('curve') + context.certbot([ + 'certonly', + '--key-type', 'ecdsa', '--elliptic-curve', curve, + '--force-renewal', '-d', domain, + ]) + key = join(context.config_dir, "live", domain, 'privkey.pem') + assert_elliptic_key(key, curve_cls) + + def test_renew_with_ec_keys(context): """Test proper renew with updated private key complexity.""" certname = context.get_domain('renew') diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index f719d6fa3..7ee81c103 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'cloudflare>=1.5.1', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index f99a2d52b..f57eb4d64 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index d0b893056..d1e84710d 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -12,8 +12,8 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'python-digitalocean>=1.11', - 'setuptools', - 'six', + 'setuptools>=39.0.1', + 'six>=1.11.0', 'zope.interface', ] diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index cf573d6d7..f73f6f7c8 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -11,7 +11,7 @@ version = '1.12.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index ea7b348fc..e7cd2e1ed 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index b0eb5d3f5..0cba57800 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -11,7 +11,7 @@ version = '1.12.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'dns-lexicon>=2.1.22', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index aafc5559f..09dace6c0 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -13,7 +13,7 @@ version = '1.12.0.dev0' install_requires = [ 'google-api-python-client>=1.5.5', 'oauth2client>=4.0', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', # already a dependency of google-api-python-client, but added for consistency 'httplib2' diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 99c602990..6f796b45c 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -11,7 +11,7 @@ version = '1.12.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'dns-lexicon>=2.2.3', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 4853e6c5e..ee4fc352e 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 862fa86c6..fe667fe6c 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'dns-lexicon>=2.2.1', # Support for >1 TXT record per name - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index f3affe92c..fc8402ff2 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'dns-lexicon>=2.7.14', # Correct proxy use on OVH provider - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index b27241d9b..2af5566c4 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'dnspython', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 77e1e9edb..4b60d8570 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -12,7 +12,7 @@ version = '1.12.0.dev0' # acme/certbot version. install_requires = [ 'boto3', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index f7ce5cdba..b4d59e7b6 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -11,7 +11,7 @@ version = '1.12.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ 'dns-lexicon>=2.1.23', - 'setuptools', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 47230eb37..4f6f7ed2a 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -12,9 +12,9 @@ version = '1.12.0.dev0' install_requires = [ 'acme>=1.4.0', 'certbot>=1.6.0', - 'PyOpenSSL', - 'pyparsing>=1.5.5', # Python3 support - 'setuptools', + 'PyOpenSSL>=17.3.0', + 'pyparsing>=2.2.0', + 'setuptools>=39.0.1', 'zope.interface', ] diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index c01fe830c..e51139225 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -10,11 +10,16 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Changed -* +* The `--preferred-chain` flag now only checks the Issuer Common Name of the + topmost (closest to the root) certificate in the chain, instead of checking + every certificate in the chain. + See [#8577](https://github.com/certbot/certbot/issues/8577). ### Fixed -* +* Fixed the apache component on openSUSE Tumbleweed which no longer provides + an apache2ctl symlink and uses apachectl instead. +* Fixed a typo in `certbot/crypto_util.py` causing an error upon attempting `secp521r1` key generation More details about these changes can be found on our GitHub repo. diff --git a/certbot/certbot/_internal/plugins/webroot.py b/certbot/certbot/_internal/plugins/webroot.py index 484d209d6..88e02998d 100644 --- a/certbot/certbot/_internal/plugins/webroot.py +++ b/certbot/certbot/_internal/plugins/webroot.py @@ -157,7 +157,8 @@ to serve all files under specified web root ({0}).""" "--webroot-path and --domains, or --webroot-map. Run with " " --help webroot for examples.") for name, path in path_map.items(): - self.full_roots[name] = os.path.join(path, challenges.HTTP01.URI_ROOT_PATH) + self.full_roots[name] = os.path.join(path, os.path.normcase( + challenges.HTTP01.URI_ROOT_PATH)) logger.debug("Creating root challenges validation dir at %s", self.full_roots[name]) diff --git a/certbot/certbot/crypto_util.py b/certbot/certbot/crypto_util.py index 256454122..edd4f9eb3 100644 --- a/certbot/certbot/crypto_util.py +++ b/certbot/certbot/crypto_util.py @@ -205,7 +205,7 @@ def make_key(bits=1024, key_type="rsa", elliptic_curve=None): elif key_type == 'ecdsa': try: name = elliptic_curve.upper() - if name in ('SECP256R1', 'SECP384R1', 'SECP512R1'): + if name in ('SECP256R1', 'SECP384R1', 'SECP521R1'): _key = ec.generate_private_key( curve=getattr(ec, elliptic_curve.upper(), None)(), backend=default_backend() @@ -573,8 +573,9 @@ def get_serial_from_cert(cert_path): def find_chain_with_issuer(fullchains, issuer_cn, warn_on_no_match=False): - """Chooses the first certificate chain from fullchains which contains an - Issuer Subject Common Name matching issuer_cn. + """Chooses the first certificate chain from fullchains whose topmost + intermediate has an Issuer Common Name matching issuer_cn (in other words + the first chain which chains to a root whose name matches issuer_cn). :param fullchains: The list of fullchains in PEM chain format. :type fullchains: `list` of `str` @@ -585,14 +586,11 @@ def find_chain_with_issuer(fullchains, issuer_cn, warn_on_no_match=False): :rtype: `str` """ for chain in fullchains: - certs = [x509.load_pem_x509_certificate(cert, default_backend()) \ - for cert in CERT_PEM_REGEX.findall(chain.encode())] - # Iterate the fullchain beginning from the leaf. For each certificate encountered, - # match against Issuer Subject CN. - for cert in certs: - cert_issuer_cn = cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME) - if cert_issuer_cn and cert_issuer_cn[0].value == issuer_cn: - return chain + certs = CERT_PEM_REGEX.findall(chain.encode()) + top_cert = x509.load_pem_x509_certificate(certs[-1], default_backend()) + top_issuer_cn = top_cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME) + if top_issuer_cn and top_issuer_cn[0].value == issuer_cn: + return chain # Nothing matched, return whatever was first in the list. if warn_on_no_match: diff --git a/certbot/certbot/interfaces.py b/certbot/certbot/interfaces.py index 6ba28bd56..28c6f2ac1 100644 --- a/certbot/certbot/interfaces.py +++ b/certbot/certbot/interfaces.py @@ -262,9 +262,9 @@ class IConfig(zope.interface.Interface): " with \"renew\" verb should be disabled.") preferred_chain = zope.interface.Attribute( - "If the CA offers multiple certificate chains, prefer the chain with " - "an issuer matching this Subject Common Name. If no match, the default " - "offered chain will be used." + "If the CA offers multiple certificate chains, prefer the chain whose " + "topmost certificate was issued from this Subject Common Name. " + "If no match, the default offered chain will be used." ) diff --git a/certbot/setup.py b/certbot/setup.py index 7cc629799..e1c86308e 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -40,16 +40,16 @@ install_requires = [ # saying so here causes a runtime error against our temporary fork of 0.9.3 # in which we added 2.6 support (see #2243), so we relax the requirement. 'ConfigArgParse>=0.9.3', - 'configobj', - 'cryptography>=1.2.3', # load_pem_x509_certificate + 'configobj>=5.0.6', + 'cryptography>=2.1.4', 'distro>=1.0.1', # 1.1.0+ is required to avoid the warnings described at # https://github.com/certbot/josepy/issues/13. 'josepy>=1.1.0', - 'parsedatetime>=1.3', # Calendar.parseDT + 'parsedatetime>=2.4', 'pyrfc3339', 'pytz', - 'setuptools', + 'setuptools>=39.0.1', 'zope.component', 'zope.interface', ] diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index 37673db99..3b9c973f7 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -184,11 +184,13 @@ class MakeKeyTest(unittest.TestCase): def test_ec(self): # pylint: disable=no-self-use # ECDSA Key Type Tests from certbot.crypto_util import make_key - # Do not test larger keys as it takes too long. - # Try a good key size for ECDSA - OpenSSL.crypto.load_privatekey( - OpenSSL.crypto.FILETYPE_PEM, make_key(elliptic_curve="secp256r1", key_type='ecdsa')) + for (name, bits) in [('secp256r1', 256), ('secp384r1', 384), ('secp521r1', 521)]: + pkey = OpenSSL.crypto.load_privatekey( + OpenSSL.crypto.FILETYPE_PEM, + make_key(elliptic_curve=name, key_type='ecdsa') + ) + self.assertEqual(pkey.bits(), bits) def test_bad_key_sizes(self): from certbot.crypto_util import make_key @@ -471,6 +473,19 @@ class FindChainWithIssuerTest(unittest.TestCase): matched = self._call(fullchains, "Pebble Root CA 0cc6f0") self.assertEqual(matched, fullchains[1]) + @mock.patch('certbot.crypto_util.logger.info') + def test_intermediate_match(self, mock_info): + """Don't pick a chain where only an intermediate matches""" + fullchains = self._all_fullchains() + # Make the second chain actually only contain "Pebble Root CA 0cc6f0" + # as an intermediate, not as the root. This wouldn't be a valid chain + # (the CERT_ISSUER cert didn't issue the CERT_ALT_ISSUER cert), but the + # function under test here doesn't care about that. + fullchains[1] = fullchains[1] + CERT_ISSUER.decode() + matched = self._call(fullchains, "Pebble Root CA 0cc6f0") + self.assertEqual(matched, fullchains[0]) + mock_info.assert_not_called() + @mock.patch('certbot.crypto_util.logger.info') def test_no_match(self, mock_info): fullchains = self._all_fullchains() diff --git a/tools/_release.sh b/tools/_release.sh index e17332f30..e9e0e49f0 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -216,8 +216,13 @@ fi # ensure we have the latest built version of leauto letsencrypt-auto-source/build.py -# and that it's signed correctly -tools/offline-sigrequest.sh || true +# Now we have to sign the built version of leauto. +SignLEAuto() { + yubico-piv-tool -a verify-pin --sign -s 9c -i letsencrypt-auto-source/letsencrypt-auto -o letsencrypt-auto-source/letsencrypt-auto.sig +} + +# Loop until letsencrypt-auto is signed correctly. +SignLEAuto || true while ! openssl dgst -sha256 -verify $RELEASE_OPENSSL_PUBKEY -signature \ letsencrypt-auto-source/letsencrypt-auto.sig \ letsencrypt-auto-source/letsencrypt-auto ; do @@ -225,7 +230,7 @@ while ! openssl dgst -sha256 -verify $RELEASE_OPENSSL_PUBKEY -signature \ read -p "Would you like this script to try and sign it again [Y/n]?" response case $response in [yY][eE][sS]|[yY]|"") - tools/offline-sigrequest.sh || true;; + SignLEAuto || true;; *) ;; esac diff --git a/tools/offline-sigrequest.sh b/tools/offline-sigrequest.sh deleted file mode 100755 index 6443ae8af..000000000 --- a/tools/offline-sigrequest.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -set -o errexit - -function sayhash { # $1 <-- HASH ; $2 <---SIGFILEBALL - while read -p "Press Enter to read the hash aloud or type 'done': " INP && [ "$INP" = "" ] ; do - if ! `which festival > /dev/null` ; then - echo \`festival\` is not installed! - echo Please install it to read the hash aloud - else - cat $1 | (echo "(Parameter.set 'Duration_Stretch 1.8)"; \ - echo -n '(SayText "'; \ - sha256sum | cut -c1-64 | fold -1 | sed 's/^a$/alpha/; s/^b$/bravo/; s/^c$/charlie/; s/^d$/delta/; s/^e$/echo/; s/^f$/foxtrot/'; \ - echo '")' ) | festival - fi - done - - echo 'Paste in the data from the QR code, then type Ctrl-D:' - cat > $2 -} - -function offlinesign { # $1 <-- INPFILE ; $2 <---SIGFILE - echo HASH FOR SIGNING: - SIGFILEBALL="$2.lzma.base64" - #echo "(place the resulting raw binary signature in $SIGFILEBALL)" - sha256sum $1 - echo metahash for confirmation only $(sha256sum $1 |cut -d' ' -f1 | tr -d '\n' | sha256sum | cut -c1-6) ... - echo - sayhash $1 $SIGFILEBALL -} - -function oncesigned { # $1 <-- INPFILE ; $2 <--SIGFILE - SIGFILEBALL="$2.lzma.base64" - cat $SIGFILEBALL | tr -d '\r' | base64 -d | unlzma -c > $2 || exit 1 - if ! [ -f $2 ] ; then - echo "Failed to find $2"'!' - exit 1 - fi - - if file $2 | grep -qv " data" ; then - echo "WARNING WARNING $2 does not look like a binary signature:" - echo `file $2` - exit 1 - fi -} - -HERE=`dirname $0` -LEAUTO="`realpath $HERE`/../letsencrypt-auto-source/letsencrypt-auto" -SIGFILE="$LEAUTO".sig -offlinesign $LEAUTO $SIGFILE -oncesigned $LEAUTO $SIGFILE diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index 5d1446005..1aabf6eeb 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -1,76 +1,79 @@ -# This file contains the oldest versions of our dependencies we say we require -# in our packages or versions we need to support to maintain compatibility with -# the versions included in the various Linux distros where we are packaged. +# This file contains the oldest versions of our dependencies we're trying to +# support. Usually these version numbers are taken from the packages of our +# dependencies available in popular LTS Linux distros. Keeping compatibility +# with those versions makes it much easier for OS maintainers to update their +# Certbot packages. +# +# When updating these dependencies, we should try to only update them to the +# oldest version of the package that is found in a non-EOL'd version of +# CentOS, Debian, or Ubuntu that has Certbot packages in their OS repositories +# using a version of Python we support. If the distro is EOL'd or using a +# version of Python we don't support, it can be ignored. # CentOS/RHEL 7 EPEL constraints -cffi==1.6.0 +# Some of these constraints may be stricter than necessary because they +# initially referred to the Python 2 packages in CentOS/RHEL 7 with EPEL. +cffi==1.9.1 chardet==2.2.1 -configobj==4.7.2 ipaddress==1.0.16 mock==1.0.1 ndg-httpsclient==0.3.2 ply==3.4 +pyOpenSSL==17.3.0 pyasn1==0.1.9 pycparser==2.14 pyRFC3339==1.0 python-augeas==0.5.0 oauth2client==4.0.0 -six==1.9.0 -# setuptools 0.9.8 is the actual version packaged, but some other dependencies -# in this file require setuptools>=1.0 and there are no relevant changes for us -# between these versions. -setuptools==1.0.0 urllib3==1.10.2 zope.component==4.1.0 zope.event==4.0.3 zope.interface==4.0.5 # Debian Jessie Backports constraints -# Debian Jessie has reached end of life. However: -# When it becomes necessary to upgrade any of these dependencies, you should only update them to the oldest version of the package found -# in a non-EOL'd version of CentOS, Debian, or Ubuntu that has Certbot packages in their OS repositories. -PyICU==1.8 +# Debian Jessie has reached end of life so these dependencies can probably be +# updated as needed or desired. colorama==0.3.2 enum34==1.0.3 html5lib==0.999 -idna==2.0 pbr==1.8.0 pytz==2012rc0 # Debian Buster constraints google-api-python-client==1.5.5 +pyparsing==2.2.0 # Our setup.py constraints apacheconfig==0.3.2 cloudflare==1.5.1 -cryptography==1.2.3 -parsedatetime==1.3 -pyparsing==1.5.5 python-digitalocean==1.11 requests[security]==2.6.0 # Ubuntu Xenial constraints +# Ubuntu Xenial only has versions of Python which we do not support available +# so these dependencies can probably be updated as needed or desired. ConfigArgParse==0.10.0 -pyOpenSSL==0.15.1 funcsigs==0.4 zope.hookable==4.0.4 # Ubuntu Bionic constraints. +cryptography==2.1.4 distro==1.0.1 # Lexicon oldest constraint is overridden appropriately on relevant DNS provider plugins # using their local-oldest-requirements.txt dns-lexicon==2.2.1 httplib2==0.9.2 +idna==2.6 +setuptools==39.0.1 +six==1.11.0 + +# Ubuntu Focal constraints +asn1crypto==0.24.0 +configobj==5.0.6 +parsedatetime==2.4 # Plugin constraints # These aren't necessarily the oldest versions we need to support # Tracking at https://github.com/certbot/certbot/issues/6473 boto3==1.4.7 botocore==1.7.41 - -# Old certbot[dev] constraints -# Old versions of certbot[dev] required ipdb and our normally pinned version of -# ipython which ipdb depends on doesn't support Python 2 so we pin an older -# version here to keep tests working while we have Python 2 support. -ipython==5.8.0 -prompt-toolkit==1.0.18 diff --git a/tools/run_oldest_tests.sh b/tools/run_oldest_tests.sh deleted file mode 100755 index 7bf9f2bc5..000000000 --- a/tools/run_oldest_tests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -set -e - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" - -pushd "${DIR}/../" - -function cleanup() { - rm -f "${DOCKERFILE}" - popd -} - -trap cleanup EXIT - -DOCKERFILE=$(mktemp /tmp/Dockerfile.XXXXXX) - -cat << "EOF" >> "${DOCKERFILE}" -FROM ubuntu:16.04 -COPY letsencrypt-auto-source/pieces/dependency-requirements.txt /tmp/letsencrypt-auto-source/pieces/ -COPY tools/ /tmp/tools/ -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - python-dev python-pip python-setuptools \ - gcc libaugeas0 libssl-dev libffi-dev \ - git ca-certificates nginx-light openssl curl \ - && curl -fsSL https://get.docker.com | bash /dev/stdin \ - && python /tmp/tools/pipstrap.py \ - && python /tmp/tools/pip_install.py tox \ - && rm -rf /var/lib/apt/lists/* -EOF - -docker build -f "${DOCKERFILE}" -t oldest-worker . -docker run --rm --network=host -w "${PWD}" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v "${PWD}:${PWD}" -v /tmp:/tmp \ - -e TOXENV -e ACME_SERVER -e PYTEST_ADDOPTS \ - oldest-worker python -m tox diff --git a/tox.ini b/tox.ini index 212d4ee76..94cd305aa 100644 --- a/tox.ini +++ b/tox.ini @@ -77,49 +77,65 @@ setenv = PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:--numprocesses auto} PYTHONHASHSEED = 0 -[testenv:py27-oldest] +[testenv:oldest] +# Setting basepython allows the tests to fail fast if that version of Python +# isn't available instead of potentially trying to use a newer version of +# Python which is unlikely to work. +basepython = python3.6 commands = {[testenv]commands} setenv = {[testenv]setenv} CERTBOT_OLDEST=1 -[testenv:py27-acme-oldest] +[testenv:acme-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} acme[dev] setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-apache-oldest] +[testenv:apache-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot-apache setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-apache-v2-oldest] +[testenv:apache-v2-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot-apache[dev] setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-certbot-oldest] +[testenv:certbot-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot[dev] setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-dns-oldest] +[testenv:dns-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} {[base]dns_packages} setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} -[testenv:py27-nginx-oldest] +[testenv:nginx-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]install_and_test} certbot-nginx python tests/lock_test.py setenv = - {[testenv:py27-oldest]setenv} + {[testenv:oldest]setenv} [testenv:lint] basepython = python3 @@ -238,22 +254,26 @@ commands = passenv = DOCKER_* [testenv:integration-certbot-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]pip_install} certbot {[base]pip_install} certbot-ci pytest certbot-ci/certbot_integration_tests/certbot_tests \ --acme-server={env:ACME_SERVER:pebble} passenv = DOCKER_* -setenv = {[testenv:py27-oldest]setenv} +setenv = {[testenv:oldest]setenv} [testenv:integration-nginx-oldest] +basepython = + {[testenv:oldest]basepython} commands = {[base]pip_install} certbot-nginx {[base]pip_install} certbot-ci pytest certbot-ci/certbot_integration_tests/nginx_tests \ --acme-server={env:ACME_SERVER:pebble} passenv = DOCKER_* -setenv = {[testenv:py27-oldest]setenv} +setenv = {[testenv:oldest]setenv} [testenv:test-farm-tests-base] changedir = tests/letstest