diff --git a/.gitignore b/.gitignore index 064e7fffe..34987d319 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ parts prime stage *.snap +snap-constraints.txt +qemu-* diff --git a/AUTHORS.md b/AUTHORS.md index 21a6e7773..a00d20375 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -36,7 +36,8 @@ Authors * [Blake Griffith](https://github.com/cowlicks) * [Brad Warren](https://github.com/bmw) * [Brandon Kraft](https://github.com/kraftbj) -* [Brandon Kreisel](https://github.com/kraftbj) +* [Brandon Kreisel](https://github.com/BKreisel) +* [Brian Heim](https://github.com/brianlheim) * [Cameron Steel](https://github.com/Tugzrida) * [Ceesjan Luiten](https://github.com/quinox) * [Chad Whitacre](https://github.com/whit537) @@ -202,6 +203,7 @@ Authors * [Pierre Jaury](https://github.com/kaiyou) * [Piotr Kasprzyk](https://github.com/kwadrat) * [Prayag Verma](https://github.com/pra85) +* [Rasesh Patel](https://github.com/raspat1) * [Reinaldo de Souza Jr](https://github.com/juniorz) * [Remi Rampin](https://github.com/remram44) * [Rémy HUBSCHER](https://github.com/Natim) @@ -237,6 +239,7 @@ Authors * [Stefan Weil](https://github.com/stweil) * [Steve Desmond](https://github.com/stevedesmond-ca) * [sydneyli](https://github.com/sydneyli) +* [taixx046](https://github.com/taixx046) * [Tan Jay Jun](https://github.com/jayjun) * [Tapple Gao](https://github.com/tapple) * [Telepenin Nikolay](https://github.com/telepenin) diff --git a/acme/setup.py b/acme/setup.py index 356410efe..c993b0f2e 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/acme/tests/standalone_test.py b/acme/tests/standalone_test.py index d03b56535..3d068fb46 100644 --- a/acme/tests/standalone_test.py +++ b/acme/tests/standalone_test.py @@ -122,8 +122,8 @@ class TLSALPN01ServerTest(unittest.TestCase): )} # Use different certificate for challenge. self.challenge_certs = {b'localhost': ( - test_util.load_pyopenssl_private_key('rsa1024_key.pem'), - test_util.load_cert('rsa1024_cert.pem'), + test_util.load_pyopenssl_private_key('rsa4096_key.pem'), + test_util.load_cert('rsa4096_cert.pem'), )} from acme.standalone import TLSALPN01Server self.server = TLSALPN01Server(("localhost", 0), certs=self.certs, diff --git a/acme/tests/testdata/README b/acme/tests/testdata/README index d65cc3018..9c1a12d80 100644 --- a/acme/tests/testdata/README +++ b/acme/tests/testdata/README @@ -4,7 +4,7 @@ to use appropriate extension for vector filenames: .pem for PEM and The following command has been used to generate test keys: - for x in 256 512 1024 2048; do openssl genrsa -out rsa${k}_key.pem $k; done + for k in 256 512 1024 2048 4096; do openssl genrsa -out rsa${k}_key.pem $k; done and for the CSR: diff --git a/acme/tests/testdata/rsa4096_cert.pem b/acme/tests/testdata/rsa4096_cert.pem new file mode 100644 index 000000000..d8f6a9896 --- /dev/null +++ b/acme/tests/testdata/rsa4096_cert.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFDTCCAvWgAwIBAgIUImqDrP53V69vFROsjP/gL0YtoA4wDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjAwNTI3MjMyNDE0WhcNMjAw +NjI2MjMyNDE0WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANY9LKLk9Dxn0MUMQFHwBoTN4ehDSWBws2KcytpF +mc8m9Mfk1wmb4fQSKYtK3wIFMfIyo9HQu0nKqMkkUw52o3ZXyOv+oWwF5qNy2BKu +lh5OMSkaZ0o13zoPpW42e+IUnyxvg70+0urD+sUue4cyTHh/nBIUjrM/05ZJ/ac8 +HR0RK3H41YoqBjq69JjMZczZZhbNFit3s6p0R1TbVAgc3ckqbtX5BDyQMQQCP4Ed +m4DgbAFVqdcPUCC5W3F3fmuQiPKHiADzONZnXpy6lUvLDWqcd6loKp+nKHM6OkXX +8hmD7pE1PYMQo4hqOfhBR2IgMjAShwd5qUFjl1m2oo0Qm3PFXOk6i2ZQdS6AA/yd +B5/mX0RnM2oIdFZPb6UZFSmtEgs9sTzn+hMUyNSZQRE54px1ur1xws2R+vbsCyM5 ++KoFVxDjVjU9TlZx3GvDvnqz/tbHjji6l8VHZYOBMBUXbKHu2U6pJFZ5Zp7k68/z +a3Fb9Pjtn3iRkXEyC0N5kLgqO4QTlExnxebV8aMvQpWd/qefnMn9qPYIZPEXSQAR +mEBIahkcACb60s+acG0WFFluwBPtBqEr8Q67XlSF0Ibf4iBiRzpPobhlWta1nrFg +4IWHMSoZ0PE75bhIGBEkhrpcXQCAxXmAfxfjKDH7jdJ1fRdnZ/9+OzwYGVX5GH/l +0QDtAgMBAAGjUzBRMB0GA1UdDgQWBBQh3xiz/o1nEU2ySylZ9gxCXvIPGzAfBgNV +HSMEGDAWgBQh3xiz/o1nEU2ySylZ9gxCXvIPGzAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQAELoXz31oR9pdAwidlv9ZBOKiC7KBWy8VMqXNVkfTn +bVRxAUex7zleLFIOkWnqadsMesU9sIwrbLzBcZ8Q/vBY+z2xOPdXcgcAoAmdKWoq +YBQNiqng9r54sqlzB/77QZCf5fdktESe7NTxhCifgx5SAWq7IUQs/lm3tnMUSAfE +5ctuN6M+w8K54y3WDprcfMHpnc3ZHeSPhVQApHM0h/bDvXq0bRS7kmq27Hb153Qm +nH3TwYB5pPSWW38NbUc+s/a7mItO7S8ly8yGbA0j9c/IbN5lM+OCdk06asz3+c8E +uo8nuCBoYO5+6AqC2N7WJ3Tdr/pFA8jTbd6VNVlgCWTIR8ZosL5Fgkfv+4fUBrHt +zdVUqMUzvga5rvZnwnJ5Qfu/drHeAAo9MTNFQNe2QgDlYfWBh5GweolgmFSwrpkY +v/5wLtIyv/ASHKswybbqMIlpttcLTXjx5yuh8swttT6Wh+FQqqQ32KSRB3StiwyK +oH0ZhrwYHiFYNlPxecGX6XUta6rFtTlEdkBGSnXzgiTzL2l+Nc0as0V5B9RninZG +qJ+VOChSQ0OFvg1riSXv7tMvbLdGQnxwTRL3t6BMS8I4LA2m3ZfWUcuXT783ODTH +16f1Q1AgXd2csstTWO9cv+N/0fpX31nqrm6+CrGduSr2u4HjYYnlLIUhmdTvK3fX +Fg== +-----END CERTIFICATE----- diff --git a/acme/tests/testdata/rsa4096_key.pem b/acme/tests/testdata/rsa4096_key.pem new file mode 100644 index 000000000..b16e1fc9b --- /dev/null +++ b/acme/tests/testdata/rsa4096_key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKgIBAAKCAgEA1j0souT0PGfQxQxAUfAGhM3h6ENJYHCzYpzK2kWZzyb0x+TX +CZvh9BIpi0rfAgUx8jKj0dC7ScqoySRTDnajdlfI6/6hbAXmo3LYEq6WHk4xKRpn +SjXfOg+lbjZ74hSfLG+DvT7S6sP6xS57hzJMeH+cEhSOsz/Tlkn9pzwdHRErcfjV +iioGOrr0mMxlzNlmFs0WK3ezqnRHVNtUCBzdySpu1fkEPJAxBAI/gR2bgOBsAVWp +1w9QILlbcXd+a5CI8oeIAPM41mdenLqVS8sNapx3qWgqn6coczo6RdfyGYPukTU9 +gxCjiGo5+EFHYiAyMBKHB3mpQWOXWbaijRCbc8Vc6TqLZlB1LoAD/J0Hn+ZfRGcz +agh0Vk9vpRkVKa0SCz2xPOf6ExTI1JlBETninHW6vXHCzZH69uwLIzn4qgVXEONW +NT1OVnHca8O+erP+1seOOLqXxUdlg4EwFRdsoe7ZTqkkVnlmnuTrz/NrcVv0+O2f +eJGRcTILQ3mQuCo7hBOUTGfF5tXxoy9ClZ3+p5+cyf2o9ghk8RdJABGYQEhqGRwA +JvrSz5pwbRYUWW7AE+0GoSvxDrteVIXQht/iIGJHOk+huGVa1rWesWDghYcxKhnQ +8TvluEgYESSGulxdAIDFeYB/F+MoMfuN0nV9F2dn/347PBgZVfkYf+XRAO0CAwEA +AQKCAgEA0hZdTkQtCYtYm9LexDsXeWYX8VcCfrMmBj7xYcg9A3oVMmzDPuYBVwH0 +gWbjd6y2hOaJ5TfGYZ99kvmvBRDsTSHaoyopC7BhssjtAKz6Ay/0X3VH8usPQ3WS +aZi+NT65tK6KRqtz08ppgLGLa1G00bl5x/Um1rpxeACI4FU/y4BJ1VMJvJpnT3KE +Z86Qyagqx5NH+UpCApZSWPFX3zjHePzGgcfXErjniCHYOnpZQrFQ2KIzkfSvQ9fg +x01ByKOM2CB2C1B33TCzBAioXRH6zyAu7A59NeCK9ywTduhDvie1a+oEryFC7IQW +4s7I/H3MGX4hsf/pLXlHMy+5CZJOjRaC2h+pypfbbcuiXu6Sn64kHNpiI7SxI5DI +MIRjyG7MdUcrzq0Rt8ogwwpbCoRqrl/w3bhxtqmeZaEZtyxbjlm7reK2YkIFDgyz +JMqiJK5ZAi+9L/8c0xhjjAQQ0sIzrjmjA8U+6YnWL9jU5qXTVnBB8XQucyeeZGgk +yRHyMur71qOXN8z3UEva7MHkDTUBlj8DgTz6sEjqCipaWl0CXfDNa4IhHIXD5qiF +wplhq7OeS0v6EGG/UFa3Q/lFntxtrayxJX7uvvSccGzjPKXTjpWUELLi/FdnIsum +eXT3RgIEYozj4BibDXaBLfHTCVzxOr7AAEvKM9XWSUgLA0paSWECggEBAO9ZBeE1 +GWzd1ejTTkcxBC9AK2rNsYG8PdNqiof/iTbuJWNeRqpG+KB/0CNIpjZ2X5xZd0tM +FDpHTFehlP26Roxuq50iRAFc+SN5KoiO0A3JuJAidreIgRTia1saUUrypHqWrYEA +VZVj2AI8Pyg3s1OkR2frFskY7hXBVb/pJNDP/m9xTXXIYiIXYkHYe+4RIJCnAxRv +q5YHKaX+0Ull9YCZJCxmwvcHat8sgu8qkiwUMEM6QSNEkrEbdnWYBABvC1AR6sws +7MP1h9+j22n4Zc/3D6kpFZEL9Erx8nNyhbOZ6q2Tdnf6YKVVjZdyVa8VyNnR0ROl +3BjkFaHb/bg4e4kCggEBAOUk8ZJS3qBeGCOjug384zbHGcnhUBYtYJiOz+RXBtP+ +PRksbFtTkgk1sHuSGO8YRddU4Qv7Av1xL8o+DEsLBSD0YQ7pmLrR/LK+iDQ5N63O +Fve9uJH0ybxAOkiua7G24+lTsVUP//KWToL4Wh5zbHBBjL5D2Z9zoeVbcE87xhva +lImMVr4Ex252DqNP9wkZxBjudFyJ/C/TnXrjPcgwhxWTC7sLQMhE5p+490G7c4hX +PywkIKrANbu37KDiAvVS+dC66ZgpL/NUDkeloAmGNO08LGzbV6YKchlvDyWU/AvW +0hYjbL0FUq7K/wp1G9fumolB+fbI25K9c13X93STzUUCggEBAJDsNFUyk5yJjbYW +C/WrRj9d+WwH9Az77+uNPSgvn+O0usq6EMuVgYGdImfa21lqv2Wp/kOHY1AOT7lX +yyD+oyzw7dSNJOQ2aVwDR6+72Vof5DLRy1RBwPbmSd61xrc8yD658YCEtU1pUSe5 +VvyBDYH9nIbdn8RP5gkiMUusXXBaIFNWJXLFzDWcNxBrhk6V7EPp/EFphFmpKJyr ++AkbRVWCZJbF+hMdWKadCwLJogwyhS6PnVU/dhrq6AU38GRa2Fy5HJRYN1xH1Oej +DX3Su8L6c28Xw0k6FcczTHx+wVoIPkKvYTIwVkiFzt/+iMckx6KsGo5tBSHFKRwC +WlQrTxECggEBALjUruLnY1oZ7AC7bTUhOimSOfQEgTQSUCtebsRxijlvhtsKYTDd +XRt+qidStjgN7S/+8DRYuZWzOeg5WnMhpXZqiOudcyume922IGl3ibjxVsdoyjs5 +J4xohlrgDlBgBMDNWGoTqNGFejjcmNydH+gAh8VlN2INxJYbxqCyx17qVgwJHmLR +uggYxD/pHYvCs9GkbknCp5/wYsOgDtKuihfV741lS1D/esN1UEQ+LrfYIEW7snno +5q7Pcdhn1hkKYCWEzy2Ec4Aj2gzixQ9JqOF/OxpnZvCw1k47rg0TeqcWFYnz8x8Y +7xO8/DH0OoxXk2GJzVXJuItJs4gLzzfCjL0CggEAJFHfC9jisdy7CoWiOpNCSF1B +S0/CWDz77cZdlWkpTdaXGGp1MA/UKUFPIH8sOHfvpKS660+X4G/1ZBHmFb4P5kFF +Qy8UyUMKtSOEdZS6KFlRlfSCAMd5aSTmCvq4OSjYEpMRwUhU/iEJNkn9Z1Soehe0 +U3dxJ8KiT1071geO6rRquSHoSJs6Y0WQKriYYQJOhh4Axs3PQihER2eyh+WGk8YJ +02m0mMsjntqnXtdc6IcdKaHp9ko+OpM9QZLsvt19fxBcrXj/i21uUXrzuNtKfO6M +JqGhsOrO2dh8lMhvodENvgKA0DmYDC9N7ogo7bxTNSedcjBF46FhJoqii8m70Q== +-----END RSA PRIVATE KEY----- diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index dbfc15468..501c7cad8 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -115,6 +115,7 @@ class ApacheConfigurator(common.Installer): handle_modules=False, handle_sites=False, challenge_location="/etc/apache2", + bin=None ) def option(self, key): @@ -145,7 +146,7 @@ class ApacheConfigurator(common.Installer): """ opts = ["enmod", "dismod", "le_vhost_ext", "server_root", "vhost_root", "logs_root", "challenge_location", "handle_modules", "handle_sites", - "ctl"] + "ctl", "bin"] for o in opts: # Config options use dashes instead of underscores if self.conf(o.replace("_", "-")) is not None: @@ -194,6 +195,8 @@ class ApacheConfigurator(common.Installer): "(Only Ubuntu/Debian currently)") add("ctl", default=DEFAULTS["ctl"], help="Full path to Apache control script") + add("bin", default=DEFAULTS["bin"], + help="Full path to apache2/httpd binary") def __init__(self, *args, **kwargs): """Initialize an Apache Configurator. @@ -269,18 +272,25 @@ class ApacheConfigurator(common.Installer): """ if self._openssl_version: return self._openssl_version - # Step 1. Check for LoadModule directive + # Step 1. Determine the location of ssl_module try: ssl_module_location = self.parser.modules['ssl_module'] except KeyError: if warn_on_no_mod_ssl: logger.warning("Could not find ssl_module; not disabling session tickets.") return None - if not ssl_module_location: - logger.warning("Could not find ssl_module; not disabling session tickets.") - return None - ssl_module_location = self.parser.standard_path_from_server_root(ssl_module_location) - # Step 2. Grep in the .so for openssl version + if ssl_module_location: + # Possibility A: ssl_module is a DSO + ssl_module_location = self.parser.standard_path_from_server_root(ssl_module_location) + else: + # Possibility B: ssl_module is statically linked into Apache + if self.option("bin"): + ssl_module_location = self.option("bin") + else: + logger.warning("ssl_module is statically linked but --apache-bin is " + "missing; not disabling session tickets.") + return None + # Step 2. Grep in the binary for openssl version contents = self._open_module_file(ssl_module_location) if not contents: logger.warning("Unable to read ssl_module file; not disabling session tickets.") @@ -595,6 +605,11 @@ class ApacheConfigurator(common.Installer): # cert_key... can all be parsed appropriately self.prepare_server_https("443") + # If we haven't managed to enable mod_ssl by this point, error out + if "ssl_module" not in self.parser.modules: + raise errors.MisconfigurationError("Could not find ssl_module; " + "not installing certificate.") + # Add directives and remove duplicates self._add_dummy_ssl_directives(vhost.path) self._clean_vhost(vhost) @@ -609,21 +624,6 @@ class ApacheConfigurator(common.Installer): path["chain_path"] = self.parser.find_dir( "SSLCertificateChainFile", None, vhost.path) - # Handle errors when certificate/key directives cannot be found - if not path["cert_path"]: - logger.warning( - "Cannot find an SSLCertificateFile directive in %s. " - "VirtualHost was not modified", vhost.path) - raise errors.PluginError( - "Unable to find an SSLCertificateFile directive") - elif not path["cert_key"]: - logger.warning( - "Cannot find an SSLCertificateKeyFile directive for " - "certificate in %s. VirtualHost was not modified", vhost.path) - raise errors.PluginError( - "Unable to find an SSLCertificateKeyFile directive for " - "certificate") - logger.info("Deploying Certificate to VirtualHost %s", vhost.filep) if self.version < (2, 4, 8) or (chain_path and not fullchain_path): diff --git a/certbot-apache/certbot_apache/_internal/http_01.py b/certbot-apache/certbot_apache/_internal/http_01.py index ce64d451e..5ef44fa2e 100644 --- a/certbot-apache/certbot_apache/_internal/http_01.py +++ b/certbot-apache/certbot_apache/_internal/http_01.py @@ -169,7 +169,7 @@ class ApacheHttp01(common.ChallengePerformer): def _set_up_challenges(self): if not os.path.isdir(self.challenge_dir): - old_umask = os.umask(0o022) + old_umask = filesystem.umask(0o022) try: filesystem.makedirs(self.challenge_dir, 0o755) except OSError as exception: @@ -177,7 +177,7 @@ class ApacheHttp01(common.ChallengePerformer): raise errors.PluginError( "Couldn't create root for http-01 challenge") finally: - os.umask(old_umask) + filesystem.umask(old_umask) responses = [] for achall in self.achalls: diff --git a/certbot-apache/certbot_apache/_internal/override_arch.py b/certbot-apache/certbot_apache/_internal/override_arch.py index 54202c087..1c3aed1dc 100644 --- a/certbot-apache/certbot_apache/_internal/override_arch.py +++ b/certbot-apache/certbot_apache/_internal/override_arch.py @@ -24,4 +24,5 @@ class ArchConfigurator(configurator.ApacheConfigurator): handle_modules=False, handle_sites=False, challenge_location="/etc/httpd/conf", + bin=None, ) diff --git a/certbot-apache/certbot_apache/_internal/override_centos.py b/certbot-apache/certbot_apache/_internal/override_centos.py index 0de882519..9b2ee54c9 100644 --- a/certbot-apache/certbot_apache/_internal/override_centos.py +++ b/certbot-apache/certbot_apache/_internal/override_centos.py @@ -35,6 +35,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator): handle_modules=False, handle_sites=False, challenge_location="/etc/httpd/conf.d", + bin=None, ) def config_test(self): diff --git a/certbot-apache/certbot_apache/_internal/override_darwin.py b/certbot-apache/certbot_apache/_internal/override_darwin.py index f19823866..106f5fbab 100644 --- a/certbot-apache/certbot_apache/_internal/override_darwin.py +++ b/certbot-apache/certbot_apache/_internal/override_darwin.py @@ -24,4 +24,5 @@ class DarwinConfigurator(configurator.ApacheConfigurator): handle_modules=False, handle_sites=False, challenge_location="/etc/apache2/other", + bin=None, ) diff --git a/certbot-apache/certbot_apache/_internal/override_debian.py b/certbot-apache/certbot_apache/_internal/override_debian.py index c977fb43e..9f938046b 100644 --- a/certbot-apache/certbot_apache/_internal/override_debian.py +++ b/certbot-apache/certbot_apache/_internal/override_debian.py @@ -33,6 +33,7 @@ class DebianConfigurator(configurator.ApacheConfigurator): handle_modules=True, handle_sites=True, challenge_location="/etc/apache2", + bin=None, ) def enable_site(self, vhost): diff --git a/certbot-apache/certbot_apache/_internal/override_fedora.py b/certbot-apache/certbot_apache/_internal/override_fedora.py index 2436c76cc..9b521846c 100644 --- a/certbot-apache/certbot_apache/_internal/override_fedora.py +++ b/certbot-apache/certbot_apache/_internal/override_fedora.py @@ -29,6 +29,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator): handle_modules=False, handle_sites=False, challenge_location="/etc/httpd/conf.d", + bin=None, ) def config_test(self): diff --git a/certbot-apache/certbot_apache/_internal/override_gentoo.py b/certbot-apache/certbot_apache/_internal/override_gentoo.py index 6b7416c0d..59a3d981f 100644 --- a/certbot-apache/certbot_apache/_internal/override_gentoo.py +++ b/certbot-apache/certbot_apache/_internal/override_gentoo.py @@ -27,6 +27,7 @@ class GentooConfigurator(configurator.ApacheConfigurator): handle_modules=False, handle_sites=False, challenge_location="/etc/apache2/vhosts.d", + bin=None, ) def _prepare_options(self): diff --git a/certbot-apache/certbot_apache/_internal/override_suse.py b/certbot-apache/certbot_apache/_internal/override_suse.py index 895e0cb05..eee9b0b64 100644 --- a/certbot-apache/certbot_apache/_internal/override_suse.py +++ b/certbot-apache/certbot_apache/_internal/override_suse.py @@ -24,4 +24,5 @@ class OpenSUSEConfigurator(configurator.ApacheConfigurator): handle_modules=False, handle_sites=False, challenge_location="/etc/apache2/vhosts.d", + bin=None, ) diff --git a/certbot-apache/local-oldest-requirements.txt b/certbot-apache/local-oldest-requirements.txt index e45a0f831..7a6a1e4b8 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 -certbot[dev]==1.1.0 \ No newline at end of file +-e certbot[dev] \ No newline at end of file diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 25fb920c2..719bea004 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -6,13 +6,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ 'acme>=0.29.0', - 'certbot>=1.1.0', + 'certbot>=1.6.0.dev0', 'python-augeas', 'setuptools', 'zope.component', diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py index 8fd3cb750..091a6a828 100644 --- a/certbot-apache/tests/configurator_test.py +++ b/certbot-apache/tests/configurator_test.py @@ -455,41 +455,6 @@ class MultipleVhostsTest(util.ApacheTest): "SSLCertificateChainFile", "two/cert_chain.pem", self.vh_truth[1].path)) - def test_deploy_cert_invalid_vhost(self): - """For test cases where the `ApacheConfigurator` class' `_deploy_cert` - method is called with an invalid vhost parameter. Currently this tests - that a PluginError is appropriately raised when important directives - are missing in an SSL module.""" - self.config.parser.modules["ssl_module"] = None - self.config.parser.modules["mod_ssl.c"] = None - self.config.parser.modules["socache_shmcb_module"] = None - - def side_effect(*args): - """Mocks case where an SSLCertificateFile directive can be found - but an SSLCertificateKeyFile directive is missing.""" - if "SSLCertificateFile" in args: - return ["example/cert.pem"] - return [] - - mock_find_dir = mock.MagicMock(return_value=[]) - mock_find_dir.side_effect = side_effect - - self.config.parser.find_dir = mock_find_dir - - # Get the default 443 vhost - self.config.assoc["random.demo"] = self.vh_truth[1] - - self.assertRaises( - errors.PluginError, self.config.deploy_cert, "random.demo", - "example/cert.pem", "example/key.pem", "example/cert_chain.pem") - - # Remove side_effect to mock case where both SSLCertificateFile - # and SSLCertificateKeyFile directives are missing - self.config.parser.find_dir.side_effect = None - self.assertRaises( - errors.PluginError, self.config.deploy_cert, "random.demo", - "example/cert.pem", "example/key.pem", "example/cert_chain.pem") - def test_is_name_vhost(self): addr = obj.Addr.fromstring("*:80") self.assertTrue(self.config.is_name_vhost(addr)) @@ -1349,6 +1314,16 @@ class MultipleVhostsTest(util.ApacheTest): self.assertTrue(mock_add.called) shutil.rmtree(tmp_path) + def test_deploy_cert_no_mod_ssl(self): + # Create + ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0]) + self.config.parser.modules["socache_shmcb_module"] = None + self.config.prepare_server_https = mock.Mock() + + self.assertRaises(errors.MisconfigurationError, self.config.deploy_cert, + "encryption-example.demo", "example/cert.pem", "example/key.pem", + "example/cert_chain.pem", "example/fullchain.pem") + @mock.patch("certbot_apache._internal.parser.ApacheParser.parsed_in_original") def test_choose_vhost_and_servername_addition_parsed(self, mock_parsed): ret_vh = self.vh_truth[8] @@ -1797,12 +1772,22 @@ class InstallSslOptionsConfTest(util.ApacheTest): AH02556: "SSLOpenSSLConfCmd %s %s" applied to %s OpenSSL 1.0.2g 1 Mar 2016 """ + # ssl_module as a DSO self.config.parser.modules['ssl_module'] = '/fake/path' with mock.patch("certbot_apache._internal.configurator." "ApacheConfigurator._open_module_file") as mock_omf: mock_omf.return_value = some_string_contents self.assertEqual(self.config.openssl_version(), "1.0.2g") + # ssl_module statically linked + self.config._openssl_version = None + self.config.parser.modules['ssl_module'] = None + self.config.options['bin'] = '/fake/path/to/httpd' + with mock.patch("certbot_apache._internal.configurator." + "ApacheConfigurator._open_module_file") as mock_omf: + mock_omf.return_value = some_string_contents + self.assertEqual(self.config.openssl_version(), "1.0.2g") + def test_current_version(self): self.config.version = (2, 4, 10) self.config._openssl_version = '1.0.2m' @@ -1824,12 +1809,21 @@ class InstallSslOptionsConfTest(util.ApacheTest): self.assertEqual(self.config.openssl_version(), None) self.assertTrue("Could not find ssl_module" in mock_log.call_args[0][0]) + # When no ssl_module is present at all self.config._openssl_version = None - self.config.parser.modules['ssl_module'] = None + self.assertTrue("ssl_module" not in self.config.parser.modules) with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: self.assertEqual(self.config.openssl_version(), None) self.assertTrue("Could not find ssl_module" in mock_log.call_args[0][0]) + # When ssl_module is statically linked but --apache-bin not provided + self.config._openssl_version = None + self.config.options['bin'] = None + self.config.parser.modules['ssl_module'] = None + with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: + self.assertEqual(self.config.openssl_version(), None) + self.assertTrue("ssl_module is statically linked but" in mock_log.call_args[0][0]) + self.config.parser.modules['ssl_module'] = "/fake/path" with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: # Check that correct logger.warning was printed diff --git a/certbot-auto b/certbot-auto index 0ea3275c3..f99993b4f 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.3.0" +LE_AUTO_VERSION="1.5.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -910,20 +910,11 @@ elif [ -f /etc/manjaro-release ]; then } BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION" elif [ -f /etc/gentoo-release ]; then - Bootstrap() { - DeprecationBootstrap "Gentoo" BootstrapGentooCommon - } - BOOTSTRAP_VERSION="BootstrapGentooCommon $BOOTSTRAP_GENTOO_COMMON_VERSION" + DEPRECATED_OS=1 elif uname | grep -iq FreeBSD ; then - Bootstrap() { - DeprecationBootstrap "FreeBSD" BootstrapFreeBsd - } - BOOTSTRAP_VERSION="BootstrapFreeBsd $BOOTSTRAP_FREEBSD_VERSION" + DEPRECATED_OS=1 elif uname | grep -iq Darwin ; then - Bootstrap() { - DeprecationBootstrap "macOS" BootstrapMac - } - BOOTSTRAP_VERSION="BootstrapMac $BOOTSTRAP_MAC_VERSION" + DEPRECATED_OS=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then Bootstrap() { ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon @@ -1343,7 +1334,9 @@ cryptography==2.8 \ distro==1.4.0 \ --hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \ --hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4 -enum34==1.1.6 \ +# Package enum34 needs to be explicitly limited to Python2.x, in order to avoid +# certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456. +enum34==1.1.6 ; python_version < '3.4' \ --hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \ --hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \ --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \ @@ -1540,18 +1533,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.3.0 \ - --hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \ - --hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8 -acme==1.3.0 \ - --hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \ - --hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d -certbot-apache==1.3.0 \ - --hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \ - --hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52 -certbot-nginx==1.3.0 \ - --hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \ - --hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b +certbot==1.5.0 \ + --hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \ + --hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf +acme==1.5.0 \ + --hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \ + --hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0 +certbot-apache==1.5.0 \ + --hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \ + --hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764 +certbot-nginx==1.5.0 \ + --hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \ + --hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/certbot-ci/certbot_integration_tests/assets/hook.py b/certbot-ci/certbot_integration_tests/assets/hook.py index 39aa72ac5..483892a93 100755 --- a/certbot-ci/certbot_integration_tests/assets/hook.py +++ b/certbot-ci/certbot_integration_tests/assets/hook.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +from __future__ import print_function import os import sys @@ -7,5 +8,4 @@ if hook_script_type == 'deploy' and ('RENEWED_DOMAINS' not in os.environ or 'REN sys.stderr.write('Environment variables not properly set!\n') sys.exit(1) -with open(sys.argv[2], 'a') as file_h: - file_h.write(hook_script_type + '\n') +print(hook_script_type) diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py b/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py index 1b5914d1a..53df6b890 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py @@ -1,4 +1,5 @@ """This module contains advanced assertions for the certbot integration tests.""" +import io import os try: @@ -21,7 +22,8 @@ def assert_hook_execution(probe_path, probe_content): :param probe_path: path to the file that received the hook output :param probe_content: content expected when the hook is executed """ - with open(probe_path, 'r') as file: + encoding = 'utf-8' if POSIX_MODE else 'utf-16' + with io.open(probe_path, 'rt', encoding=encoding) as file: data = file.read() lines = [line.strip() for line in data.splitlines()] diff --git a/certbot-ci/certbot_integration_tests/utils/misc.py b/certbot-ci/certbot_integration_tests/utils/misc.py index fbb965034..4b2774827 100644 --- a/certbot-ci/certbot_integration_tests/utils/misc.py +++ b/certbot-ci/certbot_integration_tests/utils/misc.py @@ -140,13 +140,12 @@ def generate_test_file_hooks(config_dir, hook_probe): entrypoint_script = '''\ #!/usr/bin/env bash set -e -"{0}" "{1}" "{2}" "{3}" +"{0}" "{1}" "{2}" >> "{3}" '''.format(sys.executable, hook_path, entrypoint_script_path, hook_probe) else: - entrypoint_script_path = os.path.join(hook_dir, 'entrypoint.bat') + entrypoint_script_path = os.path.join(hook_dir, 'entrypoint.ps1') entrypoint_script = '''\ -@echo off -"{0}" "{1}" "{2}" "{3}" +& "{0}" "{1}" "{2}" >> "{3}" '''.format(sys.executable, hook_path, entrypoint_script_path, hook_probe) with open(entrypoint_script_path, 'w') as file_h: diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index ed8e3f861..9a646d7ce 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -5,7 +5,7 @@ from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -version = '1.4.0.dev0' +version = '1.6.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 9ac16bc67..91c3683b6 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index f998027f9..579637dab 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 7aef67d75..d30167a14 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 4a3f863f5..9ba71a7ea 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -7,7 +7,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 2dced23bf..a5e025e66 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 7c7acc503..8965e6b8c 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 1b51a781e..27c5e6b05 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 860c40079..ebe9660fa 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 83932e140..21daf4c57 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 459c6d752..ad42991f9 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 5823b237e..eee6ddc82 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 94cda6f65..d9863aedd 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index f140d3f8d..c207e5db5 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index b57e28577..06ce9613e 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/certbot_nginx/_internal/constants.py b/certbot-nginx/certbot_nginx/_internal/constants.py index fbf6ed424..c10eb5098 100644 --- a/certbot-nginx/certbot_nginx/_internal/constants.py +++ b/certbot-nginx/certbot_nginx/_internal/constants.py @@ -3,9 +3,12 @@ import platform FREEBSD_DARWIN_SERVER_ROOT = "/usr/local/etc/nginx" LINUX_SERVER_ROOT = "/etc/nginx" +PKGSRC_SERVER_ROOT = "/usr/pkg/etc/nginx" if platform.system() in ('FreeBSD', 'Darwin'): server_root_tmp = FREEBSD_DARWIN_SERVER_ROOT +elif platform.system() in ('NetBSD',): + server_root_tmp = PKGSRC_SERVER_ROOT else: server_root_tmp = LINUX_SERVER_ROOT diff --git a/certbot-nginx/local-oldest-requirements.txt b/certbot-nginx/local-oldest-requirements.txt index 1782f15ba..e6d9f26fd 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. --e acme[dev] --e certbot[dev] +acme[dev]==1.4.0 +certbot[dev]==1.4.0 diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 0e6deceb3..6138a06c2 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -6,13 +6,13 @@ from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.4.0.dev0' +version = '1.6.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ - 'acme>=1.4.0.dev0', - 'certbot>=1.4.0.dev0', + 'acme>=1.4.0', + 'certbot>=1.4.0', 'PyOpenSSL', 'pyparsing>=1.5.5', # Python3 support 'setuptools', diff --git a/certbot.wrapper b/certbot.wrapper new file mode 100755 index 000000000..199191d5f --- /dev/null +++ b/certbot.wrapper @@ -0,0 +1,19 @@ +#!/bin/bash +set -e +join() { + sep=$1 + first=$2 + if [ "$first" != "" ]; then + shift 2 + echo -n "${first}" + for item in "$@"; do echo -n "${sep}${item}"; done + echo + fi +} + +paths=$(for plugin_snap in $(snap connections certbot|sed -n '2,$p'|awk '$1=="content[certbot-1]"{print $3}'|cut -d: -f1); do echo /snap/$plugin_snap/current/lib/python3.6/site-packages; done) +export PYTHONPATH=$(join : $PYTHONPATH $paths) +if [ -z "$PYTHONPATH" ]; then + unset PYTHONPATH +fi +exec certbot "$@" diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 9eb7cd9e8..60a5d2aaa 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,7 +2,50 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). -## 1.4.0 - master +## 1.6.0 - master + +### Added + +* Certbot snaps are now available for the i386, arm64, and armhf architectures. +* Add minimal code to run Nginx plugin on NetBSD. +* Make Certbot snap find externally snapped plugins +* Function `certbot.compat.filesystem.umask` is a drop-in replacement for `os.umask` + implementing umask for both UNIX and Windows systems. + +### Changed + +* Allow session tickets to be disabled in Apache when mod_ssl is statically linked. +* Certbot behaves similarly on Windows to on UNIX systems regarding umask, and + the umask `022` is applied by default: all files/directories are not writable by anyone + other than the user running Certbot and the system/admin users. +* Read acmev1 Let's Encrypt server URL from renewal config as acmev2 URL to prepare + for impending acmev1 deprecation. + +### Fixed + +* + +More details about these changes can be found on our GitHub repo. + +## 1.5.0 - 2020-06-02 + +### Added + +* Require explicit confirmation of snap plugin permissions before connecting. + +### Changed + +* Improved error message in apache installer when mod_ssl is not available. + +### Fixed + +* Add support for OCSP responses which use a public key hash ResponderID, fixing + interoperability with Sectigo CAs. +* Fix TLS-ALPN test that fails when run with newer versions of OpenSSL. + +More details about these changes can be found on our GitHub repo. + +## 1.4.0 - 2020-05-05 ### Added @@ -15,12 +58,16 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). * Added TLS-ALPN-01 challenge support in the `acme` library. Support of this challenge in the Certbot client is planned to be added in a future release. * Added minimal proxy support for OCSP verification. +* On Windows, hooks are now executed in a Powershell shell instead of a CMD shell, + allowing both `*.ps1` and `*.bat` as valid scripts for Certbot. ### Changed +* Reorganized error message when a user entered an invalid email address. * Stop asking interactively if the user would like to add a redirect. * `mock` dependency is now conditional on Python 2 in all of our packages. * Deprecate certbot-auto on Gentoo, macOS, and FreeBSD. +* Allow existing but empty archive and live dir to be used when creating new lineage. ### Fixed diff --git a/certbot/README.rst b/certbot/README.rst index 5ed74f247..39da06c8a 100644 --- a/certbot/README.rst +++ b/certbot/README.rst @@ -71,16 +71,12 @@ ACME spec: http://ietf-wg-acme.github.io/acme/ ACME working area in github: https://github.com/ietf-wg-acme/acme -|build-status| |container| +|build-status| .. |build-status| image:: https://travis-ci.com/certbot/certbot.svg?branch=master :target: https://travis-ci.com/certbot/certbot :alt: Travis CI status -.. |container| image:: https://quay.io/repository/letsencrypt/letsencrypt/status - :target: https://quay.io/repository/letsencrypt/letsencrypt - :alt: Docker Repository on Quay.io - .. Do not modify this comment unless you know what you're doing. tag:links-end System Requirements diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 0ce7ff6b7..79e6c16a4 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.4.0.dev0' +__version__ = '1.6.0.dev0' diff --git a/certbot/certbot/_internal/constants.py b/certbot/certbot/_internal/constants.py index 9a2220e0b..af6531fe8 100644 --- a/certbot/certbot/_internal/constants.py +++ b/certbot/certbot/_internal/constants.py @@ -120,6 +120,8 @@ CLI_DEFAULTS = dict( ) STAGING_URI = "https://acme-staging-v02.api.letsencrypt.org/directory" +V1_URI = "https://acme-v01.api.letsencrypt.org/directory" + # The set of reasons for revoking a certificate is defined in RFC 5280 in # section 5.3.1. The reasons that users are allowed to submit are restricted to # those accepted by the ACME server implementation. They are listed in diff --git a/certbot/certbot/_internal/hooks.py b/certbot/certbot/_internal/hooks.py index 589c59e89..f26c5c76b 100644 --- a/certbot/certbot/_internal/hooks.py +++ b/certbot/certbot/_internal/hooks.py @@ -2,14 +2,13 @@ from __future__ import print_function import logging -from subprocess import PIPE -from subprocess import Popen from acme.magic_typing import List from acme.magic_typing import Set from certbot import errors from certbot import util from certbot.compat import filesystem +from certbot.compat import misc from certbot.compat import os from certbot.plugins import util as plug_util @@ -229,36 +228,10 @@ def _run_hook(cmd_name, shell_cmd): :type shell_cmd: `list` of `str` or `str` :returns: stderr if there was any""" - err, _ = execute(cmd_name, shell_cmd) + err, _ = misc.execute_command(cmd_name, shell_cmd) return err -def execute(cmd_name, shell_cmd): - """Run a command. - - :param str cmd_name: the user facing name of the hook being run - :param shell_cmd: shell command to execute - :type shell_cmd: `list` of `str` or `str` - - :returns: `tuple` (`str` stderr, `str` stdout)""" - logger.info("Running %s command: %s", cmd_name, shell_cmd) - - # universal_newlines causes Popen.communicate() - # to return str objects instead of bytes in Python 3 - cmd = Popen(shell_cmd, shell=True, stdout=PIPE, - stderr=PIPE, universal_newlines=True) - out, err = cmd.communicate() - base_cmd = os.path.basename(shell_cmd.split(None, 1)[0]) - if out: - logger.info('Output from %s command %s:\n%s', cmd_name, base_cmd, out) - if cmd.returncode != 0: - logger.error('%s command "%s" returned error code %d', - cmd_name, shell_cmd, cmd.returncode) - if err: - logger.error('Error output from %s command %s:\n%s', cmd_name, base_cmd, err) - return err, out - - def list_hooks(dir_path): """List paths to all hooks found in dir_path in sorted order. diff --git a/certbot/certbot/_internal/log.py b/certbot/certbot/_internal/log.py index 0a492ba55..3b87f9bca 100644 --- a/certbot/certbot/_internal/log.py +++ b/certbot/certbot/_internal/log.py @@ -322,15 +322,23 @@ def post_arg_parse_except_hook(exc_type, exc_value, trace, debug, log_path): logger.error('Exiting abnormally:', exc_info=exc_info) else: logger.debug('Exiting abnormally:', exc_info=exc_info) + # Use logger to print the error message to take advantage of + # our logger printing warnings and errors in red text. if issubclass(exc_type, errors.Error): - sys.exit(exc_value) + logger.error(str(exc_value)) + sys.exit(1) logger.error('An unexpected error occurred:') if messages.is_acme_error(exc_value): # Remove the ACME error prefix from the exception _, _, exc_str = str(exc_value).partition(':: ') logger.error(exc_str) else: - traceback.print_exception(exc_type, exc_value, None) + output = traceback.format_exception_only(exc_type, exc_value) + # format_exception_only returns a list of strings each + # terminated by a newline. We combine them into one string + # and remove the final newline before passing it to + # logger.error. + logger.error(''.join(output).rstrip()) exit_with_log_path(log_path) diff --git a/certbot/certbot/_internal/plugins/manual.py b/certbot/certbot/_internal/plugins/manual.py index b46622796..430059445 100644 --- a/certbot/certbot/_internal/plugins/manual.py +++ b/certbot/certbot/_internal/plugins/manual.py @@ -9,6 +9,7 @@ from certbot import errors from certbot import interfaces from certbot import reverter from certbot._internal import hooks +from certbot.compat import misc from certbot.compat import os from certbot.plugins import common @@ -186,4 +187,4 @@ permitted by DNS standards.) self.reverter.recovery_routine() def _execute_hook(self, hook_name): - return hooks.execute(self.option_name(hook_name), self.conf(hook_name)) + return misc.execute_command(self.option_name(hook_name), self.conf(hook_name)) diff --git a/certbot/certbot/_internal/plugins/webroot.py b/certbot/certbot/_internal/plugins/webroot.py index 9383ce66d..484d209d6 100644 --- a/certbot/certbot/_internal/plugins/webroot.py +++ b/certbot/certbot/_internal/plugins/webroot.py @@ -164,7 +164,7 @@ to serve all files under specified web root ({0}).""" # Change the permissions to be writable (GH #1389) # Umask is used instead of chmod to ensure the client can also # run as non-root (GH #1795) - old_umask = os.umask(0o022) + old_umask = filesystem.umask(0o022) try: # We ignore the last prefix in the next iteration, # as it does not correspond to a folder path ('/' or 'C:') @@ -191,7 +191,7 @@ to serve all files under specified web root ({0}).""" "Couldn't create root for {0} http-01 " "challenge responses: {1}".format(name, exception)) finally: - os.umask(old_umask) + filesystem.umask(old_umask) def _get_validation_path(self, root_path, achall): # pylint: no-self-use return os.path.join(root_path, achall.chall.encode("token")) @@ -204,13 +204,13 @@ to serve all files under specified web root ({0}).""" logger.debug("Attempting to save validation to %s", validation_path) # Change permissions to be world-readable, owner-writable (GH #1795) - old_umask = os.umask(0o022) + old_umask = filesystem.umask(0o022) try: with safe_open(validation_path, mode="wb", chmod=0o644) as validation_file: validation_file.write(validation.encode()) finally: - os.umask(old_umask) + filesystem.umask(old_umask) self.performed[root_path].add(achall) return response diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py index fd23b0d18..47244052a 100644 --- a/certbot/certbot/_internal/renewal.py +++ b/certbot/certbot/_internal/renewal.py @@ -19,6 +19,7 @@ from certbot import errors from certbot import interfaces from certbot import util from certbot._internal import cli +from certbot._internal import constants from certbot._internal import hooks from certbot._internal import storage from certbot._internal import updater @@ -243,16 +244,28 @@ def _restore_int(name, value): raise errors.Error("Expected a numeric value for {0}".format(name)) -def _restore_str(unused_name, value): +def _restore_str(name, value): """Restores a string key-value pair from a renewal config file. - :param str unused_name: option name + :param str name: option name :param str value: option value :returns: converted option value to be stored in the runtime config :rtype: str or None """ + # Previous to v0.5.0, Certbot always stored the `server` URL in the renewal config, + # resulting in configs which explicitly use the deprecated ACMEv1 URL, today + # preventing an automatic transition to the default modern ACME URL. + # (https://github.com/certbot/certbot/issues/7978#issuecomment-625442870) + # As a mitigation, this function reinterprets the value of the `server` parameter if + # necessary, replacing the ACMEv1 URL with the default ACME URL. It is still possible + # to override this choice with the explicit `--server` CLI flag. + if name == "server" and value == constants.V1_URI: + logger.info("Using server %s instead of legacy %s", + constants.CLI_DEFAULTS["server"], value) + return constants.CLI_DEFAULTS["server"] + return None if value == "None" else value diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index 2dac163e2..05d9e3a8d 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -1007,18 +1007,18 @@ class RenewableCert(interfaces.RenewableCert): lineagename = lineagename_for_filename(config_filename) archive = full_archive_path(None, cli_config, lineagename) live_dir = _full_live_path(cli_config, lineagename) - if os.path.exists(archive): + if os.path.exists(archive) and (not os.path.isdir(archive) or os.listdir(archive)): config_file.close() raise errors.CertStorageError( "archive directory exists for " + lineagename) - if os.path.exists(live_dir): + if os.path.exists(live_dir) and (not os.path.isdir(live_dir) or os.listdir(live_dir)): config_file.close() raise errors.CertStorageError( "live directory exists for " + lineagename) - filesystem.mkdir(archive) - filesystem.mkdir(live_dir) - logger.debug("Archive directory %s and live " - "directory %s created.", archive, live_dir) + for i in (archive, live_dir): + if not os.path.exists(i): + filesystem.makedirs(i) + logger.debug("Creating directory %s.", i) # Put the data into the appropriate files on disk target = {kind: os.path.join(live_dir, kind + ".pem") for kind in ALL_FOUR} diff --git a/certbot/certbot/compat/filesystem.py b/certbot/certbot/compat/filesystem.py index b9b6e5cc6..081d5d915 100644 --- a/certbot/certbot/compat/filesystem.py +++ b/certbot/certbot/compat/filesystem.py @@ -21,17 +21,32 @@ else: POSIX_MODE = False +# Windows umask implementation, since Windows does not have a concept of umask by default. +# We choose 022 as initial value since it is the default one on most Linux distributions, and +# it is a decent choice to not have write permissions for group owner and everybody by default. +# We use a class here to avoid needing to define a global variable, and the potential mistakes +# that could happen with this kind of pattern. +class _WindowsUmask: + """Store the current umask to apply on Windows""" + def __init__(self): + self.mask = 0o022 + + +_WINDOWS_UMASK = _WindowsUmask() + + def chmod(file_path, mode): # type: (str, int) -> None """ Apply a POSIX mode on given file_path: - * for Linux, the POSIX mode will be directly applied using chmod, - * for Windows, the POSIX mode will be translated into a Windows DACL that make sense for - Certbot context, and applied to the file using kernel calls. + + - for Linux, the POSIX mode will be directly applied using chmod, + - for Windows, the POSIX mode will be translated into a Windows DACL that make sense for + Certbot context, and applied to the file using kernel calls. The definition of the Windows DACL that correspond to a POSIX mode, in the context of Certbot, is explained at https://github.com/certbot/certbot/issues/6356 and is implemented by the - method _generate_windows_flags(). + method `_generate_windows_flags()`. :param str file_path: Path of the file :param int mode: POSIX mode to apply @@ -42,6 +57,24 @@ def chmod(file_path, mode): _apply_win_mode(file_path, mode) +def umask(mask): + # type: (int) -> int + """ + Set the current numeric umask and return the previous umask. On Linux, the built-in umask + method is used. On Windows, our Certbot-side implementation is used. + + :param int mask: The user file-creation mode mask to apply. + :rtype: int + :return: The previous umask value. + """ + if POSIX_MODE: + return os.umask(mask) + + previous_umask = _WINDOWS_UMASK.mask + _WINDOWS_UMASK.mask = mask + return previous_umask + + # One could ask why there is no copy_ownership() function, or even a reimplementation # of os.chown() that would modify the ownership of file without touching the mode itself. # This is because on Windows, it would require recalculating the existing DACL against @@ -57,6 +90,7 @@ def copy_ownership_and_apply_mode(src, dst, mode, copy_user, copy_group): Copy ownership (user and optionally group on Linux) from the source to the destination, then apply given mode in compatible way for Linux and Windows. This replaces the os.chown command. + :param str src: Path of the source file :param str dst: Path of the destination file :param int mode: Permission mode to apply on the destination file @@ -78,12 +112,43 @@ def copy_ownership_and_apply_mode(src, dst, mode, copy_user, copy_group): chmod(dst, mode) +# Quite similar to copy_ownership_and_apply_mode, but this time the DACL is copied from +# the source file on Windows. The DACL stays consistent with the dynamic rights of the +# equivalent POSIX mode, because ownership and mode are copied altogether on the destination +# file, so no recomputing of the DACL against the new owner is needed, as it would be +# for a copy_ownership alone method. +def copy_ownership_and_mode(src, dst, copy_user=True, copy_group=True): + # type: (str, str, bool, bool) -> None + """ + Copy ownership (user and optionally group on Linux) and mode/DACL + from the source to the destination. + + :param str src: Path of the source file + :param str dst: Path of the destination file + :param bool copy_user: Copy user if `True` + :param bool copy_group: Copy group if `True` on Linux (has no effect on Windows) + """ + if POSIX_MODE: + # On Linux, we just delegate to chown and chmod. + stats = os.stat(src) + user_id = stats.st_uid if copy_user else -1 + group_id = stats.st_gid if copy_group else -1 + os.chown(dst, user_id, group_id) + chmod(dst, stats.st_mode) + else: + if copy_user: + # There is no group handling in Windows + _copy_win_ownership(src, dst) + _copy_win_mode(src, dst) + + def check_mode(file_path, mode): # type: (str, int) -> bool """ Check if the given mode matches the permissions of the given file. On Linux, will make a direct comparison, on Windows, mode will be compared against the security model. + :param str file_path: Path of the file :param int mode: POSIX mode to test :rtype: bool @@ -99,6 +164,7 @@ def check_owner(file_path): # type: (str) -> bool """ Check if given file is owned by current user. + :param str file_path: File path to check :rtype: bool :return: True if given file is owned by current user, False otherwise. @@ -121,6 +187,7 @@ def check_permissions(file_path, mode): # type: (str, int) -> bool """ Check if given file has the given mode and is owned by current user. + :param str file_path: File path to check :param int mode: POSIX mode to check :rtype: bool @@ -134,6 +201,7 @@ def open(file_path, flags, mode=0o777): # pylint: disable=redefined-builtin """ Wrapper of original os.open function, that will ensure on Windows that given mode is correctly applied. + :param str file_path: The file path to open :param int flags: Flags to apply on file while opened :param int mode: POSIX mode to apply on file when opened, @@ -142,7 +210,7 @@ def open(file_path, flags, mode=0o777): # pylint: disable=redefined-builtin :rtype: int :raise: OSError(errno.EEXIST) if the file already exists and os.O_CREAT & os.O_EXCL are set, OSError(errno.EACCES) on Windows if the file already exists and is a directory, and - os.O_CREAT is set. + os.O_CREAT is set. """ if POSIX_MODE: # On Linux, invoke os.open directly. @@ -158,7 +226,7 @@ def open(file_path, flags, mode=0o777): # pylint: disable=redefined-builtin attributes = win32security.SECURITY_ATTRIBUTES() security = attributes.SECURITY_DESCRIPTOR user = _get_current_user() - dacl = _generate_dacl(user, mode) + dacl = _generate_dacl(user, mode, _WINDOWS_UMASK.mask) # We set second parameter to 0 (`False`) to say that this security descriptor is # NOT constructed from a default mechanism, but is explicitly set by the user. # See https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptorowner # pylint: disable=line-too-long @@ -203,21 +271,32 @@ def makedirs(file_path, mode=0o777): """ Rewrite of original os.makedirs function, that will ensure on Windows that given mode is correctly applied. + :param str file_path: The file path to open :param int mode: POSIX mode to apply on leaf directory when created, Python defaults will be applied if ``None`` """ - if POSIX_MODE: - return os.makedirs(file_path, mode) - - orig_mkdir_fn = os.mkdir + current_umask = umask(0) try: - # As we know that os.mkdir is called internally by os.makedirs, we will swap the function in - # os module for the time of makedirs execution on Windows. - os.mkdir = mkdir # type: ignore - return os.makedirs(file_path, mode) + # Since Python 3.7, os.makedirs does not set the given mode to the intermediate + # directories that could be created in the process. To keep things safe and consistent + # on all Python versions, we set the umask accordingly to have all directories + # (intermediate and leaf) created with the given mode. + umask(current_umask | 0o777 ^ mode) + + if POSIX_MODE: + return os.makedirs(file_path, mode) + + orig_mkdir_fn = os.mkdir + try: + # As we know that os.mkdir is called internally by os.makedirs, we will swap the + # function in os module for the time of makedirs execution on Windows. + os.mkdir = mkdir # type: ignore + return os.makedirs(file_path, mode) + finally: + os.mkdir = orig_mkdir_fn finally: - os.mkdir = orig_mkdir_fn + umask(current_umask) def mkdir(file_path, mode=0o777): @@ -225,6 +304,7 @@ def mkdir(file_path, mode=0o777): """ Rewrite of original os.mkdir function, that will ensure on Windows that given mode is correctly applied. + :param str file_path: The file path to open :param int mode: POSIX mode to apply on directory when created, Python defaults will be applied if ``None`` @@ -235,7 +315,7 @@ def mkdir(file_path, mode=0o777): attributes = win32security.SECURITY_ATTRIBUTES() security = attributes.SECURITY_DESCRIPTOR user = _get_current_user() - dacl = _generate_dacl(user, mode) + dacl = _generate_dacl(user, mode, _WINDOWS_UMASK.mask) security.SetSecurityDescriptorOwner(user, False) security.SetSecurityDescriptorDacl(1, dacl, 0) @@ -255,6 +335,7 @@ def replace(src, dst): # type: (str, str) -> None """ Rename a file to a destination path and handles situations where the destination exists. + :param str src: The current file path. :param str dst: The new file path. """ @@ -272,6 +353,10 @@ def realpath(file_path): """ Find the real path for the given path. This method resolves symlinks, including recursive symlinks, and is protected against symlinks that creates an infinite loop. + + :param str file_path: The path to resolve + :returns: The real path for the given path + :rtype: str """ original_path = file_path @@ -308,6 +393,7 @@ def is_executable(path): # type: (str) -> bool """ Is path an executable file? + :param str path: path to test :return: True if path is an executable file :rtype: bool @@ -321,7 +407,8 @@ def is_executable(path): def has_world_permissions(path): # type: (str) -> bool """ - Check if everybody/world has any right (read/write/execute) on a file given its path + Check if everybody/world has any right (read/write/execute) on a file given its path. + :param str path: path to test :return: True if everybody/world has any right to the file :rtype: bool @@ -342,7 +429,8 @@ def has_world_permissions(path): def compute_private_key_mode(old_key, base_mode): # type: (str, int) -> int """ - Calculate the POSIX mode to apply to a private key given the previous private key + Calculate the POSIX mode to apply to a private key given the previous private key. + :param str old_key: path to the previous private key :param int base_mode: the minimum modes to apply to a private key :return: the POSIX mode to apply @@ -365,6 +453,7 @@ def has_same_ownership(path1, path2): """ Return True if the ownership of two files given their respective path is the same. On Windows, ownership is checked against owner only, since files do not have a group owner. + :param str path1: path to the first file :param str path2: path to the second file :return: True if both files have the same ownership, False otherwise @@ -390,6 +479,7 @@ def has_min_permissions(path, min_mode): """ Check if a file given its path has at least the permissions defined by the given minimal mode. On Windows, group permissions are ignored since files do not have a group owner. + :param str path: path to the file to check :param int min_mode: the minimal permissions expected :return: True if the file matches the minimal permissions expectations, False otherwise @@ -465,7 +555,9 @@ def _apply_win_mode(file_path, mode): win32security.SetFileSecurity(file_path, win32security.DACL_SECURITY_INFORMATION, security) -def _generate_dacl(user_sid, mode): +def _generate_dacl(user_sid, mode, mask=None): + if mask: + mode = mode & (0o777 - mask) analysis = _analyze_mode(mode) # Get standard accounts from "well-known" sid @@ -515,6 +607,9 @@ def _analyze_mode(mode): def _copy_win_ownership(src, dst): + # Resolve symbolic links + src = realpath(src) + security_src = win32security.GetFileSecurity(src, win32security.OWNER_SECURITY_INFORMATION) user_src = security_src.GetSecurityDescriptorOwner() @@ -526,6 +621,19 @@ def _copy_win_ownership(src, dst): win32security.SetFileSecurity(dst, win32security.OWNER_SECURITY_INFORMATION, security_dst) +def _copy_win_mode(src, dst): + # Resolve symbolic links + src = realpath(src) + + # Copy the DACL from src to dst. + security_src = win32security.GetFileSecurity(src, win32security.DACL_SECURITY_INFORMATION) + dacl = security_src.GetSecurityDescriptorDacl() + + security_dst = win32security.GetFileSecurity(dst, win32security.DACL_SECURITY_INFORMATION) + security_dst.SetSecurityDescriptorDacl(1, dacl, 0) + win32security.SetFileSecurity(dst, win32security.DACL_SECURITY_INFORMATION, security_dst) + + def _generate_windows_flags(rights_desc): # Some notes about how each POSIX right is interpreted. # diff --git a/certbot/certbot/compat/misc.py b/certbot/certbot/compat/misc.py index 956c56370..49a0814f4 100644 --- a/certbot/certbot/compat/misc.py +++ b/certbot/certbot/compat/misc.py @@ -4,12 +4,16 @@ particular category. """ from __future__ import absolute_import +import logging import select +import subprocess import sys from certbot import errors from certbot.compat import os +from acme.magic_typing import Tuple + try: from win32com.shell import shell as shellwin32 POSIX_MODE = False @@ -17,6 +21,7 @@ except ImportError: # pragma: no cover POSIX_MODE = True +logger = logging.getLogger(__name__) # For Linux: define OS specific standard binary directories STANDARD_BINARY_DIRS = ["/usr/sbin", "/usr/local/bin", "/usr/local/sbin"] if POSIX_MODE else [] @@ -109,3 +114,39 @@ def underscores_for_unsupported_characters_in_path(path): # Windows specific drive, tail = os.path.splitdrive(path) return drive + tail.replace(':', '_') + + +def execute_command(cmd_name, shell_cmd): + # type: (str, str) -> Tuple[str, str] + """ + Run a command: + - on Linux command will be run by the standard shell selected with Popen(shell=True) + - on Windows command will be run in a Powershell shell + + :param str cmd_name: the user facing name of the hook being run + :param str shell_cmd: shell command to execute + + :returns: `tuple` (`str` stderr, `str` stdout) + """ + logger.info("Running %s command: %s", cmd_name, shell_cmd) + + if POSIX_MODE: + cmd = subprocess.Popen(shell_cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + else: + line = ['powershell.exe', '-Command', shell_cmd] + cmd = subprocess.Popen(line, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) + + # universal_newlines causes Popen.communicate() + # to return str objects instead of bytes in Python 3 + out, err = cmd.communicate() + base_cmd = os.path.basename(shell_cmd.split(None, 1)[0]) + if out: + logger.info('Output from %s command %s:\n%s', cmd_name, base_cmd, out) + if cmd.returncode != 0: + logger.error('%s command "%s" returned error code %d', + cmd_name, shell_cmd, cmd.returncode) + if err: + logger.error('Error output from %s command %s:\n%s', cmd_name, base_cmd, err) + return err, out diff --git a/certbot/certbot/compat/os.py b/certbot/certbot/compat/os.py index 0231dd51a..d262409c1 100644 --- a/certbot/certbot/compat/os.py +++ b/certbot/certbot/compat/os.py @@ -56,6 +56,16 @@ def chmod(*unused_args, **unused_kwargs): 'Use certbot.compat.filesystem.chmod() instead.') +# Since there is no mode on Windows, there is no umask either, and so this method is a noop for +# this platform. In order to have a consistent behavior between Linux and Windows on Certbot files +# and directories, the filesystem umask method must be used instead, since it implements umask for +# Windows. +def umask(*unused_args, **unused_kwargs): + """Method os.chmod() is forbidden""" + raise RuntimeError('Usage of os.umask() is forbidden. ' + 'Use certbot.compat.filesystem.umask() instead.') + + # Because uid is not a concept on Windows, chown is useless. In fact, it is not even available # on Python for Windows. So to be consistent on both platforms for Certbot, this method is # always forbidden. diff --git a/certbot/certbot/display/ops.py b/certbot/certbot/display/ops.py index 21d169a55..2c3503eab 100644 --- a/certbot/certbot/display/ops.py +++ b/certbot/certbot/display/ops.py @@ -30,7 +30,7 @@ def get_email(invalid=False, optional=True): """ invalid_prefix = "There seem to be problems with that address. " - msg = "Enter email address (used for urgent renewal and security notices)" + msg = "Enter email address (used for urgent renewal and security notices)\n" unsafe_suggestion = ("\n\nIf you really want to skip this, you can run " "the client with --register-unsafely-without-email " "but make sure you then backup your account key from " @@ -64,7 +64,7 @@ def get_email(invalid=False, optional=True): if util.safe_email(email): return email if suggest_unsafe: - msg += unsafe_suggestion + msg = unsafe_suggestion + msg suggest_unsafe = False # add this message at most once invalid = bool(email) diff --git a/certbot/certbot/ocsp.py b/certbot/certbot/ocsp.py index 863c5f163..51ada012a 100644 --- a/certbot/certbot/ocsp.py +++ b/certbot/certbot/ocsp.py @@ -256,7 +256,11 @@ def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert, cert_path): def _check_ocsp_response_signature(response_ocsp, issuer_cert, cert_path): """Verify an OCSP response signature against certificate issuer or responder""" - if response_ocsp.responder_name == issuer_cert.subject: + def _key_hash(cert): + return x509.SubjectKeyIdentifier.from_public_key(cert.public_key()).digest + + if response_ocsp.responder_name == issuer_cert.subject or \ + response_ocsp.responder_key_hash == _key_hash(issuer_cert): # Case where the OCSP responder is also the certificate issuer logger.debug('OCSP response for certificate %s is signed by the certificate\'s issuer.', cert_path) @@ -267,7 +271,8 @@ def _check_ocsp_response_signature(response_ocsp, issuer_cert, cert_path): cert_path) responder_certs = [cert for cert in response_ocsp.certificates - if cert.subject == response_ocsp.responder_name] + if response_ocsp.responder_name == cert.subject or \ + response_ocsp.responder_key_hash == _key_hash(cert)] if not responder_certs: raise AssertionError('no matching responder certificate could be found') diff --git a/certbot/docs/ciphers.rst b/certbot/docs/ciphers.rst index 325d6244c..e3d9cf54e 100644 --- a/certbot/docs/ciphers.rst +++ b/certbot/docs/ciphers.rst @@ -114,9 +114,6 @@ the Qualys SSL Labs site, which Certbot will suggest when installing a certificate, to test your server and see whether it will be compatible with particular software versions. -It will be possible to ask Certbot to instead apply (and track) Modern -or Old configurations. - The Let's Encrypt project expects to follow the Mozilla recommendations in the future as those recommendations are updated. (For example, some users have proposed prioritizing a new ciphersuite known as ``0xcc13`` @@ -159,51 +156,6 @@ welcome suggestions of other resources to add to this list. Please keep in mind that different recommendations may reflect different priorities or evaluations of trade-offs, especially related to compatibility! - -Changing your settings ----------------------- - -This will probably look something like - -.. code-block:: shell - - certbot --cipher-recommendations mozilla-secure - certbot --cipher-recommendations mozilla-intermediate - certbot --cipher-recommendations mozilla-old - -to track Mozilla's *Secure*, *Intermediate*, or *Old* recommendations, -and - -.. code-block:: shell - - certbot --update-ciphers on - -to enable updating ciphers with each new Certbot release, or - -.. code-block:: shell - - certbot --update-ciphers off - -to disable automatic configuration updates. These features have not yet -been implemented and this syntax may change when they are implemented. - - -TODO ----- - -The status of this feature is tracked as part of issue #1123 in our -bug tracker. - -https://github.com/certbot/certbot/issues/1123 - -Prior to implementation of #1123, the client does not actually modify -ciphersuites (this is intended to be implemented as a "configuration -enhancement", but the only configuration enhancement implemented -so far is redirecting HTTP requests to HTTPS in web servers, the -"redirect" enhancement). The changes here would probably be either a new -"ciphersuite" enhancement in each plugin that provides an installer, -or a family of enhancements, one per selectable ciphersuite configuration. - Feedback ======== We receive lots of feedback on the type of ciphersuites that Let's Encrypt supports and list some collated feedback below. This section aims to track suggestions and references that people have offered or identified to improve the ciphersuites that Let's Encrypt enables when configuring TLS on servers. diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt index 3c2289030..d37e19b71 100644 --- a/certbot/docs/cli-help.txt +++ b/certbot/docs/cli-help.txt @@ -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.3.0 (certbot(-auto); + "". (default: CertbotACMEClient/1.5.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, @@ -188,10 +188,12 @@ security: supported setups (Apache version >= 2.3.3 ). (default: False) --redirect Automatically redirect all HTTP traffic to HTTPS for - the newly authenticated vhost. (default: Ask) + the newly authenticated vhost. (default: redirect + enabled for install and run, disabled for enhance) --no-redirect Do not automatically redirect all HTTP traffic to HTTPS for the newly authenticated vhost. (default: - Ask) + redirect enabled for install and run, disabled for + enhance) --hsts Add the Strict-Transport-Security header to every HTTP response. Forcing browser to always use SSL for the domain. Defends against SSL Stripping. (default: None) @@ -213,8 +215,8 @@ testing: --test-cert, --staging Use the staging server to obtain or revoke test - (invalid) certificates; equivalent to --server https - ://acme-staging-v02.api.letsencrypt.org/directory + (invalid) certificates; equivalent to --server + https://acme-staging-v02.api.letsencrypt.org/directory (default: False) --debug Show tracebacks in case of errors, and allow certbot- auto execution on experimental platforms (default: @@ -319,8 +321,8 @@ renew: of renewed certificate domains (for example, "example.com www.example.com" (default: None) --disable-hook-validation - Ordinarily the commands specified for --pre-hook - /--post-hook/--deploy-hook will be checked for + Ordinarily the commands specified for --pre- + hook/--post-hook/--deploy-hook will be checked for validity, to see if the programs being run are in the $PATH, so that mistakes can be caught early, even when the hooks aren't being run just yet. The validation is @@ -669,7 +671,11 @@ manual: requested when performing an HTTP-01 challenge. An additional cleanup script can also be provided and can use the additional variable $CERTBOT_AUTH_OUTPUT which contains the stdout output from the auth - script. + script.For both authenticator and cleanup script, on HTTP-01 and DNS-01 + challenges,$CERTBOT_REMAINING_CHALLENGES will be equal to the number of + challenges that remain after the current one, and $CERTBOT_ALL_DOMAINS + contains a comma-separated list of all domains that are challenged for the + current certificate. --manual-auth-hook MANUAL_AUTH_HOOK Path or command to execute for the authentication diff --git a/certbot/local-oldest-requirements.txt b/certbot/local-oldest-requirements.txt index 0acc68652..bb4a4851f 100644 --- a/certbot/local-oldest-requirements.txt +++ b/certbot/local-oldest-requirements.txt @@ -1,2 +1,2 @@ # Remember to update setup.py to match the package versions below. --e acme[dev] +acme[dev]==1.4.0 diff --git a/certbot/setup.py b/certbot/setup.py index 143e1a10a..54dcea071 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -36,7 +36,7 @@ version = meta['version'] # specified here to avoid masking the more specific request requirements in # acme. See https://github.com/pypa/pip/issues/988 for more info. install_requires = [ - 'acme>=1.4.0.dev0', + 'acme>=1.4.0', # We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but # 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. diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index 1c2d2df0d..262fd02b5 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -1,6 +1,7 @@ """Tests for certbot.compat.filesystem""" import contextlib import errno +import stat import unittest try: @@ -150,6 +151,57 @@ class WindowsChmodTests(TempDirTestCase): self.assertEqual(security_dacl.GetSecurityDescriptorDacl().GetAceCount(), 2) +class UmaskTest(TempDirTestCase): + def test_umask_on_dir(self): + previous_umask = filesystem.umask(0o022) + + try: + dir1 = os.path.join(self.tempdir, 'probe1') + filesystem.mkdir(dir1) + self.assertTrue(filesystem.check_mode(dir1, 0o755)) + + filesystem.umask(0o077) + + dir2 = os.path.join(self.tempdir, 'dir2') + filesystem.mkdir(dir2) + self.assertTrue(filesystem.check_mode(dir2, 0o700)) + + dir3 = os.path.join(self.tempdir, 'dir3') + filesystem.mkdir(dir3, mode=0o777) + self.assertTrue(filesystem.check_mode(dir3, 0o700)) + finally: + filesystem.umask(previous_umask) + + def test_umask_on_file(self): + previous_umask = filesystem.umask(0o022) + + try: + file1 = os.path.join(self.tempdir, 'probe1') + UmaskTest._create_file(file1) + self.assertTrue(filesystem.check_mode(file1, 0o755)) + + filesystem.umask(0o077) + + file2 = os.path.join(self.tempdir, 'probe2') + UmaskTest._create_file(file2) + self.assertTrue(filesystem.check_mode(file2, 0o700)) + + file3 = os.path.join(self.tempdir, 'probe3') + UmaskTest._create_file(file3) + self.assertTrue(filesystem.check_mode(file3, 0o700)) + finally: + filesystem.umask(previous_umask) + + @staticmethod + def _create_file(path, mode=0o777): + file_desc = None + try: + file_desc = filesystem.open(path, flags=os.O_CREAT, mode=mode) + finally: + if file_desc: + os.close(file_desc) + + class ComputePrivateKeyModeTest(TempDirTestCase): def setUp(self): super(ComputePrivateKeyModeTest, self).setUp() @@ -280,14 +332,31 @@ class WindowsMkdirTests(test_util.TempDirTestCase): self.assertEqual(original_mkdir, std_os.mkdir) -class OwnershipTest(test_util.TempDirTestCase): - """Tests about copy_ownership_and_apply_mode and has_same_ownership""" +class MakedirsTests(test_util.TempDirTestCase): + """Unit tests for makedirs function in filesystem module""" + def test_makedirs_correct_permissions(self): + path = os.path.join(self.tempdir, 'dir') + subpath = os.path.join(path, 'subpath') + + previous_umask = filesystem.umask(0o022) + + try: + filesystem.makedirs(subpath, 0o700) + + assert filesystem.check_mode(path, 0o700) + assert filesystem.check_mode(subpath, 0o700) + finally: + filesystem.umask(previous_umask) + + +class CopyOwnershipAndModeTest(test_util.TempDirTestCase): + """Tests about copy_ownership_and_apply_mode, copy_ownership_and_mode and has_same_ownership""" def setUp(self): - super(OwnershipTest, self).setUp() + super(CopyOwnershipAndModeTest, self).setUp() self.probe_path = _create_probe(self.tempdir) @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') - def test_copy_ownership_windows(self): + def test_copy_ownership_and_apply_mode_windows(self): system = win32security.ConvertStringSidToSid(SYSTEM_SID) security = win32security.SECURITY_ATTRIBUTES().SECURITY_DESCRIPTOR security.SetSecurityDescriptorOwner(system, False) @@ -313,7 +382,7 @@ class OwnershipTest(test_util.TempDirTestCase): if dacl.GetAce(index)[2] == everybody]) @unittest.skipUnless(POSIX_MODE, reason='Test specific to Linux security') - def test_copy_ownership_linux(self): + def test_copy_ownership_and_apply_mode_linux(self): with mock.patch('os.chown') as mock_chown: with mock.patch('os.chmod') as mock_chmod: with mock.patch('os.stat') as mock_stat: @@ -334,6 +403,24 @@ class OwnershipTest(test_util.TempDirTestCase): self.assertTrue(filesystem.has_same_ownership(path1, path2)) + @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') + def test_copy_ownership_and_mode_windows(self): + src = self.probe_path + dst = _create_probe(self.tempdir, name='dst') + + filesystem.chmod(src, 0o700) + self.assertTrue(filesystem.check_mode(src, 0o700)) + self.assertTrue(filesystem.check_mode(dst, 0o744)) + + # Checking an actual change of owner is tricky during a unit test, since we do not know + # if any user exists beside the current one. So we mock _copy_win_ownership. It's behavior + # have been checked theoretically with test_copy_ownership_and_apply_mode_windows. + with mock.patch('certbot.compat.filesystem._copy_win_ownership') as mock_copy_owner: + filesystem.copy_ownership_and_mode(src, dst) + + mock_copy_owner.assert_called_once_with(src, dst) + self.assertTrue(filesystem.check_mode(dst, 0o700)) + class CheckPermissionsTest(test_util.TempDirTestCase): """Tests relative to functions that check modes.""" @@ -474,8 +561,8 @@ class IsExecutableTest(test_util.TempDirTestCase): from certbot.compat.filesystem import _generate_dacl - def _execute_mock(user_sid, mode): - dacl = _generate_dacl(user_sid, mode) + def _execute_mock(user_sid, mode, mask=None): + dacl = _generate_dacl(user_sid, mode, mask) for _ in range(1, dacl.GetAceCount()): dacl.DeleteAce(1) # DeleteAce dynamically updates the internal index mapping. return dacl @@ -537,9 +624,9 @@ def _set_owner(target, security_owner, user): target, win32security.OWNER_SECURITY_INFORMATION, security_owner) -def _create_probe(tempdir): +def _create_probe(tempdir, name='probe'): filesystem.chmod(tempdir, 0o744) - probe_path = os.path.join(tempdir, 'probe') + probe_path = os.path.join(tempdir, name) util.safe_open(probe_path, 'w', chmod=0o744).close() return probe_path diff --git a/certbot/tests/compat/misc_test.py b/certbot/tests/compat/misc_test.py new file mode 100644 index 000000000..642f395ba --- /dev/null +++ b/certbot/tests/compat/misc_test.py @@ -0,0 +1,48 @@ +"""Tests for certbot.compat.misc""" +try: + import mock +except ImportError: # pragma: no cover + from unittest import mock # type: ignore +import unittest + +from certbot.compat import os + + +class ExecuteTest(unittest.TestCase): + """Tests for certbot.compat.misc.execute_command.""" + + @classmethod + def _call(cls, *args, **kwargs): + from certbot.compat.misc import execute_command + return execute_command(*args, **kwargs) + + def test_it(self): + for returncode in range(0, 2): + for stdout in ("", "Hello World!",): + for stderr in ("", "Goodbye Cruel World!"): + self._test_common(returncode, stdout, stderr) + + def _test_common(self, returncode, stdout, stderr): + given_command = "foo" + given_name = "foo-hook" + with mock.patch("certbot.compat.misc.subprocess.Popen") as mock_popen: + mock_popen.return_value.communicate.return_value = (stdout, stderr) + mock_popen.return_value.returncode = returncode + with mock.patch("certbot.compat.misc.logger") as mock_logger: + self.assertEqual(self._call(given_name, given_command), (stderr, stdout)) + + executed_command = mock_popen.call_args[1].get( + "args", mock_popen.call_args[0][0]) + if os.name == 'nt': + expected_command = ['powershell.exe', '-Command', given_command] + else: + expected_command = given_command + self.assertEqual(executed_command, expected_command) + + mock_logger.info.assert_any_call("Running %s command: %s", + given_name, given_command) + if stdout: + mock_logger.info.assert_any_call(mock.ANY, mock.ANY, + mock.ANY, stdout) + if stderr or returncode: + self.assertTrue(mock_logger.error.called) diff --git a/certbot/tests/hook_test.py b/certbot/tests/hook_test.py index 32081f9d0..b8fd02461 100644 --- a/certbot/tests/hook_test.py +++ b/certbot/tests/hook_test.py @@ -72,13 +72,13 @@ class HookTest(test_util.ConfigTestCase): @classmethod def _call_with_mock_execute(cls, *args, **kwargs): - """Calls self._call after mocking out certbot._internal.hooks.execute. + """Calls self._call after mocking out certbot.compat.misc.execute_command. The mock execute object is returned rather than the return value of self._call. """ - with mock.patch("certbot._internal.hooks.execute") as mock_execute: + with mock.patch("certbot.compat.misc.execute_command") as mock_execute: mock_execute.return_value = ("", "") cls._call(*args, **kwargs) return mock_execute @@ -292,7 +292,7 @@ class RenewalHookTest(HookTest): # pylint: disable=abstract-method def _call_with_mock_execute(self, *args, **kwargs): - """Calls self._call after mocking out certbot._internal.hooks.execute. + """Calls self._call after mocking out certbot.compat.misc.execute_command. The mock execute object is returned rather than the return value of self._call. The mock execute object asserts that environment @@ -313,7 +313,7 @@ class RenewalHookTest(HookTest): self.assertEqual(os.environ["RENEWED_LINEAGE"], lineage) return ("", "") - with mock.patch("certbot._internal.hooks.execute") as mock_execute: + with mock.patch("certbot.compat.misc.execute_command") as mock_execute: mock_execute.side_effect = execute_side_effect self._call(*args, **kwargs) return mock_execute @@ -418,42 +418,6 @@ class RenewHookTest(RenewalHookTest): mock_execute.assert_called_with("deploy-hook", self.config.renew_hook) -class ExecuteTest(unittest.TestCase): - """Tests for certbot._internal.hooks.execute.""" - - @classmethod - def _call(cls, *args, **kwargs): - from certbot._internal.hooks import execute - return execute(*args, **kwargs) - - def test_it(self): - for returncode in range(0, 2): - for stdout in ("", "Hello World!",): - for stderr in ("", "Goodbye Cruel World!"): - self._test_common(returncode, stdout, stderr) - - def _test_common(self, returncode, stdout, stderr): - given_command = "foo" - given_name = "foo-hook" - with mock.patch("certbot._internal.hooks.Popen") as mock_popen: - mock_popen.return_value.communicate.return_value = (stdout, stderr) - mock_popen.return_value.returncode = returncode - with mock.patch("certbot._internal.hooks.logger") as mock_logger: - self.assertEqual(self._call(given_name, given_command), (stderr, stdout)) - - executed_command = mock_popen.call_args[1].get( - "args", mock_popen.call_args[0][0]) - self.assertEqual(executed_command, given_command) - - mock_logger.info.assert_any_call("Running %s command: %s", - given_name, given_command) - if stdout: - mock_logger.info.assert_any_call(mock.ANY, mock.ANY, - mock.ANY, stdout) - if stderr or returncode: - self.assertTrue(mock_logger.error.called) - - class ListHooksTest(test_util.TempDirTestCase): """Tests for certbot._internal.hooks.list_hooks.""" diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index af54844cf..fe89fff9f 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -182,13 +182,23 @@ class OSCPTestCryptography(unittest.TestCase): with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks: + # OCSP response with ResponseID as Name mocks['mock_response'].return_value.responder_name = issuer.subject + mocks['mock_response'].return_value.responder_key_hash = None self.checker.ocsp_revoked(self.cert_obj) + # OCSP response with ResponseID as KeyHash + key_hash = x509.SubjectKeyIdentifier.from_public_key(issuer.public_key()).digest + mocks['mock_response'].return_value.responder_name = None + mocks['mock_response'].return_value.responder_key_hash = key_hash + self.checker.ocsp_revoked(self.cert_obj) + # Here responder and issuer are the same. So only the signature of the OCSP # response is checked (using the issuer/responder public key). - self.assertEqual(mocks['mock_check'].call_count, 1) - self.assertEqual(mocks['mock_check'].call_args[0][0].public_numbers(), - issuer.public_key().public_numbers()) + self.assertEqual(mocks['mock_check'].call_count, 2) + self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(), + issuer.public_key().public_numbers()) + self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(), + issuer.public_key().public_numbers()) def test_responder_is_authorized_delegate(self): issuer = x509.load_pem_x509_certificate( @@ -198,15 +208,28 @@ class OSCPTestCryptography(unittest.TestCase): with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks: + # OCSP response with ResponseID as Name + mocks['mock_response'].return_value.responder_name = responder.subject + mocks['mock_response'].return_value.responder_key_hash = None self.checker.ocsp_revoked(self.cert_obj) + # OCSP response with ResponseID as KeyHash + key_hash = x509.SubjectKeyIdentifier.from_public_key(responder.public_key()).digest + mocks['mock_response'].return_value.responder_name = None + mocks['mock_response'].return_value.responder_key_hash = key_hash + self.checker.ocsp_revoked(self.cert_obj) + # Here responder and issuer are not the same. Two signatures will be checked then, # first to verify the responder cert (using the issuer public key), second to # to verify the OCSP response itself (using the responder public key). - self.assertEqual(mocks['mock_check'].call_count, 2) + self.assertEqual(mocks['mock_check'].call_count, 4) self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(), issuer.public_key().public_numbers()) self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(), responder.public_key().public_numbers()) + self.assertEqual(mocks['mock_check'].call_args_list[2][0][0].public_numbers(), + issuer.public_key().public_numbers()) + self.assertEqual(mocks['mock_check'].call_args_list[3][0][0].public_numbers(), + responder.public_key().public_numbers()) def test_revoke_resiliency(self): # Server return an invalid HTTP response diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index 1fc54b42e..83796cd4f 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -110,6 +110,14 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): self.assertRaises( errors.Error, self._call, self.config, renewalparams) + @mock.patch('certbot._internal.renewal.cli.set_by_cli') + def test_ancient_server_renewal_conf(self, mock_set_by_cli): + from certbot._internal import constants + self.config.server = None + mock_set_by_cli.return_value = False + self._call(self.config, {'server': constants.V1_URI}) + self.assertEqual(self.config.server, constants.CLI_DEFAULTS['server']) + if __name__ == "__main__": unittest.main() # pragma: no cover diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 5aa37824d..b67c4cbce 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -610,17 +610,25 @@ class RenewableCertTests(BaseRenewableCertTest): self.config.renewal_configs_dir, "the-lineage.com-0001.conf"))) self.assertTrue(os.path.exists(os.path.join( self.config.live_dir, "the-lineage.com-0001", "README"))) + # Allow write to existing but empty dir + filesystem.mkdir(os.path.join(self.config.default_archive_dir, "the-lineage.com-0002")) + result = storage.RenewableCert.new_lineage( + "the-lineage.com", b"cert3", b"privkey3", b"chain3", self.config) + self.assertTrue(os.path.exists(os.path.join( + self.config.live_dir, "the-lineage.com-0002", "README"))) + self.assertTrue(filesystem.check_mode(result.key_path, 0o600)) # Now trigger the detection of already existing files - filesystem.mkdir(os.path.join( - self.config.live_dir, "the-lineage.com-0002")) + shutil.copytree(os.path.join(self.config.live_dir, "the-lineage.com"), + os.path.join(self.config.live_dir, "the-lineage.com-0003")) self.assertRaises(errors.CertStorageError, storage.RenewableCert.new_lineage, "the-lineage.com", - b"cert3", b"privkey3", b"chain3", self.config) - filesystem.mkdir(os.path.join(self.config.default_archive_dir, "other-example.com")) + b"cert4", b"privkey4", b"chain4", self.config) + shutil.copytree(os.path.join(self.config.live_dir, "the-lineage.com"), + os.path.join(self.config.live_dir, "other-example.com")) self.assertRaises(errors.CertStorageError, storage.RenewableCert.new_lineage, - "other-example.com", b"cert4", - b"privkey4", b"chain4", self.config) + "other-example.com", b"cert5", + b"privkey5", b"chain5", self.config) # Make sure it can accept renewal parameters result = storage.RenewableCert.new_lineage( "the-lineage.com", b"cert2", b"privkey2", b"chain2", self.config) diff --git a/letsencrypt-auto b/letsencrypt-auto index 0ea3275c3..f99993b4f 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.3.0" +LE_AUTO_VERSION="1.5.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -910,20 +910,11 @@ elif [ -f /etc/manjaro-release ]; then } BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION" elif [ -f /etc/gentoo-release ]; then - Bootstrap() { - DeprecationBootstrap "Gentoo" BootstrapGentooCommon - } - BOOTSTRAP_VERSION="BootstrapGentooCommon $BOOTSTRAP_GENTOO_COMMON_VERSION" + DEPRECATED_OS=1 elif uname | grep -iq FreeBSD ; then - Bootstrap() { - DeprecationBootstrap "FreeBSD" BootstrapFreeBsd - } - BOOTSTRAP_VERSION="BootstrapFreeBsd $BOOTSTRAP_FREEBSD_VERSION" + DEPRECATED_OS=1 elif uname | grep -iq Darwin ; then - Bootstrap() { - DeprecationBootstrap "macOS" BootstrapMac - } - BOOTSTRAP_VERSION="BootstrapMac $BOOTSTRAP_MAC_VERSION" + DEPRECATED_OS=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then Bootstrap() { ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon @@ -1343,7 +1334,9 @@ cryptography==2.8 \ distro==1.4.0 \ --hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \ --hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4 -enum34==1.1.6 \ +# Package enum34 needs to be explicitly limited to Python2.x, in order to avoid +# certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456. +enum34==1.1.6 ; python_version < '3.4' \ --hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \ --hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \ --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \ @@ -1540,18 +1533,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.3.0 \ - --hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \ - --hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8 -acme==1.3.0 \ - --hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \ - --hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d -certbot-apache==1.3.0 \ - --hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \ - --hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52 -certbot-nginx==1.3.0 \ - --hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \ - --hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b +certbot==1.5.0 \ + --hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \ + --hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf +acme==1.5.0 \ + --hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \ + --hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0 +certbot-apache==1.5.0 \ + --hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \ + --hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764 +certbot-nginx==1.5.0 \ + --hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \ + --hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index 84473dc30..9d1253b9d 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl5ewVUACgkQTRfJlc2X -dfJnZAf+KmxYl1YoP/FlTG5Npb64qaDdxm59SeEVJez6fZh15xq71tRPYR+4xszE -XTeyGt7uAxjYqeiBJU5xBvGC1Veprhj5AbflVOTP+5yiBr9iNWC35zmgaE63UlZ/ -V94sfL0pkax7wLngil7a0OuzUjikzK3gXOqrY8LoUdr4mAA9AhSjajWHmyY3tpDR -84GKrVhybIt0sjy/172VuPPbXZKno/clztkKMZHXNrDeL5jgJ15Va4Ts5FK0j9VT -HQvuazbGkYVCuvlp8Np5ESDje69LCJfPZxl34htoa8WNJoVIOsQWZpoXp5B5huSP -vGrh4LabZ5UDsl+k11ikHBRUpO7E5w== -=IgRH +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl7WjTUACgkQTRfJlc2X +dfI9pQf/bqfbpHAkO6iRd/LcnEXujICG4CIfJxZUlhh7HoMnmtFmWLp9k3pN6iRZ +LKpl8gbKTek6yGnYuNQjp2/C87WyY9w06niCkg/D2W14ii/MuHGA99OVhc0M99dv +ZG5Vh6Qu3WAXP4sHADmMHjM8CKsG//SrFfE2ZQ6kCg20l3h4MaaKaN85JwNO0RpO +OKOj1LF29OlZ2G8HKGi0VmeO/++Z8QSDwKAYdimS3B/5DTGUciR/7BgR8a90goPl +BOhDR00MHdRuBRuAj3siZUVTxNT3xLgxaa6QYZf6by/Bb6+A02VzW0oF6XYJPdEK +TtSiQzKrmaoOkXz/4WF99W9HAxYpyw== +=WVyF -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index c43e6d6d8..f69a1fe37 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.4.0.dev0" +LE_AUTO_VERSION="1.6.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1265,45 +1265,40 @@ if [ "$1" = "--le-auto-phase2" ]; then # pip install hashin # hashin -r dependency-requirements.txt cryptography==1.5.2 # ``` -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 \ - --hash=sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5 \ - --hash=sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54 \ - --hash=sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba \ - --hash=sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57 \ - --hash=sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396 \ - --hash=sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12 \ - --hash=sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97 \ - --hash=sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43 \ - --hash=sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db \ - --hash=sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3 \ - --hash=sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b \ - --hash=sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579 \ - --hash=sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346 \ - --hash=sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159 \ - --hash=sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652 \ - --hash=sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e \ - --hash=sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a \ - --hash=sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506 \ - --hash=sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f \ - --hash=sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d \ - --hash=sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c \ - --hash=sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20 \ - --hash=sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858 \ - --hash=sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc \ - --hash=sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a \ - --hash=sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3 \ - --hash=sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e \ - --hash=sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410 \ - --hash=sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25 \ - --hash=sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b \ - --hash=sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d +ConfigArgParse==1.2.3 \ + --hash=sha256:edd17be986d5c1ba2e307150b8e5f5107aba125f3574dddd02c85d5cdcfd37dc +certifi==2020.4.5.1 \ + --hash=sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304 \ + --hash=sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519 +cffi==1.14.0 \ + --hash=sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff \ + --hash=sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b \ + --hash=sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac \ + --hash=sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0 \ + --hash=sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384 \ + --hash=sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26 \ + --hash=sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6 \ + --hash=sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b \ + --hash=sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e \ + --hash=sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd \ + --hash=sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2 \ + --hash=sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66 \ + --hash=sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc \ + --hash=sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8 \ + --hash=sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55 \ + --hash=sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4 \ + --hash=sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5 \ + --hash=sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d \ + --hash=sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78 \ + --hash=sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa \ + --hash=sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793 \ + --hash=sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f \ + --hash=sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a \ + --hash=sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f \ + --hash=sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30 \ + --hash=sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f \ + --hash=sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3 \ + --hash=sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c chardet==3.0.4 \ --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 @@ -1331,65 +1326,66 @@ cryptography==2.8 \ --hash=sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2 \ --hash=sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf \ --hash=sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8 -distro==1.4.0 \ - --hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \ - --hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4 -enum34==1.1.6 \ - --hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \ - --hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \ - --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \ - --hash=sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1 +distro==1.5.0 \ + --hash=sha256:0e58756ae38fbd8fc3020d54badb8eae17c5b9dcbed388b17bb55b8a5928df92 \ + --hash=sha256:df74eed763e18d10d0da624258524ae80486432cd17392d9c3d96f5e83cd2799 +enum34==1.1.10; python_version < '3.4' \ + --hash=sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53 \ + --hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \ + --hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 funcsigs==1.0.2 \ --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \ --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50 -idna==2.8 \ - --hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \ - --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c +idna==2.9 \ + --hash=sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb \ + --hash=sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa ipaddress==1.0.23 \ --hash=sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc \ --hash=sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2 -josepy==1.2.0 \ - --hash=sha256:8ea15573203f28653c00f4ac0142520777b1c59d9eddd8da3f256c6ba3cac916 \ - --hash=sha256:9cec9a839fe9520f0420e4f38e7219525daccce4813296627436fe444cd002d3 +josepy==1.3.0 \ + --hash=sha256:c341ffa403399b18e9eae9012f804843045764d1390f9cb4648980a7569b1619 \ + --hash=sha256:e54882c64be12a2a76533f73d33cba9e331950fda9e2731e843490b774e7a01c mock==1.3.0 \ --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6 \ --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb parsedatetime==2.5 \ --hash=sha256:3b835fc54e472c17ef447be37458b400e3fefdf14bb1ffdedb5d2c853acf4ba1 \ --hash=sha256:d2e9ddb1e463de871d32088a3f3cea3dc8282b1b2800e081bd0ef86900451667 -pbr==5.4.4 \ - --hash=sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b \ - --hash=sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488 +pbr==5.4.5 \ + --hash=sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c \ + --hash=sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8 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.6 \ - --hash=sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f \ - --hash=sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec +pycparser==2.20 \ + --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \ + --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 +pyparsing==2.4.7 \ + --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ + --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b python-augeas==0.5.0 \ --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 -pytz==2019.3 \ - --hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \ - --hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be -requests==2.22.0 \ - --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 \ - --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 +pytz==2020.1 \ + --hash=sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed \ + --hash=sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048 +requests==2.23.0 \ + --hash=sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee \ + --hash=sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6 requests-toolbelt==0.9.1 \ --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f \ --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 -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 +six==1.15.0 \ + --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ + --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced +urllib3==1.25.9 \ + --hash=sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527 \ + --hash=sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115 +zope.component==4.6.1 \ + --hash=sha256:bfbe55d4a93e70a78b10edc3aad4de31bb8860919b7cbd8d66f717f7d7b279ac \ + --hash=sha256:d9c7c27673d787faff8a83797ce34d6ebcae26a370e25bddb465ac2182766aca zope.deferredimport==4.3.1 \ --hash=sha256:57b2345e7b5eef47efcd4f634ff16c93e4265de3dcf325afc7315ade48d909e1 \ --hash=sha256:9a0c211df44aa95f1c4e6d2626f90b400f56989180d3ef96032d708da3d23e0a @@ -1399,126 +1395,129 @@ zope.deprecation==4.4.0 \ zope.event==4.4 \ --hash=sha256:69c27debad9bdacd9ce9b735dad382142281ac770c4a432b533d6d65c4614bcf \ --hash=sha256:d8e97d165fd5a0997b45f5303ae11ea3338becfe68c401dd88ffd2113fe5cae7 -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 \ - --hash=sha256:1ef452cc02e0e2f8e3c917b1a5b936ef3280f2c2ca854ee70ac2164d1655f7e6 \ - --hash=sha256:22bf61857c5977f34d4e391476d40f9a3b8c6ab24fb0cac448d42d8f8b9bf7b2 \ - --hash=sha256:299870e3428cbff1cd9f9b34144e76ecdc1d9e3192a8cf5f1b0258f47a239f58 \ - --hash=sha256:2bfc36bfccbe047671170ea5677efd3d5ab730a55d7e45611d76d495e5b96766 \ - --hash=sha256:32e82d5a640febc688c0789e15ea875bf696a10cf358f049e1ed841f01710a9b \ - --hash=sha256:3b2051bdc4bc3f02fa52483f6381cf40d4d48167645241993f9d7ebbd142ed9b \ - --hash=sha256:3f734bd8a08f5185a64fb6abb8f14dc97ec27a689ca808fb7a83cdd38d745e4f \ - --hash=sha256:3f78dd8de3112df8bbd970f0916ac876dc3fbe63810bd1cf7cc5eec4cbac4f04 \ - --hash=sha256:4eabeb48508953ba1f3590ad0773b8daea9e104eec66d661917e9bbcd7125a67 \ - --hash=sha256:4f05ecc33808187f430f249cb1ccab35c38f570b181f2d380fbe253da94b18d8 \ - --hash=sha256:4f4f4cbf23d3afc1526294a31e7b3eaa0f682cc28ac5366065dc1d6bb18bd7be \ - --hash=sha256:5483d5e70aacd06f0aa3effec9fed597c0b50f45060956eeeb1203c44d4338c3 \ - --hash=sha256:56a5f9b46892b115a75d0a1f2292431ad5988461175826600acc69a24cb3edee \ - --hash=sha256:64bb63af8a06f736927d260efdd4dfc5253d42244f281a8063e4b9eea2ddcbc5 \ - --hash=sha256:653f8cbefcf7c6ac4cece2cdef367c4faa2b7c19795d52bd7cbec11a8739a7c1 \ - --hash=sha256:664211d63306e4bd4eec35bf2b4bd9db61c394037911cf2d1804c43b511a49f1 \ - --hash=sha256:6651e6caed66a8fff0fef1a3e81c0ed2253bf361c0fdc834500488732c5d16e9 \ - --hash=sha256:6c1fba6cdfdf105739d3069cf7b07664f2944d82a8098218ab2300a82d8f40fc \ - --hash=sha256:6e64246e6e9044a4534a69dca1283c6ddab6e757be5e6874f69024329b3aa61f \ - --hash=sha256:838390245c7ec137af4993c0c8052f49d5ec79e422b4451bfa37fee9b9ccaa01 \ - --hash=sha256:856b410a14793069d8ba35f33fff667213ea66f2df25a0024cc72a7493c56d4c \ - --hash=sha256:8b932c364c1d1605a91907a41128ed0ee8a2d326fc0fafb2c55cd46f545f4599 \ - --hash=sha256:9086cf6d20f08dae7f296a78f6c77d1f8d24079d448f023ee0eb329078dd35e1 \ - --hash=sha256:9698533c14afa0548188de4968a7932d1f3f965f3f5ba1474de673596bb875af \ - --hash=sha256:9b12b05dd7c28f5068387c1afee8cb94f9d02501e7ef495a7c5c7e27139b96ad \ - --hash=sha256:a884c7426a5bc6fb7fc71a55ad14e66818e13f05b78b20a6f37175f324b7acb8 \ - --hash=sha256:abe9e7f1a3e76286c5f5baf2bf5162d41dc0310da493b34a2c36555f38d928f7 \ - --hash=sha256:bd6fde63b015a27262be06bd6bbdd895273cc2bdf2d4c7e1c83711d26a8fbace \ - --hash=sha256:bda7c62c954f47b87ed9a89f525eee1b318ec7c2162dfdba76c2ccfa334e0caa \ - --hash=sha256:be8a4908dd3f6e965993c0068b006bdbd0474fbcbd1da4893b49356e73fc1557 \ - --hash=sha256:ced65fc3c7d7205267506d854bb1815bb445899cca9d21d1d4b949070a635546 \ - --hash=sha256:dac4279aa05055d3897ab5e5ee5a7b39db121f91df65a530f8b1ac7f9bd93119 \ - --hash=sha256:e4f1863056e3e4f399c285b67fa816f411a7bfa1c81ef50e186126164e396e59 \ - --hash=sha256:ecd85f68b8cd9ab78a0141e87ea9a53b2f31fd9b1350a1c44da1f7481b5363ef \ - --hash=sha256:ed269b83750413e8fc5c96276372f49ee3fcb7ed61c49fe8e5a67f54459a5a4a \ - --hash=sha256:f19b0b80cba73b204dee68501870b11067711d21d243fb6774256d3ca2e5391f \ - --hash=sha256:ffdafb98db7574f9da84c489a10a5d582079a888cb43c64e9e6b0e3fe1034685 +zope.hookable==5.0.1 \ + --hash=sha256:0194b9b9e7f614abba60c90b231908861036578297515d3d6508eb10190f266d \ + --hash=sha256:0c2977473918bdefc6fa8dfb311f154e7f13c6133957fe649704deca79b92093 \ + --hash=sha256:17b8bdb3b77e03a152ca0d5ca185a7ae0156f5e5a2dbddf538676633a1f7380f \ + --hash=sha256:29d07681a78042cdd15b268ae9decffed9ace68a53eebeb61d65ae931d158841 \ + --hash=sha256:36fb1b35d1150267cb0543a1ddd950c0bc2c75ed0e6e92e3aaa6ac2e29416cb7 \ + --hash=sha256:3aed60c2bb5e812bbf9295c70f25b17ac37c233f30447a96c67913ba5073642f \ + --hash=sha256:3cac1565cc768911e72ca9ec4ddf5c5109e1fef0104f19f06649cf1874943b60 \ + --hash=sha256:3d4bc0cc4a37c3cd3081063142eeb2125511db3c13f6dc932d899c512690378e \ + --hash=sha256:3f73096f27b8c28be53ffb6604f7b570fbbb82f273c6febe5f58119009b59898 \ + --hash=sha256:522d1153d93f2d48aa0bd9fb778d8d4500be2e4dcf86c3150768f0e3adbbc4ef \ + --hash=sha256:523d2928fb7377bbdbc9af9c0b14ad73e6eaf226349f105733bdae27efd15b5a \ + --hash=sha256:5848309d4fc5c02150a45e8f8d2227e5bfda386a508bbd3160fed7c633c5a2fa \ + --hash=sha256:6781f86e6d54a110980a76e761eb54590630fd2af2a17d7edf02a079d2646c1d \ + --hash=sha256:6fd27921ebf3aaa945fa25d790f1f2046204f24dba4946f82f5f0a442577c3e9 \ + --hash=sha256:70d581862863f6bf9e175e85c9d70c2d7155f53fb04dcdb2f73cf288ca559a53 \ + --hash=sha256:81867c23b0dc66c8366f351d00923f2bc5902820a24c2534dfd7bf01a5879963 \ + --hash=sha256:81db29edadcbb740cd2716c95a297893a546ed89db1bfe9110168732d7f0afdd \ + --hash=sha256:86bd12624068cea60860a0759af5e2c3adc89c12aef6f71cf12f577e28deefe3 \ + --hash=sha256:9c184d8f9f7a76e1ced99855ccf390ffdd0ec3765e5cbf7b9cada600accc0a1e \ + --hash=sha256:acc789e8c29c13555e43fe4bf9fcd15a65512c9645e97bbaa5602e3201252b02 \ + --hash=sha256:afaa740206b7660d4cc3b8f120426c85761f51379af7a5b05451f624ad12b0af \ + --hash=sha256:b5f5fa323f878bb16eae68ea1ba7f6c0419d4695d0248bed4b18f51d7ce5ab85 \ + --hash=sha256:bd89e0e2c67bf4ac3aca2a19702b1a37269fb1923827f68324ac2e7afd6e3406 \ + --hash=sha256:c212de743283ec0735db24ec6ad913758df3af1b7217550ff270038062afd6ae \ + --hash=sha256:ca553f524293a0bdea05e7f44c3e685e4b7b022cb37d87bc4a3efa0f86587a8d \ + --hash=sha256:cab67065a3db92f636128d3157cc5424a145f82d96fb47159c539132833a6d36 \ + --hash=sha256:d3b3b3eedfdbf6b02898216e85aa6baf50207f4378a2a6803d6d47650cd37031 \ + --hash=sha256:d9f4a5a72f40256b686d31c5c0b1fde503172307beb12c1568296e76118e402c \ + --hash=sha256:df5067d87aaa111ed5d050e1ee853ba284969497f91806efd42425f5348f1c06 \ + --hash=sha256:e2587644812c6138f05b8a41594a8337c6790e3baf9a01915e52438c13fc6bef \ + --hash=sha256:e27fd877662db94f897f3fd532ef211ca4901eb1a70ba456f15c0866a985464a \ + --hash=sha256:e427ebbdd223c72e06ba94c004bb04e996c84dec8a0fa84e837556ae145c439e \ + --hash=sha256:e583ad4309c203ef75a09d43434cf9c2b4fa247997ecb0dcad769982c39411c7 \ + --hash=sha256:e760b2bc8ece9200804f0c2b64d10147ecaf18455a2a90827fbec4c9d84f3ad5 \ + --hash=sha256:ea9a9cc8bcc70e18023f30fa2f53d11ae069572a162791224e60cd65df55fb69 \ + --hash=sha256:ecb3f17dce4803c1099bd21742cd126b59817a4e76a6544d31d2cca6e30dbffd \ + --hash=sha256:ed794e3b3de42486d30444fb60b5561e724ee8a2d1b17b0c2e0f81e3ddaf7a87 \ + --hash=sha256:ee885d347279e38226d0a437b6a932f207f691c502ee565aba27a7022f1285df \ + --hash=sha256:fd5e7bc5f24f7e3d490698f7b854659a9851da2187414617cd5ed360af7efd63 \ + --hash=sha256:fe45f6870f7588ac7b2763ff1ce98cce59369717afe70cc353ec5218bc854bcc +zope.interface==5.1.0 \ + --hash=sha256:0103cba5ed09f27d2e3de7e48bb320338592e2fabc5ce1432cf33808eb2dfd8b \ + --hash=sha256:14415d6979356629f1c386c8c4249b4d0082f2ea7f75871ebad2e29584bd16c5 \ + --hash=sha256:1ae4693ccee94c6e0c88a4568fb3b34af8871c60f5ba30cf9f94977ed0e53ddd \ + --hash=sha256:1b87ed2dc05cb835138f6a6e3595593fea3564d712cb2eb2de963a41fd35758c \ + --hash=sha256:269b27f60bcf45438e8683269f8ecd1235fa13e5411de93dae3b9ee4fe7f7bc7 \ + --hash=sha256:27d287e61639d692563d9dab76bafe071fbeb26818dd6a32a0022f3f7ca884b5 \ + --hash=sha256:39106649c3082972106f930766ae23d1464a73b7d30b3698c986f74bf1256a34 \ + --hash=sha256:40e4c42bd27ed3c11b2c983fecfb03356fae1209de10686d03c02c8696a1d90e \ + --hash=sha256:461d4339b3b8f3335d7e2c90ce335eb275488c587b61aca4b305196dde2ff086 \ + --hash=sha256:4f98f70328bc788c86a6a1a8a14b0ea979f81ae6015dd6c72978f1feff70ecda \ + --hash=sha256:558a20a0845d1a5dc6ff87cd0f63d7dac982d7c3be05d2ffb6322a87c17fa286 \ + --hash=sha256:562dccd37acec149458c1791da459f130c6cf8902c94c93b8d47c6337b9fb826 \ + --hash=sha256:5e86c66a6dea8ab6152e83b0facc856dc4d435fe0f872f01d66ce0a2131b7f1d \ + --hash=sha256:60a207efcd8c11d6bbeb7862e33418fba4e4ad79846d88d160d7231fcb42a5ee \ + --hash=sha256:645a7092b77fdbc3f68d3cc98f9d3e71510e419f54019d6e282328c0dd140dcd \ + --hash=sha256:6874367586c020705a44eecdad5d6b587c64b892e34305bb6ed87c9bbe22a5e9 \ + --hash=sha256:74bf0a4f9091131de09286f9a605db449840e313753949fe07c8d0fe7659ad1e \ + --hash=sha256:7b726194f938791a6691c7592c8b9e805fc6d1b9632a833b9c0640828cd49cbc \ + --hash=sha256:8149ded7f90154fdc1a40e0c8975df58041a6f693b8f7edcd9348484e9dc17fe \ + --hash=sha256:8cccf7057c7d19064a9e27660f5aec4e5c4001ffcf653a47531bde19b5aa2a8a \ + --hash=sha256:911714b08b63d155f9c948da2b5534b223a1a4fc50bb67139ab68b277c938578 \ + --hash=sha256:a5f8f85986197d1dd6444763c4a15c991bfed86d835a1f6f7d476f7198d5f56a \ + --hash=sha256:a744132d0abaa854d1aad50ba9bc64e79c6f835b3e92521db4235a1991176813 \ + --hash=sha256:af2c14efc0bb0e91af63d00080ccc067866fb8cbbaca2b0438ab4105f5e0f08d \ + --hash=sha256:b054eb0a8aa712c8e9030065a59b5e6a5cf0746ecdb5f087cca5ec7685690c19 \ + --hash=sha256:b0becb75418f8a130e9d465e718316cd17c7a8acce6fe8fe07adc72762bee425 \ + --hash=sha256:b1d2ed1cbda2ae107283befd9284e650d840f8f7568cb9060b5466d25dc48975 \ + --hash=sha256:ba4261c8ad00b49d48bbb3b5af388bb7576edfc0ca50a49c11dcb77caa1d897e \ + --hash=sha256:d1fe9d7d09bb07228650903d6a9dc48ea649e3b8c69b1d263419cc722b3938e8 \ + --hash=sha256:d7804f6a71fc2dda888ef2de266727ec2f3915373d5a785ed4ddc603bbc91e08 \ + --hash=sha256:da2844fba024dd58eaa712561da47dcd1e7ad544a257482392472eae1c86d5e5 \ + --hash=sha256:dcefc97d1daf8d55199420e9162ab584ed0893a109f45e438b9794ced44c9fd0 \ + --hash=sha256:dd98c436a1fc56f48c70882cc243df89ad036210d871c7427dc164b31500dc11 \ + --hash=sha256:e74671e43ed4569fbd7989e5eecc7d06dc134b571872ab1d5a88f4a123814e9f \ + --hash=sha256:eb9b92f456ff3ec746cd4935b73c1117538d6124b8617bc0fe6fda0b3816e345 \ + --hash=sha256:ebb4e637a1fb861c34e48a00d03cffa9234f42bef923aec44e5625ffb9a8e8f9 \ + --hash=sha256:ef739fe89e7f43fb6494a43b1878a36273e5924869ba1d866f752c5812ae8d58 \ + --hash=sha256:f40db0e02a8157d2b90857c24d89b6310f9b6c3642369852cdc3b5ac49b92afc \ + --hash=sha256:f68bf937f113b88c866d090fea0bc52a098695173fc613b055a17ff0cf9683b6 \ + --hash=sha256:fb55c182a3f7b84c1a2d6de5fa7b1a05d4660d866b91dbf8d74549c57a1499e8 +zope.proxy==4.3.5 \ + --hash=sha256:00573dfa755d0703ab84bb23cb6ecf97bb683c34b340d4df76651f97b0bab068 \ + --hash=sha256:092049280f2848d2ba1b57b71fe04881762a220a97b65288bcb0968bb199ec30 \ + --hash=sha256:0cbd27b4d3718b5ec74fc65ffa53c78d34c65c6fd9411b8352d2a4f855220cf1 \ + --hash=sha256:17fc7e16d0c81f833a138818a30f366696653d521febc8e892858041c4d88785 \ + --hash=sha256:19577dfeb70e8a67249ba92c8ad20589a1a2d86a8d693647fa8385408a4c17b0 \ + --hash=sha256:207aa914576b1181597a1516e1b90599dc690c095343ae281b0772e44945e6a4 \ + --hash=sha256:219a7db5ed53e523eb4a4769f13105118b6d5b04ed169a283c9775af221e231f \ + --hash=sha256:2b50ea79849e46b5f4f2b0247a3687505d32d161eeb16a75f6f7e6cd81936e43 \ + --hash=sha256:5903d38362b6c716e66bbe470f190579c530a5baf03dbc8500e5c2357aa569a5 \ + --hash=sha256:5c24903675e271bd688c6e9e7df5775ac6b168feb87dbe0e4bcc90805f21b28f \ + --hash=sha256:5ef6bc5ed98139e084f4e91100f2b098a0cd3493d4e76f9d6b3f7b95d7ad0f06 \ + --hash=sha256:61b55ae3c23a126a788b33ffb18f37d6668e79a05e756588d9e4d4be7246ab1c \ + --hash=sha256:63ddb992931a5e616c87d3d89f5a58db086e617548005c7f9059fac68c03a5cc \ + --hash=sha256:6943da9c09870490dcfd50c4909c0cc19f434fa6948f61282dc9cb07bcf08160 \ + --hash=sha256:6ad40f85c1207803d581d5d75e9ea25327cd524925699a83dfc03bf8e4ba72b7 \ + --hash=sha256:6b44433a79bdd7af0e3337bd7bbcf53dd1f9b0fa66bf21bcb756060ce32a96c1 \ + --hash=sha256:6bbaa245015d933a4172395baad7874373f162955d73612f0b66b6c2c33b6366 \ + --hash=sha256:7007227f4ea85b40a2f5e5a244479f6a6dfcf906db9b55e812a814a8f0e2c28d \ + --hash=sha256:74884a0aec1f1609190ec8b34b5d58fb3b5353cf22b96161e13e0e835f13518f \ + --hash=sha256:7d25fe5571ddb16369054f54cdd883f23de9941476d97f2b92eb6d7d83afe22d \ + --hash=sha256:7e162bdc5e3baad26b2262240be7d2bab36991d85a6a556e48b9dfb402370261 \ + --hash=sha256:814d62678dc3a30f4aa081982d830b7c342cf230ffc9d030b020cb154eeebf9e \ + --hash=sha256:8878a34c5313ee52e20aa50b03138af8d472bae465710fb954d133a9bfd3c38d \ + --hash=sha256:a66a0d94e5b081d5d695e66d6667e91e74d79e273eee95c1747717ba9cb70792 \ + --hash=sha256:a69f5cbf4addcfdf03dda564a671040127a6b7c34cf9fe4973582e68441b63fa \ + --hash=sha256:b00f9f0c334d07709d3f73a7cb8ae63c6ca1a90c790a63b5e7effa666ef96021 \ + --hash=sha256:b6ed71e4a7b4690447b626f499d978aa13197a0e592950e5d7020308f6054698 \ + --hash=sha256:bdf5041e5851526e885af579d2f455348dba68d74f14a32781933569a327fddf \ + --hash=sha256:be034360dd34e62608419f86e799c97d389c10a0e677a25f236a971b2f40dac9 \ + --hash=sha256:cc8f590a5eed30b314ae6b0232d925519ade433f663de79cc3783e4b10d662ba \ + --hash=sha256:cd7a318a15fe6cc4584bf3c4426f092ed08c0fd012cf2a9173114234fe193e11 \ + --hash=sha256:cf19b5f63a59c20306e034e691402b02055c8f4e38bf6792c23cad489162a642 \ + --hash=sha256:cfc781ce442ec407c841e9aa51d0e1024f72b6ec34caa8fdb6ef9576d549acf2 \ + --hash=sha256:dea9f6f8633571e18bc20cad83603072e697103a567f4b0738d52dd0211b4527 \ + --hash=sha256:e4a86a1d5eb2cce83c5972b3930c7c1eac81ab3508464345e2b8e54f119d5505 \ + --hash=sha256:e7106374d4a74ed9ff00c46cc00f0a9f06a0775f8868e423f85d4464d2333679 \ + --hash=sha256:e98a8a585b5668aa9e34d10f7785abf9545fe72663b4bfc16c99a115185ae6a5 \ + --hash=sha256:f64840e68483316eb58d82c376ad3585ca995e69e33b230436de0cdddf7363f9 \ + --hash=sha256:f8f4b0a9e6683e43889852130595c8854d8ae237f2324a053cdd884de936aa9b \ + --hash=sha256:fc45a53219ed30a7f670a6d8c98527af0020e6fd4ee4c0a8fb59f147f06d816c # Contains the requirements for the letsencrypt package. # @@ -1531,18 +1530,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.3.0 \ - --hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \ - --hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8 -acme==1.3.0 \ - --hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \ - --hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d -certbot-apache==1.3.0 \ - --hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \ - --hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52 -certbot-nginx==1.3.0 \ - --hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \ - --hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b +certbot==1.5.0 \ + --hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \ + --hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf +acme==1.5.0 \ + --hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \ + --hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0 +certbot-apache==1.5.0 \ + --hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \ + --hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764 +certbot-nginx==1.5.0 \ + --hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \ + --hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index 8c4f52d6e..23bd795ab 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/pieces/certbot-requirements.txt b/letsencrypt-auto-source/pieces/certbot-requirements.txt index a8e275a45..4e647413f 100644 --- a/letsencrypt-auto-source/pieces/certbot-requirements.txt +++ b/letsencrypt-auto-source/pieces/certbot-requirements.txt @@ -1,12 +1,12 @@ -certbot==1.3.0 \ - --hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \ - --hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8 -acme==1.3.0 \ - --hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \ - --hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d -certbot-apache==1.3.0 \ - --hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \ - --hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52 -certbot-nginx==1.3.0 \ - --hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \ - --hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b +certbot==1.5.0 \ + --hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \ + --hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf +acme==1.5.0 \ + --hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \ + --hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0 +certbot-apache==1.5.0 \ + --hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \ + --hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764 +certbot-nginx==1.5.0 \ + --hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \ + --hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983 diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index eec5a9946..f7a517e06 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -9,45 +9,40 @@ # pip install hashin # hashin -r dependency-requirements.txt cryptography==1.5.2 # ``` -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 \ - --hash=sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5 \ - --hash=sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54 \ - --hash=sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba \ - --hash=sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57 \ - --hash=sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396 \ - --hash=sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12 \ - --hash=sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97 \ - --hash=sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43 \ - --hash=sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db \ - --hash=sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3 \ - --hash=sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b \ - --hash=sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579 \ - --hash=sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346 \ - --hash=sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159 \ - --hash=sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652 \ - --hash=sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e \ - --hash=sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a \ - --hash=sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506 \ - --hash=sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f \ - --hash=sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d \ - --hash=sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c \ - --hash=sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20 \ - --hash=sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858 \ - --hash=sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc \ - --hash=sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a \ - --hash=sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3 \ - --hash=sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e \ - --hash=sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410 \ - --hash=sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25 \ - --hash=sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b \ - --hash=sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d +ConfigArgParse==1.2.3 \ + --hash=sha256:edd17be986d5c1ba2e307150b8e5f5107aba125f3574dddd02c85d5cdcfd37dc +certifi==2020.4.5.1 \ + --hash=sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304 \ + --hash=sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519 +cffi==1.14.0 \ + --hash=sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff \ + --hash=sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b \ + --hash=sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac \ + --hash=sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0 \ + --hash=sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384 \ + --hash=sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26 \ + --hash=sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6 \ + --hash=sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b \ + --hash=sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e \ + --hash=sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd \ + --hash=sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2 \ + --hash=sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66 \ + --hash=sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc \ + --hash=sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8 \ + --hash=sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55 \ + --hash=sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4 \ + --hash=sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5 \ + --hash=sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d \ + --hash=sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78 \ + --hash=sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa \ + --hash=sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793 \ + --hash=sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f \ + --hash=sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a \ + --hash=sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f \ + --hash=sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30 \ + --hash=sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f \ + --hash=sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3 \ + --hash=sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c chardet==3.0.4 \ --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 @@ -75,65 +70,66 @@ cryptography==2.8 \ --hash=sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2 \ --hash=sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf \ --hash=sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8 -distro==1.4.0 \ - --hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \ - --hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4 -enum34==1.1.6 \ - --hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \ - --hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \ - --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \ - --hash=sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1 +distro==1.5.0 \ + --hash=sha256:0e58756ae38fbd8fc3020d54badb8eae17c5b9dcbed388b17bb55b8a5928df92 \ + --hash=sha256:df74eed763e18d10d0da624258524ae80486432cd17392d9c3d96f5e83cd2799 +enum34==1.1.10; python_version < '3.4' \ + --hash=sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53 \ + --hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \ + --hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 funcsigs==1.0.2 \ --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \ --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50 -idna==2.8 \ - --hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \ - --hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c +idna==2.9 \ + --hash=sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb \ + --hash=sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa ipaddress==1.0.23 \ --hash=sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc \ --hash=sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2 -josepy==1.2.0 \ - --hash=sha256:8ea15573203f28653c00f4ac0142520777b1c59d9eddd8da3f256c6ba3cac916 \ - --hash=sha256:9cec9a839fe9520f0420e4f38e7219525daccce4813296627436fe444cd002d3 +josepy==1.3.0 \ + --hash=sha256:c341ffa403399b18e9eae9012f804843045764d1390f9cb4648980a7569b1619 \ + --hash=sha256:e54882c64be12a2a76533f73d33cba9e331950fda9e2731e843490b774e7a01c mock==1.3.0 \ --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6 \ --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb parsedatetime==2.5 \ --hash=sha256:3b835fc54e472c17ef447be37458b400e3fefdf14bb1ffdedb5d2c853acf4ba1 \ --hash=sha256:d2e9ddb1e463de871d32088a3f3cea3dc8282b1b2800e081bd0ef86900451667 -pbr==5.4.4 \ - --hash=sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b \ - --hash=sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488 +pbr==5.4.5 \ + --hash=sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c \ + --hash=sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8 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.6 \ - --hash=sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f \ - --hash=sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec +pycparser==2.20 \ + --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \ + --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 +pyparsing==2.4.7 \ + --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ + --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b python-augeas==0.5.0 \ --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 -pytz==2019.3 \ - --hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \ - --hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be -requests==2.22.0 \ - --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 \ - --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 +pytz==2020.1 \ + --hash=sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed \ + --hash=sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048 +requests==2.23.0 \ + --hash=sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee \ + --hash=sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6 requests-toolbelt==0.9.1 \ --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f \ --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 -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 +six==1.15.0 \ + --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ + --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced +urllib3==1.25.9 \ + --hash=sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527 \ + --hash=sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115 +zope.component==4.6.1 \ + --hash=sha256:bfbe55d4a93e70a78b10edc3aad4de31bb8860919b7cbd8d66f717f7d7b279ac \ + --hash=sha256:d9c7c27673d787faff8a83797ce34d6ebcae26a370e25bddb465ac2182766aca zope.deferredimport==4.3.1 \ --hash=sha256:57b2345e7b5eef47efcd4f634ff16c93e4265de3dcf325afc7315ade48d909e1 \ --hash=sha256:9a0c211df44aa95f1c4e6d2626f90b400f56989180d3ef96032d708da3d23e0a @@ -143,123 +139,126 @@ zope.deprecation==4.4.0 \ zope.event==4.4 \ --hash=sha256:69c27debad9bdacd9ce9b735dad382142281ac770c4a432b533d6d65c4614bcf \ --hash=sha256:d8e97d165fd5a0997b45f5303ae11ea3338becfe68c401dd88ffd2113fe5cae7 -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 \ - --hash=sha256:1ef452cc02e0e2f8e3c917b1a5b936ef3280f2c2ca854ee70ac2164d1655f7e6 \ - --hash=sha256:22bf61857c5977f34d4e391476d40f9a3b8c6ab24fb0cac448d42d8f8b9bf7b2 \ - --hash=sha256:299870e3428cbff1cd9f9b34144e76ecdc1d9e3192a8cf5f1b0258f47a239f58 \ - --hash=sha256:2bfc36bfccbe047671170ea5677efd3d5ab730a55d7e45611d76d495e5b96766 \ - --hash=sha256:32e82d5a640febc688c0789e15ea875bf696a10cf358f049e1ed841f01710a9b \ - --hash=sha256:3b2051bdc4bc3f02fa52483f6381cf40d4d48167645241993f9d7ebbd142ed9b \ - --hash=sha256:3f734bd8a08f5185a64fb6abb8f14dc97ec27a689ca808fb7a83cdd38d745e4f \ - --hash=sha256:3f78dd8de3112df8bbd970f0916ac876dc3fbe63810bd1cf7cc5eec4cbac4f04 \ - --hash=sha256:4eabeb48508953ba1f3590ad0773b8daea9e104eec66d661917e9bbcd7125a67 \ - --hash=sha256:4f05ecc33808187f430f249cb1ccab35c38f570b181f2d380fbe253da94b18d8 \ - --hash=sha256:4f4f4cbf23d3afc1526294a31e7b3eaa0f682cc28ac5366065dc1d6bb18bd7be \ - --hash=sha256:5483d5e70aacd06f0aa3effec9fed597c0b50f45060956eeeb1203c44d4338c3 \ - --hash=sha256:56a5f9b46892b115a75d0a1f2292431ad5988461175826600acc69a24cb3edee \ - --hash=sha256:64bb63af8a06f736927d260efdd4dfc5253d42244f281a8063e4b9eea2ddcbc5 \ - --hash=sha256:653f8cbefcf7c6ac4cece2cdef367c4faa2b7c19795d52bd7cbec11a8739a7c1 \ - --hash=sha256:664211d63306e4bd4eec35bf2b4bd9db61c394037911cf2d1804c43b511a49f1 \ - --hash=sha256:6651e6caed66a8fff0fef1a3e81c0ed2253bf361c0fdc834500488732c5d16e9 \ - --hash=sha256:6c1fba6cdfdf105739d3069cf7b07664f2944d82a8098218ab2300a82d8f40fc \ - --hash=sha256:6e64246e6e9044a4534a69dca1283c6ddab6e757be5e6874f69024329b3aa61f \ - --hash=sha256:838390245c7ec137af4993c0c8052f49d5ec79e422b4451bfa37fee9b9ccaa01 \ - --hash=sha256:856b410a14793069d8ba35f33fff667213ea66f2df25a0024cc72a7493c56d4c \ - --hash=sha256:8b932c364c1d1605a91907a41128ed0ee8a2d326fc0fafb2c55cd46f545f4599 \ - --hash=sha256:9086cf6d20f08dae7f296a78f6c77d1f8d24079d448f023ee0eb329078dd35e1 \ - --hash=sha256:9698533c14afa0548188de4968a7932d1f3f965f3f5ba1474de673596bb875af \ - --hash=sha256:9b12b05dd7c28f5068387c1afee8cb94f9d02501e7ef495a7c5c7e27139b96ad \ - --hash=sha256:a884c7426a5bc6fb7fc71a55ad14e66818e13f05b78b20a6f37175f324b7acb8 \ - --hash=sha256:abe9e7f1a3e76286c5f5baf2bf5162d41dc0310da493b34a2c36555f38d928f7 \ - --hash=sha256:bd6fde63b015a27262be06bd6bbdd895273cc2bdf2d4c7e1c83711d26a8fbace \ - --hash=sha256:bda7c62c954f47b87ed9a89f525eee1b318ec7c2162dfdba76c2ccfa334e0caa \ - --hash=sha256:be8a4908dd3f6e965993c0068b006bdbd0474fbcbd1da4893b49356e73fc1557 \ - --hash=sha256:ced65fc3c7d7205267506d854bb1815bb445899cca9d21d1d4b949070a635546 \ - --hash=sha256:dac4279aa05055d3897ab5e5ee5a7b39db121f91df65a530f8b1ac7f9bd93119 \ - --hash=sha256:e4f1863056e3e4f399c285b67fa816f411a7bfa1c81ef50e186126164e396e59 \ - --hash=sha256:ecd85f68b8cd9ab78a0141e87ea9a53b2f31fd9b1350a1c44da1f7481b5363ef \ - --hash=sha256:ed269b83750413e8fc5c96276372f49ee3fcb7ed61c49fe8e5a67f54459a5a4a \ - --hash=sha256:f19b0b80cba73b204dee68501870b11067711d21d243fb6774256d3ca2e5391f \ - --hash=sha256:ffdafb98db7574f9da84c489a10a5d582079a888cb43c64e9e6b0e3fe1034685 +zope.hookable==5.0.1 \ + --hash=sha256:0194b9b9e7f614abba60c90b231908861036578297515d3d6508eb10190f266d \ + --hash=sha256:0c2977473918bdefc6fa8dfb311f154e7f13c6133957fe649704deca79b92093 \ + --hash=sha256:17b8bdb3b77e03a152ca0d5ca185a7ae0156f5e5a2dbddf538676633a1f7380f \ + --hash=sha256:29d07681a78042cdd15b268ae9decffed9ace68a53eebeb61d65ae931d158841 \ + --hash=sha256:36fb1b35d1150267cb0543a1ddd950c0bc2c75ed0e6e92e3aaa6ac2e29416cb7 \ + --hash=sha256:3aed60c2bb5e812bbf9295c70f25b17ac37c233f30447a96c67913ba5073642f \ + --hash=sha256:3cac1565cc768911e72ca9ec4ddf5c5109e1fef0104f19f06649cf1874943b60 \ + --hash=sha256:3d4bc0cc4a37c3cd3081063142eeb2125511db3c13f6dc932d899c512690378e \ + --hash=sha256:3f73096f27b8c28be53ffb6604f7b570fbbb82f273c6febe5f58119009b59898 \ + --hash=sha256:522d1153d93f2d48aa0bd9fb778d8d4500be2e4dcf86c3150768f0e3adbbc4ef \ + --hash=sha256:523d2928fb7377bbdbc9af9c0b14ad73e6eaf226349f105733bdae27efd15b5a \ + --hash=sha256:5848309d4fc5c02150a45e8f8d2227e5bfda386a508bbd3160fed7c633c5a2fa \ + --hash=sha256:6781f86e6d54a110980a76e761eb54590630fd2af2a17d7edf02a079d2646c1d \ + --hash=sha256:6fd27921ebf3aaa945fa25d790f1f2046204f24dba4946f82f5f0a442577c3e9 \ + --hash=sha256:70d581862863f6bf9e175e85c9d70c2d7155f53fb04dcdb2f73cf288ca559a53 \ + --hash=sha256:81867c23b0dc66c8366f351d00923f2bc5902820a24c2534dfd7bf01a5879963 \ + --hash=sha256:81db29edadcbb740cd2716c95a297893a546ed89db1bfe9110168732d7f0afdd \ + --hash=sha256:86bd12624068cea60860a0759af5e2c3adc89c12aef6f71cf12f577e28deefe3 \ + --hash=sha256:9c184d8f9f7a76e1ced99855ccf390ffdd0ec3765e5cbf7b9cada600accc0a1e \ + --hash=sha256:acc789e8c29c13555e43fe4bf9fcd15a65512c9645e97bbaa5602e3201252b02 \ + --hash=sha256:afaa740206b7660d4cc3b8f120426c85761f51379af7a5b05451f624ad12b0af \ + --hash=sha256:b5f5fa323f878bb16eae68ea1ba7f6c0419d4695d0248bed4b18f51d7ce5ab85 \ + --hash=sha256:bd89e0e2c67bf4ac3aca2a19702b1a37269fb1923827f68324ac2e7afd6e3406 \ + --hash=sha256:c212de743283ec0735db24ec6ad913758df3af1b7217550ff270038062afd6ae \ + --hash=sha256:ca553f524293a0bdea05e7f44c3e685e4b7b022cb37d87bc4a3efa0f86587a8d \ + --hash=sha256:cab67065a3db92f636128d3157cc5424a145f82d96fb47159c539132833a6d36 \ + --hash=sha256:d3b3b3eedfdbf6b02898216e85aa6baf50207f4378a2a6803d6d47650cd37031 \ + --hash=sha256:d9f4a5a72f40256b686d31c5c0b1fde503172307beb12c1568296e76118e402c \ + --hash=sha256:df5067d87aaa111ed5d050e1ee853ba284969497f91806efd42425f5348f1c06 \ + --hash=sha256:e2587644812c6138f05b8a41594a8337c6790e3baf9a01915e52438c13fc6bef \ + --hash=sha256:e27fd877662db94f897f3fd532ef211ca4901eb1a70ba456f15c0866a985464a \ + --hash=sha256:e427ebbdd223c72e06ba94c004bb04e996c84dec8a0fa84e837556ae145c439e \ + --hash=sha256:e583ad4309c203ef75a09d43434cf9c2b4fa247997ecb0dcad769982c39411c7 \ + --hash=sha256:e760b2bc8ece9200804f0c2b64d10147ecaf18455a2a90827fbec4c9d84f3ad5 \ + --hash=sha256:ea9a9cc8bcc70e18023f30fa2f53d11ae069572a162791224e60cd65df55fb69 \ + --hash=sha256:ecb3f17dce4803c1099bd21742cd126b59817a4e76a6544d31d2cca6e30dbffd \ + --hash=sha256:ed794e3b3de42486d30444fb60b5561e724ee8a2d1b17b0c2e0f81e3ddaf7a87 \ + --hash=sha256:ee885d347279e38226d0a437b6a932f207f691c502ee565aba27a7022f1285df \ + --hash=sha256:fd5e7bc5f24f7e3d490698f7b854659a9851da2187414617cd5ed360af7efd63 \ + --hash=sha256:fe45f6870f7588ac7b2763ff1ce98cce59369717afe70cc353ec5218bc854bcc +zope.interface==5.1.0 \ + --hash=sha256:0103cba5ed09f27d2e3de7e48bb320338592e2fabc5ce1432cf33808eb2dfd8b \ + --hash=sha256:14415d6979356629f1c386c8c4249b4d0082f2ea7f75871ebad2e29584bd16c5 \ + --hash=sha256:1ae4693ccee94c6e0c88a4568fb3b34af8871c60f5ba30cf9f94977ed0e53ddd \ + --hash=sha256:1b87ed2dc05cb835138f6a6e3595593fea3564d712cb2eb2de963a41fd35758c \ + --hash=sha256:269b27f60bcf45438e8683269f8ecd1235fa13e5411de93dae3b9ee4fe7f7bc7 \ + --hash=sha256:27d287e61639d692563d9dab76bafe071fbeb26818dd6a32a0022f3f7ca884b5 \ + --hash=sha256:39106649c3082972106f930766ae23d1464a73b7d30b3698c986f74bf1256a34 \ + --hash=sha256:40e4c42bd27ed3c11b2c983fecfb03356fae1209de10686d03c02c8696a1d90e \ + --hash=sha256:461d4339b3b8f3335d7e2c90ce335eb275488c587b61aca4b305196dde2ff086 \ + --hash=sha256:4f98f70328bc788c86a6a1a8a14b0ea979f81ae6015dd6c72978f1feff70ecda \ + --hash=sha256:558a20a0845d1a5dc6ff87cd0f63d7dac982d7c3be05d2ffb6322a87c17fa286 \ + --hash=sha256:562dccd37acec149458c1791da459f130c6cf8902c94c93b8d47c6337b9fb826 \ + --hash=sha256:5e86c66a6dea8ab6152e83b0facc856dc4d435fe0f872f01d66ce0a2131b7f1d \ + --hash=sha256:60a207efcd8c11d6bbeb7862e33418fba4e4ad79846d88d160d7231fcb42a5ee \ + --hash=sha256:645a7092b77fdbc3f68d3cc98f9d3e71510e419f54019d6e282328c0dd140dcd \ + --hash=sha256:6874367586c020705a44eecdad5d6b587c64b892e34305bb6ed87c9bbe22a5e9 \ + --hash=sha256:74bf0a4f9091131de09286f9a605db449840e313753949fe07c8d0fe7659ad1e \ + --hash=sha256:7b726194f938791a6691c7592c8b9e805fc6d1b9632a833b9c0640828cd49cbc \ + --hash=sha256:8149ded7f90154fdc1a40e0c8975df58041a6f693b8f7edcd9348484e9dc17fe \ + --hash=sha256:8cccf7057c7d19064a9e27660f5aec4e5c4001ffcf653a47531bde19b5aa2a8a \ + --hash=sha256:911714b08b63d155f9c948da2b5534b223a1a4fc50bb67139ab68b277c938578 \ + --hash=sha256:a5f8f85986197d1dd6444763c4a15c991bfed86d835a1f6f7d476f7198d5f56a \ + --hash=sha256:a744132d0abaa854d1aad50ba9bc64e79c6f835b3e92521db4235a1991176813 \ + --hash=sha256:af2c14efc0bb0e91af63d00080ccc067866fb8cbbaca2b0438ab4105f5e0f08d \ + --hash=sha256:b054eb0a8aa712c8e9030065a59b5e6a5cf0746ecdb5f087cca5ec7685690c19 \ + --hash=sha256:b0becb75418f8a130e9d465e718316cd17c7a8acce6fe8fe07adc72762bee425 \ + --hash=sha256:b1d2ed1cbda2ae107283befd9284e650d840f8f7568cb9060b5466d25dc48975 \ + --hash=sha256:ba4261c8ad00b49d48bbb3b5af388bb7576edfc0ca50a49c11dcb77caa1d897e \ + --hash=sha256:d1fe9d7d09bb07228650903d6a9dc48ea649e3b8c69b1d263419cc722b3938e8 \ + --hash=sha256:d7804f6a71fc2dda888ef2de266727ec2f3915373d5a785ed4ddc603bbc91e08 \ + --hash=sha256:da2844fba024dd58eaa712561da47dcd1e7ad544a257482392472eae1c86d5e5 \ + --hash=sha256:dcefc97d1daf8d55199420e9162ab584ed0893a109f45e438b9794ced44c9fd0 \ + --hash=sha256:dd98c436a1fc56f48c70882cc243df89ad036210d871c7427dc164b31500dc11 \ + --hash=sha256:e74671e43ed4569fbd7989e5eecc7d06dc134b571872ab1d5a88f4a123814e9f \ + --hash=sha256:eb9b92f456ff3ec746cd4935b73c1117538d6124b8617bc0fe6fda0b3816e345 \ + --hash=sha256:ebb4e637a1fb861c34e48a00d03cffa9234f42bef923aec44e5625ffb9a8e8f9 \ + --hash=sha256:ef739fe89e7f43fb6494a43b1878a36273e5924869ba1d866f752c5812ae8d58 \ + --hash=sha256:f40db0e02a8157d2b90857c24d89b6310f9b6c3642369852cdc3b5ac49b92afc \ + --hash=sha256:f68bf937f113b88c866d090fea0bc52a098695173fc613b055a17ff0cf9683b6 \ + --hash=sha256:fb55c182a3f7b84c1a2d6de5fa7b1a05d4660d866b91dbf8d74549c57a1499e8 +zope.proxy==4.3.5 \ + --hash=sha256:00573dfa755d0703ab84bb23cb6ecf97bb683c34b340d4df76651f97b0bab068 \ + --hash=sha256:092049280f2848d2ba1b57b71fe04881762a220a97b65288bcb0968bb199ec30 \ + --hash=sha256:0cbd27b4d3718b5ec74fc65ffa53c78d34c65c6fd9411b8352d2a4f855220cf1 \ + --hash=sha256:17fc7e16d0c81f833a138818a30f366696653d521febc8e892858041c4d88785 \ + --hash=sha256:19577dfeb70e8a67249ba92c8ad20589a1a2d86a8d693647fa8385408a4c17b0 \ + --hash=sha256:207aa914576b1181597a1516e1b90599dc690c095343ae281b0772e44945e6a4 \ + --hash=sha256:219a7db5ed53e523eb4a4769f13105118b6d5b04ed169a283c9775af221e231f \ + --hash=sha256:2b50ea79849e46b5f4f2b0247a3687505d32d161eeb16a75f6f7e6cd81936e43 \ + --hash=sha256:5903d38362b6c716e66bbe470f190579c530a5baf03dbc8500e5c2357aa569a5 \ + --hash=sha256:5c24903675e271bd688c6e9e7df5775ac6b168feb87dbe0e4bcc90805f21b28f \ + --hash=sha256:5ef6bc5ed98139e084f4e91100f2b098a0cd3493d4e76f9d6b3f7b95d7ad0f06 \ + --hash=sha256:61b55ae3c23a126a788b33ffb18f37d6668e79a05e756588d9e4d4be7246ab1c \ + --hash=sha256:63ddb992931a5e616c87d3d89f5a58db086e617548005c7f9059fac68c03a5cc \ + --hash=sha256:6943da9c09870490dcfd50c4909c0cc19f434fa6948f61282dc9cb07bcf08160 \ + --hash=sha256:6ad40f85c1207803d581d5d75e9ea25327cd524925699a83dfc03bf8e4ba72b7 \ + --hash=sha256:6b44433a79bdd7af0e3337bd7bbcf53dd1f9b0fa66bf21bcb756060ce32a96c1 \ + --hash=sha256:6bbaa245015d933a4172395baad7874373f162955d73612f0b66b6c2c33b6366 \ + --hash=sha256:7007227f4ea85b40a2f5e5a244479f6a6dfcf906db9b55e812a814a8f0e2c28d \ + --hash=sha256:74884a0aec1f1609190ec8b34b5d58fb3b5353cf22b96161e13e0e835f13518f \ + --hash=sha256:7d25fe5571ddb16369054f54cdd883f23de9941476d97f2b92eb6d7d83afe22d \ + --hash=sha256:7e162bdc5e3baad26b2262240be7d2bab36991d85a6a556e48b9dfb402370261 \ + --hash=sha256:814d62678dc3a30f4aa081982d830b7c342cf230ffc9d030b020cb154eeebf9e \ + --hash=sha256:8878a34c5313ee52e20aa50b03138af8d472bae465710fb954d133a9bfd3c38d \ + --hash=sha256:a66a0d94e5b081d5d695e66d6667e91e74d79e273eee95c1747717ba9cb70792 \ + --hash=sha256:a69f5cbf4addcfdf03dda564a671040127a6b7c34cf9fe4973582e68441b63fa \ + --hash=sha256:b00f9f0c334d07709d3f73a7cb8ae63c6ca1a90c790a63b5e7effa666ef96021 \ + --hash=sha256:b6ed71e4a7b4690447b626f499d978aa13197a0e592950e5d7020308f6054698 \ + --hash=sha256:bdf5041e5851526e885af579d2f455348dba68d74f14a32781933569a327fddf \ + --hash=sha256:be034360dd34e62608419f86e799c97d389c10a0e677a25f236a971b2f40dac9 \ + --hash=sha256:cc8f590a5eed30b314ae6b0232d925519ade433f663de79cc3783e4b10d662ba \ + --hash=sha256:cd7a318a15fe6cc4584bf3c4426f092ed08c0fd012cf2a9173114234fe193e11 \ + --hash=sha256:cf19b5f63a59c20306e034e691402b02055c8f4e38bf6792c23cad489162a642 \ + --hash=sha256:cfc781ce442ec407c841e9aa51d0e1024f72b6ec34caa8fdb6ef9576d549acf2 \ + --hash=sha256:dea9f6f8633571e18bc20cad83603072e697103a567f4b0738d52dd0211b4527 \ + --hash=sha256:e4a86a1d5eb2cce83c5972b3930c7c1eac81ab3508464345e2b8e54f119d5505 \ + --hash=sha256:e7106374d4a74ed9ff00c46cc00f0a9f06a0775f8868e423f85d4464d2333679 \ + --hash=sha256:e98a8a585b5668aa9e34d10f7785abf9545fe72663b4bfc16c99a115185ae6a5 \ + --hash=sha256:f64840e68483316eb58d82c376ad3585ca995e69e33b230436de0cdddf7363f9 \ + --hash=sha256:f8f4b0a9e6683e43889852130595c8854d8ae237f2324a053cdd884de936aa9b \ + --hash=sha256:fc45a53219ed30a7f670a6d8c98527af0020e6fd4ee4c0a8fb59f147f06d816c diff --git a/letsencrypt-auto-source/rebuild_dependencies.py b/letsencrypt-auto-source/rebuild_dependencies.py old mode 100644 new mode 100755 index 3093b6bb0..a28fa2693 --- a/letsencrypt-auto-source/rebuild_dependencies.py +++ b/letsencrypt-auto-source/rebuild_dependencies.py @@ -44,11 +44,14 @@ AUTHORITATIVE_CONSTRAINTS = { 'python-augeas': '0.5.0', # Package enum34 needs to be explicitly limited to Python2.x, in order to avoid # 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\'', + 'enum34': '1.1.10; python_version < \'3.4\'', + # Cryptography 2.9+ drops support for OpenSSL 1.0.1, but we still want to support it + # for officially supported non-x86_64 ancient distributions like RHEL 6 or Debian 8. + 'cryptography': '2.8', + # Parsedatetime 2.6 is broken on Python 2.7, see https://github.com/bear/parsedatetime/issues/246 + 'parsedatetime': '2.5', } - # ./certbot/letsencrypt-auto-source/rebuild_dependencies.py (2 levels from certbot root path) CERTBOT_REPO_PATH = dirname(dirname(abspath(__file__))) @@ -226,6 +229,10 @@ def _write_requirements(dest_file, requirements, conflicts): ''') for req in requirements: + if req[0] in AUTHORITATIVE_CONSTRAINTS: + # If requirement is in AUTHORITATIVE_CONSTRAINTS, take its value instead of the + # computed one to get any environment descriptor that would have been added. + req = (req[0], AUTHORITATIVE_CONSTRAINTS[req[0]]) subprocess.check_call(['hashin', '{0}=={1}'.format(req[0], req[1]), '--requirements-file', dest_file]) diff --git a/pytest.ini b/pytest.ini index e09813e52..16aa9a193 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,6 +4,13 @@ [pytest] # In general, all warnings are treated as errors. Here are the exceptions: # 1- decodestring: https://github.com/rthalley/dnspython/issues/338 +# Warnings being triggered by our plugins using deprecated features in +# acme/certbot should be fixed by having our plugins no longer using the +# deprecated code rather than adding them to the list of ignored warnings here. +# Fixing things in this way prevents us from shipping packages raising our own +# deprecation warnings and gives time for plugins that don't use the deprecated +# API to propagate, especially for plugins packaged as an external snap, before +# we release breaking changes. filterwarnings = error ignore:decodestring:DeprecationWarning diff --git a/snap/hooks/configure b/snap/hooks/configure new file mode 100644 index 000000000..2678c47b2 --- /dev/null +++ b/snap/hooks/configure @@ -0,0 +1,3 @@ +#!/bin/bash -e + +exit 0 diff --git a/snap/hooks/prepare-plug-plugin b/snap/hooks/prepare-plug-plugin new file mode 100644 index 000000000..ee309addf --- /dev/null +++ b/snap/hooks/prepare-plug-plugin @@ -0,0 +1,11 @@ +#!/bin/bash -e + +if [ "$(snapctl get trust-plugin-with-root)" = "ok" ]; then + # allow the connection, but reset config to allow for other slots to go through this auth flow + snapctl unset trust-plugin-with-root + exit 0 +else + echo "Only connect this interface if you trust the plugin author to have root on the system" + echo "Run \`snap set $SNAP_NAME trust-plugin-with-root=ok\` to acknowledge this and then run this command again to perform the connection" + exit 1 +fi diff --git a/snap/local/build_and_install.sh b/snap/local/build_and_install.sh index 833027a8c..225bd54ec 100755 --- a/snap/local/build_and_install.sh +++ b/snap/local/build_and_install.sh @@ -1,4 +1,8 @@ #!/bin/bash +# Cross-compile the Certbot snap from local sources for the specified architecture, +# and install it if this architecture is also the the current machine one. +# This script is designed for CI tests purpose. +# Usage: build_and_install.sh [amd64,arm64,armhf] set -ex if [[ -z "$TRAVIS" && -z "$SYSTEM_TEAMFOUNDATIONSERVERURI" ]]; then @@ -6,9 +10,44 @@ if [[ -z "$TRAVIS" && -z "$SYSTEM_TEAMFOUNDATIONSERVERURI" ]]; then exit 1 fi -sudo /snap/bin/lxd.migrate -yes -sudo /snap/bin/lxd waitready -sudo /snap/bin/lxd init --auto -tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > constraints.txt -sudo snapcraft --use-lxd -sudo snap install --dangerous --classic *.snap +SNAP_ARCH=$1 + +if [[ -z "${SNAP_ARCH}" ]]; then + echo "You need to specify the target architecture" + exit 1 +fi + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +CERTBOT_DIR="$(dirname "$(dirname "${DIR}")")" + +# shellcheck source=common.sh +source "${DIR}/common.sh" + +RegisterQemuHandlers +ResolveArch "${SNAP_ARCH}" + +tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > snap-constraints.txt + +pushd "${DIR}/packages" +"${CERTBOT_DIR}/tools/simple_http_server.py" 8080 >/dev/null 2>&1 & +HTTP_SERVER_PID="$!" +popd + +function cleanup() { + kill "${HTTP_SERVER_PID}" +} + +trap cleanup EXIT + +docker run \ + --rm \ + --net=host \ + -v "${CERTBOT_DIR}:/certbot" \ + -w "/certbot" \ + -e "PIP_EXTRA_INDEX_URL=http://localhost:8080" \ + "adferrand/snapcraft:${DOCKER_ARCH}-stable" \ + snapcraft + +if [[ "$(arch)" == "${QEMU_ARCH}" ]]; then + sudo snap install --dangerous --classic *.snap +fi diff --git a/snap/local/common.sh b/snap/local/common.sh new file mode 100644 index 000000000..00a7614e8 --- /dev/null +++ b/snap/local/common.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Common bash functions useful for cross-compiling Certbot snaps. + +# Resolve the Snap architecture to Docker architecture (DOCKER_ARCH variable) +# and QEMU architecture (QEMU_ARCH variable). +# Usage: ResolveArch [amd64|i386|arm64|armhf] +ResolveArch() { + local SNAP_ARCH=$1 + + case "${SNAP_ARCH}" in + "amd64") + DOCKER_ARCH="amd64" + QEMU_ARCH="x86_64" + ;; + "i386") + DOCKER_ARCH="i386" + QEMU_ARCH="i386" + ;; + "arm64") + DOCKER_ARCH="arm64v8" + QEMU_ARCH="aarch64" + ;; + "armhf") + DOCKER_ARCH="arm32v7" + QEMU_ARCH="arm" + ;; + "*") + echo "Not supported build architecture '$1'." >&2 + exit 1 + esac +} + +# Downloads QEMU static binary file for architecture +# Usage: DownloadQemuStatic [x86_64|aarch64|arm] DEST_DIR +DownloadQemuStatic() { + local QEMU_ARCH=$1 + local DEST_DIR=$2 + local QEMU_DOWNLOAD_URL + local QEMU_LATEST_TAG + + if [ ! -f "${DIR}/qemu-${QEMU_ARCH}-static" ]; then + QEMU_DOWNLOAD_URL="https://github.com/multiarch/qemu-user-static/releases/download" + QEMU_LATEST_TAG=$(curl -s https://api.github.com/repos/multiarch/qemu-user-static/tags \ + | grep 'name.*v[0-9]' \ + | head -n 1 \ + | cut -d '"' -f 4) + echo "${QEMU_DOWNLOAD_URL}/${QEMU_LATEST_TAG}/x86_64_qemu-${QEMU_ARCH}-static.tar.gz" + curl -SL "${QEMU_DOWNLOAD_URL}/${QEMU_LATEST_TAG}/x86_64_qemu-${QEMU_ARCH}-static.tar.gz" \ + | tar xzv -C "${DEST_DIR}" + fi +} + +# Executes the QEMU register script +# Usage: RegisterQemuHandlers +RegisterQemuHandlers() { + docker run --rm --privileged multiarch/qemu-user-static:register --reset +} diff --git a/snap/local/compile_native_wheels.sh b/snap/local/compile_native_wheels.sh new file mode 100755 index 000000000..5dbb0f5d6 --- /dev/null +++ b/snap/local/compile_native_wheels.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Cross-compile cryptography and cffi native wheels for arm64 and armhf architectures, +# on the versions required by the current pinning of Certbot dependencies. +# Wheels are stored in snap/local/packages folder to speed up cross-compilation of Certbot snap. +set -ex + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +TARGET_ARCHS="i386 arm64 armhf" + +rm -rf "${DIR}/packages/"* + +# shellcheck source=common.sh +source "${DIR}/common.sh" + +RegisterQemuHandlers + +tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > "${DIR}/snap-constraints.txt" +for SNAP_ARCH in ${TARGET_ARCHS}; do + ResolveArch "${SNAP_ARCH}" + DownloadQemuStatic "${QEMU_ARCH}" "${DIR}" + + docker run \ + --rm \ + -v "${DIR}/qemu-${QEMU_ARCH}-static:/usr/bin/qemu-${QEMU_ARCH}-static" \ + -v "${DIR}:/workspace" \ + -w "/workspace" \ + "${DOCKER_ARCH}/ubuntu:18.04" \ + sh -c "\ + apt-get update \ +&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends python3 python3-venv python3-dev libffi-dev libssl-dev gcc \ +&& mkdir -p /build \ +&& python3 -m venv /build/venv \ +&& /build/venv/bin/pip install wheel \ +&& /build/venv/bin/pip wheel cryptography cffi -c snap-constraints.txt -w /build \ +&& mkdir -p /workspace/packages/cffi /workspace/packages/cryptography \ +&& mv /build/cryptography-* /workspace/packages/cryptography \ +&& mv /build/cffi-* /workspace/packages/cffi \ +&& chmod 777 /workspace/packages /workspace/packages/cffi /workspace/packages/cryptography \ +&& chmod 666 /workspace/packages/cffi/* /workspace/packages/cryptography/* +" +done diff --git a/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-linux_aarch64.whl b/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-linux_aarch64.whl new file mode 100644 index 000000000..36dfa9ade Binary files /dev/null and b/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-linux_aarch64.whl differ diff --git a/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-linux_armv7l.whl b/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-linux_armv7l.whl new file mode 100644 index 000000000..26f107cc9 Binary files /dev/null and b/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-linux_armv7l.whl differ diff --git a/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl b/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl new file mode 100644 index 000000000..1e5491b6e Binary files /dev/null and b/snap/local/packages/cffi/cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl differ diff --git a/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_aarch64.whl b/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_aarch64.whl new file mode 100644 index 000000000..3a969945a Binary files /dev/null and b/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_aarch64.whl differ diff --git a/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_armv7l.whl b/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_armv7l.whl new file mode 100644 index 000000000..ea49f5dab Binary files /dev/null and b/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_armv7l.whl differ diff --git a/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_i686.whl b/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_i686.whl new file mode 100644 index 000000000..18d7e6fd7 Binary files /dev/null and b/snap/local/packages/cryptography/cryptography-2.8-cp36-cp36m-linux_i686.whl differ diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 9c6a519a7..30959dacd 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -7,7 +7,7 @@ description: | browser-trusted certificate, without any human intervention. This is accomplished by running a certificate management agent on the web server. - + This agent is used to: - Automatically prove to the Let's Encrypt CA that you control the website - Obtain a browser-trusted certificate and set it up on your web server @@ -20,7 +20,7 @@ adopt-info: certbot apps: certbot: - command: certbot + command: certbot.wrapper environment: PATH: "$SNAP/bin:$SNAP/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" AUGEAS_LENS_LIB: "$SNAP/usr/share/augeas/lenses/dist" @@ -32,9 +32,8 @@ apps: PATH: "$SNAP/bin:$SNAP/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" AUGEAS_LENS_LIB: $SNAP/usr/share/augeas/lenses/dist LD_LIBRARY_PATH: "$SNAP/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH" - passthrough: - # Run approximately twice a day with randomization - timer: 00:00~24:00/2 + # Run approximately twice a day with randomization + timer: 00:00~24:00/2 parts: python-augeas: @@ -47,13 +46,15 @@ parts: plugin: python source: . source-subdir: acme - constraints: [$SNAPCRAFT_PART_SRC/constraints.txt] + constraints: [$SNAPCRAFT_PART_SRC/snap-constraints.txt] python-version: python3 + # To build cryptography and cffi if needed + build-packages: [libffi-dev, libssl-dev] certbot: plugin: python source: . source-subdir: certbot - constraints: [$SNAPCRAFT_PART_SRC/constraints.txt] + constraints: [$SNAPCRAFT_PART_SRC/snap-constraints.txt] python-version: python3 after: [acme] override-pull: | @@ -66,7 +67,7 @@ parts: plugin: python source: . source-subdir: certbot-apache - constraints: [$SNAPCRAFT_PART_SRC/constraints.txt] + constraints: [$SNAPCRAFT_PART_SRC/snap-constraints.txt] python-version: python3 after: [python-augeas, certbot] stage-packages: [libaugeas0] @@ -77,7 +78,7 @@ parts: plugin: python source: . source-subdir: certbot-nginx - constraints: [$SNAPCRAFT_PART_SRC/constraints.txt] + constraints: [$SNAPCRAFT_PART_SRC/snap-constraints.txt] python-version: python3 # This is the last step, compile pycache now as there should be no conflicts. override-prime: | @@ -86,3 +87,13 @@ parts: # After certbot-apache to not rebuild duplicates (essentially sharing what was already staged, # like zope) after: [certbot-apache] + wrappers: + plugin: dump + source: . + stage: [certbot.wrapper] + +plugs: + plugin: + interface: content + content: certbot-1 + target: $SNAP/certbot-plugin diff --git a/tests/letstest/README.md b/tests/letstest/README.md index 5bd326e2a..4cf6c83c3 100644 --- a/tests/letstest/README.md +++ b/tests/letstest/README.md @@ -15,9 +15,10 @@ Simple AWS testfarm scripts for certbot client testing are needed, they need to be requested via online webform. ## Installation and configuration -These tests require Python 3, awscli, boto3, PyYAML, and fabric 2.0+. If you -have Python 3 installed, you can use requirements.txt to create a virtual -environment with a known set of dependencies by running: +These tests require Python 3, awscli, boto3, PyYAML, and fabric 2.0+. If you're +on a Debian based system, make sure you also have the python3-venv package +installed. If you have Python 3 installed, you can use requirements.txt to +create a virtual environment with a known set of dependencies by running: ``` python3 -m venv venv3 . ./venv3/bin/activate diff --git a/tests/letstest/scripts/test_sdists.sh b/tests/letstest/scripts/test_sdists.sh index 204f55d55..338569e6d 100755 --- a/tests/letstest/scripts/test_sdists.sh +++ b/tests/letstest/scripts/test_sdists.sh @@ -34,7 +34,7 @@ fi VERSION=$("$PYTHON_NAME" letsencrypt-auto-source/version.py) # setup venv -"$VENV_SCRIPT" --requirement letsencrypt-auto-source/pieces/dependency-requirements.txt +CERTBOT_PIP_NO_BINARY=":all:" "$VENV_SCRIPT" --requirement letsencrypt-auto-source/pieces/dependency-requirements.txt . "$VENV_PATH/bin/activate" # pytest is needed to run tests on some of our packages so we install a pinned version here. tools/pip_install.py pytest diff --git a/tools/_venv_common.py b/tools/_venv_common.py index 5196cf9c4..b1c873918 100644 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -12,6 +12,7 @@ VENV_NAME. from __future__ import print_function +from distutils.version import LooseVersion import glob import os import re @@ -131,6 +132,13 @@ def subprocess_with_print(cmd, env=None, shell=False): subprocess.check_call(cmd, env=env, shell=shell) +def subprocess_output_with_print(cmd, env=None, shell=False): + if env is None: + env = os.environ + print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd) + return subprocess.check_output(cmd, env=env, shell=shell) + + def get_venv_python_path(venv_path): python_linux = os.path.join(venv_path, 'bin/python') if os.path.isfile(python_linux): @@ -191,9 +199,31 @@ def install_packages(venv_name, pip_args): # Using the python executable from venv, we ensure to execute following commands in this venv. py_venv = get_venv_python_path(venv_name) subprocess_with_print([py_venv, os.path.abspath('letsencrypt-auto-source/pieces/pipstrap.py')]) + # We only use this value during pip install because: + # 1) We're really only adding it for installing cryptography, which happens here, and + # 2) There are issues with calling it along with VIRTUALENV_NO_DOWNLOAD, which applies at the + # steps above, not during pip install. + env_pip_no_binary = os.environ.get('CERTBOT_PIP_NO_BINARY') + if env_pip_no_binary: + # Check OpenSSL version. If it's too low, don't apply the env variable. + openssl_version_string = str(subprocess_output_with_print(['openssl', 'version'])) + matches = re.findall(r'OpenSSL ([^ ]+) ', openssl_version_string) + if not matches: + print('Could not find OpenSSL version, not setting PIP_NO_BINARY.') + else: + openssl_version = matches[0] + + if LooseVersion(openssl_version) >= LooseVersion('1.0.2'): + print('Setting PIP_NO_BINARY to {0}' + ' as specified in CERTBOT_PIP_NO_BINARY'.format(env_pip_no_binary)) + os.environ['PIP_NO_BINARY'] = env_pip_no_binary + else: + print('Not setting PIP_NO_BINARY, as OpenSSL version is too old.') command = [py_venv, os.path.abspath('tools/pip_install.py')] command.extend(pip_args) subprocess_with_print(command) + if 'PIP_NO_BINARY' in os.environ: + del os.environ['PIP_NO_BINARY'] if os.path.isdir(os.path.join(venv_name, 'bin')): # Linux/OSX specific diff --git a/tools/pip_install_editable.py b/tools/pip_install_editable.py index 3f7c02ba9..abfe9f214 100755 --- a/tools/pip_install_editable.py +++ b/tools/pip_install_editable.py @@ -1,6 +1,11 @@ #!/usr/bin/env python # pip installs packages in editable mode using certbot-auto's requirements file # as constraints +# +# cryptography is currently using this script in their CI at +# https://github.com/pyca/cryptography/blob/a02fdd60d98273ca34427235c4ca96687a12b239/.travis/downstream.d/certbot.sh#L8-L9. +# We should try to remember to keep their repo updated if we make any changes +# to this script which may break things for them. from __future__ import absolute_import diff --git a/tox.cover.py b/tox.cover.py index 4848b2740..dc2ce5226 100755 --- a/tox.cover.py +++ b/tox.cover.py @@ -14,7 +14,7 @@ DEFAULT_PACKAGES = [ 'certbot_dns_sakuracloud', 'certbot_nginx'] COVER_THRESHOLDS = { - 'certbot': {'linux': 96, 'windows': 96}, + 'certbot': {'linux': 95, 'windows': 96}, 'acme': {'linux': 100, 'windows': 99}, 'certbot_apache': {'linux': 100, 'windows': 100}, 'certbot_dns_cloudflare': {'linux': 98, 'windows': 98},