acme: remove deprecated functions

This commit is contained in:
Will Greenberg
2026-02-26 12:49:48 -08:00
parent 15e73753a6
commit df4f05e85e
2 changed files with 0 additions and 221 deletions
@@ -14,14 +14,6 @@ from cryptography.hazmat.primitives.asymmetric import rsa, x25519
from acme._internal.tests import test_util from acme._internal.tests import test_util
class FormatTest(unittest.TestCase):
def test_to_cryptography_encoding(self):
with pytest.warns(DeprecationWarning, match='Format is deprecated'):
from acme.crypto_util import Format
assert Format.DER.to_cryptography_encoding() == serialization.Encoding.DER
assert Format.PEM.to_cryptography_encoding() == serialization.Encoding.PEM
class MiscTests(unittest.TestCase): class MiscTests(unittest.TestCase):
def test_dump_cryptography_chain(self): def test_dump_cryptography_chain(self):
@@ -105,93 +97,6 @@ class CryptographyCertOrReqSANTest(unittest.TestCase):
['chicago-cubs.venafi.example', 'cubs.venafi.example'] ['chicago-cubs.venafi.example', 'cubs.venafi.example']
class GenMakeSelfSignedCertTest(unittest.TestCase):
"""Test for make_self_signed_cert."""
def setUp(self):
self.cert_count = 5
self.serial_num: list[int] = []
self.privkey = rsa.generate_private_key(public_exponent=65537, key_size=2048)
@classmethod
def _call(cls, *args, **kwargs):
from acme.crypto_util import make_self_signed_cert
with pytest.warns(DeprecationWarning, match='make_self_signed_cert is deprecated'):
return make_self_signed_cert(*args, **kwargs)
def test_sn_collisions(self):
for _ in range(self.cert_count):
cert = self._call(self.privkey, ['dummy'], force_san=True,
ips=[ipaddress.ip_address("10.10.10.10")])
self.serial_num.append(cert.serial_number)
assert len(set(self.serial_num)) >= self.cert_count
def test_no_ips(self):
self._call(self.privkey, ['dummy'])
@mock.patch("acme.crypto_util._now")
def test_expiry_times(self, mock_now):
from datetime import datetime, timedelta, timezone
not_before = 1736200830
validity = 100
not_before_dt = datetime.fromtimestamp(not_before)
validity_td = timedelta(validity)
not_after_dt = not_before_dt + validity_td
cert = self._call(
self.privkey,
['dummy'],
not_before=not_before_dt,
validity=validity_td,
)
# TODO: This should be `not_valid_before_utc` once we raise the minimum
# cryptography version.
# https://github.com/certbot/certbot/issues/10105
with warnings.catch_warnings():
warnings.filterwarnings(
'ignore',
message='Properties that return.*datetime object'
)
self.assertEqual(cert.not_valid_before, not_before_dt)
self.assertEqual(cert.not_valid_after, not_after_dt)
now = not_before + 1
now_dt = datetime.fromtimestamp(now)
mock_now.return_value = now_dt.replace(tzinfo=timezone.utc)
valid_after_now_dt = now_dt + validity_td
cert = self._call(
self.privkey,
['dummy'],
validity=validity_td,
)
with warnings.catch_warnings():
warnings.filterwarnings(
'ignore',
message='Properties that return.*datetime object'
)
self.assertEqual(cert.not_valid_before, now_dt)
self.assertEqual(cert.not_valid_after, valid_after_now_dt)
def test_no_name(self):
with pytest.raises(AssertionError):
self._call(self.privkey, ips=[ipaddress.ip_address("1.1.1.1")])
self._call(self.privkey)
def test_extensions(self):
extension_type = x509.TLSFeature([x509.TLSFeatureType.status_request])
extension = x509.Extension(
x509.TLSFeature.oid,
False,
extension_type
)
cert = self._call(
self.privkey,
ips=[ipaddress.ip_address("1.1.1.1")],
extensions=[extension]
)
self.assertIn(extension, cert.extensions)
class MakeCSRTest(unittest.TestCase): class MakeCSRTest(unittest.TestCase):
"""Test for standalone functions.""" """Test for standalone functions."""
-126
View File
@@ -16,59 +16,10 @@ from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa, rsa, ec, ed25519, ed448, types from cryptography.hazmat.primitives.asymmetric import dsa, rsa, ec, ed25519, ed448, types
from cryptography.hazmat.primitives.serialization import Encoding from cryptography.hazmat.primitives.serialization import Encoding
from OpenSSL import crypto
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# https://github.com/pyca/cryptography/blob/1eab7a67dcc34b568e3c0df64e6222a2ac74b1ee/src/cryptography/utils.py#L66-L113
class _ClientDeprecationModule(ModuleType):
"""
Internal class delegating to a module, and displaying warnings when attributes
related to deprecated attributes in the acme.client module.
"""
def __init__(self, module: ModuleType) -> None:
super().__init__(module.__name__)
self.__dict__['_module'] = module
def __getattr__(self, attr: str) -> Any:
if attr == 'Format':
warnings.warn("acme.crypto_util.Format is deprecated and will be removed in "
"the next major release.", DeprecationWarning)
return getattr(self._module, attr)
def __setattr__(self, attr: str, value: Any) -> None: # pragma: no cover
setattr(self._module, attr, value)
def __delattr__(self, attr: str) -> None: # pragma: no cover
delattr(self._module, attr)
def __dir__(self) -> list[str]: # pragma: no cover
return ['_module'] + dir(self._module)
# Patching ourselves to warn about deprecation and planned removal of some elements in the module.
sys.modules[__name__] = _ClientDeprecationModule(sys.modules[__name__])
class Format(enum.IntEnum):
"""File format to be used when parsing or serializing X.509 structures. Deprecated.
Backwards compatible with the `FILETYPE_ASN1` and `FILETYPE_PEM` constants
from pyOpenSSL.
"""
DER = crypto.FILETYPE_ASN1
PEM = crypto.FILETYPE_PEM
def to_cryptography_encoding(self) -> Encoding:
"""Converts the Format to the corresponding cryptography `Encoding`.
"""
if self == Format.DER:
return Encoding.DER
else:
return Encoding.PEM
# Annoyingly, due to a mypy bug, we can't use Union[] types in # Annoyingly, due to a mypy bug, we can't use Union[] types in
# isinstance expressions without causing false mypy errors. So we have to # isinstance expressions without causing false mypy errors. So we have to
# recreate the type collection as a tuple here. And no, typing.get_args doesn't # recreate the type collection as a tuple here. And no, typing.get_args doesn't
@@ -228,83 +179,6 @@ def _now() -> datetime:
return datetime.now(tz=timezone.utc) return datetime.now(tz=timezone.utc)
def make_self_signed_cert(private_key: types.CertificateIssuerPrivateKeyTypes,
domains: Optional[list[str]] = None,
not_before: Optional[datetime] = None,
validity: Optional[timedelta] = None, force_san: bool = True,
extensions: Optional[list[x509.Extension]] = None,
ips: Optional[list[Union[ipaddress.IPv4Address,
ipaddress.IPv6Address]]] = None
) -> x509.Certificate:
"""Generate new self-signed certificate.
:param buffer private_key_pem: Private key, in PEM PKCS#8 format.
:type domains: `list` of `str`
:param int not_before: A datetime after which the cert is valid. If no
timezone is specified, UTC is assumed
:type not_before: `datetime.datetime`
:param validity: Duration for which the cert will be valid. Defaults to 1
week
:type validity: `datetime.timedelta`
:param buffer private_key_pem: One of
`cryptography.hazmat.primitives.asymmetric.types.CertificateIssuerPrivateKeyTypes`
:param bool force_san:
:param extensions: List of additional extensions to include in the cert.
:type extensions: `list` of `x509.Extension[x509.ExtensionType]`
:type ips: `list` of (`ipaddress.IPv4Address` or `ipaddress.IPv6Address`)
If more than one domain is provided, all of the domains are put into
``subjectAltName`` X.509 extension and first domain is set as the
subject CN. If only one domain is provided no ``subjectAltName``
extension is used, unless `force_san` is ``True``.
"""
warnings.warn("make_self_signed_cert is deprecated and will be removed in "
"an upcoming release", DeprecationWarning)
assert domains or ips, "Must provide one or more hostnames or IPs for the cert."
builder = x509.CertificateBuilder()
builder = builder.serial_number(x509.random_serial_number())
if extensions is not None:
for ext in extensions:
builder = builder.add_extension(ext.value, ext.critical)
if domains is None:
domains = []
if ips is None:
ips = []
builder = builder.add_extension(x509.BasicConstraints(ca=True, path_length=0), critical=True)
name_attrs = []
if len(domains) > 0:
name_attrs.append(x509.NameAttribute(
x509.OID_COMMON_NAME,
domains[0]
))
builder = builder.subject_name(x509.Name(name_attrs))
builder = builder.issuer_name(x509.Name(name_attrs))
sanlist: list[x509.GeneralName] = []
for address in domains:
sanlist.append(x509.DNSName(address))
for ip in ips:
sanlist.append(x509.IPAddress(ip))
if force_san or len(domains) > 1 or len(ips) > 0:
builder = builder.add_extension(
x509.SubjectAlternativeName(sanlist),
critical=False
)
if not_before is None:
not_before = _now()
if validity is None:
validity = timedelta(seconds=7 * 24 * 60 * 60)
builder = builder.not_valid_before(not_before)
builder = builder.not_valid_after(not_before + validity)
public_key = private_key.public_key()
builder = builder.public_key(public_key)
return builder.sign(private_key, hashes.SHA256())
def dump_cryptography_chain( def dump_cryptography_chain(
chain: list[x509.Certificate], chain: list[x509.Certificate],
encoding: Literal[Encoding.PEM, Encoding.DER] = Encoding.PEM, encoding: Literal[Encoding.PEM, Encoding.DER] = Encoding.PEM,