ipa/0033-ipalib-x509-support-PyCA-44.0.patch
Florence Blanc-Renaud 4c20458190 ipa-4.12.2-7
- Resolves: RHEL-70760
Fix typo in ipa-migrate log file i.e 'Privledges' to 'Privileges'
- Resolves: RHEL-70481
ipa-server-upgrade fails after established trust with ad
- Resolves: RHEL-69927
add support for python cryptography 44.0.0
- Resolves: RHEL-69908
All user groups are not being included during HSM token validation
- Resolves: RHEL-69900
Upgrade to ipa-server-4.12.2-1.el9 OTP-based bind to LDAP without enforceldapotp is broken

Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
2024-12-11 10:47:47 +01:00

167 lines
6.6 KiB
Diff

From d4d56a6705c870901bc73882e4804367f7c9c91a Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Sun, 1 Dec 2024 20:16:54 +0200
Subject: [PATCH] ipalib/x509: support PyCA 44.0
PyCA made x509.Certificate class concrete, it cannot be extended anymore
by Python code. The intent is to use helper functions to instantiate
certificate objects and never create them directly.
FreeIPA wraps PyCA's x509.Certificate class and provides own shim
on top of it. In most cases we load the certificate content via the
helper functions and don't really need to derive from the certificate
class.
Move IPACertificate to be a normal Python object class that stores
x509.Certificate internally. The only place where this breaks is when
IPACertificate object needs to be passed to a code that expects
x509.Certificate (Dogtag PKI). In such cases, expose the underlying
certificate instance via IPACertificate.cert property.
Fixes: https://pagure.io/freeipa/issue/9708
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipalib/ipajson.py | 4 ++--
ipalib/x509.py | 10 +++++++++-
ipapython/ipaldap.py | 15 +++++++--------
ipaserver/plugins/dogtag.py | 3 ++-
4 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/ipalib/ipajson.py b/ipalib/ipajson.py
index 5551d12e5fec7e458fa6fe85560664b2fd897337..fd99c8219c722c52321336f28ff27e1573e906c7 100644
--- a/ipalib/ipajson.py
+++ b/ipalib/ipajson.py
@@ -9,7 +9,7 @@ from decimal import Decimal
import json
import six
from ipalib.constants import LDAP_GENERALIZED_TIME_FORMAT
-from ipalib import capabilities
+from ipalib import capabilities, x509
from ipalib.x509 import Encoding as x509_Encoding
from ipapython.dn import DN
from ipapython.dnsutil import DNSName
@@ -72,7 +72,7 @@ class _JSONPrimer(dict):
list: self._enc_list,
tuple: self._enc_list,
dict: self._enc_dict,
- crypto_x509.Certificate: self._enc_certificate,
+ x509.IPACertificate: self._enc_certificate,
crypto_x509.CertificateSigningRequest: self._enc_certificate,
})
diff --git a/ipalib/x509.py b/ipalib/x509.py
index fd08238962b2b5e9cd056fb13c0a81ee8f31b092..6780bead00b50efdf03c62ce717572eeb9df2e5f 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -88,7 +88,7 @@ SAN_UPN = '1.3.6.1.4.1.311.20.2.3'
SAN_KRB5PRINCIPALNAME = '1.3.6.1.5.2.2'
-class IPACertificate(crypto_x509.Certificate):
+class IPACertificate:
"""
A proxy class wrapping a python-cryptography certificate representation for
IPA purposes
@@ -205,6 +205,10 @@ class IPACertificate(crypto_x509.Certificate):
"""
return self._cert.fingerprint(algorithm)
+ @property
+ def cert(self):
+ return self._cert
+
@property
def serial_number(self):
return self._cert.serial_number
@@ -457,6 +461,8 @@ def load_pem_x509_certificate(data):
:returns: a ``IPACertificate`` object.
:raises: ``ValueError`` if unable to load the certificate.
"""
+ if isinstance(data, IPACertificate):
+ return data
return IPACertificate(
crypto_x509.load_pem_x509_certificate(data, backend=default_backend())
)
@@ -469,6 +475,8 @@ def load_der_x509_certificate(data):
:returns: a ``IPACertificate`` object.
:raises: ``ValueError`` if unable to load the certificate.
"""
+ if isinstance(data, IPACertificate):
+ return data
return IPACertificate(
crypto_x509.load_der_x509_certificate(data, backend=default_backend())
)
diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index 1888e40916aa6e641542f08fb30ff2b0d4b850b1..5bb81c1bc844fce9b14251d3702e09099d85cdb5 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -33,7 +33,6 @@ import warnings
from collections import OrderedDict
-from cryptography import x509 as crypto_x509
from cryptography.hazmat.primitives import serialization
import ldap
@@ -748,10 +747,10 @@ class LDAPClient:
'dnszoneidnsname': DNSName,
'krbcanonicalname': Principal,
'krbprincipalname': Principal,
- 'usercertificate': crypto_x509.Certificate,
- 'usercertificate;binary': crypto_x509.Certificate,
- 'cACertificate': crypto_x509.Certificate,
- 'cACertificate;binary': crypto_x509.Certificate,
+ 'usercertificate': x509.IPACertificate,
+ 'usercertificate;binary': x509.IPACertificate,
+ 'cACertificate': x509.IPACertificate,
+ 'cACertificate;binary': x509.IPACertificate,
'nsds5replicalastupdatestart': unicode,
'nsds5replicalastupdateend': unicode,
'nsds5replicalastinitstart': unicode,
@@ -1000,7 +999,7 @@ class LDAPClient:
return dct
elif isinstance(val, datetime):
return val.strftime(LDAP_GENERALIZED_TIME_FORMAT).encode('utf-8')
- elif isinstance(val, crypto_x509.Certificate):
+ elif isinstance(val, x509.IPACertificate):
return val.public_bytes(x509.Encoding.DER)
elif val is None:
return None
@@ -1027,7 +1026,7 @@ class LDAPClient:
return DNSName.from_text(val.decode('utf-8'))
elif target_type in (DN, Principal):
return target_type(val.decode('utf-8'))
- elif target_type is crypto_x509.Certificate:
+ elif target_type is x509.IPACertificate:
return x509.load_der_x509_certificate(val)
else:
return target_type(val)
@@ -1381,7 +1380,7 @@ class LDAPClient:
]
return cls.combine_filters(flts, rules)
elif value is not None:
- if isinstance(value, crypto_x509.Certificate):
+ if isinstance(value, x509.IPACertificate):
value = value.public_bytes(serialization.Encoding.DER)
if isinstance(value, bytes):
value = binascii.hexlify(value).decode('ascii')
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index 78afb279795ecf74f296cbbb8724505075a6e4a9..ee6d0e347d640a2664e38ba64785c3d8af54bbad 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -1581,7 +1581,8 @@ class kra(Backend):
crypto = cryptoutil.CryptographyCryptoProvider(
transport_cert_nick="ra_agent",
- transport_cert=x509.load_certificate_from_file(paths.RA_AGENT_PEM)
+ transport_cert=x509.load_certificate_from_file(
+ paths.RA_AGENT_PEM).cert
)
# TODO: obtain KRA host & port from IPA service list or point to KRA load balancer
--
2.47.1