Deprecate TLS-ALPN support in ACME (#10268)

Fixes #10266.

See example deprecation in
https://github.com/certbot/josepy/pull/207/files

I can add stacklevel=2, though I find that usually I just look at the
whole stack anyway when debugging, myself, so it doesn't really matter.
This commit is contained in:
ohemorange 2025-04-28 15:09:15 -07:00 committed by GitHub
parent 508fba1da6
commit 6ac951e146
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 66 additions and 11 deletions

View file

@ -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"))

View file

@ -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()

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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)]))

View file

@ -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