Merge pull request #9460 from alexzorin/2.0.x

Merge `master` into `2.0.x`
This commit is contained in:
Brad Warren 2022-11-11 12:36:48 -08:00 committed by GitHub
commit 10f60bab0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 487 additions and 388 deletions

View file

@ -210,6 +210,7 @@ Authors
* [Peter Conrad](https://github.com/pconrad-fb)
* [Peter Eckersley](https://github.com/pde)
* [Peter Mosmans](https://github.com/PeterMosmans)
* [Phil Martin](https://github.com/frillip)
* [Philippe Langlois](https://github.com/langloisjp)
* [Philipp Spitzer](https://github.com/spitza)
* [Piero Steinger](https://github.com/Jadaw1n)

View file

@ -141,7 +141,7 @@ class Error(jose.JSONObjectWithFields, errors.Error):
# Mypy does not understand the josepy magic happening here, and falsely claims
# that subproblems is redefined. Let's ignore the type check here.
@subproblems.decoder # type: ignore
def subproblems(value: List[Dict[str, Any]]) -> Tuple['Error', ...]: # type: ignore[misc] # pylint: disable=no-self-argument,missing-function-docstring
def subproblems(value: List[Dict[str, Any]]) -> Tuple['Error', ...]: # pylint: disable=no-self-argument,missing-function-docstring
return tuple(Error.from_json(subproblem) for subproblem in value)
@classmethod
@ -546,7 +546,7 @@ class Authorization(ResourceBody):
# Mypy does not understand the josepy magic happening here, and falsely claims
# that challenge is redefined. Let's ignore the type check here.
@challenges.decoder # type: ignore
def challenges(value: List[Dict[str, Any]]) -> Tuple[ChallengeBody, ...]: # type: ignore[misc] # pylint: disable=no-self-argument,missing-function-docstring
def challenges(value: List[Dict[str, Any]]) -> Tuple[ChallengeBody, ...]: # pylint: disable=no-self-argument,missing-function-docstring
return tuple(ChallengeBody.from_json(chall) for chall in value)
@ -629,7 +629,7 @@ class Order(ResourceBody):
# Mypy does not understand the josepy magic happening here, and falsely claims
# that identifiers is redefined. Let's ignore the type check here.
@identifiers.decoder # type: ignore
def identifiers(value: List[Dict[str, Any]]) -> Tuple[Identifier, ...]: # type: ignore[misc] # pylint: disable=no-self-argument,missing-function-docstring
def identifiers(value: List[Dict[str, Any]]) -> Tuple[Identifier, ...]: # pylint: disable=no-self-argument,missing-function-docstring
return tuple(Identifier.from_json(identifier) for identifier in value)

View file

@ -3,6 +3,6 @@ usage: jws [-h] [--compact] {sign,verify} ...
positional arguments:
{sign,verify}
options:
optional arguments:
-h, --help show this help message and exit
--compact

View file

@ -136,20 +136,18 @@ def included_in_paths(filepath: str, paths: Iterable[str]) -> bool:
return any(fnmatch.fnmatch(filepath, path) for path in paths)
def parse_defines(apachectl: str) -> Dict[str, str]:
def parse_defines(define_cmd: List[str]) -> Dict[str, str]:
"""
Gets Defines from httpd process and returns a dictionary of
the defined variables.
:param str apachectl: Path to apachectl executable
:param list define_cmd: httpd command to dump defines
:returns: dictionary of defined variables
:rtype: dict
"""
variables: Dict[str, str] = {}
define_cmd = [apachectl, "-t", "-D",
"DUMP_RUN_CFG"]
matches = parse_from_subprocess(define_cmd, r"Define: ([^ \n]*)")
try:
matches.remove("DUMP_RUN_CFG")
@ -165,33 +163,31 @@ def parse_defines(apachectl: str) -> Dict[str, str]:
return variables
def parse_includes(apachectl: str) -> List[str]:
def parse_includes(inc_cmd: List[str]) -> List[str]:
"""
Gets Include directives from httpd process and returns a list of
their values.
:param str apachectl: Path to apachectl executable
:param list inc_cmd: httpd command to dump includes
:returns: list of found Include directive values
:rtype: list of str
"""
inc_cmd: List[str] = [apachectl, "-t", "-D", "DUMP_INCLUDES"]
return parse_from_subprocess(inc_cmd, r"\(.*\) (.*)")
def parse_modules(apachectl: str) -> List[str]:
def parse_modules(mod_cmd: List[str]) -> List[str]:
"""
Get loaded modules from httpd process, and return the list
of loaded module names.
:param str apachectl: Path to apachectl executable
:param list mod_cmd: httpd command to dump loaded modules
:returns: list of found LoadModule module names
:rtype: list of str
"""
mod_cmd = [apachectl, "-t", "-D", "DUMP_MODULES"]
return parse_from_subprocess(mod_cmd, r"(.*)_module")

View file

@ -118,7 +118,8 @@ class ApacheBlockNode(ApacheDirectiveNode):
# pylint: disable=unused-argument
def add_child_directive(self, name: str, parameters: Optional[List[str]] = None,
position: int = None) -> ApacheDirectiveNode: # pragma: no cover
position: Optional[int] = None
) -> ApacheDirectiveNode: # pragma: no cover
"""Adds a new DirectiveNode to the sequence of children"""
new_dir = ApacheDirectiveNode(name=assertions.PASS,
parameters=assertions.PASS,

View file

@ -85,6 +85,10 @@ class OsOptions:
self.restart_cmd = ['apache2ctl', 'graceful'] if not restart_cmd else restart_cmd
self.restart_cmd_alt = restart_cmd_alt
self.conftest_cmd = ['apache2ctl', 'configtest'] if not conftest_cmd else conftest_cmd
syntax_tests_cmd_base = [ctl, '-t', '-D']
self.get_defines_cmd = syntax_tests_cmd_base + ['DUMP_RUN_CFG']
self.get_includes_cmd = syntax_tests_cmd_base + ['DUMP_INCLUDES']
self.get_modules_cmd = syntax_tests_cmd_base + ['DUMP_MODULES']
self.enmod = enmod
self.dismod = dismod
self.le_vhost_ext = le_vhost_ext
@ -166,6 +170,17 @@ class ApacheConfigurator(common.Configurator):
return apache_util.find_ssl_apache_conf("old")
return apache_util.find_ssl_apache_conf("current")
def _override_cmds(self) -> None:
"""
Set our various command binaries to whatever the user has overridden for apachectl
"""
self.options.version_cmd[0] = self.options.ctl
self.options.restart_cmd[0] = self.options.ctl
self.options.conftest_cmd[0] = self.options.ctl
self.options.get_modules_cmd[0] = self.options.ctl
self.options.get_includes_cmd[0] = self.options.ctl
self.options.get_defines_cmd[0] = self.options.ctl
def _prepare_options(self) -> None:
"""
Set the values possibly changed by command line parameters to
@ -181,10 +196,7 @@ class ApacheConfigurator(common.Configurator):
else:
setattr(self.options, o, getattr(self.OS_DEFAULTS, o))
# Special cases
self.options.version_cmd[0] = self.options.ctl
self.options.restart_cmd[0] = self.options.ctl
self.options.conftest_cmd[0] = self.options.ctl
self._override_cmds()
@classmethod
def add_parser_arguments(cls, add: Callable[..., None]) -> None:
@ -476,9 +488,9 @@ class ApacheConfigurator(common.Configurator):
if HAS_APACHECONFIG:
apache_vars = {
"defines": apache_util.parse_defines(self.options.ctl),
"includes": apache_util.parse_includes(self.options.ctl),
"modules": apache_util.parse_modules(self.options.ctl),
"defines": apache_util.parse_defines(self.options.get_defines_cmd),
"includes": apache_util.parse_includes(self.options.get_includes_cmd),
"modules": apache_util.parse_modules(self.options.get_modules_cmd),
}
metadata["apache_vars"] = apache_vars
@ -800,7 +812,7 @@ class ApacheConfigurator(common.Configurator):
return self._find_best_vhost(target, filtered_vhosts, filter_defaults)
def _find_best_vhost(
self, target_name: str, vhosts: List[obj.VirtualHost] = None,
self, target_name: str, vhosts: Optional[List[obj.VirtualHost]] = None,
filter_defaults: bool = True
) -> Optional[obj.VirtualHost]:
"""Finds the best vhost for a target_name.

View file

@ -22,6 +22,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator):
vhost_files="*.conf",
logs_root="/var/log/httpd",
ctl="apachectl",
apache_bin="httpd",
version_cmd=['apachectl', '-v'],
restart_cmd=['apachectl', 'graceful'],
restart_cmd_alt=['apachectl', 'restart'],
@ -48,6 +49,37 @@ class CentOSConfigurator(configurator.ApacheConfigurator):
else:
raise
def _rhel9_or_newer(self) -> bool:
os_name, os_version = util.get_os_info()
rhel_derived = os_name in [
"centos", "centos linux",
"cloudlinux",
"ol", "oracle",
"rhel", "redhatenterpriseserver", "red hat enterprise linux server",
"scientific", "scientific linux",
]
at_least_v9 = util.parse_loose_version(os_version) >= util.parse_loose_version('9')
return rhel_derived and at_least_v9
def _override_cmds(self) -> None:
super()._override_cmds()
# As of RHEL 9, apachectl can't be passed flags like "-v" or "-t -D", so
# instead use options.bin (i.e. httpd) for version_cmd and the various
# get_X commands
if self._rhel9_or_newer():
if not self.options.bin:
raise ValueError("OS option apache_bin must be set for CentOS") # pragma: no cover
self.options.version_cmd[0] = self.options.bin
self.options.get_modules_cmd[0] = self.options.bin
self.options.get_includes_cmd[0] = self.options.bin
self.options.get_defines_cmd[0] = self.options.bin
if not self.options.restart_cmd_alt: # pragma: no cover
raise ValueError("OS option restart_cmd_alt must be set for CentOS.")
self.options.restart_cmd_alt[0] = self.options.ctl
def _try_restart_fedora(self) -> None:
"""
Tries to restart httpd using systemctl to generate the self signed key pair.
@ -61,16 +93,6 @@ class CentOSConfigurator(configurator.ApacheConfigurator):
# Finish with actual config check to see if systemctl restart helped
super().config_test()
def _prepare_options(self) -> None:
"""
Override the options dictionary initialization in order to support
alternative restart cmd used in CentOS.
"""
super()._prepare_options()
if not self.options.restart_cmd_alt: # pragma: no cover
raise ValueError("OS option restart_cmd_alt must be set for CentOS.")
self.options.restart_cmd_alt[0] = self.options.ctl
def get_parser(self) -> "CentOSParser":
"""Initializes the ApacheParser"""
return CentOSParser(

View file

@ -297,7 +297,7 @@ class ApacheParser:
def update_defines(self) -> None:
"""Updates the dictionary of known variables in the configuration"""
self.variables = apache_util.parse_defines(self.configurator.options.ctl)
self.variables = apache_util.parse_defines(self.configurator.options.get_defines_cmd)
def update_includes(self) -> None:
"""Get includes from httpd process, and add them to DOM if needed"""
@ -307,7 +307,7 @@ class ApacheParser:
# configuration files
_ = self.find_dir("Include")
matches = apache_util.parse_includes(self.configurator.options.ctl)
matches = apache_util.parse_includes(self.configurator.options.get_includes_cmd)
if matches:
for i in matches:
if not self.parsed_in_current(i):
@ -316,7 +316,7 @@ class ApacheParser:
def update_modules(self) -> None:
"""Get loaded modules from httpd process, and add them to DOM"""
matches = apache_util.parse_modules(self.configurator.options.ctl)
matches = apache_util.parse_modules(self.configurator.options.get_modules_cmd)
for mod in matches:
self.add_mod(mod.strip())

View file

@ -5,8 +5,8 @@ from unittest import mock
from certbot import errors
from certbot.compat import filesystem
from certbot.compat import os
from certbot_apache._internal import obj
from certbot_apache._internal import override_centos
from certbot_apache._internal import obj
import util
@ -84,10 +84,8 @@ class FedoraRestartTest(util.ApacheTest):
['systemctl', 'restart', 'httpd'])
class MultipleVhostsTestCentOS(util.ApacheTest):
"""Multiple vhost tests for CentOS / RHEL family of distros"""
_multiprocess_can_split_ = True
class UseCorrectApacheExecutableTest(util.ApacheTest):
"""Make sure the various CentOS/RHEL versions use the right httpd executable"""
def setUp(self): # pylint: disable=arguments-differ
test_dir = "centos7_apache/apache"
@ -97,6 +95,55 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
config_root=config_root,
vhost_root=vhost_root)
@mock.patch("certbot.util.get_os_info")
def test_old_centos_rhel_and_fedora(self, mock_get_os_info):
for os_info in [("centos", "7"), ("rhel", "7"), ("fedora", "28"), ("scientific", "6")]:
mock_get_os_info.return_value = os_info
config = util.get_apache_configurator(
self.config_path, self.vhost_path, self.config_dir, self.work_dir,
os_info="centos")
self.assertEqual(config.options.ctl, "apachectl")
self.assertEqual(config.options.bin, "httpd")
self.assertEqual(config.options.version_cmd, ["apachectl", "-v"])
self.assertEqual(config.options.restart_cmd, ["apachectl", "graceful"])
self.assertEqual(config.options.restart_cmd_alt, ["apachectl", "restart"])
self.assertEqual(config.options.conftest_cmd, ["apachectl", "configtest"])
self.assertEqual(config.options.get_defines_cmd, ["apachectl", "-t", "-D", "DUMP_RUN_CFG"])
self.assertEqual(config.options.get_includes_cmd, ["apachectl", "-t", "-D", "DUMP_INCLUDES"])
self.assertEqual(config.options.get_modules_cmd, ["apachectl", "-t", "-D", "DUMP_MODULES"])
@mock.patch("certbot.util.get_os_info")
def test_new_rhel_derived(self, mock_get_os_info):
for os_info in [("centos", "9"), ("rhel", "9"), ("oracle", "9")]:
mock_get_os_info.return_value = os_info
config = util.get_apache_configurator(
self.config_path, self.vhost_path, self.config_dir, self.work_dir,
os_info=os_info[0])
self.assertEqual(config.options.ctl, "apachectl")
self.assertEqual(config.options.bin, "httpd")
self.assertEqual(config.options.version_cmd, ["httpd", "-v"])
self.assertEqual(config.options.restart_cmd, ["apachectl", "graceful"])
self.assertEqual(config.options.restart_cmd_alt, ["apachectl", "restart"])
self.assertEqual(config.options.conftest_cmd, ["apachectl", "configtest"])
self.assertEqual(config.options.get_defines_cmd, ["httpd", "-t", "-D", "DUMP_RUN_CFG"])
self.assertEqual(config.options.get_includes_cmd, ["httpd", "-t", "-D", "DUMP_INCLUDES"])
self.assertEqual(config.options.get_modules_cmd, ["httpd", "-t", "-D", "DUMP_MODULES"])
class MultipleVhostsTestCentOS(util.ApacheTest):
"""Multiple vhost tests for CentOS / RHEL family of distros"""
_multiprocess_can_split_ = True
@mock.patch("certbot.util.get_os_info")
def setUp(self, mock_get_os_info): # pylint: disable=arguments-differ
test_dir = "centos7_apache/apache"
config_root = "centos7_apache/apache/httpd"
vhost_root = "centos7_apache/apache/httpd/conf.d"
super().setUp(test_dir=test_dir,
config_root=config_root,
vhost_root=vhost_root)
mock_get_os_info.return_value = ("centos", "9")
self.config = util.get_apache_configurator(
self.config_path, self.vhost_path, self.config_dir, self.work_dir,
os_info="centos")
@ -120,9 +167,9 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
)
def mock_get_cfg(command):
"""Mock httpd process stdout"""
if command == ['apachectl', '-t', '-D', 'DUMP_RUN_CFG']:
if command == ['httpd', '-t', '-D', 'DUMP_RUN_CFG']:
return define_val
elif command == ['apachectl', '-t', '-D', 'DUMP_MODULES']:
elif command == ['httpd', '-t', '-D', 'DUMP_MODULES']:
return mod_val
return ""
mock_get.side_effect = mock_get_cfg
@ -131,7 +178,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
with mock.patch("certbot.util.get_os_info") as mock_osi:
# Make sure we have the have the CentOS httpd constants
mock_osi.return_value = ("centos", "7")
mock_osi.return_value = ("centos", "9")
self.config.parser.update_runtime_variables()
self.assertEqual(mock_get.call_count, 3)
@ -166,7 +213,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
with mock.patch("certbot.util.get_os_info") as mock_osi:
# Make sure we have the have the CentOS httpd constants
mock_osi.return_value = ("centos", "7")
mock_osi.return_value = ("centos", "9")
self.config.parser.update_runtime_variables()
self.assertIn("mock_define", self.config.parser.variables)

View file

@ -119,6 +119,7 @@ def get_apache_configurator(
# Custom virtualhost path was requested
config.config.apache_vhost_root = conf_vhost_path
config.config.apache_ctl = config_class.OS_DEFAULTS.ctl
config.config.apache_bin = config_class.OS_DEFAULTS.bin
config.prepare()
return config

View file

@ -17,8 +17,8 @@ class IntegrationTestsContext:
self.request = request
if hasattr(request.config, 'workerinput'): # Worker node
self.worker_id = request.config.workerinput['workerid'] # type: ignore[attr-defined]
acme_xdist = request.config.workerinput['acme_xdist'] # type: ignore[attr-defined]
self.worker_id = request.config.workerinput['workerid']
acme_xdist = request.config.workerinput['acme_xdist']
else: # Primary node
self.worker_id = 'primary'
acme_xdist = request.config.acme_xdist # type: ignore[attr-defined]

View file

@ -9,6 +9,7 @@ import pytest
from certbot_integration_tests.certbot_tests import context as certbot_context
from certbot_integration_tests.nginx_tests import nginx_config as config
from certbot_integration_tests.utils import certbot_call
from certbot_integration_tests.utils import constants
from certbot_integration_tests.utils import misc
@ -65,4 +66,4 @@ class IntegrationTestsContext(certbot_context.IntegrationTestsContext):
def _stop_nginx(self) -> None:
assert self.process.poll() is None
self.process.terminate()
self.process.wait()
self.process.wait(constants.MAX_SUBPROCESS_WAIT)

View file

@ -21,7 +21,7 @@ class IntegrationTestsContext(certbot_context.IntegrationTestsContext):
self.request = request
if hasattr(request.config, 'workerinput'): # Worker node
self._dns_xdist = request.config.workerinput['dns_xdist'] # type: ignore[attr-defined]
self._dns_xdist = request.config.workerinput['dns_xdist']
else: # Primary node
self._dns_xdist = request.config.dns_xdist # type: ignore[attr-defined]

View file

@ -18,6 +18,7 @@ from typing import Dict
from typing import List
from typing import Mapping
from typing import Optional
from typing import Tuple
from typing import Type
import requests
@ -63,6 +64,7 @@ class ACMEServer:
self._stdout = sys.stdout if stdout else open(os.devnull, 'w') # pylint: disable=consider-using-with
self._dns_server = dns_server
self._http_01_port = http_01_port
self._preterminate_cmds_args: List[Tuple[Tuple[Any, ...], Dict[str, Any]]] = []
if http_01_port != DEFAULT_HTTP_01_PORT:
if self._acme_type != 'pebble' or self._proxy:
raise ValueError('setting http_01_port is not currently supported '
@ -85,6 +87,7 @@ class ACMEServer:
"""Stop the test stack, and clean its resources"""
print('=> Tear down the test infrastructure...')
try:
self._run_preterminate_cmds()
for process in self._processes:
try:
process.terminate()
@ -94,17 +97,7 @@ class ACMEServer:
if e.errno != errno.ESRCH:
raise
for process in self._processes:
process.wait()
if os.path.exists(os.path.join(self._workspace, 'boulder')):
# Boulder docker generates build artifacts owned by root with 0o744 permissions.
# If we started the acme server from a normal user that has access to the Docker
# daemon, this user will not be able to delete these artifacts from the host.
# We need to do it through a docker.
process = self._launch_process(['docker', 'run', '--rm', '-v',
'{0}:/workspace'.format(self._workspace),
'alpine', 'rm', '-rf', '/workspace/boulder'])
process.wait()
process.wait(MAX_SUBPROCESS_WAIT)
finally:
if os.path.exists(self._workspace):
shutil.rmtree(self._workspace)
@ -187,7 +180,7 @@ class ACMEServer:
# Load Boulder from git, that includes a docker-compose.yml ready for production.
process = self._launch_process(['git', 'clone', 'https://github.com/letsencrypt/boulder',
'--single-branch', '--depth=1', instance_path])
process.wait()
process.wait(MAX_SUBPROCESS_WAIT)
# Allow Boulder to ignore usual limit rate policies, useful for tests.
os.rename(join(instance_path, 'test/rate-limit-policies-b.yml'),
@ -202,6 +195,17 @@ class ACMEServer:
with open(join(instance_path, 'test/config/va{}.json'.format(suffix)), 'w') as f:
f.write(json.dumps(config, indent=2, separators=(',', ': ')))
# This command needs to be run before we try and terminate running processes because
# docker-compose up doesn't always respond to SIGTERM. See
# https://github.com/certbot/certbot/pull/9435.
self._register_preterminate_cmd(['docker-compose', 'down'], cwd=instance_path)
# Boulder docker generates build artifacts owned by root with 0o744 permissions.
# If we started the acme server from a normal user that has access to the Docker
# daemon, this user will not be able to delete these artifacts from the host.
# We need to do it through a docker.
self._register_preterminate_cmd(['docker', 'run', '--rm', '-v',
'{0}:/workspace'.format(self._workspace), 'alpine', 'rm',
'-rf', '/workspace/boulder'])
try:
# Launch the Boulder server
self._launch_process(['docker-compose', 'up', '--force-recreate'], cwd=instance_path)
@ -224,7 +228,7 @@ class ACMEServer:
process = self._launch_process([
'docker-compose', 'logs'], cwd=instance_path, force_stderr=True
)
process.wait()
process.wait(MAX_SUBPROCESS_WAIT)
raise
print('=> Finished boulder instance deployment.')
@ -253,6 +257,17 @@ class ACMEServer:
self._processes.append(process)
return process
def _register_preterminate_cmd(self, *args: Any, **kwargs: Any) -> None:
self._preterminate_cmds_args.append((args, kwargs))
def _run_preterminate_cmds(self) -> None:
for args, kwargs in self._preterminate_cmds_args:
process = self._launch_process(*args, **kwargs)
process.wait(MAX_SUBPROCESS_WAIT)
# It's unlikely to matter, but let's clear the list of cleanup commands
# once they've been run.
self._preterminate_cmds_args.clear()
def main() -> None:
# pylint: disable=missing-function-docstring

View file

@ -9,3 +9,4 @@ PEBBLE_MANAGEMENT_URL = 'https://localhost:15000'
PEBBLE_CHALLTESTSRV_URL = f'http://localhost:{CHALLTESTSRV_PORT}'
MOCK_OCSP_SERVER_PORT = 4002
PEBBLE_ALTERNATE_ROOTS = 2
MAX_SUBPROCESS_WAIT = 120

View file

@ -17,6 +17,8 @@ from typing import Type
from pkg_resources import resource_filename
from certbot_integration_tests.utils import constants
BIND_DOCKER_IMAGE = "internetsystemsconsortium/bind9:9.16"
BIND_BIND_ADDRESS = ("127.0.0.1", 45953)
@ -67,7 +69,7 @@ class DNSServer:
if self.process:
try:
self.process.terminate()
self.process.wait()
self.process.wait(constants.MAX_SUBPROCESS_WAIT)
except BaseException as e:
print("BIND9 did not stop cleanly: {}".format(e), file=sys.stderr)

View file

@ -15,7 +15,6 @@ if parse_version(setuptools_version) < parse_version(min_setuptools_version):
install_requires = [
'coverage',
'cryptography',
'docker-compose',
'pyopenssl',
'pytest',
'pytest-cov',

View file

@ -107,12 +107,11 @@ permission to issue updates on the target DNS zone.
.. code-block:: bash
:caption: Generate a new SHA512 TSIG key
dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST keyname.
tsig-keygen -a HMAC-SHA512 keyname.
.. note::
There are a few tools shipped with BIND that can all generate TSIG keys;
``dnssec-keygen``, ``rndc-confgen``, and ``ddns-confgen``. Try and use the
most secure algorithm supported by your DNS server.
Prior to BIND version 9.10.0, you will need to use ``dnssec-keygen`` to generate
TSIG keys. Try and use the most secure algorithm supported by your DNS server.
.. code-block:: none
:caption: Sample BIND configuration

View file

@ -216,6 +216,8 @@ class _RFC2136Client:
request = dns.message.make_query(domain, dns.rdatatype.SOA, dns.rdataclass.IN)
# Turn off Recursion Desired bit in query
request.flags ^= dns.flags.RD
# Use our TSIG keyring
request.use_tsig(self.keyring, algorithm=self.algorithm) # type: ignore[attr-defined]
try:
try:

View file

@ -1112,7 +1112,7 @@ class NginxConfigurator(common.Configurator):
###################################################
# Wrapper functions for Reverter class (Installer)
###################################################
def save(self, title: str = None, temporary: bool = False) -> None:
def save(self, title: Optional[str] = None, temporary: bool = False) -> None:
"""Saves all changes to the configuration files.
:param str title: The title of the save. If a title is given, the

View file

@ -2,7 +2,7 @@
Certbot adheres to [Semantic Versioning](https://semver.org/).
## 1.32.0 - master
## 1.33.0 - master
### Added
@ -18,6 +18,23 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
More details about these changes can be found on our GitHub repo.
## 1.32.0 - 2022-11-08
### Added
*
### Changed
* DNS RFC2136 module now uses the TSIG key to check for an authoritative SOA record. Helps the use of split-horizon and multiple views in BIND9 using the key in an ACL to determine which view to use.
### Fixed
* CentOS 9 and other RHEL-derived OSes now correctly use httpd instead of apachectl for
various Apache-related commands
More details about these changes can be found on our GitHub repo.
## 1.31.0 - 2022-10-04
### Added

View file

@ -108,7 +108,7 @@ class Account:
class AccountMemoryStorage(interfaces.AccountStorage):
"""In-memory account storage."""
def __init__(self, initial_accounts: Dict[str, Account] = None) -> None:
def __init__(self, initial_accounts: Optional[Dict[str, Account]] = None) -> None:
self.accounts = initial_accounts if initial_accounts is not None else {}
def find_all(self) -> List[Account]:

View file

@ -11,6 +11,7 @@ def get_completer() -> Optional[Callable[[], str]]:
def get_completer_delims() -> List[str]:
"""An empty implementation of readline.get_completer_delims."""
return []
def parse_and_bind(unused_command: str) -> None:

View file

@ -1683,7 +1683,7 @@ def make_displayer(config: configuration.NamespaceConfig
devnull.close()
def main(cli_args: List[str] = None) -> Optional[Union[str, int]]:
def main(cli_args: Optional[List[str]] = None) -> Optional[Union[str, int]]:
"""Run Certbot.
:param cli_args: command line to Certbot, defaults to ``sys.argv[1:]``

View file

@ -39,7 +39,7 @@ from certbot.plugins import common
class DummyInstaller(common.Installer):
"""Dummy installer plugin for test purpose."""
def get_all_names(self) -> Iterable[str]:
pass
return []
def deploy_cert(self, domain: str, cert_path: str, key_path: str, chain_path: str,
fullchain_path: str) -> None:
@ -50,7 +50,7 @@ class DummyInstaller(common.Installer):
pass
def supported_enhancements(self) -> List[str]:
pass
return []
def save(self, title: Optional[str] = None, temporary: bool = False) -> None:
pass
@ -69,7 +69,7 @@ class DummyInstaller(common.Installer):
pass
def more_info(self) -> str:
pass
return ""
def vector_path(*names: str) -> str:
@ -253,7 +253,7 @@ class FreezableMock:
value of func is ignored.
"""
def __init__(self, frozen: bool = False, func: Callable[..., Any] = None,
def __init__(self, frozen: bool = False, func: Optional[Callable[..., Any]] = None,
return_value: Any = mock.sentinel.DEFAULT) -> None:
self._frozen_set = set() if frozen else {'freeze', }
self._func = func

View file

@ -35,7 +35,7 @@ manage your account:
--agree-tos Agree to the ACME server's Subscriber Agreement
-m EMAIL Email address for important account notifications
options:
optional arguments:
-h, --help show this help message and exit
-c CONFIG_FILE, --config CONFIG_FILE
path to config file (default: /etc/letsencrypt/cli.ini
@ -126,7 +126,7 @@ options:
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.31.0 (certbot;
"". (default: CertbotACMEClient/1.32.0 (certbot;
OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
The flags encoded in the user agent are: --duplicate,

View file

@ -321,6 +321,7 @@ njalla_ Y N DNS Authentication for njalla
DuckDNS_ Y N DNS Authentication for DuckDNS
Porkbun_ Y N DNS Authentication for Porkbun
Infomaniak_ Y N DNS Authentication using Infomaniak Domains API
dns-multi_ Y N DNS authentication of 100+ providers using go-acme/lego
================== ==== ==== ===============================================================
.. _haproxy: https://github.com/greenhost/certbot-haproxy
@ -343,6 +344,7 @@ Infomaniak_ Y N DNS Authentication using Infomaniak Domains API
.. _DuckDNS: https://github.com/infinityofspace/certbot_dns_duckdns
.. _Porkbun: https://github.com/infinityofspace/certbot_dns_porkbun
.. _Infomaniak: https://github.com/Infomaniak/certbot-dns-infomaniak
.. _dns-multi: https://github.com/alexzorin/certbot-dns-multi
If you're interested, you can also :ref:`write your own plugin <dev-plugin>`.

View file

@ -67,7 +67,11 @@ dev_extras = [
'ipdb',
# poetry 1.2.0+ is required for it to pin pip, setuptools, and wheel. See
# https://github.com/python-poetry/poetry/issues/1584.
'poetry>=1.2.0a1',
'poetry>=1.2.0',
# poetry-plugin-export>=1.1.0 is required to use the constraints.txt export
# format. See
# https://github.com/python-poetry/poetry-plugin-export/blob/efcfd34859e72f6a79a80398f197ce6eb2bbd7cd/CHANGELOG.md#added.
'poetry-plugin-export>=1.1.0',
'twine',
]

View file

@ -16,7 +16,10 @@
# 2) botocore's default TLS settings raise deprecation warnings in Python
# 3.10+, but their values are sane from a security perspective. See
# https://github.com/boto/botocore/issues/2550.
# 3) pytest-cov uses deprecated functionality in pytest-xdist, to be resolved by
# https://github.com/pytest-dev/pytest-cov/issues/557.
filterwarnings =
error
ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns
ignore:'urllib3.contrib.pyopenssl:DeprecationWarning:botocore
ignore:.*rsyncdir:DeprecationWarning

View file

@ -46,6 +46,10 @@ ParseRequestedArch "${2}"
TagAndPushForAllRequestedArch() {
DOCKER_REPO="${DOCKER_HUB_ORG}/${1}"
for TARGET_ARCH in "${ALL_REQUESTED_ARCH[@]}"; do
# NOTE: In early 2022, we were experiencing regular "docker push"
# timeouts, so we added these "--debug" flags to learn more. Since we
# added them, we haven't had another timeout, so until we experience
# another timeout & can get the deubg logs, we're leaving them in.
docker --debug push "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}"
if [[ "${TAG_BASE}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then

View file

@ -1,110 +1,94 @@
# This file was generated by tools/pinning/oldest/repin.sh and can be updated using
# that script.
apacheconfig==0.3.2
asn1crypto==0.24.0
astroid==2.11.7; python_version >= "3.7"
atomicwrites==1.4.1; sys_platform == "win32" and python_version >= "3.7"
attrs==22.1.0; python_version >= "3.7"
bcrypt==3.2.2; python_version >= "3.7"
boto3==1.15.15
botocore==1.18.15
cached-property==1.5.2; python_version >= "3.7"
certifi==2022.6.15; python_version >= "3.7"
cffi==1.9.1
chardet==3.0.4
cloudflare==1.5.1
colorama==0.4.5; sys_platform == "win32" and python_version >= "3.7"
configargparse==0.10.0
configobj==5.0.6
coverage==6.4.2; python_version >= "3.7"
cryptography==3.2.1
cython==0.29.31
dill==0.3.5.1; python_version >= "3.7"
distlib==0.3.5; python_version >= "3.7"
distro==1.0.1
dns-lexicon==3.2.1
dnspython==1.15.0
docker-compose==1.25.5; python_version >= "3.7"
docker==4.2.2; python_version >= "3.7"
dockerpty==0.4.1; python_version >= "3.7"
docopt==0.6.2; python_version >= "3.7"
execnet==1.9.0; python_version >= "3.7"
filelock==3.7.1; python_version >= "3.7"
funcsigs==0.4
future==0.18.2; python_version >= "3.7"
google-api-python-client==1.5.5
httplib2==0.9.2
idna==2.6
importlib-metadata==4.12.0; python_version < "3.8" and python_version >= "3.7"
iniconfig==1.1.1; python_version >= "3.7"
ipaddress==1.0.16
isort==5.10.1; python_version >= "3.7" and python_version < "4.0"
jmespath==0.10.0; python_version >= "3.7"
josepy==1.13.0; python_version >= "3.7"
jsonschema==3.2.0; python_version >= "3.7"
lazy-object-proxy==1.7.1; python_version >= "3.7"
logger==1.4; python_version >= "3.7"
mccabe==0.7.0; python_version >= "3.7"
mypy-extensions==0.4.3; python_version >= "3.7"
mypy==0.971; python_version >= "3.7"
ndg-httpsclient==0.3.2
oauth2client==4.0.0
packaging==21.3; python_version >= "3.7"
paramiko==2.11.0; python_version >= "3.7"
parsedatetime==2.4
pbr==1.8.0
pip==22.2.1; python_version >= "3.7"
platformdirs==2.5.2; python_version >= "3.7"
pluggy==1.0.0; python_version >= "3.7"
ply==3.4
py==1.11.0; python_version >= "3.7"
pyasn1-modules==0.0.10; python_version >= "3.7"
pyasn1==0.1.9
pycparser==2.14
pylint==2.13.9
pynacl==1.5.0; python_version >= "3.7"
pyopenssl==17.5.0
pyparsing==2.2.1
pypiwin32==223; sys_platform == "win32" and python_version >= "3.7"
pyrfc3339==1.0
pyrsistent==0.18.1; python_version >= "3.7"
pytest-cov==3.0.0; python_version >= "3.7"
pytest-forked==1.4.0; python_version >= "3.7"
pytest-xdist==2.5.0; python_version >= "3.7"
pytest==7.1.2; python_version >= "3.7"
python-augeas==0.5.0
python-dateutil==2.8.2; python_version >= "3.7"
python-digitalocean==1.11
pytz==2019.3
pywin32==304; sys_platform == "win32" and python_version >= "3.7"
pyyaml==5.4.1; python_version >= "3.7"
requests-file==1.5.1; python_version >= "3.7"
requests-toolbelt==0.9.1; python_version >= "3.7"
requests==2.20.0
rsa==4.9; python_version >= "3.7" and python_version < "4"
s3transfer==0.3.7; python_version >= "3.7"
setuptools==41.6.0
six==1.11.0
texttable==1.6.4; python_version >= "3.7"
tldextract==3.3.1; python_version >= "3.7"
tomli==2.0.1; python_version < "3.11" and python_version >= "3.7" or python_full_version <= "3.11.0a6" and python_version >= "3.7" or python_version >= "3.7"
tox==1.9.2; python_version >= "3.7"
typed-ast==1.5.4; python_version >= "3.7" and python_version < "3.8" or implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.7"
types-cryptography==3.3.21; python_version >= "3.7"
types-pyopenssl==22.0.9; python_version >= "3.7"
types-pyrfc3339==1.1.1; python_version >= "3.7"
types-python-dateutil==2.8.19; python_version >= "3.7"
types-pytz==2022.1.2; python_version >= "3.7"
types-requests==2.28.5; python_version >= "3.7"
types-setuptools==63.2.2; python_version >= "3.7"
types-six==1.16.18; python_version >= "3.7"
types-urllib3==1.26.17; python_version >= "3.7"
typing-extensions==4.3.0; python_version >= "3.7" or python_version < "3.10" and python_version >= "3.7" or python_version < "3.8" and python_version >= "3.7"
uritemplate==3.0.1; python_version >= "3.7"
urllib3==1.24.2
virtualenv==20.16.2; python_version >= "3.7"
websocket-client==0.59.0; python_version >= "3.7"
wheel==0.33.6
wheel==0.33.6; python_version >= "3.7"
wrapt==1.14.1; python_version >= "3.7"
zipp==3.8.1; python_version < "3.8" and python_version >= "3.7"
apacheconfig==0.3.2 ; python_full_version < "3.8.0" and python_version >= "3.7"
asn1crypto==0.24.0 ; python_full_version >= "3.7.0" and python_full_version < "3.8.0"
astroid==2.11.7 ; python_full_version < "3.8.0" and python_version >= "3.7"
attrs==22.1.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
boto3==1.15.15 ; python_full_version < "3.8.0" and python_version >= "3.7"
botocore==1.18.15 ; python_full_version < "3.8.0" and python_version >= "3.7"
certifi==2022.9.24 ; python_full_version < "3.8.0" and python_version >= "3.7"
cffi==1.9.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
chardet==3.0.4 ; python_full_version < "3.8.0" and python_version >= "3.7"
cloudflare==1.5.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
colorama==0.4.6 ; python_full_version < "3.8.0" and sys_platform == "win32" and python_version >= "3.7"
configargparse==0.10.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
configobj==5.0.6 ; python_full_version < "3.8.0" and python_version >= "3.7"
coverage==6.5.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
cryptography==3.2.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
cython==0.29.32 ; python_full_version >= "3.7.0" and python_full_version < "3.8.0"
dill==0.3.6 ; python_version >= "3.7" and python_full_version < "3.8.0"
distlib==0.3.6 ; python_version >= "3.7" and python_full_version < "3.8.0"
distro==1.0.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
dns-lexicon==3.2.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
dnspython==1.15.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
exceptiongroup==1.0.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
execnet==1.9.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
filelock==3.8.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
funcsigs==0.4 ; python_full_version >= "3.7.0" and python_full_version < "3.8.0"
future==0.18.2 ; python_full_version < "3.8.0" and python_version >= "3.7"
google-api-python-client==1.5.5 ; python_full_version < "3.8.0" and python_version >= "3.7"
httplib2==0.9.2 ; python_full_version < "3.8.0" and python_version >= "3.7"
idna==2.6 ; python_full_version < "3.8.0" and python_version >= "3.7"
importlib-metadata==5.0.0 ; python_version >= "3.7" and python_version < "3.8"
iniconfig==1.1.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
ipaddress==1.0.16 ; python_full_version >= "3.7.0" and python_full_version < "3.8.0"
isort==5.10.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
jmespath==0.10.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
josepy==1.13.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
lazy-object-proxy==1.8.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
logger==1.4 ; python_full_version < "3.8.0" and python_version >= "3.7"
mccabe==0.7.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
mypy-extensions==0.4.3 ; python_version >= "3.7" and python_full_version < "3.8.0"
mypy==0.990 ; python_version >= "3.7" and python_full_version < "3.8.0"
ndg-httpsclient==0.3.2 ; python_full_version >= "3.7.0" and python_full_version < "3.8.0"
oauth2client==4.0.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
packaging==21.3 ; python_version >= "3.7" and python_full_version < "3.8.0"
parsedatetime==2.4 ; python_full_version < "3.8.0" and python_version >= "3.7"
pbr==1.8.0 ; python_full_version >= "3.7.0" and python_full_version < "3.8.0"
pip==22.3.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
platformdirs==2.5.3 ; python_version >= "3.7" and python_full_version < "3.8.0"
pluggy==1.0.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
ply==3.4 ; python_full_version < "3.8.0" and python_version >= "3.7"
py==1.11.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
pyasn1-modules==0.0.10 ; python_full_version < "3.8.0" and python_version >= "3.7"
pyasn1==0.1.9 ; python_full_version < "3.8.0" and python_version >= "3.7"
pycparser==2.14 ; python_full_version < "3.8.0" and python_version >= "3.7"
pylint==2.13.9 ; python_full_version < "3.8.0" and python_version >= "3.7"
pyopenssl==17.5.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
pyparsing==2.2.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
pyrfc3339==1.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
pytest-cov==4.0.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
pytest-xdist==3.0.2 ; python_version >= "3.7" and python_full_version < "3.8.0"
pytest==7.2.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
python-augeas==0.5.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
python-dateutil==2.8.2 ; python_full_version < "3.8.0" and python_version >= "3.7"
python-digitalocean==1.11 ; python_full_version < "3.8.0" and python_version >= "3.7"
pytz==2019.3 ; python_full_version < "3.8.0" and python_version >= "3.7"
pywin32==305 ; python_version >= "3.7" and python_full_version < "3.8.0" and sys_platform == "win32"
pyyaml==6.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
requests-file==1.5.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
requests==2.20.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
rsa==4.9 ; python_full_version < "3.8.0" and python_version >= "3.7"
s3transfer==0.3.7 ; python_full_version < "3.8.0" and python_version >= "3.7"
setuptools==41.6.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
six==1.11.0 ; python_full_version < "3.8.0" and python_version >= "3.7"
tldextract==3.4.0 ; python_version >= "3.7" and python_full_version < "3.8.0"
tomli==2.0.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
tox==1.9.2 ; python_version >= "3.7" and python_full_version < "3.8.0"
typed-ast==1.5.4 ; python_version < "3.8" and python_version >= "3.7"
types-cryptography==3.3.23.2 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-pyopenssl==22.1.0.2 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-pyrfc3339==1.1.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-python-dateutil==2.8.19.3 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-pytz==2022.6.0.1 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-requests==2.28.11.4 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-setuptools==65.5.0.2 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-six==1.16.21.2 ; python_version >= "3.7" and python_full_version < "3.8.0"
types-urllib3==1.26.25.3 ; python_version >= "3.7" and python_full_version < "3.8.0"
typing-extensions==4.4.0 ; python_version >= "3.7" and python_version < "3.8"
uritemplate==3.0.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
urllib3==1.24.2 ; python_full_version < "3.8.0" and python_version >= "3.7"
virtualenv==20.16.6 ; python_version >= "3.7" and python_full_version < "3.8.0"
wheel==0.33.6 ; python_full_version < "3.8.0" and python_version >= "3.7"
wrapt==1.14.1 ; python_full_version < "3.8.0" and python_version >= "3.7"
zipp==3.10.0 ; python_version >= "3.7" and python_version < "3.8"

View file

@ -37,8 +37,11 @@ if [ -f poetry.lock ]; then
rm poetry.lock
fi
poetry lock >&2
# If you're running this with different Python versions (say to update both our
# "current" and "oldest" pinnings), poetry's cache can become corrupted causing
# poetry to hang indefinitely. --no-cache avoids this.
poetry lock --no-cache >&2
trap 'rm poetry.lock' EXIT
# We need to remove local packages from the output.
poetry export --without-hashes | sed '/^acme @/d; /certbot/d;'
poetry export --format constraints.txt --without-hashes | sed '/^acme @/d; /certbot/d;'

View file

@ -50,18 +50,6 @@ awscli = ">=1.22.76"
# as a dependency here to ensure a version of cython is pinned for extra
# stability.
cython = "*"
# poetry 1.2.0+ is required for it to pin pip, setuptools, and wheel. See
# https://github.com/python-poetry/poetry/issues/1584. This version is required
# here in addition to certbot/setup.py because otherwise the pre-release
# version of poetry will not be installed.
#
# Additionally, newer versions of poetry/poetry-core include package extras
# (e.g. "docker[ssh]") in its `poetry export` output which is valid for
# requirements files, but not constraints files. We are currently using that
# output as constraints so let's also pin back poetry and poetry-core until we
# have a better workaround.
poetry = "1.2.0a2"
poetry-core = "1.1.0a7"
# setuptools-rust is a build dependency of cryptography, and since we don't have
# a great way of pinning build dependencies, we simply list it here to ensure a
# working version. Note: if build dependencies of setuptools-rust break at some

View file

@ -10,7 +10,7 @@ license = "Apache License 2.0"
[tool.poetry.dependencies]
# The Python version here should be kept in sync with the one used in our
# oldest tests in tox.ini.
python = "3.7"
python = "3.7.*"
# Local dependencies
# Any local packages that have dependencies on other local packages must be

View file

@ -5,187 +5,181 @@
# requirements.txt so that is scanned by GitHub. See
# https://docs.github.com/en/github/visualizing-repository-data-with-graphs/about-the-dependency-graph#supported-package-ecosystems
# for more info.
alabaster==0.7.12; python_version >= "3.7"
apacheconfig==0.3.2; python_version >= "3.7"
appdirs==1.4.4; python_version >= "3.7" and python_version < "4.0"
appnope==0.1.3; python_version >= "3.7" and sys_platform == "darwin"
astroid==2.11.7; python_version >= "3.7"
attrs==22.1.0; python_version >= "3.7"
awscli==1.25.76
awscli==1.25.76; python_version >= "3.7"
azure-devops==6.0.0b4; python_version >= "3.7"
babel==2.10.3; python_version >= "3.7"
backcall==0.2.0; python_version >= "3.7"
bcrypt==4.0.0; python_version >= "3.7"
beautifulsoup4==4.11.1; python_version >= "3.7"
bleach==5.0.1; python_version >= "3.7"
boto3==1.24.75; python_version >= "3.7"
botocore==1.27.75; python_version >= "3.7"
cachecontrol==0.12.12; python_version >= "3.7" and python_version < "4.0"
cached-property==1.5.2; python_version < "3.8" and python_version >= "3.7"
cachetools==5.2.0; python_version >= "3.7" and python_version < "4.0"
cachy==0.3.0; python_version >= "3.7" and python_version < "4.0"
certifi==2022.9.14; python_version >= "3.7" and python_version < "4" or python_version >= "3.7"
cffi==1.15.1; python_version >= "3.7"
charset-normalizer==2.1.1; python_version >= "3.7" and python_version < "4"
cleo==1.0.0a5; python_version >= "3.7" and python_version < "4.0"
cloudflare==2.10.1; python_version >= "3.7"
colorama==0.4.4; python_version >= "3.7"
configargparse==1.5.3; python_version >= "3.7"
configobj==5.0.6; python_version >= "3.7"
coverage==6.4.4; python_version >= "3.7"
crashtest==0.3.1; python_version >= "3.7" and python_version < "4.0"
cryptography==38.0.1
cryptography==38.0.1; python_version >= "3.7"
cython==0.29.32
decorator==5.1.1; python_version >= "3.7"
dill==0.3.5.1; python_version >= "3.7"
distlib==0.3.6; python_version >= "3.7"
distro==1.7.0; python_version >= "3.7"
dns-lexicon==3.11.1; python_version >= "3.7" and python_version < "4.0"
dnspython==2.2.1; python_version >= "3.7" and python_version < "4.0"
docker-compose==1.29.2; python_version >= "3.7"
docker==6.0.0; python_version >= "3.7"
dockerpty==0.4.1; python_version >= "3.7"
docopt==0.6.2; python_version >= "3.7"
docutils==0.16; python_version >= "3.7"
entrypoints==0.3; python_version >= "3.7" and python_version < "4.0"
execnet==1.9.0; python_version >= "3.7"
fabric==2.7.1; python_version >= "3.7"
filelock==3.8.0; python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0"
google-api-core==2.10.1; python_version >= "3.7"
google-api-python-client==2.61.0; python_version >= "3.7"
google-auth-httplib2==0.1.0; python_version >= "3.7"
google-auth==2.11.0; python_version >= "3.7"
googleapis-common-protos==1.56.4; python_version >= "3.7"
html5lib==1.1; python_version >= "3.7" and python_version < "4.0"
httplib2==0.20.4; python_version >= "3.7"
idna==3.4; python_version >= "3.7" and python_version < "4" or python_version >= "3.7" and python_version < "4.0"
imagesize==1.4.1; python_version >= "3.7"
importlib-metadata==1.7.0; python_version >= "3.7" and python_version < "3.8"
iniconfig==1.1.1; python_version >= "3.7"
invoke==1.7.1; python_version >= "3.7"
ipdb==0.13.9; python_version >= "3.7"
ipython==7.34.0; python_version >= "3.7"
isodate==0.6.1; python_version >= "3.7"
isort==5.10.1; python_version >= "3.7" and python_version < "4.0"
jedi==0.18.1; python_version >= "3.7"
jeepney==0.8.0; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
jinja2==3.1.2; python_version >= "3.7"
jmespath==1.0.1; python_version >= "3.7"
josepy==1.13.0; python_version >= "3.7"
jsonlines==3.1.0; python_version >= "3.7"
jsonpickle==2.2.0; python_version >= "3.7"
jsonschema==3.2.0; python_version >= "3.7"
keyring==22.3.0; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
lazy-object-proxy==1.7.1; python_version >= "3.7"
markupsafe==2.1.1; python_version >= "3.7"
matplotlib-inline==0.1.6; python_version >= "3.7"
mccabe==0.7.0; python_version >= "3.7"
msgpack==1.0.4; python_version >= "3.7" and python_version < "4.0"
msrest==0.6.21; python_version >= "3.7"
mypy-extensions==0.4.3; python_version >= "3.7"
mypy==0.971; python_version >= "3.7"
oauth2client==4.1.3; python_version >= "3.7"
oauthlib==3.2.1; python_version >= "3.7"
packaging==20.9; python_version >= "3.7"
paramiko==2.11.0; python_version >= "3.7"
parsedatetime==2.6; python_version >= "3.7"
parso==0.8.3; python_version >= "3.7"
pathlib2==2.3.7.post1; python_version >= "3.7"
pexpect==4.8.0; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7" and sys_platform != "win32"
pickleshare==0.7.5; python_version >= "3.7"
pip==22.2.2; python_version >= "3.7"
pkginfo==1.8.3; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
platformdirs==2.5.2; python_version >= "3.7"
pluggy==1.0.0; python_version >= "3.7"
ply==3.11; python_version >= "3.7"
poetry-core==1.1.0a7
poetry==1.2.0a2
prompt-toolkit==3.0.31; python_version >= "3.7"
protobuf==4.21.6; python_version >= "3.7"
ptyprocess==0.7.0; python_version >= "3.7" and python_version < "4.0"
py==1.11.0; python_version >= "3.7"
pyasn1-modules==0.2.8; python_version >= "3.7"
pyasn1==0.4.8; python_version >= "3.7"
pycparser==2.21; python_version >= "3.7"
pygments==2.13.0; python_version >= "3.7"
pylev==1.4.0; python_version >= "3.7" and python_version < "4.0"
pylint==2.13.9
pynacl==1.5.0; python_version >= "3.7"
pynsist==2.7; python_version >= "3.7"
pyopenssl==22.0.0; python_version >= "3.7"
pyparsing==3.0.9; python_version >= "3.7"
pyrfc3339==1.1; python_version >= "3.7"
pyrsistent==0.18.1; python_version >= "3.7"
pytest-cov==3.0.0; python_version >= "3.7"
pytest-forked==1.4.0; python_version >= "3.7"
pytest-xdist==2.5.0; python_version >= "3.7"
pytest==7.1.3; python_version >= "3.7"
python-augeas==1.1.0; python_version >= "3.7"
python-dateutil==2.8.2; python_version >= "3.7"
python-digitalocean==1.17.0; python_version >= "3.7"
python-dotenv==0.21.0; python_version >= "3.7"
pytz==2022.2.1; python_version >= "3.7"
pywin32-ctypes==0.2.0; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32"
pywin32==304; sys_platform == "win32" and python_version >= "3.7"
pyyaml==5.4.1; python_version >= "3.7"
readme-renderer==37.1; python_version >= "3.7"
requests-download==0.1.2; python_version >= "3.7"
requests-file==1.5.1; python_version >= "3.7" and python_version < "4.0"
requests-oauthlib==1.3.1; python_version >= "3.7"
requests-toolbelt==0.9.1; python_version >= "3.7"
requests==2.28.1; python_version >= "3.7" and python_version < "4"
rfc3986==2.0.0; python_version >= "3.7"
rsa==4.7.2; python_version >= "3.7" and python_version < "4"
s3transfer==0.6.0; python_version >= "3.7"
secretstorage==3.3.3; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
semantic-version==2.10.0; python_version >= "3.7"
setuptools-rust==1.5.1
setuptools==65.3.0; python_version >= "3.7"
shellingham==1.5.0; python_version >= "3.7" and python_version < "4.0"
six==1.16.0; python_version >= "3.7"
snowballstemmer==2.2.0; python_version >= "3.7"
soupsieve==2.3.2.post1; python_version >= "3.7"
sphinx-rtd-theme==1.0.0; python_version >= "3.7"
sphinx==4.3.2; python_version >= "3.7"
sphinxcontrib-applehelp==1.0.2; python_version >= "3.7"
sphinxcontrib-devhelp==1.0.2; python_version >= "3.7"
sphinxcontrib-htmlhelp==2.0.0; python_version >= "3.7"
sphinxcontrib-jsmath==1.0.1; python_version >= "3.7"
sphinxcontrib-qthelp==1.0.3; python_version >= "3.7"
sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.7"
texttable==1.6.4; python_version >= "3.7"
tldextract==3.3.1; python_version >= "3.7" and python_version < "4.0"
toml==0.10.2; python_version >= "3.7"
tomli==2.0.1; python_version < "3.11" and python_version >= "3.7" or python_full_version <= "3.11.0a6" and python_version >= "3.7" or python_version >= "3.7"
tomlkit==0.11.4; python_version >= "3.7" and python_version < "4.0"
tox==3.26.0; python_version >= "3.7"
tqdm==4.64.1; python_version >= "3.7"
traitlets==5.4.0; python_version >= "3.7"
twine==3.3.0; python_version >= "3.7"
typed-ast==1.5.4; python_version >= "3.7" and python_version < "3.8" or implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.7"
types-cryptography==3.3.23; python_version >= "3.7"
types-pyopenssl==22.0.10; python_version >= "3.7"
types-pyrfc3339==1.1.1; python_version >= "3.7"
types-python-dateutil==2.8.19; python_version >= "3.7"
types-pytz==2022.2.1.0; python_version >= "3.7"
types-requests==2.28.10; python_version >= "3.7"
types-setuptools==65.3.0; python_version >= "3.7"
types-six==1.16.19; python_version >= "3.7"
types-urllib3==1.26.24; python_version >= "3.7"
typing-extensions==4.3.0; python_version >= "3.7" or python_version < "3.10" and python_version >= "3.7" or python_version < "3.8" and python_version >= "3.7"
uritemplate==4.1.1; python_version >= "3.7"
urllib3==1.26.12; python_version >= "3.7" and python_version < "4"
virtualenv==20.4.4; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
wcwidth==0.2.5; python_version >= "3.7"
webencodings==0.5.1; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
websocket-client==0.59.0; python_version >= "3.7"
wheel==0.37.1; python_version >= "3.7"
wrapt==1.14.1; python_version >= "3.7"
yarg==0.1.9; python_version >= "3.7"
zipp==3.8.1; python_version >= "3.7" and python_version < "3.8"
zope.component==5.0.1; python_version >= "3.7"
zope.event==4.5.0; python_version >= "3.7"
zope.hookable==5.2; python_version >= "3.7"
zope.interface==5.4.0; python_version >= "3.7"
alabaster==0.7.12 ; python_version >= "3.7" and python_version < "4.0"
apacheconfig==0.3.2 ; python_version >= "3.7" and python_version < "4.0"
appnope==0.1.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "darwin"
astroid==2.11.7 ; python_version >= "3.7" and python_version < "4.0"
attrs==22.1.0 ; python_version >= "3.7" and python_version < "4.0"
awscli==1.27.7 ; python_version >= "3.7" and python_version < "4.0"
azure-devops==6.0.0b4 ; python_version >= "3.7" and python_version < "4.0"
babel==2.11.0 ; python_version >= "3.7" and python_version < "4.0"
backcall==0.2.0 ; python_version >= "3.7" and python_version < "4.0"
backports-cached-property==1.0.2 ; python_version >= "3.7" and python_version < "3.8"
bcrypt==4.0.1 ; python_version >= "3.7" and python_version < "4.0"
beautifulsoup4==4.11.1 ; python_version >= "3.7" and python_version < "4.0"
bleach==5.0.1 ; python_version >= "3.7" and python_version < "4.0"
boto3==1.26.7 ; python_version >= "3.7" and python_version < "4.0"
botocore==1.29.7 ; python_version >= "3.7" and python_version < "4.0"
cachecontrol==0.12.11 ; python_version >= "3.7" and python_version < "4.0"
cachetools==5.2.0 ; python_version >= "3.7" and python_version < "4.0"
cachy==0.3.0 ; python_version >= "3.7" and python_version < "4.0"
certifi==2022.9.24 ; python_version >= "3.7" and python_version < "4"
cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0"
charset-normalizer==2.1.1 ; python_version >= "3.7" and python_version < "4"
cleo==1.0.0a5 ; python_version >= "3.7" and python_version < "4.0"
cloudflare==2.10.4 ; python_version >= "3.7" and python_version < "4.0"
colorama==0.4.4 ; python_version >= "3.7" and python_version < "4.0"
commonmark==0.9.1 ; python_version >= "3.7" and python_version < "4.0"
configargparse==1.5.3 ; python_version >= "3.7" and python_version < "4.0"
configobj==5.0.6 ; python_version >= "3.7" and python_version < "4.0"
coverage==6.5.0 ; python_version >= "3.7" and python_version < "4.0"
crashtest==0.3.1 ; python_version >= "3.7" and python_version < "4.0"
cryptography==38.0.3 ; python_version >= "3.7" and python_version < "4.0"
cython==0.29.32 ; python_version >= "3.7" and python_version < "4.0"
decorator==5.1.1 ; python_version >= "3.7" and python_version < "4.0"
dill==0.3.6 ; python_version >= "3.7" and python_version < "4.0"
distlib==0.3.6 ; python_version >= "3.7" and python_version < "4.0"
distro==1.8.0 ; python_version >= "3.7" and python_version < "4.0"
dns-lexicon==3.11.7 ; python_version >= "3.7" and python_version < "4.0"
dnspython==2.2.1 ; python_version >= "3.7" and python_version < "4.0"
docutils==0.16 ; python_version >= "3.7" and python_version < "4.0"
dulwich==0.20.50 ; python_version >= "3.7" and python_version < "4.0"
exceptiongroup==1.0.1 ; python_version >= "3.7" and python_version < "3.11"
execnet==1.9.0 ; python_version >= "3.7" and python_version < "4.0"
fabric==2.7.1 ; python_version >= "3.7" and python_version < "4.0"
filelock==3.8.0 ; python_version >= "3.7" and python_version < "4.0"
google-api-core==2.10.2 ; python_version >= "3.7" and python_version < "4.0"
google-api-python-client==2.65.0 ; python_version >= "3.7" and python_version < "4.0"
google-auth-httplib2==0.1.0 ; python_version >= "3.7" and python_version < "4.0"
google-auth==2.14.1 ; python_version >= "3.7" and python_version < "4.0"
googleapis-common-protos==1.56.4 ; python_version >= "3.7" and python_version < "4.0"
html5lib==1.1 ; python_version >= "3.7" and python_version < "4.0"
httplib2==0.21.0 ; python_version >= "3.7" and python_version < "4.0"
idna==3.4 ; python_version >= "3.7" and python_version < "4"
imagesize==1.4.1 ; python_version >= "3.7" and python_version < "4.0"
importlib-metadata==4.13.0 ; python_version >= "3.7" and python_version < "4.0"
importlib-resources==5.10.0 ; python_version >= "3.7" and python_version < "3.9"
iniconfig==1.1.1 ; python_version >= "3.7" and python_version < "4.0"
invoke==1.7.3 ; python_version >= "3.7" and python_version < "4.0"
ipdb==0.13.9 ; python_version >= "3.7" and python_version < "4.0"
ipython==7.34.0 ; python_version >= "3.7" and python_version < "4.0"
isodate==0.6.1 ; python_version >= "3.7" and python_version < "4.0"
isort==5.10.1 ; python_version >= "3.7" and python_version < "4.0"
jaraco-classes==3.2.3 ; python_version >= "3.7" and python_version < "4.0"
jedi==0.18.1 ; python_version >= "3.7" and python_version < "4.0"
jeepney==0.8.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
jinja2==3.1.2 ; python_version >= "3.7" and python_version < "4.0"
jmespath==1.0.1 ; python_version >= "3.7" and python_version < "4.0"
josepy==1.13.0 ; python_version >= "3.7" and python_version < "4.0"
jsonlines==3.1.0 ; python_version >= "3.7" and python_version < "4.0"
jsonpickle==2.2.0 ; python_version >= "3.7" and python_version < "4.0"
jsonschema==4.17.0 ; python_version >= "3.7" and python_version < "4.0"
keyring==23.11.0 ; python_version >= "3.7" and python_version < "4.0"
lazy-object-proxy==1.8.0 ; python_version >= "3.7" and python_version < "4.0"
lockfile==0.12.2 ; python_version >= "3.7" and python_version < "4.0"
markupsafe==2.1.1 ; python_version >= "3.7" and python_version < "4.0"
matplotlib-inline==0.1.6 ; python_version >= "3.7" and python_version < "4.0"
mccabe==0.7.0 ; python_version >= "3.7" and python_version < "4.0"
more-itertools==9.0.0 ; python_version >= "3.7" and python_version < "4.0"
msgpack==1.0.4 ; python_version >= "3.7" and python_version < "4.0"
msrest==0.6.21 ; python_version >= "3.7" and python_version < "4.0"
mypy-extensions==0.4.3 ; python_version >= "3.7" and python_version < "4.0"
mypy==0.990 ; python_version >= "3.7" and python_version < "4.0"
oauth2client==4.1.3 ; python_version >= "3.7" and python_version < "4.0"
oauthlib==3.2.2 ; python_version >= "3.7" and python_version < "4.0"
packaging==21.3 ; python_version >= "3.7" and python_version < "4.0"
paramiko==2.12.0 ; python_version >= "3.7" and python_version < "4.0"
parsedatetime==2.6 ; python_version >= "3.7" and python_version < "4.0"
parso==0.8.3 ; python_version >= "3.7" and python_version < "4.0"
pathlib2==2.3.7.post1 ; python_version >= "3.7" and python_version < "4.0"
pexpect==4.8.0 ; python_version >= "3.7" and python_version < "4.0"
pickleshare==0.7.5 ; python_version >= "3.7" and python_version < "4.0"
pip==22.3.1 ; python_version >= "3.7" and python_version < "4.0"
pkginfo==1.8.3 ; python_version >= "3.7" and python_version < "4.0"
pkgutil-resolve-name==1.3.10 ; python_version >= "3.7" and python_version < "3.9"
platformdirs==2.5.3 ; python_version >= "3.7" and python_version < "4.0"
pluggy==1.0.0 ; python_version >= "3.7" and python_version < "4.0"
ply==3.11 ; python_version >= "3.7" and python_version < "4.0"
poetry-core==1.3.2 ; python_version >= "3.7" and python_version < "4.0"
poetry-plugin-export==1.2.0 ; python_version >= "3.7" and python_version < "4.0"
poetry==1.2.2 ; python_version >= "3.7" and python_version < "4.0"
prompt-toolkit==3.0.32 ; python_version >= "3.7" and python_version < "4.0"
protobuf==4.21.9 ; python_version >= "3.7" and python_version < "4.0"
ptyprocess==0.7.0 ; python_version >= "3.7" and python_version < "4.0"
py==1.11.0 ; python_version >= "3.7" and python_version < "4.0"
pyasn1-modules==0.2.8 ; python_version >= "3.7" and python_version < "4.0"
pyasn1==0.4.8 ; python_version >= "3.7" and python_version < "4.0"
pycparser==2.21 ; python_version >= "3.7" and python_version < "4.0"
pygments==2.13.0 ; python_version >= "3.7" and python_version < "4.0"
pylev==1.4.0 ; python_version >= "3.7" and python_version < "4.0"
pylint==2.13.9 ; python_version >= "3.7" and python_version < "4.0"
pynacl==1.5.0 ; python_version >= "3.7" and python_version < "4.0"
pynsist==2.7 ; python_version >= "3.7" and python_version < "4.0"
pyopenssl==22.1.0 ; python_version >= "3.7" and python_version < "4.0"
pyparsing==3.0.9 ; python_version >= "3.7" and python_version < "4.0"
pyrfc3339==1.1 ; python_version >= "3.7" and python_version < "4.0"
pyrsistent==0.19.2 ; python_version >= "3.7" and python_version < "4.0"
pytest-cov==4.0.0 ; python_version >= "3.7" and python_version < "4.0"
pytest-xdist==3.0.2 ; python_version >= "3.7" and python_version < "4.0"
pytest==7.2.0 ; python_version >= "3.7" and python_version < "4.0"
python-augeas==1.1.0 ; python_version >= "3.7" and python_version < "4.0"
python-dateutil==2.8.2 ; python_version >= "3.7" and python_version < "4.0"
python-digitalocean==1.17.0 ; python_version >= "3.7" and python_version < "4.0"
pytz==2022.6 ; python_version >= "3.7" and python_version < "4.0"
pywin32-ctypes==0.2.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32"
pywin32==305 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32"
pyyaml==5.4.1 ; python_version >= "3.7" and python_version < "4.0"
readme-renderer==37.3 ; python_version >= "3.7" and python_version < "4.0"
requests-download==0.1.2 ; python_version >= "3.7" and python_version < "4.0"
requests-file==1.5.1 ; python_version >= "3.7" and python_version < "4.0"
requests-oauthlib==1.3.1 ; python_version >= "3.7" and python_version < "4.0"
requests-toolbelt==0.9.1 ; python_version >= "3.7" and python_version < "4.0"
requests==2.28.1 ; python_version >= "3.7" and python_version < "4"
rfc3986==2.0.0 ; python_version >= "3.7" and python_version < "4.0"
rich==12.6.0 ; python_version >= "3.7" and python_version < "4.0"
rsa==4.7.2 ; python_version >= "3.7" and python_version < "4"
s3transfer==0.6.0 ; python_version >= "3.7" and python_version < "4.0"
secretstorage==3.3.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
semantic-version==2.10.0 ; python_version >= "3.7" and python_version < "4.0"
setuptools-rust==1.5.2 ; python_version >= "3.7" and python_version < "4.0"
setuptools==65.5.1 ; python_version >= "3.7" and python_version < "4.0"
shellingham==1.5.0 ; python_version >= "3.7" and python_version < "4.0"
six==1.16.0 ; python_version >= "3.7" and python_version < "4.0"
snowballstemmer==2.2.0 ; python_version >= "3.7" and python_version < "4.0"
soupsieve==2.3.2.post1 ; python_version >= "3.7" and python_version < "4.0"
sphinx-rtd-theme==1.1.1 ; python_version >= "3.7" and python_version < "4.0"
sphinx==5.1.1 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-applehelp==1.0.2 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-devhelp==1.0.2 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-htmlhelp==2.0.0 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-jsmath==1.0.1 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-qthelp==1.0.3 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-serializinghtml==1.1.5 ; python_version >= "3.7" and python_version < "4.0"
tldextract==3.4.0 ; python_version >= "3.7" and python_version < "4.0"
toml==0.10.2 ; python_version >= "3.7" and python_version < "4.0"
tomli==2.0.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6"
tomlkit==0.11.6 ; python_version >= "3.7" and python_version < "4.0"
tox==3.27.0 ; python_version >= "3.7" and python_version < "4.0"
traitlets==5.5.0 ; python_version >= "3.7" and python_version < "4.0"
twine==4.0.1 ; python_version >= "3.7" and python_version < "4.0"
typed-ast==1.5.4 ; python_version >= "3.7" and python_version < "3.8"
types-cryptography==3.3.23.2 ; python_version >= "3.7" and python_version < "4.0"
types-pyopenssl==22.1.0.2 ; python_version >= "3.7" and python_version < "4.0"
types-pyrfc3339==1.1.1 ; python_version >= "3.7" and python_version < "4.0"
types-python-dateutil==2.8.19.3 ; python_version >= "3.7" and python_version < "4.0"
types-pytz==2022.6.0.1 ; python_version >= "3.7" and python_version < "4.0"
types-requests==2.28.11.4 ; python_version >= "3.7" and python_version < "4.0"
types-setuptools==65.5.0.2 ; python_version >= "3.7" and python_version < "4.0"
types-six==1.16.21.2 ; python_version >= "3.7" and python_version < "4.0"
types-urllib3==1.26.25.3 ; python_version >= "3.7" and python_version < "4.0"
typing-extensions==4.4.0 ; python_version >= "3.7" and python_version < "4.0"
uritemplate==4.1.1 ; python_version >= "3.7" and python_version < "4.0"
urllib3==1.26.12 ; python_version >= "3.7" and python_version < "4"
virtualenv==20.16.6 ; python_version >= "3.7" and python_version < "4.0"
wcwidth==0.2.5 ; python_version >= "3.7" and python_version < "4.0"
webencodings==0.5.1 ; python_version >= "3.7" and python_version < "4.0"
wheel==0.38.4 ; python_version >= "3.7" and python_version < "4.0"
wrapt==1.14.1 ; python_version >= "3.7" and python_version < "4.0"
xattr==0.9.9 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "darwin"
yarg==0.1.9 ; python_version >= "3.7" and python_version < "4.0"
zipp==3.10.0 ; python_version >= "3.7" and python_version < "4.0"

View file

@ -17,7 +17,7 @@ These steps need to be done once to set up your VM and do not need to be run aga
5. Add your current user to the lxd group and update your shell to have the new assignment by running `sudo usermod -a -G lxd ${USER} && newgrp lxd`.
6. Install snapcraft with `sudo snap install --classic snapcraft`.
7. `cd ~` (or any other directory where you want our source files to be)
8. Run `git clone git://github.com/certbot/certbot`
8. Run `git clone https://github.com/certbot/certbot`
9. `cd certbot` (All further instructions are relative to this directory.)
### Certbot Snap
@ -80,7 +80,7 @@ It is easiest to run this from a local machine.
2. Install git and python with `sudo apt update && sudo apt install -y git python`.
3. Install snapcraft with `sudo snap install --classic snapcraft`.
4. `cd ~` (or any other directory where you want our source files to be)
5. Run `git clone git://github.com/certbot/certbot`
5. Run `git clone https://github.com/certbot/certbot`
6. `cd certbot` (All further instructions are relative to this directory.)
7. To trigger `snapcraft` to request access to your Launchpad account, run
`snapcraft remote-build --launchpad-accept-public-upload --status`. A URL where you need