Merge remote-tracking branch 'origin/master' into update-2.0.x

This commit is contained in:
Alex Zorin
2022-09-09 08:37:56 +10:00
52 changed files with 326 additions and 257 deletions
@@ -2,7 +2,7 @@ jobs:
- job: extended_test - job: extended_test
variables: variables:
- name: IMAGE_NAME - name: IMAGE_NAME
value: ubuntu-18.04 value: ubuntu-22.04
- name: PYTHON_VERSION - name: PYTHON_VERSION
value: 3.10 value: 3.10
- group: certbot-common - group: certbot-common
@@ -47,13 +47,13 @@ jobs:
nginx-compat: nginx-compat:
TOXENV: nginx_compat TOXENV: nginx_compat
linux-integration-rfc2136: linux-integration-rfc2136:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.8 PYTHON_VERSION: 3.8
TOXENV: integration-dns-rfc2136 TOXENV: integration-dns-rfc2136
docker-dev: docker-dev:
TOXENV: docker_dev TOXENV: docker_dev
le-modification: le-modification:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
TOXENV: modification TOXENV: modification
farmtest-apache2: farmtest-apache2:
PYTHON_VERSION: 3.8 PYTHON_VERSION: 3.8
@@ -1,7 +1,7 @@
jobs: jobs:
- job: docker_build - job: docker_build
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
strategy: strategy:
matrix: matrix:
amd64: amd64:
@@ -37,7 +37,7 @@ jobs:
- job: docker_run - job: docker_run
dependsOn: docker_build dependsOn: docker_build
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
steps: steps:
- task: DownloadPipelineArtifact@2 - task: DownloadPipelineArtifact@2
inputs: inputs:
@@ -116,7 +116,7 @@ jobs:
displayName: Run certbot integration tests displayName: Run certbot integration tests
- job: snaps_build - job: snaps_build
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
strategy: strategy:
matrix: matrix:
amd64: amd64:
@@ -164,7 +164,7 @@ jobs:
- job: snap_run - job: snap_run
dependsOn: snaps_build dependsOn: snaps_build
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
steps: steps:
- task: UsePythonVersion@0 - task: UsePythonVersion@0
inputs: inputs:
@@ -194,7 +194,7 @@ jobs:
- job: snap_dns_run - job: snap_dns_run
dependsOn: snaps_build dependsOn: snaps_build
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
steps: steps:
- script: | - script: |
set -e set -e
@@ -5,11 +5,11 @@ jobs:
strategy: strategy:
matrix: matrix:
macos-py37-cover: macos-py37-cover:
IMAGE_NAME: macOS-10.15 IMAGE_NAME: macOS-12
PYTHON_VERSION: 3.7 PYTHON_VERSION: 3.7
TOXENV: py37-cover TOXENV: py37-cover
macos-py310-cover: macos-py310-cover:
IMAGE_NAME: macOS-10.15 IMAGE_NAME: macOS-12
PYTHON_VERSION: 3.10 PYTHON_VERSION: 3.10
TOXENV: py310-cover TOXENV: py310-cover
windows-py37: windows-py37:
@@ -25,42 +25,42 @@ jobs:
PYTHON_VERSION: 3.9 PYTHON_VERSION: 3.9
TOXENV: integration-certbot TOXENV: integration-certbot
linux-oldest-tests-1: linux-oldest-tests-1:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.7 PYTHON_VERSION: 3.7
TOXENV: '{acme,apache,apache-v2,certbot}-oldest' TOXENV: '{acme,apache,apache-v2,certbot}-oldest'
linux-oldest-tests-2: linux-oldest-tests-2:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.7 PYTHON_VERSION: 3.7
TOXENV: '{dns,nginx}-oldest' TOXENV: '{dns,nginx}-oldest'
linux-py37: linux-py37:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.7 PYTHON_VERSION: 3.7
TOXENV: py37 TOXENV: py37
linux-py310-cover: linux-py310-cover:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.10 PYTHON_VERSION: 3.10
TOXENV: py310-cover TOXENV: py310-cover
linux-py310-lint: linux-py310-lint:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.10 PYTHON_VERSION: 3.10
TOXENV: lint-posix TOXENV: lint-posix
linux-py310-mypy: linux-py310-mypy:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.10 PYTHON_VERSION: 3.10
TOXENV: mypy-posix TOXENV: mypy-posix
linux-integration: linux-integration:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
PYTHON_VERSION: 3.8 PYTHON_VERSION: 3.8
TOXENV: integration TOXENV: integration
ACME_SERVER: pebble ACME_SERVER: pebble
apache-compat: apache-compat:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
TOXENV: apache_compat TOXENV: apache_compat
apacheconftest: apacheconftest:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
TOXENV: apacheconftest-with-pebble TOXENV: apacheconftest-with-pebble
nginxroundtrip: nginxroundtrip:
IMAGE_NAME: ubuntu-18.04 IMAGE_NAME: ubuntu-22.04
TOXENV: nginxroundtrip TOXENV: nginxroundtrip
pool: pool:
vmImage: $(IMAGE_NAME) vmImage: $(IMAGE_NAME)
@@ -35,7 +35,7 @@ stages:
# more info. # more info.
- job: publish_snap - job: publish_snap
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
variables: variables:
- group: certbot-common - group: certbot-common
strategy: strategy:
@@ -71,7 +71,7 @@ stages:
displayName: Publish to Snap store displayName: Publish to Snap store
- job: publish_docker - job: publish_docker
pool: pool:
vmImage: ubuntu-18.04 vmImage: ubuntu-22.04
strategy: strategy:
matrix: matrix:
amd64: amd64:
@@ -96,11 +96,16 @@ stages:
# which was created by following the instructions at # which was created by following the instructions at
# https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-docreg. # https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-docreg.
# The name given to this service account must match the value # The name given to this service account must match the value
# given to containerRegistry below. "Grant access to all # given to containerRegistry below. The authentication used when
# pipelines" should also be checked. To revoke these # creating this service account was a personal access token
# credentials, we can change the password on the certbotbot # rather than a password to bypass 2FA. When Brad set this up,
# Docker Hub account or remove the account from the # Azure Pipelines failed to verify the credentials with an error
# Certbot organization on Docker Hub. # like "access is forbidden with a JWT issued from a personal
# access token", but after saving them without verification, the
# access token worked when the pipeline actually ran. "Grant
# access to all pipelines" should also be checked on the service
# account. The access token can be deleted on Docker Hub if
# these credentials need to be revoked.
containerRegistry: docker-hub containerRegistry: docker-hub
displayName: Login to Docker Hub displayName: Login to Docker Hub
- bash: set -e && tools/docker/deploy.sh $(dockerTag) $DOCKER_ARCH - bash: set -e && tools/docker/deploy.sh $(dockerTag) $DOCKER_ARCH
@@ -12,7 +12,7 @@ steps:
set -e set -e
sudo apt-get update sudo apt-get update
sudo apt-get install -y --no-install-recommends \ sudo apt-get install -y --no-install-recommends \
python-dev \ python3-dev \
gcc \ gcc \
libaugeas0 \ libaugeas0 \
libssl-dev \ libssl-dev \
@@ -36,8 +36,8 @@ steps:
# problems with its lack of real dependency resolution. # problems with its lack of real dependency resolution.
- bash: | - bash: |
set -e set -e
python tools/pipstrap.py python3 tools/pipstrap.py
python tools/pip_install.py -I tox virtualenv python3 tools/pip_install.py -I tox virtualenv
displayName: Install runtime dependencies displayName: Install runtime dependencies
- task: DownloadSecureFile@1 - task: DownloadSecureFile@1
name: testFarmPem name: testFarmPem
@@ -49,7 +49,7 @@ steps:
export TARGET_BRANCH="`echo "${BUILD_SOURCEBRANCH}" | sed -E 's!refs/(heads|tags)/!!g'`" export TARGET_BRANCH="`echo "${BUILD_SOURCEBRANCH}" | sed -E 's!refs/(heads|tags)/!!g'`"
[ -z "${SYSTEM_PULLREQUEST_TARGETBRANCH}" ] || export TARGET_BRANCH="${SYSTEM_PULLREQUEST_TARGETBRANCH}" [ -z "${SYSTEM_PULLREQUEST_TARGETBRANCH}" ] || export TARGET_BRANCH="${SYSTEM_PULLREQUEST_TARGETBRANCH}"
env env
python -m tox python3 -m tox
env: env:
AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID) AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
+1
View File
@@ -1,5 +1,6 @@
## Pull Request Checklist ## Pull Request Checklist
- [ ] The Certbot team has recently expressed interest in reviewing a PR for this. If not, this PR may be closed due our limited resources and need to prioritize how we spend them.
- [ ] If the change being made is to a [distributed component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout), edit the `master` section of `certbot/CHANGELOG.md` to include a description of the change being made. - [ ] If the change being made is to a [distributed component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout), edit the `master` section of `certbot/CHANGELOG.md` to include a description of the change being made.
- [ ] Add or update any documentation as needed to support the changes in this PR. - [ ] Add or update any documentation as needed to support the changes in this PR.
- [ ] Include your name in `AUTHORS.md` if you like. - [ ] Include your name in `AUTHORS.md` if you like.
+2
View File
@@ -178,6 +178,7 @@ Authors
* [Mathieu Leduc-Hamel](https://github.com/mlhamel) * [Mathieu Leduc-Hamel](https://github.com/mlhamel)
* [Matt Bostock](https://github.com/mattbostock) * [Matt Bostock](https://github.com/mattbostock)
* [Matthew Ames](https://github.com/SuperMatt) * [Matthew Ames](https://github.com/SuperMatt)
* [Matthew W. Thomas](https://github.com/mwt)
* [Michael Schumacher](https://github.com/schumaml) * [Michael Schumacher](https://github.com/schumaml)
* [Michael Strache](https://github.com/Jarodiv) * [Michael Strache](https://github.com/Jarodiv)
* [Michael Sverdlin](https://github.com/sveder) * [Michael Sverdlin](https://github.com/sveder)
@@ -215,6 +216,7 @@ Authors
* [Pierre Jaury](https://github.com/kaiyou) * [Pierre Jaury](https://github.com/kaiyou)
* [Piotr Kasprzyk](https://github.com/kwadrat) * [Piotr Kasprzyk](https://github.com/kwadrat)
* [Prayag Verma](https://github.com/pra85) * [Prayag Verma](https://github.com/pra85)
* [Preston Locke](https://github.com/Preston12321)
* [Rasesh Patel](https://github.com/raspat1) * [Rasesh Patel](https://github.com/raspat1)
* [Reinaldo de Souza Jr](https://github.com/juniorz) * [Reinaldo de Souza Jr](https://github.com/juniorz)
* [Remi Rampin](https://github.com/remram44) * [Remi Rampin](https://github.com/remram44)
+1 -1
View File
@@ -410,7 +410,7 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse):
""" """
ID_PE_ACME_IDENTIFIER_V1 = b"1.3.6.1.5.5.7.1.30.1" ID_PE_ACME_IDENTIFIER_V1 = b"1.3.6.1.5.5.7.1.30.1"
ACME_TLS_1_PROTOCOL = "acme-tls/1" ACME_TLS_1_PROTOCOL = b"acme-tls/1"
@property @property
def h(self) -> bytes: def h(self) -> bytes:
+12 -2
View File
@@ -15,13 +15,20 @@ from typing import Set
from typing import Text from typing import Text
from typing import Tuple from typing import Tuple
from typing import Union from typing import Union
import warnings
import josepy as jose import josepy as jose
import OpenSSL import OpenSSL
import requests import requests
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from requests.utils import parse_header_links from requests.utils import parse_header_links
from requests_toolbelt.adapters.source import SourceAddressAdapter # We're capturing the warnings described at
# https://github.com/requests/toolbelt/issues/331 until we can remove this
# dependency in Certbot 2.0.
with warnings.catch_warnings():
warnings.filterwarnings("ignore", "'urllib3.contrib.pyopenssl",
DeprecationWarning)
from requests_toolbelt.adapters.source import SourceAddressAdapter
from acme import challenges from acme import challenges
from acme import crypto_util from acme import crypto_util
@@ -482,7 +489,8 @@ class ClientNetwork:
:param bool verify_ssl: Whether to verify certificates on SSL connections. :param bool verify_ssl: Whether to verify certificates on SSL connections.
:param str user_agent: String to send as User-Agent header. :param str user_agent: String to send as User-Agent header.
:param float timeout: Timeout for requests. :param float timeout: Timeout for requests.
:param source_address: Optional source address to bind to when making requests. :param source_address: Optional source address to bind to when making
requests. (deprecated since 1.30.0)
:type source_address: str or tuple(str, int) :type source_address: str or tuple(str, int)
""" """
def __init__(self, key: jose.JWK, account: Optional[messages.RegistrationResource] = None, def __init__(self, key: jose.JWK, account: Optional[messages.RegistrationResource] = None,
@@ -500,6 +508,8 @@ class ClientNetwork:
adapter = HTTPAdapter() adapter = HTTPAdapter()
if source_address is not None: if source_address is not None:
warnings.warn("Support for source_address is deprecated and will be "
"removed soon.", DeprecationWarning, stacklevel=2)
adapter = SourceAddressAdapter(source_address) adapter = SourceAddressAdapter(source_address)
self.session.mount("http://", adapter) self.session.mount("http://", adapter)
+13 -7
View File
@@ -11,6 +11,7 @@ from typing import Callable
from typing import List from typing import List
from typing import Mapping from typing import Mapping
from typing import Optional from typing import Optional
from typing import Sequence
from typing import Set from typing import Set
from typing import Tuple from typing import Tuple
from typing import Union from typing import Union
@@ -39,7 +40,9 @@ class _DefaultCertSelection:
def __call__(self, connection: SSL.Connection) -> Optional[Tuple[crypto.PKey, crypto.X509]]: def __call__(self, connection: SSL.Connection) -> Optional[Tuple[crypto.PKey, crypto.X509]]:
server_name = connection.get_servername() server_name = connection.get_servername()
return self.certs.get(server_name, None) if server_name:
return self.certs.get(server_name, None)
return None # pragma: no cover
class SSLSocket: # pylint: disable=too-few-public-methods class SSLSocket: # pylint: disable=too-few-public-methods
@@ -60,7 +63,8 @@ class SSLSocket: # pylint: disable=too-few-public-methods
method: int = _DEFAULT_SSL_METHOD, method: int = _DEFAULT_SSL_METHOD,
alpn_selection: Optional[Callable[[SSL.Connection, List[bytes]], bytes]] = None, alpn_selection: Optional[Callable[[SSL.Connection, List[bytes]], bytes]] = None,
cert_selection: Optional[Callable[[SSL.Connection], cert_selection: Optional[Callable[[SSL.Connection],
Tuple[crypto.PKey, crypto.X509]]] = None Optional[Tuple[crypto.PKey,
crypto.X509]]]] = None
) -> None: ) -> None:
self.sock = sock self.sock = sock
self.alpn_selection = alpn_selection self.alpn_selection = alpn_selection
@@ -71,8 +75,8 @@ class SSLSocket: # pylint: disable=too-few-public-methods
raise ValueError("Both cert_selection and certs specified.") raise ValueError("Both cert_selection and certs specified.")
actual_cert_selection: Union[_DefaultCertSelection, actual_cert_selection: Union[_DefaultCertSelection,
Optional[Callable[[SSL.Connection], Optional[Callable[[SSL.Connection],
Tuple[crypto.PKey, Optional[Tuple[crypto.PKey,
crypto.X509]]]] = cert_selection crypto.X509]]]]] = cert_selection
if actual_cert_selection is None: if actual_cert_selection is None:
actual_cert_selection = _DefaultCertSelection(certs if certs else {}) actual_cert_selection = _DefaultCertSelection(certs if certs else {})
self.cert_selection = actual_cert_selection self.cert_selection = actual_cert_selection
@@ -157,7 +161,7 @@ class SSLSocket: # pylint: disable=too-few-public-methods
def probe_sni(name: bytes, host: bytes, port: int = 443, timeout: int = 300, # pylint: disable=too-many-arguments def probe_sni(name: bytes, host: bytes, port: int = 443, timeout: int = 300, # pylint: disable=too-many-arguments
method: int = _DEFAULT_SSL_METHOD, source_address: Tuple[str, int] = ('', 0), method: int = _DEFAULT_SSL_METHOD, source_address: Tuple[str, int] = ('', 0),
alpn_protocols: Optional[List[str]] = None) -> crypto.X509: alpn_protocols: Optional[Sequence[bytes]] = None) -> crypto.X509:
"""Probe SNI server for SSL certificate. """Probe SNI server for SSL certificate.
:param bytes name: Byte string to send as the server name in the :param bytes name: Byte string to send as the server name in the
@@ -170,7 +174,7 @@ def probe_sni(name: bytes, host: bytes, port: int = 443, timeout: int = 300, #
of source interface). See `socket.creation_connection` for more of source interface). See `socket.creation_connection` for more
info. Available only in Python 2.7+. info. Available only in Python 2.7+.
:param alpn_protocols: Protocols to request using ALPN. :param alpn_protocols: Protocols to request using ALPN.
:type alpn_protocols: `list` of `str` :type alpn_protocols: `Sequence` of `bytes`
:raises acme.errors.Error: In case of any problems. :raises acme.errors.Error: In case of any problems.
@@ -207,7 +211,9 @@ def probe_sni(name: bytes, host: bytes, port: int = 443, timeout: int = 300, #
client_ssl.shutdown() client_ssl.shutdown()
except SSL.Error as error: except SSL.Error as error:
raise errors.Error(error) raise errors.Error(error)
return client_ssl.get_peer_certificate() cert = client_ssl.get_peer_certificate()
assert cert # Appease mypy. We would have crashed out by now if there was no certificate.
return cert
def make_csr(private_key_pem: bytes, domains: Optional[Union[Set[str], List[str]]] = None, def make_csr(private_key_pem: bytes, domains: Optional[Union[Set[str], List[str]]] = None,
+11 -6
View File
@@ -46,10 +46,12 @@ class TLSServer(socketserver.TCPServer):
method=self.method)) method=self.method))
def _cert_selection(self, connection: SSL.Connection def _cert_selection(self, connection: SSL.Connection
) -> Tuple[crypto.PKey, crypto.X509]: # pragma: no cover ) -> Optional[Tuple[crypto.PKey, crypto.X509]]: # pragma: no cover
"""Callback selecting certificate for connection.""" """Callback selecting certificate for connection."""
server_name = connection.get_servername() server_name = connection.get_servername()
return self.certs.get(server_name, None) if server_name:
return self.certs.get(server_name, None)
return None
def server_bind(self) -> None: def server_bind(self) -> None:
self._wrap_sock() self._wrap_sock()
@@ -151,7 +153,7 @@ class TLSALPN01Server(TLSServer, ACMEServerMixin):
def __init__(self, server_address: Tuple[str, int], def __init__(self, server_address: Tuple[str, int],
certs: List[Tuple[crypto.PKey, crypto.X509]], certs: List[Tuple[crypto.PKey, crypto.X509]],
challenge_certs: Mapping[str, Tuple[crypto.PKey, crypto.X509]], challenge_certs: Mapping[bytes, Tuple[crypto.PKey, crypto.X509]],
ipv6: bool = False) -> None: ipv6: bool = False) -> None:
# We don't need to implement a request handler here because the work # We don't need to implement a request handler here because the work
# (including logging) is being done by wrapped socket set up in the # (including logging) is being done by wrapped socket set up in the
@@ -161,7 +163,8 @@ class TLSALPN01Server(TLSServer, ACMEServerMixin):
ipv6=ipv6) ipv6=ipv6)
self.challenge_certs = challenge_certs self.challenge_certs = challenge_certs
def _cert_selection(self, connection: SSL.Connection) -> Tuple[crypto.PKey, crypto.X509]: def _cert_selection(self, connection: SSL.Connection) -> Optional[Tuple[crypto.PKey,
crypto.X509]]:
# TODO: We would like to serve challenge cert only if asked for it via # TODO: We would like to serve challenge cert only if asked for it via
# ALPN. To do this, we need to retrieve the list of protos from client # ALPN. To do this, we need to retrieve the list of protos from client
# hello, but this is currently impossible with openssl [0], and ALPN # hello, but this is currently impossible with openssl [0], and ALPN
@@ -170,8 +173,10 @@ class TLSALPN01Server(TLSServer, ACMEServerMixin):
# handshake in alpn_selection() if ALPN protos are not what we expect. # handshake in alpn_selection() if ALPN protos are not what we expect.
# [0] https://github.com/openssl/openssl/issues/4952 # [0] https://github.com/openssl/openssl/issues/4952
server_name = connection.get_servername() server_name = connection.get_servername()
logger.debug("Serving challenge cert for server name %s", server_name) if server_name:
return self.challenge_certs[server_name] logger.debug("Serving challenge cert for server name %s", server_name)
return self.challenge_certs[server_name]
return None # pragma: no cover
def _alpn_selection(self, _connection: SSL.Connection, alpn_protos: List[bytes]) -> bytes: def _alpn_selection(self, _connection: SSL.Connection, alpn_protos: List[bytes]) -> bytes:
"""Callback to select alpn protocol.""" """Callback to select alpn protocol."""
+1 -1
View File
@@ -3,7 +3,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'cryptography>=2.5.0', 'cryptography>=2.5.0',
+2 -2
View File
@@ -325,12 +325,12 @@ class TLSALPN01ResponseTest(unittest.TestCase):
mock_gethostbyname.assert_called_once_with('foo.com') mock_gethostbyname.assert_called_once_with('foo.com')
mock_probe_sni.assert_called_once_with( mock_probe_sni.assert_called_once_with(
host=b'127.0.0.1', port=self.response.PORT, name=b'foo.com', host=b'127.0.0.1', port=self.response.PORT, name=b'foo.com',
alpn_protocols=['acme-tls/1']) alpn_protocols=[b'acme-tls/1'])
self.response.probe_cert('foo.com', host='8.8.8.8') self.response.probe_cert('foo.com', host='8.8.8.8')
mock_probe_sni.assert_called_with( mock_probe_sni.assert_called_with(
host=b'8.8.8.8', port=mock.ANY, name=b'foo.com', host=b'8.8.8.8', port=mock.ANY, name=b'foo.com',
alpn_protocols=['acme-tls/1']) alpn_protocols=[b'acme-tls/1'])
@mock.patch('acme.challenges.TLSALPN01Response.probe_cert') @mock.patch('acme.challenges.TLSALPN01Response.probe_cert')
def test_simple_verify_false_on_probe_error(self, mock_probe_cert): def test_simple_verify_false_on_probe_error(self, mock_probe_cert):
+5 -5
View File
@@ -15,6 +15,7 @@ from acme import challenges
from acme import errors from acme import errors
from acme import jws as acme_jws from acme import jws as acme_jws
from acme import messages from acme import messages
from acme.client import ClientNetwork
from acme.client import ClientV2 from acme.client import ClientV2
import messages_test import messages_test
import test_util import test_util
@@ -410,7 +411,6 @@ class ClientNetworkTest(unittest.TestCase):
self.verify_ssl = mock.MagicMock() self.verify_ssl = mock.MagicMock()
self.wrap_in_jws = mock.MagicMock(return_value=mock.sentinel.wrapped) self.wrap_in_jws = mock.MagicMock(return_value=mock.sentinel.wrapped)
from acme.client import ClientNetwork
self.net = ClientNetwork( self.net = ClientNetwork(
key=KEY, alg=jose.RS256, verify_ssl=self.verify_ssl, key=KEY, alg=jose.RS256, verify_ssl=self.verify_ssl,
user_agent='acme-python-test') user_agent='acme-python-test')
@@ -638,7 +638,6 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase):
"""Tests for acme.client.ClientNetwork which mock out response.""" """Tests for acme.client.ClientNetwork which mock out response."""
def setUp(self): def setUp(self):
from acme.client import ClientNetwork
self.net = ClientNetwork(key=None, alg=None) self.net = ClientNetwork(key=None, alg=None)
self.response = mock.MagicMock(ok=True, status_code=http_client.OK) self.response = mock.MagicMock(ok=True, status_code=http_client.OK)
@@ -800,15 +799,16 @@ class ClientNetworkSourceAddressBindingTest(unittest.TestCase):
self.source_address = "8.8.8.8" self.source_address = "8.8.8.8"
def test_source_address_set(self): def test_source_address_set(self):
from acme.client import ClientNetwork with mock.patch('warnings.warn') as mock_warn:
net = ClientNetwork(key=None, alg=None, source_address=self.source_address) net = ClientNetwork(key=None, alg=None, source_address=self.source_address)
mock_warn.assert_called_once()
self.assertIn('source_address', mock_warn.call_args[0][0])
for adapter in net.session.adapters.values(): for adapter in net.session.adapters.values():
self.assertIn(self.source_address, adapter.source_address) self.assertIn(self.source_address, adapter.source_address)
def test_behavior_assumption(self): def test_behavior_assumption(self):
"""This is a test that guardrails the HTTPAdapter behavior so that if the default for """This is a test that guardrails the HTTPAdapter behavior so that if the default for
a Session() changes, the assumptions here aren't violated silently.""" a Session() changes, the assumptions here aren't violated silently."""
from acme.client import ClientNetwork
# Source address not specified, so the default adapter type should be bound -- this # Source address not specified, so the default adapter type should be bound -- this
# test should fail if the default adapter type is changed by requests # test should fail if the default adapter type is changed by requests
net = ClientNetwork(key=None, alg=None) net = ClientNetwork(key=None, alg=None)
+1
View File
@@ -1,6 +1,7 @@
"""Tests for acme.fields.""" """Tests for acme.fields."""
import datetime import datetime
import unittest import unittest
import warnings
import josepy as jose import josepy as jose
import pytz import pytz
+1
View File
@@ -2,6 +2,7 @@
from typing import Dict from typing import Dict
import unittest import unittest
from unittest import mock from unittest import mock
import warnings
import josepy as jose import josepy as jose
+1 -1
View File
@@ -1,7 +1,7 @@
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
# We specify the minimum acme and certbot version as the current plugin # We specify the minimum acme and certbot version as the current plugin
@@ -125,7 +125,7 @@ def assert_equals_world_read_permissions(file1: str, file2: str) -> None:
mode_file1 = os.stat(file1).st_mode & 0o004 mode_file1 = os.stat(file1).st_mode & 0o004
mode_file2 = os.stat(file2).st_mode & 0o004 mode_file2 = os.stat(file2).st_mode & 0o004
else: else:
everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) # pylint: disable=used-before-assignment
security1 = win32security.GetFileSecurity(file1, win32security.DACL_SECURITY_INFORMATION) security1 = win32security.GetFileSecurity(file1, win32security.DACL_SECURITY_INFORMATION)
dacl1 = security1.GetSecurityDescriptorDacl() dacl1 = security1.GetSecurityDescriptorDacl()
@@ -135,7 +135,7 @@ def assert_equals_world_read_permissions(file1: str, file2: str) -> None:
'TrusteeType': win32security.TRUSTEE_IS_USER, 'TrusteeType': win32security.TRUSTEE_IS_USER,
'Identifier': everybody, 'Identifier': everybody,
}) })
mode_file1 = mode_file1 & ntsecuritycon.FILE_GENERIC_READ mode_file1 = mode_file1 & ntsecuritycon.FILE_GENERIC_READ # pylint: disable=used-before-assignment
security2 = win32security.GetFileSecurity(file2, win32security.DACL_SECURITY_INFORMATION) security2 = win32security.GetFileSecurity(file2, win32security.DACL_SECURITY_INFORMATION)
dacl2 = security2.GetSecurityDescriptorDacl() dacl2 = security2.GetSecurityDescriptorDacl()
@@ -133,18 +133,9 @@ class ACMEServer:
acme_xdist['directory_url'] = BOULDER_V2_DIRECTORY_URL acme_xdist['directory_url'] = BOULDER_V2_DIRECTORY_URL
acme_xdist['challtestsrv_url'] = BOULDER_V2_CHALLTESTSRV_URL acme_xdist['challtestsrv_url'] = BOULDER_V2_CHALLTESTSRV_URL
acme_xdist['http_port'] = { acme_xdist['http_port'] = dict(zip(nodes, range(5200, 5200 + len(nodes))))
node: port for (node, port) in # pylint: disable=unnecessary-comprehension acme_xdist['https_port'] = dict(zip(nodes, range(5100, 5100 + len(nodes))))
zip(nodes, range(5200, 5200 + len(nodes))) acme_xdist['other_port'] = dict(zip(nodes, range(5300, 5300 + len(nodes))))
}
acme_xdist['https_port'] = {
node: port for (node, port) in # pylint: disable=unnecessary-comprehension
zip(nodes, range(5100, 5100 + len(nodes)))
}
acme_xdist['other_port'] = {
node: port for (node, port) in # pylint: disable=unnecessary-comprehension
zip(nodes, range(5300, 5300 + len(nodes)))
}
self.acme_xdist = acme_xdist self.acme_xdist = acme_xdist
+1 -1
View File
@@ -1,7 +1,7 @@
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'certbot', 'certbot',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'cloudflare>=1.5.1', 'cloudflare>=1.5.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support 'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
# This version of lexicon is required to address the problem described in # This version of lexicon is required to address the problem described in
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'google-api-python-client>=1.5.5', 'google-api-python-client>=1.5.5',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dnspython>=1.15.0', 'dnspython>=1.15.0',
@@ -38,7 +38,8 @@ class Authenticator(dns_common.DNSAuthenticator):
def __init__(self, *args: Any, **kwargs: Any) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.r53 = boto3.client("route53") self.r53 = boto3.client("route53")
self._resource_records: DefaultDict[str, List[Dict[str, str]]] = collections.defaultdict(list) self._resource_records: DefaultDict[str, List[Dict[str, str]]] = \
collections.defaultdict(list)
def more_info(self) -> str: def more_info(self) -> str:
return "Solve a DNS01 challenge using AWS Route53" return "Solve a DNS01 challenge using AWS Route53"
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'boto3>=1.15.15', 'boto3>=1.15.15',
+1 -1
View File
@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
'dns-lexicon>=3.2.1', 'dns-lexicon>=3.2.1',
+1 -1
View File
@@ -1,7 +1,7 @@
from setuptools import find_packages from setuptools import find_packages
from setuptools import setup from setuptools import setup
version = '1.30.0.dev0' version = '1.31.0.dev0'
install_requires = [ install_requires = [
# We specify the minimum acme and certbot version as the current plugin # We specify the minimum acme and certbot version as the current plugin
+30 -1
View File
@@ -2,7 +2,7 @@
Certbot adheres to [Semantic Versioning](https://semver.org/). Certbot adheres to [Semantic Versioning](https://semver.org/).
## 1.30.0 - master ## 1.31.0 - master
### Added ### Added
@@ -18,6 +18,35 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
More details about these changes can be found on our GitHub repo. More details about these changes can be found on our GitHub repo.
## 1.30.0 - 2022-09-07
### Added
*
### Changed
* `acme.client.ClientBase`, `acme.messages.Authorization.resolved_combinations`,
`acme.messages.Authorization.combinations`, `acme.mixins`, `acme.fields.resource`,
and `acme.fields.Resource` are deprecated and will be removed in a future release.
* `acme.messages.OLD_ERROR_PREFIX` (`urn:acme:error:`) is deprecated and support for
the old ACME error prefix in Certbot will be removed in the next major release of
Certbot.
* `acme.messages.Directory.register` is deprecated and will be removed in the next
major release of Certbot. Furthermore, `.Directory` will only support lookups
by the exact resource name string in the ACME directory (e.g. `directory['newOrder']`).
* The `certbot-dns-cloudxns` plugin is now deprecated and will be removed in the
next major release of Certbot.
* The `source_address` argument for `acme.client.ClientNetwork` is deprecated
and support for it will be removed in the next major release.
* Add UI text suggesting users create certs for multiple domains, when possible
### Fixed
*
More details about these changes can be found on our GitHub repo.
## 1.29.0 - 2022-07-05 ## 1.29.0 - 2022-07-05
### Added ### Added
+1 -1
View File
@@ -1,3 +1,3 @@
"""Certbot client.""" """Certbot client."""
# version number like 1.2.3a0, must have at least 2 parts, like 1.2 # version number like 1.2.3a0, must have at least 2 parts, like 1.2
__version__ = '1.30.0.dev0' __version__ = '1.31.0.dev0'
+3 -3
View File
@@ -194,7 +194,7 @@ class _WindowsLockMechanism(_BaseLockMechanism):
low level APIs, and Python does not do it. As of Python 3.7 and below, Python developers low level APIs, and Python does not do it. As of Python 3.7 and below, Python developers
state that deleting a file opened by a process from another process is not possible with state that deleting a file opened by a process from another process is not possible with
os.open and io.open. os.open and io.open.
Consequently, mscvrt.locking is sufficient to obtain an effective lock, and the race Consequently, msvcrt.locking is sufficient to obtain an effective lock, and the race
condition encountered on Linux is not possible on Windows, leading to a simpler workflow. condition encountered on Linux is not possible on Windows, leading to a simpler workflow.
""" """
def acquire(self) -> None: def acquire(self) -> None:
@@ -209,7 +209,7 @@ class _WindowsLockMechanism(_BaseLockMechanism):
# This "type: ignore" is currently needed because msvcrt methods # This "type: ignore" is currently needed because msvcrt methods
# are only defined on Windows. See # are only defined on Windows. See
# https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi.
msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) # type: ignore msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) # type: ignore # pylint: disable=used-before-assignment
except (IOError, OSError) as err: except (IOError, OSError) as err:
if fd: if fd:
os.close(fd) os.close(fd)
@@ -229,7 +229,7 @@ class _WindowsLockMechanism(_BaseLockMechanism):
# This "type: ignore" is currently needed because msvcrt methods # This "type: ignore" is currently needed because msvcrt methods
# are only defined on Windows. See # are only defined on Windows. See
# https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi.
msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1) # type: ignore msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1) # type: ignore # pylint: disable=used-before-assignment
os.close(self._fd) os.close(self._fd)
try: try:
+2 -2
View File
@@ -47,7 +47,7 @@ class AnnotatedChallenge(jose.ImmutableMap):
class KeyAuthorizationAnnotatedChallenge(AnnotatedChallenge): class KeyAuthorizationAnnotatedChallenge(AnnotatedChallenge):
"""Client annotated `KeyAuthorizationChallenge` challenge.""" """Client annotated `KeyAuthorizationChallenge` challenge."""
__slots__ = ('challb', 'domain', 'account_key') __slots__ = ('challb', 'domain', 'account_key') # pylint: disable=redefined-slots-in-subclass
def response_and_validation(self, *args: Any, **kwargs: Any) -> Any: def response_and_validation(self, *args: Any, **kwargs: Any) -> Any:
"""Generate response and validation.""" """Generate response and validation."""
@@ -57,5 +57,5 @@ class KeyAuthorizationAnnotatedChallenge(AnnotatedChallenge):
class DNS(AnnotatedChallenge): class DNS(AnnotatedChallenge):
"""Client annotated "dns" ACME challenge.""" """Client annotated "dns" ACME challenge."""
__slots__ = ('challb', 'domain') __slots__ = ('challb', 'domain') # pylint: disable=redefined-slots-in-subclass
acme_type = challenges.DNS acme_type = challenges.DNS
+4 -1
View File
@@ -181,7 +181,10 @@ def _filter_names(names: Iterable[str],
if override_question: if override_question:
question = override_question question = override_question
else: else:
question = "Which names would you like to activate HTTPS for?" question = (
"Which names would you like to activate HTTPS for?\n"
"We recommend selecting either all domains, or all domains in a VirtualHost/server "
"block.")
code, names = display_util.checklist( code, names = display_util.checklist(
question, tags=sorted_names, cli_flag="--domains", force_interactive=True) question, tags=sorted_names, cli_flag="--domains", force_interactive=True)
return code, [str(s) for s in names] return code, [str(s) for s in names]
@@ -38,14 +38,12 @@ class _AuthenticatorCallableTestCase(Protocol):
See See
https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue
""" """
...
def assertEqual(self, *unused_args: Any) -> None: def assertEqual(self, *unused_args: Any) -> None:
""" """
See See
https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual
""" """
...
class BaseAuthenticatorTest: class BaseAuthenticatorTest:
@@ -57,7 +57,6 @@ class _LexiconAwareTestCase(Protocol):
See See
https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises
""" """
...
# These classes are intended to be subclassed/mixed in, so not all members are defined. # These classes are intended to be subclassed/mixed in, so not all members are defined.
+4 -2
View File
@@ -126,7 +126,7 @@ optional arguments:
case, and to know when to deprecate support for past case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to information from the Let's Encrypt server, set this to
"". (default: CertbotACMEClient/1.29.0 (certbot; "". (default: CertbotACMEClient/1.30.0 (certbot;
OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
The flags encoded in the user agent are: --duplicate, The flags encoded in the user agent are: --duplicate,
@@ -236,7 +236,9 @@ testing:
(default: False) (default: False)
--debug Show tracebacks in case of errors (default: False) --debug Show tracebacks in case of errors (default: False)
--no-verify-ssl Disable verification of the ACME server's certificate. --no-verify-ssl Disable verification of the ACME server's certificate.
(default: False) The root certificates trusted by Certbot can be
overriden by setting the REQUESTS_CA_BUNDLE
environment variable. (default: False)
--http-01-port HTTP01_PORT --http-01-port HTTP01_PORT
Port used in the http-01 challenge. This only affects Port used in the http-01 challenge. This only affects
the port Certbot listens on. A conforming ACME server the port Certbot listens on. A conforming ACME server
+1 -1
View File
@@ -84,7 +84,7 @@ release = meta['version']
# #
# This is also used if you do content translation via gettext catalogs. # This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases. # Usually you set "language" from the command line for these cases.
language = None language = 'en'
# There are two options for replacing |today|: either, you set today to some # There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used: # non-false value, then it is used:
+3
View File
@@ -500,6 +500,9 @@ Submitting a pull request
Steps: Steps:
0. We recommend you talk with us in a GitHub issue or :ref:`Mattermost <ask for
help>` before writing a pull request to ensure the changes you're making is
something we have the time and interest to review.
1. Write your code! When doing this, you should add :ref:`mypy type annotations 1. Write your code! When doing this, you should add :ref:`mypy type annotations
<type annotations>` for any functions you add or modify. You can check that <type annotations>` for any functions you add or modify. You can check that
you've done this correctly by running ``tox -e mypy`` on a machine that has you've done this correctly by running ``tox -e mypy`` on a machine that has
+9
View File
@@ -315,6 +315,8 @@ dns-lightsail_ Y N DNS Authentication using Amazon Lightsail DNS API
dns-inwx_ Y Y DNS Authentication for INWX through the XML API dns-inwx_ Y Y DNS Authentication for INWX through the XML API
dns-azure_ Y N DNS Authentication using Azure DNS dns-azure_ Y N DNS Authentication using Azure DNS
dns-godaddy_ Y N DNS Authentication using Godaddy DNS dns-godaddy_ Y N DNS Authentication using Godaddy DNS
dns-yandexcloud_ Y N DNS Authentication using Yandex Cloud DNS
dns-bunny_ Y N DNS Authentication using BunnyDNS
njalla_ Y N DNS Authentication for njalla njalla_ Y N DNS Authentication for njalla
DuckDNS_ Y N DNS Authentication for DuckDNS DuckDNS_ Y N DNS Authentication for DuckDNS
Porkbun_ Y N DNS Authentication for Porkbun Porkbun_ Y N DNS Authentication for Porkbun
@@ -335,6 +337,8 @@ Infomaniak_ Y N DNS Authentication using Infomaniak Domains API
.. _dns-inwx: https://github.com/oGGy990/certbot-dns-inwx/ .. _dns-inwx: https://github.com/oGGy990/certbot-dns-inwx/
.. _dns-azure: https://github.com/binkhq/certbot-dns-azure .. _dns-azure: https://github.com/binkhq/certbot-dns-azure
.. _dns-godaddy: https://github.com/miigotu/certbot-dns-godaddy .. _dns-godaddy: https://github.com/miigotu/certbot-dns-godaddy
.. _dns-yandexcloud: https://github.com/PykupeJIbc/certbot-dns-yandexcloud
.. _dns-bunny: https://github.com/mwt/certbot-dns-bunny
.. _njalla: https://github.com/chaptergy/certbot-dns-njalla .. _njalla: https://github.com/chaptergy/certbot-dns-njalla
.. _DuckDNS: https://github.com/infinityofspace/certbot_dns_duckdns .. _DuckDNS: https://github.com/infinityofspace/certbot_dns_duckdns
.. _Porkbun: https://github.com/infinityofspace/certbot_dns_porkbun .. _Porkbun: https://github.com/infinityofspace/certbot_dns_porkbun
@@ -557,6 +561,11 @@ If you need to delete a certificate, use the ``delete`` subcommand.
.. note:: Read this and the `Safely deleting certificates`_ sections carefully. This is an irreversible operation and must .. note:: Read this and the `Safely deleting certificates`_ sections carefully. This is an irreversible operation and must
be done with care. be done with care.
Certbot does not automatically revoke a certificate before deleting it. If you're no longer using a certificate and don't
plan to use it anywhere else, you may want to follow the instructions in `Revoking certificates`_ instead. Generally, there's
no need to revoke a certificate if its private key has not been compromised, but you may still receive expiration emails
from Let's Encrypt unless you revoke.
.. note:: Do not manually delete certificate files from inside ``/etc/letsencrypt/``. Always use the ``delete`` subcommand. .. note:: Do not manually delete certificate files from inside ``/etc/letsencrypt/``. Always use the ``delete`` subcommand.
A certificate may be deleted by providing its name with ``--cert-name``. \ A certificate may be deleted by providing its name with ``--cert-name``. \
+2 -2
View File
@@ -6,8 +6,8 @@
targets: targets:
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
#Ubuntu #Ubuntu
- ami: ami-0c2d5393cb5b518f6 - ami: ami-051dcca84f1edfff1
name: ubuntu21.10 name: ubuntu22.04
type: ubuntu type: ubuntu
virt: hvm virt: hvm
user: ubuntu user: ubuntu
+4 -11
View File
@@ -13,19 +13,12 @@
# The current warnings being ignored are: # The current warnings being ignored are:
# 1) The warning raised when importing certbot.tests.util and the external mock # 1) The warning raised when importing certbot.tests.util and the external mock
# library is installed. # library is installed.
# 2) The deprecation warning raised when importing deprecated attributes from # 2) A deprecation warning is raised in dnspython==1.15.0 in the oldest tests for
# the certbot.display.util module.
# 3) A deprecation warning is raised in dnspython==1.15.0 in the oldest tests for
# certbot-dns-rfc2136. # certbot-dns-rfc2136.
# 4) The vendored version of six in botocore causes ImportWarnings in Python # 3) botocore is currently using deprecated urllib3 functionality. See
# 3.10+. See https://github.com/boto/botocore/issues/2548. # https://github.com/boto/botocore/issues/2744.
# 5) 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.
filterwarnings = filterwarnings =
error error
ignore:The external mock module:PendingDeprecationWarning ignore:The external mock module:PendingDeprecationWarning
ignore:.*attribute in certbot.display.util module is deprecated:DeprecationWarning
ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns
ignore:_SixMetaPathImporter.:ImportWarning ignore:'urllib3.contrib.pyopenssl:DeprecationWarning:botocore
ignore:ssl.PROTOCOL_TLS:DeprecationWarning:botocore
-1
View File
@@ -63,7 +63,6 @@ pyasn1-modules==0.0.10; python_version >= "3.7"
pyasn1==0.1.9 pyasn1==0.1.9
pycparser==2.14 pycparser==2.14
pylint==2.13.9 pylint==2.13.9
pylint==2.13.9; python_version >= "3.7"
pynacl==1.5.0; python_version >= "3.7" pynacl==1.5.0; python_version >= "3.7"
pyopenssl==17.5.0 pyopenssl==17.5.0
pyparsing==2.2.1 pyparsing==2.2.1
+15 -6
View File
@@ -61,18 +61,27 @@ mock = "*"
# https://github.com/python-poetry/poetry/issues/1584. This version is required # https://github.com/python-poetry/poetry/issues/1584. This version is required
# here in addition to certbot/setup.py because otherwise the pre-release # here in addition to certbot/setup.py because otherwise the pre-release
# version of poetry will not be installed. # version of poetry will not be installed.
poetry = ">=1.2.0a1" #
# 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 # 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 # 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 # working version. Note: if build dependencies of setuptools-rust break at some
# point, it's probably worth enumerating and pinning them (and recursing to # point, it's probably worth enumerating and pinning them (and recursing to
# THEIR build dependencies) as well. # THEIR build dependencies) as well.
setuptools-rust = "*" setuptools-rust = "*"
# A bad python_requires constraint in pylint 2.6.2 can sometimes crash poetry # pylint often adds new checks that we need to conform our code to when
# before it has finished resolving. No newer releases have the same issue. Remove # upgrading our dependencies. To help control when this needs to be done, we
# this once we can upgrade to a release of Poetry containing this commit: # pin pylint to a compatible version here.
# https://github.com/python-poetry/poetry-core/commit/4e1f2ab582d1fef0033c0d3f35a3f2f2365a4bc9 #
pylint = ">2.6.2" # If this pinning is removed, we may still need to add a lower bound for the
# pylint version. See https://github.com/certbot/certbot/pull/9229.
pylint = "2.13.9"
# Bug in poetry, where still installes yanked versions from pypi (source: https://github.com/python-poetry/poetry/issues/2453) # Bug in poetry, where still installes yanked versions from pypi (source: https://github.com/python-poetry/poetry/issues/2453)
# this version of cryptography introduced a security vulnrability. # this version of cryptography introduced a security vulnrability.
+7 -5
View File
@@ -98,11 +98,13 @@ cython = "*"
# wheel 0.34.0 is buggy). # wheel 0.34.0 is buggy).
wheel = "<0.34.0" wheel = "<0.34.0"
# A bad python_requires constraint in pylint 2.6.2 can sometimes crash poetry # pylint often adds new checks that we need to conform our code to when
# before it has finished resolving. No newer releases have the same issue. Remove # upgrading our dependencies. To help control when this needs to be done, we
# this once we can upgrade to a release of Poetry containing this commit: # pin pylint to a compatible version here.
# https://github.com/python-poetry/poetry-core/commit/4e1f2ab582d1fef0033c0d3f35a3f2f2365a4bc9 #
pylint = ">2.6.2" # If this pinning is removed, we may still need to add a lower bound for the
# pylint version. See https://github.com/certbot/certbot/pull/9229.
pylint = "2.13.9"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
+132 -132
View File
@@ -7,186 +7,186 @@
# for more info. # for more info.
alabaster==0.7.12; python_version >= "3.7" alabaster==0.7.12; python_version >= "3.7"
apacheconfig==0.3.2; python_version >= "3.7" apacheconfig==0.3.2; python_version >= "3.7"
appdirs==1.4.4; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" appdirs==1.4.4; python_version >= "3.7" and python_version < "4.0"
appnope==0.1.2; python_version >= "3.7" and sys_platform == "darwin" appnope==0.1.3; python_version >= "3.7" and sys_platform == "darwin"
astroid==2.9.3; python_version >= "3.7" and python_full_version >= "3.6.2" astroid==2.11.7; python_version >= "3.7"
atomicwrites==1.4.0; python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.7" and python_full_version >= "3.4.0" atomicwrites==1.4.1; sys_platform == "win32" and python_version >= "3.7"
attrs==21.4.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" attrs==22.1.0; python_version >= "3.7"
awscli==1.22.75; python_version >= "3.6" awscli==1.25.40
awscli==1.25.40; python_version >= "3.7"
azure-devops==6.0.0b4; python_version >= "3.7" azure-devops==6.0.0b4; python_version >= "3.7"
babel==2.9.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" babel==2.10.3; python_version >= "3.7"
backcall==0.2.0; python_version >= "3.7" backcall==0.2.0; python_version >= "3.7"
bcrypt==3.2.0; python_version >= "3.7" bcrypt==3.2.2; python_version >= "3.7"
beautifulsoup4==4.10.0; python_full_version > "3.0.0" and python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0" and python_full_version > "3.0.0" beautifulsoup4==4.11.1; python_version >= "3.7"
bleach==4.1.0; python_version >= "3.7" bleach==5.0.1; python_version >= "3.7"
boto3==1.21.20; python_version >= "3.7" boto3==1.24.40; python_version >= "3.7"
botocore==1.24.20; python_version >= "3.7" botocore==1.27.40; python_version >= "3.7"
cachecontrol==0.12.10; python_version >= "3.7" and python_version < "4.0" cachecontrol==0.12.11; python_version >= "3.7" and python_version < "4.0"
cached-property==1.5.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" cached-property==1.5.2; python_version >= "3.7"
cachetools==5.0.0; python_version >= "3.7" and python_version < "4.0" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" 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_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" cachy==0.3.0; python_version >= "3.7" and python_version < "4.0"
certifi==2021.10.8; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" or python_version >= "3.7" certifi==2022.6.15; python_version >= "3.7" and python_version < "4" or python_version >= "3.7"
cffi==1.15.0; python_version >= "3.7" or python_version >= "3.7" cffi==1.15.1; python_version >= "3.7"
charset-normalizer==2.0.12; python_full_version >= "3.6.0" and python_version >= "3.7" charset-normalizer==2.1.0; python_version >= "3.7" and python_version < "4"
cleo==1.0.0a4; python_version >= "3.7" and python_version < "4.0" cleo==1.0.0a5; python_version >= "3.7" and python_version < "4.0"
cloudflare==2.8.15; python_version >= "3.7" cloudflare==2.9.11; python_version >= "3.7"
colorama==0.4.3; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" or sys_platform == "win32" and python_full_version >= "3.6.2" and python_version >= "3.7" or python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or python_full_version >= "3.5.0" and python_version >= "3.7" and sys_platform == "win32" or python_version >= "3.7" and python_full_version < "3.0.0" and platform_system == "Windows" or python_version >= "3.7" and python_full_version >= "3.5.0" and platform_system == "Windows" colorama==0.4.4; python_version >= "3.7"
configargparse==1.5.3; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" configargparse==1.5.3; python_version >= "3.7"
configobj==5.0.6; python_version >= "3.7" configobj==5.0.6; python_version >= "3.7"
coverage==6.3.2; python_version >= "3.7" or python_version >= "3.7" coverage==6.4.2; python_version >= "3.7"
crashtest==0.3.1; python_version >= "3.7" and python_version < "4.0" crashtest==0.3.1; python_version >= "3.7" and python_version < "4.0"
cryptography==36.0.2; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" cryptography==37.0.4
cython==0.29.28; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") cryptography==37.0.4; python_version >= "3.7"
cython==0.29.31
decorator==5.1.1; python_version >= "3.7" decorator==5.1.1; python_version >= "3.7"
deprecated==1.2.13; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" dill==0.3.5.1; python_version >= "3.7"
distlib==0.3.4; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" or python_version >= "3.7" distlib==0.3.5; python_version >= "3.7"
distro==1.7.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" or python_version >= "3.7" distro==1.7.0; python_version >= "3.7"
dns-lexicon==3.9.4; python_version >= "3.7" and python_version < "4.0" 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" dnspython==2.2.1; python_version >= "3.7" and python_version < "4.0"
docker-compose==1.26.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" docker-compose==1.26.2; python_version >= "3.7"
docker==4.2.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" docker==4.2.2; python_version >= "3.7"
dockerpty==0.4.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" dockerpty==0.4.1; python_version >= "3.7"
docopt==0.6.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" docopt==0.6.2; python_version >= "3.7"
docutils==0.15.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7" or python_version >= "3.7" and python_full_version >= "3.4.0" docutils==0.16; python_version >= "3.7"
entrypoints==0.3; python_version >= "3.7" and python_version < "4.0" entrypoints==0.3; python_version >= "3.7" and python_version < "4.0"
execnet==1.9.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" execnet==1.9.0; python_version >= "3.7"
fabric==2.6.0; python_version >= "3.7" fabric==2.7.1; python_version >= "3.7"
filelock==3.6.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.5.0" or python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" or python_version >= "3.7" and python_version < "4.0" filelock==3.7.1; python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0"
google-api-core==2.7.1; python_version >= "3.7" google-api-core==2.8.2; python_version >= "3.7"
google-api-python-client==2.41.0; python_version >= "3.7" google-api-python-client==2.55.0; python_version >= "3.7"
google-auth-httplib2==0.1.0; python_version >= "3.7" google-auth-httplib2==0.1.0; python_version >= "3.7"
google-auth==2.6.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" google-auth==2.9.1; python_version >= "3.7"
googleapis-common-protos==1.55.0; python_version >= "3.7" googleapis-common-protos==1.56.4; python_version >= "3.7"
html5lib==1.1; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.5.0" html5lib==1.1; python_version >= "3.7" and python_version < "4.0"
httplib2==0.20.4; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" httplib2==0.20.4; python_version >= "3.7"
idna==3.3; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0" idna==3.3; python_version >= "3.7" and python_version < "4" or python_version >= "3.7" and python_version < "4.0"
imagesize==1.3.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" imagesize==1.4.1; python_version >= "3.7"
importlib-metadata==1.7.0; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "3.8" or python_version >= "3.7" and python_version < "3.8" and python_full_version >= "3.5.0" importlib-metadata==1.7.0; python_version >= "3.7" and python_version < "3.8"
iniconfig==1.1.1; python_version >= "3.7" iniconfig==1.1.1; python_version >= "3.7"
invoke==1.6.0; python_version >= "3.7" invoke==1.7.1; python_version >= "3.7"
ipdb==0.13.9; python_version >= "3.7" ipdb==0.13.9; python_version >= "3.7"
ipython==7.32.0; python_version >= "3.7" ipython==7.34.0; python_version >= "3.7"
isodate==0.6.1; python_version >= "3.7" isodate==0.6.1; python_version >= "3.7"
isort==5.10.1; python_full_version >= "3.6.2" and python_version < "4.0" and 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" jedi==0.18.1; python_version >= "3.7"
jeepney==0.7.1; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" jeepney==0.8.0; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
jinja2==3.0.3; python_version >= "3.7" or python_version >= "3.7" jinja2==3.1.2; python_version >= "3.7"
jmespath==0.10.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7" jmespath==1.0.1; python_version >= "3.7"
josepy==1.13.0; python_version >= "3.7" josepy==1.13.0; python_version >= "3.7"
jsonlines==3.0.0; python_version >= "3.7" jsonlines==3.1.0; python_version >= "3.7"
jsonpickle==2.1.0; python_version >= "3.7" jsonpickle==2.2.0; python_version >= "3.7"
jsonschema==3.2.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and 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" 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" and python_full_version >= "3.6.2" lazy-object-proxy==1.7.1; python_version >= "3.7"
lockfile==0.12.2 lockfile==0.12.2
markupsafe==2.1.1; python_version >= "3.7" markupsafe==2.1.1; python_version >= "3.7"
matplotlib-inline==0.1.3; python_version >= "3.7" matplotlib-inline==0.1.3; python_version >= "3.7"
mccabe==0.6.1; python_version >= "3.7" and python_full_version >= "3.6.2" mccabe==0.7.0; python_version >= "3.7"
mock==4.0.3; python_version >= "3.6" mock==4.0.3
msgpack==1.0.3; 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" msrest==0.6.21; python_version >= "3.7"
mypy-extensions==0.4.3; python_version >= "3.7" mypy-extensions==0.4.3; python_version >= "3.7"
mypy==0.941; python_version >= "3.7" mypy==0.971; python_version >= "3.7"
oauth2client==4.1.3; python_version >= "3.7" oauth2client==4.1.3; python_version >= "3.7"
oauthlib==3.2.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" oauthlib==3.2.0; python_version >= "3.7"
packaging==20.9; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" or python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" or python_version >= "3.7" and python_full_version >= "3.5.0" packaging==20.9; python_version >= "3.7"
paramiko==2.10.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" or python_version >= "3.7" paramiko==2.11.0; python_version >= "3.7"
parsedatetime==2.6; python_version >= "3.7" parsedatetime==2.6; python_version >= "3.7"
parso==0.8.3; python_version >= "3.7" parso==0.8.3; python_version >= "3.7"
pathlib2==2.3.7.post1; 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" 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" pickleshare==0.7.5; python_version >= "3.7"
pip==22.0.4; python_version >= "3.7" pip==22.2.1; python_version >= "3.7"
pkginfo==1.8.2; python_version >= "3.7" and python_version < "4.0" or 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.1; python_version >= "3.7" and python_full_version >= "3.6.2" platformdirs==2.5.2; python_version >= "3.7"
pluggy==1.0.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.5.0" or python_version >= "3.7" pluggy==1.0.0; python_version >= "3.7"
ply==3.11; python_version >= "3.7" ply==3.11; python_version >= "3.7"
poetry-core==1.1.0a7; python_version >= "3.7" and python_version < "4.0" poetry-core==1.1.0a7
poetry==1.2.0a2; python_version >= "3.6" and python_version < "4.0" poetry==1.2.0a2
prompt-toolkit==3.0.28; python_version >= "3.7" and python_full_version >= "3.6.2" prompt-toolkit==3.0.30; python_version >= "3.7"
protobuf==3.19.4; python_version >= "3.7" protobuf==4.21.4; python_version >= "3.7"
ptyprocess==0.7.0; 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_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" py==1.11.0; python_version >= "3.7"
pyasn1-modules==0.2.8; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" or python_version >= "3.7" pyasn1-modules==0.2.8; python_version >= "3.7"
pyasn1==0.4.8; python_version >= "3.7" and python_version < "4" or python_version >= "3.7" pyasn1==0.4.8; python_version >= "3.7"
pycparser==2.21; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" pycparser==2.21; python_version >= "3.7"
pygithub==1.55; python_version >= "3.7" pygments==2.12.0; python_version >= "3.7"
pygments==2.11.2; python_version >= "3.7"
pyjwt==2.3.0; python_version >= "3.7"
pylev==1.4.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.12.2; python_full_version >= "3.6.2" pylint==2.13.9
pynacl==1.5.0; python_version >= "3.7" or python_version >= "3.7" pynacl==1.5.0; python_version >= "3.7"
pynsist==2.7; python_version >= "3.7" pynsist==2.7; python_version >= "3.7"
pyopenssl==22.0.0; python_version >= "3.7" pyopenssl==22.0.0; python_version >= "3.7"
pyparsing==3.0.7; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" or python_version >= "3.7" or python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" pyparsing==3.0.9; python_version >= "3.7"
pypiwin32==223; sys_platform == "win32" and python_version >= "3.6" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7") pypiwin32==223; sys_platform == "win32" and python_version >= "3.7"
pyrfc3339==1.1; python_version >= "3.7" pyrfc3339==1.1; python_version >= "3.7"
pyrsistent==0.18.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" pyrsistent==0.18.1; python_version >= "3.7"
pytest-cov==3.0.0; python_version >= "3.7" or python_version >= "3.7" pytest-cov==3.0.0; python_version >= "3.7"
pytest-forked==1.4.0; python_version >= "3.7" pytest-forked==1.4.0; python_version >= "3.7"
pytest-xdist==2.5.0; python_version >= "3.7" or python_version >= "3.7" pytest-xdist==2.5.0; python_version >= "3.7"
pytest==7.1.0; python_version >= "3.7" or python_version >= "3.7" pytest==7.1.2; python_version >= "3.7"
python-augeas==1.1.0; python_version >= "3.7" python-augeas==1.1.0; python_version >= "3.7"
python-dateutil==2.8.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7" python-dateutil==2.8.2; python_version >= "3.7"
python-digitalocean==1.17.0; python_version >= "3.7" python-digitalocean==1.17.0; python_version >= "3.7"
python-dotenv==0.19.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" python-dotenv==0.20.0; python_version >= "3.7"
pytz==2021.3; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" or python_version >= "3.7" pytz==2022.1; python_version >= "3.7"
pywin32-ctypes==0.2.0; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" pywin32-ctypes==0.2.0; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32"
pywin32==303; sys_platform == "win32" and python_version >= "3.7" or sys_platform == "win32" and python_version >= "3.6" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7") pywin32==304; sys_platform == "win32" and python_version >= "3.7"
pyyaml==5.4.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" or python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.6.0" pyyaml==5.4.1; python_version >= "3.7"
readme-renderer==34.0; python_version >= "3.7" readme-renderer==35.0; python_version >= "3.7"
requests-download==0.1.2; 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-file==1.5.1; python_version >= "3.7" and python_version < "4.0"
requests-oauthlib==1.3.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" requests-oauthlib==1.3.1; python_version >= "3.7"
requests-toolbelt==0.9.1; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7" or python_version >= "3.7" requests-toolbelt==0.9.1; python_version >= "3.7"
requests==2.27.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" or python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.6.0" requests==2.28.1; python_version >= "3.7" and python_version < "4"
rfc3986==2.0.0; python_version >= "3.7" rfc3986==2.0.0; python_version >= "3.7"
rsa==4.7.2; python_version >= "3.7" and python_version < "4" or python_version >= "3.5" and python_version < "4" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") rsa==4.7.2; python_version >= "3.7" and python_version < "4"
s3transfer==0.5.2; python_version >= "3.7" s3transfer==0.6.0; python_version >= "3.7"
secretstorage==3.3.1; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" secretstorage==3.3.2; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
semantic-version==2.9.0; python_version >= "3.6" semantic-version==2.10.0; python_version >= "3.7"
setuptools-rust==1.1.2; python_version >= "3.6" setuptools-rust==1.4.1
setuptools==60.9.3; python_version >= "3.7" or python_version >= "3.7" or python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" or python_version >= "3.7" and python_full_version >= "3.6.2" or python_full_version >= "3.4.0" and python_version >= "3.7" setuptools==63.2.0; python_version >= "3.7"
shellingham==1.4.0; python_version >= "3.7" and python_version < "4.0" shellingham==1.4.0; python_version >= "3.7" and python_version < "4.0"
six==1.16.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" or python_full_version >= "3.3.0" and python_version >= "3.7" or python_version >= "3.7" and python_full_version >= "3.5.0" or python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.5.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" or python_full_version >= "3.6.0" and python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.3.0" six==1.16.0; python_version >= "3.7"
snowballstemmer==2.2.0; python_version >= "3.7" snowballstemmer==2.2.0; python_version >= "3.7"
soupsieve==2.3.1; python_full_version > "3.0.0" and python_version >= "3.7" soupsieve==2.3.2.post1; python_version >= "3.7"
sphinx-rtd-theme==1.0.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" sphinx-rtd-theme==1.0.0; python_version >= "3.7"
sphinx==4.3.2; python_version >= "3.7" or python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" sphinx==4.3.2; python_version >= "3.7"
sphinxcontrib-applehelp==1.0.2; python_version >= "3.7" sphinxcontrib-applehelp==1.0.2; python_version >= "3.7"
sphinxcontrib-devhelp==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-htmlhelp==2.0.0; python_version >= "3.7"
sphinxcontrib-jsmath==1.0.1; python_version >= "3.7" sphinxcontrib-jsmath==1.0.1; python_version >= "3.7"
sphinxcontrib-qthelp==1.0.3; python_version >= "3.7" sphinxcontrib-qthelp==1.0.3; python_version >= "3.7"
sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.7" sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.7"
texttable==1.6.4; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" texttable==1.6.4; python_version >= "3.7"
tldextract==3.2.0; python_version >= "3.7" and python_version < "4.0" tldextract==3.3.1; python_version >= "3.7" and python_version < "4.0"
toml==0.10.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.3.0" or python_version >= "3.7" and python_full_version >= "3.6.2" or python_version >= "3.7" and python_full_version >= "3.5.0" toml==0.10.2; python_version >= "3.7"
tomli==2.0.1; python_version >= "3.7" or 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.10.0; python_version >= "3.7" and python_version < "4.0" tomlkit==0.11.1; python_version >= "3.7" and python_version < "4.0"
tox==3.24.5; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.5.0" tox==3.25.1; python_version >= "3.7"
tqdm==4.63.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.4.0" tqdm==4.64.0; python_version >= "3.7"
traitlets==5.1.1; python_version >= "3.7" traitlets==5.3.0; python_version >= "3.7"
twine==3.3.0; python_version >= "3.7" twine==3.3.0; python_version >= "3.7"
typed-ast==1.5.2; python_version >= "3.7" and python_version < "3.8" or implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.7" and python_full_version >= "3.6.2" 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.18; python_version >= "3.7" types-cryptography==3.3.21; python_version >= "3.7"
types-mock==4.0.11; python_version >= "3.7" types-mock==4.0.15; python_version >= "3.7"
types-pyopenssl==22.0.0; python_version >= "3.7" types-pyopenssl==22.0.9; python_version >= "3.7"
types-pyrfc3339==1.1.1; python_version >= "3.7" types-pyrfc3339==1.1.1; python_version >= "3.7"
types-python-dateutil==2.8.9; python_version >= "3.7" types-python-dateutil==2.8.19; python_version >= "3.7"
types-pytz==2021.3.5; python_version >= "3.7" types-pytz==2022.1.2; python_version >= "3.7"
types-requests==2.27.12; python_version >= "3.7" types-requests==2.28.5; python_version >= "3.7"
types-setuptools==57.4.10; python_version >= "3.7" types-setuptools==63.2.2; python_version >= "3.7"
types-six==1.16.12; python_version >= "3.7" types-six==1.16.18; python_version >= "3.7"
types-urllib3==1.26.11; python_version >= "3.7" types-urllib3==1.26.17; python_version >= "3.7"
typing-extensions==4.1.1; python_version >= "3.7" or python_version >= "3.6" or python_version < "3.10" and python_full_version >= "3.6.2" and python_version >= "3.7" or python_version < "3.8" and 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" uritemplate==4.1.1; python_version >= "3.7"
urllib3==1.26.8; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.7" urllib3==1.26.11; python_version >= "3.7" and python_version < "4"
virtualenv==20.4.4; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.4.0" or python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.5.0" 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" and python_full_version >= "3.6.2" wcwidth==0.2.5; python_version >= "3.7"
webencodings==0.5.1; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.5.0" or 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" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" or python_full_version >= "3.5.0" and python_version >= "3.7" websocket-client==0.59.0; python_version >= "3.7"
wheel==0.37.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.5.0" wheel==0.37.1; python_version >= "3.7"
wrapt==1.13.3; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version >= "3.5.0" or python_version >= "3.7" and python_full_version >= "3.6.2" wrapt==1.14.1; python_version >= "3.7"
yarg==0.1.9; 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" zipp==3.8.1; python_version >= "3.7" and python_version < "3.8"