ipa/0032-Use-OpenSSL-provider-with-BIND-for-Fedora-41-and-RHE.patch
Florence Blanc-Renaud 255a8322a5 ipa-4.12.2-7
- Resolves: RHEL-66599 vault-add fails in FIPS mode
- Resolves: RHEL-66598 ipa-migrate should also migrate DNS forward zones
- Resolves: RHEL-66597 ipa-migrate in stage mode fails with TypeError: 'NoneType' object is not iterable
- Resolves: RHEL-66595 Sentences truncated in man pages
- Resolves: RHEL-66592 IDP configuration in the IdM WebUI shows Organization is required
- Resolves: RHEL-65650 ipa-server-install with setup-dns fails 'job for ipa.service failed because the control process exited with error code'

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

364 lines
15 KiB
Diff

From ace726cb83320d7fcb051751591817fd419a8f6b Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Wed, 6 Nov 2024 09:59:23 +0200
Subject: [PATCH] Use OpenSSL provider with BIND for Fedora 41+ and RHEL10+
OpenSSL Engine API is deprecated and ability to compile against it is
removed in RHEL10. OpenSSL provider API is the future.
Fedora 41+ also defaults to OpenSSL provider. With pkcs11-provider, the
same PKCS#11 modules can be loaded transparently like with OpenSSL
engines. Thus, we can update configuration to use the provider API.
TODO:
- dnssec-keyfromlabel does not work without engine, needs backport from
bind 9.20
Fixes: https://pagure.io/freeipa/issue/9696
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
freeipa.spec.in | 12 +++-
install/share/Makefile.am | 2 +
.../share/bind.openssl.provider.cnf.template | 19 +++++++
.../bind.openssl.provider.crp.cnf.template | 25 +++++++++
ipaplatform/base/constants.py | 1 +
ipaplatform/fedora/constants.py | 9 ++-
ipaplatform/rhel/constants.py | 7 ++-
ipaserver/dnssec/bindmgr.py | 21 ++++---
ipaserver/install/dnskeysyncinstance.py | 55 +++++++++++++++----
ipaserver/install/server/upgrade.py | 12 ++--
10 files changed, 136 insertions(+), 27 deletions(-)
create mode 100644 install/share/bind.openssl.provider.cnf.template
create mode 100644 install/share/bind.openssl.provider.crp.cnf.template
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 72d7013a6c49873f4a59734c684c6c5510e669d0..3f6b133eee4ec40193b618882ad0813971beb5ec 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -158,12 +158,20 @@
# BIND employs 'pkcs11' OpenSSL engine instead of native PKCS11
# Fedora 31+ uses OpenSSL engine, as well as Fedora ELN (RHEL9)
-%if 0%{?fedora} || 0%{?rhel} >= 9
+# Howevever, Fedora 40+ and RHEL10+ use OpenSSL provider
+%if 0%{?fedora} < 40 || 0%{?rhel} == 9
%global openssl_pkcs11_version 0.4.10-6
+ %global openssl_pkcs11_name openssl-pkcs11
%global softhsm_version 2.5.0-4
+%else
+%if 0%{?fedora} >= 40 || 0%{?rhel} >= 10
+ %global openssl_pkcs11_version 0.3
+ %global openssl_pkcs11_name pkcs11-provider
+ %global softhsm_version 2.6.1
%else
%global with_bind_pkcs11 1
%endif
+%endif
%if 0%{?rhel} == 8
# Make sure to use PKI versions that work with 389-ds fix for https://github.com/389ds/389-ds-base/issues/4609
@@ -623,7 +631,7 @@ Requires: bind-dnssec-utils >= %{bind_version}
Requires: bind-pkcs11 >= %{bind_version}
%else
Requires: softhsm >= %{softhsm_version}
-Requires: openssl-pkcs11 >= %{openssl_pkcs11_version}
+Requires: %{openssl_pkcs11_name} >= %{openssl_pkcs11_version}
%endif
# See https://bugzilla.redhat.com/show_bug.cgi?id=1825812
# RHEL 8.3+ and Fedora 32+ have 2.1
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 24664ca3bacb01fa4c57e9d7a5ea4ab48cfbdd90..0adebf8a3b0e01dbf62fe4b86190e60a3fbfea3b 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -50,6 +50,8 @@ dist_app_DATA = \
bind.named.conf.template \
bind.openssl.cnf.template \
bind.openssl.cryptopolicy.cnf.template \
+ bind.openssl.provider.cnf.template \
+ bind.openssl.provider.crp.cnf.template \
certmap.conf.template \
kdc.conf.template \
kdc_extensions.template \
diff --git a/install/share/bind.openssl.provider.cnf.template b/install/share/bind.openssl.provider.cnf.template
new file mode 100644
index 0000000000000000000000000000000000000000..1bd5599cd32f9601416cbaca815dc73fca22b560
--- /dev/null
+++ b/install/share/bind.openssl.provider.cnf.template
@@ -0,0 +1,19 @@
+# OpenSSL configuration file
+# File generated by IPA instalation
+openssl_conf = openssl_init
+
+[openssl_init]
+providers = provider_section
+
+[provider_sect]
+default = default_sect
+pkcs11 = pkcs11_bind_sect
+
+[default_sect]
+activate = 1
+
+[pkcs11_bind_sect]
+pkcs11-module-path = $SOFTHSM_MODULE
+pkcs11-module-token-pin = file:$SOFTHSM_PIN
+activate = 1
+
diff --git a/install/share/bind.openssl.provider.crp.cnf.template b/install/share/bind.openssl.provider.crp.cnf.template
new file mode 100644
index 0000000000000000000000000000000000000000..b52175e8f9971fa1a25a6c1c7a7121b2fc4c8c36
--- /dev/null
+++ b/install/share/bind.openssl.provider.crp.cnf.template
@@ -0,0 +1,25 @@
+# OpenSSL configuration file
+# File generated by IPA instalation
+openssl_conf = openssl_init
+
+[openssl_init]
+ssl_conf = ssl_configuration
+providers = provider_sect
+
+[ssl_configuration]
+system_default = crypto_policy
+
+[crypto_policy]
+.include $CRYPTO_POLICY_FILE
+
+[provider_sect]
+default = default_sect
+pkcs11 = pkcs11_bind_sect
+
+[default_sect]
+activate = 1
+
+[pkcs11_bind_sect]
+pkcs11-module-path = $SOFTHSM_MODULE
+pkcs11-module-token-pin = file:$SOFTHSM_PIN
+activate = 1
diff --git a/ipaplatform/base/constants.py b/ipaplatform/base/constants.py
index 1689efe52466f00fd8b014f720e1d21ebdbf2504..3f607ecbf961fbd78d78e05bcc1af3cd15a549d5 100644
--- a/ipaplatform/base/constants.py
+++ b/ipaplatform/base/constants.py
@@ -120,6 +120,7 @@ class BaseConstantsNamespace:
NAMED_DATA_DIR = "data/"
NAMED_OPTIONS_VAR = "OPTIONS"
NAMED_OPENSSL_ENGINE = None
+ NAMED_OPENSSL_PROVIDER = None
NAMED_ZONE_COMMENT = ""
PKI_USER = User("pkiuser")
PKI_GROUP = Group("pkiuser")
diff --git a/ipaplatform/fedora/constants.py b/ipaplatform/fedora/constants.py
index 896e6f60737a904b06ac5fba6c1d1711577c79ec..78a53db28755d5394441ed6d5350648c80de54df 100644
--- a/ipaplatform/fedora/constants.py
+++ b/ipaplatform/fedora/constants.py
@@ -19,6 +19,10 @@ from ipaplatform.osinfo import osinfo
# Fedora 29 has both
HAS_NFS_CONF = osinfo.version_number >= (30,)
+# Fedora 40 and later deprecated OpenSSL engine and recommend using OpenSSL
+# provider API.
+HAS_OPENSSL_PROVIDER = osinfo.version_number >= (40,)
+
__all__ = ("constants", "User", "Group")
@@ -32,6 +36,9 @@ class FedoraConstantsNamespace(RedHatConstantsNamespace):
if HAS_NFS_CONF:
SECURE_NFS_VAR = None
- NAMED_OPENSSL_ENGINE = "pkcs11"
+ if HAS_OPENSSL_PROVIDER:
+ NAMED_OPENSSL_PROVIDER = True
+ else:
+ NAMED_OPENSSL_ENGINE = "pkcs11"
constants = FedoraConstantsNamespace()
diff --git a/ipaplatform/rhel/constants.py b/ipaplatform/rhel/constants.py
index bc8c65a5d35af9afd27bc728768e49cd937e79a5..f4b50352190811db9dc780e3cec9d02cc0cab354 100644
--- a/ipaplatform/rhel/constants.py
+++ b/ipaplatform/rhel/constants.py
@@ -18,8 +18,11 @@ from ipaplatform.osinfo import osinfo
# RHEL 8 uses /etc/nfs.conf
HAS_NFS_CONF = osinfo.version_number >= (8,)
# RHEL 9 uses pkcs11 as openssl engine
-HAS_PKCS11_OPENSSL_ENGINE = osinfo.version_number >= (9,)
+HAS_PKCS11_OPENSSL_ENGINE = osinfo.version_number == (9,)
+# RHEL 10 and later deprecated OpenSSL engine and recommend using OpenSSL
+# provider API.
+HAS_OPENSSL_PROVIDER = osinfo.version_number >= (10,)
__all__ = ("constants", "User", "Group")
@@ -31,5 +34,7 @@ class RHELConstantsNamespace(RedHatConstantsNamespace):
SECURE_NFS_VAR = None
if HAS_PKCS11_OPENSSL_ENGINE:
NAMED_OPENSSL_ENGINE = "pkcs11"
+ if HAS_OPENSSL_PROVIDER:
+ NAMED_OPENSSL_PROVIDER = True
constants = RHELConstantsNamespace()
diff --git a/ipaserver/dnssec/bindmgr.py b/ipaserver/dnssec/bindmgr.py
index 0c79cc03d404f0fb54bc3c6ab591206127c5870c..aeb8b919c64361fd8175366827fecba9705af3c3 100644
--- a/ipaserver/dnssec/bindmgr.py
+++ b/ipaserver/dnssec/bindmgr.py
@@ -121,17 +121,24 @@ class BINDMgr:
assert attrs.get('idnsseckeyzone', [b'FALSE'])[0] == b'TRUE', \
b'object %s is not a DNS zone key' % attrs['dn']
- uri = b"%s;pin-source=%s" % (
- attrs['idnsSecKeyRef'][0],
- paths.DNSSEC_SOFTHSM_PIN.encode('utf-8')
- )
+ uri = None
+ if platformconstants.NAMED_OPENSSL_ENGINE is not None:
+ uri = "%s;pin-source=%s" % (
+ attrs['idnsSecKeyRef'][0],
+ paths.DNSSEC_SOFTHSM_PIN.encode('utf-8')
+ )
+ elif platformconstants.NAMED_OPENSSL_PROVIDER is not None:
+ uri = "%s;token=%s" % (
+ attrs['idnsSecKeyRef'][0],
+ ipalib.constants.SOFTHSM_DNSSEC_TOKEN_LABEL.encode('utf-8')
+ )
cmd = [
paths.DNSSEC_KEYFROMLABEL,
- '-E', 'pkcs11',
'-K', workdir,
- '-a', attrs['idnsSecAlgorithm'][0],
- '-l', uri
+ '-a', attrs['idnsSecAlgorithm'][0].encode('utf-8'),
]
+ if uri is not None:
+ cmd.extend(['-l', uri])
cmd.extend(self.dates2params(attrs))
if attrs.get('idnsSecKeySep', [b'FALSE'])[0].upper() == b'TRUE':
cmd.extend(['-f', 'KSK'])
diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py
index 36524655265130fca910eceb63fd4793ccc60d48..1979a472dd882a70cb0a41d782689debc66017a9 100644
--- a/ipaserver/install/dnskeysyncinstance.py
+++ b/ipaserver/install/dnskeysyncinstance.py
@@ -155,21 +155,36 @@ class DNSKeySyncInstance(service.Service):
return False
def setup_named_openssl_conf(self):
+ opensslcnf_tmpl = None
+ conf_file_dict = {
+ 'CRYPTO_POLICY_FILE': paths.CRYPTO_POLICY_OPENSSLCNF_FILE,
+ 'SOFTHSM_MODULE': paths.LIBSOFTHSM2_SO,
+ 'SOFTHSM_PIN': paths.DNSSEC_SOFTHSM_PIN,
+ }
if constants.NAMED_OPENSSL_ENGINE is not None:
- logger.debug("Setup OpenSSL config for BIND")
- # setup OpenSSL config for BIND,
- # this one is needed because FreeIPA installation
- # disables p11-kit-proxy PKCS11 module
- conf_file_dict = {
- 'OPENSSL_ENGINE': constants.NAMED_OPENSSL_ENGINE,
- 'SOFTHSM_MODULE': paths.LIBSOFTHSM2_SO,
- 'CRYPTO_POLICY_FILE': paths.CRYPTO_POLICY_OPENSSLCNF_FILE,
- }
+ # Traditional configuration using OpenSSL engine API
+ # requires openssl-pkcs11 engine to load PKCS#11 token
+ # provided by SoftHSMv2
+ conf_file_dict['OPENSSL_ENGINE'] = constants.NAMED_OPENSSL_ENGINE
if paths.CRYPTO_POLICY_OPENSSLCNF_FILE is None:
opensslcnf_tmpl = "bind.openssl.cnf.template"
else:
opensslcnf_tmpl = "bind.openssl.cryptopolicy.cnf.template"
+ elif constants.NAMED_OPENSSL_PROVIDER is not None:
+ # OpenSSL provider API is preferred and requires
+ # pkcs11-provider to load PKCS#11 token provided by SoftHSMv2
+ if paths.CRYPTO_POLICY_OPENSSLCNF_FILE is None:
+ opensslcnf_tmpl = "bind.openssl.provider.cnf.template"
+ else:
+ opensslcnf_tmpl = "bind.openssl.provider.crp.cnf.template"
+ else:
+ conf_file_dict = None
+ if opensslcnf_tmpl is not None and conf_file_dict is not None:
+ logger.debug("Setup OpenSSL config for BIND")
+ # setup OpenSSL config for BIND,
+ # this one is needed because FreeIPA installation
+ # disables p11-kit-proxy PKCS11 module
named_openssl_txt = ipautil.template_file(
os.path.join(paths.USR_SHARE_IPA_DIR, opensslcnf_tmpl),
conf_file_dict
@@ -189,7 +204,8 @@ class DNSKeySyncInstance(service.Service):
'SOFTHSM2_CONF', paths.DNSSEC_SOFTHSM2_CONF,
quotes=False, separator='=')
- if constants.NAMED_OPENSSL_ENGINE is not None:
+ if any([constants.NAMED_OPENSSL_ENGINE is not None,
+ constants.NAMED_OPENSSL_PROVIDER is not None]):
directivesetter.set_directive(
sysconfig,
'OPENSSL_CONF', paths.DNSSEC_OPENSSL_CONF,
@@ -200,9 +216,23 @@ class DNSKeySyncInstance(service.Service):
constants.NAMED_OPTIONS_VAR,
separator="="
) or ''
- if not self._are_named_options_configured(options):
+ new_options = None
+ if all([constants.NAMED_OPENSSL_ENGINE is not None,
+ not self._are_named_options_configured(options)]):
engine_cmd = "-E {}".format(constants.NAMED_OPENSSL_ENGINE)
new_options = ' '.join([options, engine_cmd])
+ # Remove '-E pkcs11' from the options in the OpenSSL provider case
+ if all([constants.NAMED_OPENSSL_ENGINE is None,
+ self._are_named_options_configured(options)]):
+ lst_options = options.split()
+ try:
+ idx = lst_options.index('-E')
+ lst_options.pop(idx)
+ lst_options.pop(idx)
+ new_options = ' '.join(lst_options)
+ except ValueError:
+ pass
+ if new_options is not None:
directivesetter.set_directive(
sysconfig,
constants.NAMED_OPTIONS_VAR, new_options,
@@ -216,7 +246,8 @@ class DNSKeySyncInstance(service.Service):
'SOFTHSM2_CONF', paths.DNSSEC_SOFTHSM2_CONF,
quotes=False, separator='=')
- if constants.NAMED_OPENSSL_ENGINE is not None:
+ if any([constants.NAMED_OPENSSL_ENGINE is not None,
+ constants.NAMED_OPENSSL_PROVIDER is not None]):
directivesetter.set_directive(
sysconfig,
'OPENSSL_CONF', paths.DNSSEC_OPENSSL_CONF,
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index fb71df81a6bf8ecbb1631ca8f0a5fe55cc222782..e2aabb2845602aacda1ca3289b7d7e338bd2dba3 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -549,15 +549,19 @@ def ca_initialize_hsm_state(ca):
def dnssec_set_openssl_engine(dnskeysyncd):
"""
- Setup OpenSSL engine for BIND
+ Setup OpenSSL engine or provider for BIND
"""
- if constants.NAMED_OPENSSL_ENGINE is None:
+ if all([constants.NAMED_OPENSSL_ENGINE is None,
+ constants.NAMED_OPENSSL_PROVIDER is None]):
return False
- if sysupgrade.get_upgrade_state('dns', 'openssl_engine'):
+ # Nothing to do if we are using OpenSSL engine already and not on the OS
+ # that requires OpenSSL provider instead.
+ if all([sysupgrade.get_upgrade_state('dns', 'openssl_engine'),
+ constants.NAMED_OPENSSL_PROVIDER is None]):
return False
- logger.info('[Set OpenSSL engine for BIND]')
+ logger.info('[Set OpenSSL engine or provider for BIND]')
dnskeysyncd.setup_named_openssl_conf()
dnskeysyncd.setup_named_sysconfig()
dnskeysyncd.setup_ipa_dnskeysyncd_sysconfig()
--
2.47.0