diff --git a/acme/src/acme/challenges.py b/acme/src/acme/challenges.py index 4204adfa4..9ece484cd 100644 --- a/acme/src/acme/challenges.py +++ b/acme/src/acme/challenges.py @@ -13,6 +13,7 @@ from typing import Tuple from typing import Type from typing import TypeVar from typing import Union +import warnings from cryptography import x509 from cryptography.hazmat.primitives import hashes @@ -399,7 +400,11 @@ class HTTP01(KeyAuthorizationChallenge): @ChallengeResponse.register class TLSALPN01Response(KeyAuthorizationChallengeResponse): - """ACME tls-alpn-01 challenge response.""" + """ACME tls-alpn-01 challenge response. + + .. deprecated:: 4.1.0 + + """ typ = "tls-alpn-01" PORT = 443 @@ -413,6 +418,11 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse): ID_PE_ACME_IDENTIFIER_V1 = b"1.3.6.1.5.5.7.1.30.1" ACME_TLS_1_PROTOCOL = b"acme-tls/1" + def __init__(self, *args: Any, **kwargs: Any) -> None: + warnings.warn("TLSALPN01Response is deprecated and will be removed in an " + "upcoming certbot major version update", DeprecationWarning) + super().__init__(*args, **kwargs) + @property def h(self) -> bytes: """Hash value stored in challenge certificate""" @@ -467,7 +477,12 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse): if port is None: port = self.PORT - return crypto_util.probe_sni(host=host.encode(), port=port, name=domain.encode(), + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', + message='alpn_protocols parameter is deprecated' + ) + return crypto_util.probe_sni(host=host.encode(), port=port, name=domain.encode(), alpn_protocols=[self.ACME_TLS_1_PROTOCOL]) def verify_cert(self, domain: str, cert: x509.Certificate, ) -> bool: @@ -540,10 +555,19 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse): @Challenge.register # pylint: disable=too-many-ancestors class TLSALPN01(KeyAuthorizationChallenge): - """ACME tls-alpn-01 challenge.""" + """ACME tls-alpn-01 challenge. + + .. deprecated:: 4.1.0 + + """ response_cls = TLSALPN01Response typ = response_cls.typ + def __init__(self, *args: Any, **kwargs: Any) -> None: + warnings.warn("TLSALPN01 is deprecated and will be removed in an " + "upcoming certbot major version update", DeprecationWarning) + super().__init__(*args, **kwargs) + def validation(self, account_key: jose.JWK, **kwargs: Any) -> Tuple[x509.Certificate, crypto.PKey]: """Generate validation. @@ -573,6 +597,8 @@ class TLSALPN01(KeyAuthorizationChallenge): :rtype: bool """ + warnings.warn("TLSALPN01 is deprecated and will be removed in an " + "upcoming certbot major version update", DeprecationWarning) return (hasattr(SSL.Connection, "set_alpn_protos") and hasattr(SSL.Context, "set_alpn_select_callback")) diff --git a/acme/src/acme/crypto_util.py b/acme/src/acme/crypto_util.py index c20c49c7d..b0783952c 100644 --- a/acme/src/acme/crypto_util.py +++ b/acme/src/acme/crypto_util.py @@ -16,6 +16,7 @@ from typing import Sequence from typing import Set from typing import Tuple from typing import Union +import warnings from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization @@ -101,6 +102,9 @@ class SSLSocket: # pylint: disable=too-few-public-methods ) -> None: self.sock = sock self.alpn_selection = alpn_selection + if alpn_selection: + warnings.warn("alpn_selection ivar is deprecated and will be removed in an " + "upcoming certbot major version update", DeprecationWarning) self.method = method if not cert_selection and not certs: raise ValueError("Neither cert_selection or certs specified.") @@ -242,6 +246,8 @@ def probe_sni(name: bytes, host: bytes, port: int = 443, timeout: int = 300, # client_ssl.set_tlsext_host_name(name) # pyOpenSSL>=0.13 if alpn_protocols is not None: client_ssl.set_alpn_protos(list(alpn_protocols)) + warnings.warn("alpn_protocols parameter is deprecated and will be removed in an " + "upcoming certbot major version update", DeprecationWarning) try: client_ssl.do_handshake() client_ssl.shutdown() diff --git a/acme/src/acme/standalone.py b/acme/src/acme/standalone.py index 10cbb1ea5..cf3df7081 100644 --- a/acme/src/acme/standalone.py +++ b/acme/src/acme/standalone.py @@ -15,6 +15,7 @@ from typing import Optional from typing import Set from typing import Tuple from typing import Type +import warnings from OpenSSL import SSL @@ -39,10 +40,15 @@ class TLSServer(socketserver.TCPServer): super().__init__(*args, **kwargs) def _wrap_sock(self) -> None: - self.socket = cast(socket.socket, crypto_util.SSLSocket( - self.socket, cert_selection=self._cert_selection, - alpn_selection=getattr(self, '_alpn_selection', None), - method=self.method)) + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', + message='alpn_selection ivar is deprecated' + ) + self.socket = cast(socket.socket, crypto_util.SSLSocket( + self.socket, cert_selection=self._cert_selection, + alpn_selection=getattr(self, '_alpn_selection', None), + method=self.method)) def _cert_selection(self, connection: SSL.Connection ) -> Optional[crypto_util._KeyAndCert]: # pragma: no cover @@ -146,7 +152,11 @@ class BaseDualNetworkedServers: class TLSALPN01Server(TLSServer, ACMEServerMixin): - """TLSALPN01 Server.""" + """TLSALPN01 Server. + + .. deprecated:: 4.1.0 + + """ ACME_TLS_1_PROTOCOL = b"acme-tls/1" @@ -154,6 +164,8 @@ class TLSALPN01Server(TLSServer, ACMEServerMixin): certs: List[crypto_util._KeyAndCert], challenge_certs: Mapping[bytes, crypto_util._KeyAndCert], ipv6: bool = False) -> None: + warnings.warn("TLSALPN01Server is deprecated and will be removed in an " + "upcoming certbot major version update", DeprecationWarning) # 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 # parent TLSServer class. diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index e5396144f..f0b89129c 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -11,6 +11,11 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Changed * Switched to src-layout from flat-layout to accommodate PEP 517 pip editable installs +* Deprecated `acme.challenges.TLSALPN01Response` +* Deprecated `acme.challenges.TLSALPN01` +* Deprecated ivar `alpn_selection` from `acme.crypto_util.SSLSocket` +* Deprecated parameter `alpn_protocols` from `acme.crypto_util.probe_sni` +* Deprecated `acme.standalone.TLSALPN01Server` ### Fixed diff --git a/certbot/docs/contributing.rst b/certbot/docs/contributing.rst index 9825caea2..5bace3602 100644 --- a/certbot/docs/contributing.rst +++ b/certbot/docs/contributing.rst @@ -269,8 +269,8 @@ Authenticators -------------- Authenticators are plugins that prove control of a domain name by solving a -challenge provided by the ACME server. ACME currently defines several types of -challenges: HTTP, TLS-ALPN, and DNS, represented by classes in `acme.challenges`. +challenge provided by the ACME server. ACME currently defines two types of +challenges: HTTP and DNS, represented by classes in `acme.challenges`. An authenticator plugin should implement support for at least one challenge type. An Authenticator indicates which challenges it supports by implementing diff --git a/certbot/src/certbot/_internal/plugins/manual.py b/certbot/src/certbot/_internal/plugins/manual.py index cbc575fcb..4049984ec 100644 --- a/certbot/src/certbot/_internal/plugins/manual.py +++ b/certbot/src/certbot/_internal/plugins/manual.py @@ -139,7 +139,6 @@ permitted by DNS standards.) resource_names = { challenges.DNS01: 'DNS TXT records', challenges.HTTP01: 'challenge files', - challenges.TLSALPN01: 'TLS-ALPN certificates' } resources = ' and '.join(sorted([v for k, v in resource_names.items() if has_chall(k)])) diff --git a/pytest.ini b/pytest.ini index 6a08ab57d..1bcf2640b 100644 --- a/pytest.ini +++ b/pytest.ini @@ -22,6 +22,8 @@ # 4 & 5) The pyOpenSSL X509/PKey warnings are due to TLS-ALPN-01 support. # Resolving these warnings is being tracked by # https://github.com/certbot/certbot/issues/10079. +# 6 - 10) Planning to remove unused TLS-ALPN support in acme. +# See https://github.com/certbot/certbot/issues/10266 filterwarnings = error ignore:.*rsyncdir:DeprecationWarning @@ -29,3 +31,8 @@ filterwarnings = ignore:.*datetime.utcfromtimestamp\(\) is deprecated:DeprecationWarning:dateutil ignore:Passing pyOpenSSL X509 objects is deprecated:DeprecationWarning ignore:Passing pyOpenSSL PKey objects is deprecated:DeprecationWarning + ignore:alpn_selection ivar is deprecated:DeprecationWarning + ignore:alpn_protocols parameter is deprecated:DeprecationWarning + ignore:TLSALPN01Server is deprecated:DeprecationWarning + ignore:TLSALPN01Response is deprecated:DeprecationWarning + ignore:TLSALPN01 is deprecated:DeprecationWarning