mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
named: Allow using of a custom OpenSSL engine for BIND
For now Debian, Fedora, RHEL, etc. build BIND with 'native PKCS11' support. Till recently, that was the strict requirement of DNSSEC. The problem is that this restricts cross-platform features of FreeIPA. With the help of libp11, which provides `pkcs11` engine plugin for the OpenSSL library for accessing PKCS11 modules in a semi- transparent way, FreeIPA could utilize OpenSSL version of BIND. BIND in turn provides ability to specify the OpenSSL engine on the command line of `named` and all the BIND `dnssec-*` tools by using the `-E engine_name`. Fixes: https://pagure.io/freeipa/issue/8094 Signed-off-by: Stanislav Levin <slev@altlinux.org> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Christian Heimes <cheimes@redhat.com>
This commit is contained in:
committed by
Alexander Bokovoy
parent
a9334ce5e5
commit
5c907e34ae
@@ -657,7 +657,7 @@ class BindInstance(service.Service):
|
||||
self.no_dnssec_validation = False
|
||||
self.sub_dict = None
|
||||
self.reverse_zones = ()
|
||||
self.named_regular = services.service('named-regular', api)
|
||||
self.named_conflict = services.service('named-conflict', api)
|
||||
|
||||
suffix = ipautil.dn_attribute_property('_suffix')
|
||||
|
||||
@@ -764,7 +764,7 @@ class BindInstance(service.Service):
|
||||
# named has to be started after softhsm initialization
|
||||
# self.step("restarting named", self.__start)
|
||||
|
||||
self.step("configuring named to start on boot", self.__enable)
|
||||
self.step("configuring named to start on boot", self.switch_service)
|
||||
self.step("changing resolv.conf to point to ourselves", self.__setup_resolv_conf)
|
||||
self.start_creation()
|
||||
|
||||
@@ -774,19 +774,16 @@ class BindInstance(service.Service):
|
||||
|
||||
def __start(self):
|
||||
try:
|
||||
if self.get_state("running") is None:
|
||||
# first time store status
|
||||
self.backup_state("running", self.is_running())
|
||||
self.restart()
|
||||
except Exception as e:
|
||||
logger.error("Named service failed to start (%s)", e)
|
||||
print("named service failed to start")
|
||||
|
||||
def switch_service(self):
|
||||
self.mask_conflict()
|
||||
self.__enable()
|
||||
|
||||
def __enable(self):
|
||||
if self.get_state("enabled") is None:
|
||||
self.backup_state("enabled", self.is_running())
|
||||
self.backup_state("named-regular-enabled",
|
||||
self.named_regular.is_running())
|
||||
# We do not let the system start IPA components on its own,
|
||||
# Instead we reply on the IPA init script to start only enabled
|
||||
# components as found in our LDAP configuration tree
|
||||
@@ -797,20 +794,19 @@ class BindInstance(service.Service):
|
||||
# don't crash, just report error
|
||||
logger.error("DNS service already exists")
|
||||
|
||||
# disable named, we need to run named-pkcs11 only
|
||||
if self.get_state("named-regular-running") is None:
|
||||
# first time store status
|
||||
self.backup_state("named-regular-running",
|
||||
self.named_regular.is_running())
|
||||
def mask_conflict(self):
|
||||
# disable named-conflict (either named or named-pkcs11)
|
||||
try:
|
||||
self.named_regular.stop()
|
||||
self.named_conflict.stop()
|
||||
except Exception as e:
|
||||
logger.debug("Unable to stop named (%s)", e)
|
||||
logger.debug("Unable to stop %s (%s)",
|
||||
self.named_conflict.systemd_name, e)
|
||||
|
||||
try:
|
||||
self.named_regular.mask()
|
||||
self.named_conflict.mask()
|
||||
except Exception as e:
|
||||
logger.debug("Unable to mask named (%s)", e)
|
||||
logger.debug("Unable to mask %s (%s)",
|
||||
self.named_conflict.systemd_name, e)
|
||||
|
||||
def _get_dnssec_validation(self):
|
||||
"""get dnssec-validation value
|
||||
@@ -1307,11 +1303,6 @@ class BindInstance(service.Service):
|
||||
if self.is_configured():
|
||||
self.print_msg("Unconfiguring %s" % self.service_name)
|
||||
|
||||
running = self.restore_state("running")
|
||||
enabled = self.restore_state("enabled")
|
||||
named_regular_running = self.restore_state("named-regular-running")
|
||||
named_regular_enabled = self.restore_state("named-regular-enabled")
|
||||
|
||||
self.dns_backup.clear_records(self.api.Backend.ldap2.isconnected())
|
||||
|
||||
try:
|
||||
@@ -1326,23 +1317,10 @@ class BindInstance(service.Service):
|
||||
|
||||
ipautil.rmtree(paths.BIND_LDAP_DNS_IPA_WORKDIR)
|
||||
|
||||
# disabled by default, by ldap_configure()
|
||||
if enabled:
|
||||
self.enable()
|
||||
else:
|
||||
self.disable()
|
||||
self.disable()
|
||||
self.stop()
|
||||
|
||||
if running:
|
||||
self.restart()
|
||||
else:
|
||||
self.stop()
|
||||
|
||||
self.named_regular.unmask()
|
||||
if named_regular_enabled:
|
||||
self.named_regular.enable()
|
||||
|
||||
if named_regular_running:
|
||||
self.named_regular.start()
|
||||
self.named_conflict.unmask()
|
||||
|
||||
ipautil.remove_file(paths.NAMED_CONF_BAK)
|
||||
ipautil.remove_file(paths.NAMED_CUSTOM_CONF)
|
||||
|
||||
@@ -164,6 +164,61 @@ class DNSKeySyncInstance(service.Service):
|
||||
|
||||
self._ldap_mod("dnssec.ldif", {'SUFFIX': self.suffix, })
|
||||
|
||||
def setup_named_openssl_conf(self):
|
||||
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,
|
||||
}
|
||||
named_openssl_txt = ipautil.template_file(
|
||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
||||
"bind.openssl.cnf.template"),
|
||||
conf_file_dict)
|
||||
with open(paths.DNSSEC_OPENSSL_CONF, 'w') as f:
|
||||
os.fchmod(f.fileno(), 0o640)
|
||||
os.fchown(f.fileno(), 0, self.named_gid)
|
||||
f.write(named_openssl_txt)
|
||||
|
||||
def setup_named_sysconfig(self):
|
||||
logger.debug("Setup BIND sysconfig")
|
||||
sysconfig = paths.SYSCONFIG_NAMED
|
||||
self.fstore.backup_file(sysconfig)
|
||||
|
||||
directivesetter.set_directive(
|
||||
sysconfig,
|
||||
'SOFTHSM2_CONF', paths.DNSSEC_SOFTHSM2_CONF,
|
||||
quotes=False, separator='=')
|
||||
|
||||
if constants.NAMED_OPENSSL_ENGINE is not None:
|
||||
directivesetter.set_directive(
|
||||
sysconfig,
|
||||
'OPENSSL_CONF', paths.DNSSEC_OPENSSL_CONF,
|
||||
quotes=False, separator='=')
|
||||
|
||||
engine_txt = "-E {}".format(constants.NAMED_OPENSSL_ENGINE)
|
||||
directivesetter.set_directive(
|
||||
sysconfig,
|
||||
constants.NAMED_OPTIONS_VAR, engine_txt,
|
||||
quotes=True, separator='=')
|
||||
|
||||
def setup_ipa_dnskeysyncd_sysconfig(self):
|
||||
logger.debug("Setup ipa-dnskeysyncd sysconfig")
|
||||
sysconfig = paths.SYSCONFIG_IPA_DNSKEYSYNCD
|
||||
directivesetter.set_directive(
|
||||
sysconfig,
|
||||
'SOFTHSM2_CONF', paths.DNSSEC_SOFTHSM2_CONF,
|
||||
quotes=False, separator='=')
|
||||
|
||||
if constants.NAMED_OPENSSL_ENGINE is not None:
|
||||
directivesetter.set_directive(
|
||||
sysconfig,
|
||||
'OPENSSL_CONF', paths.DNSSEC_OPENSSL_CONF,
|
||||
quotes=False, separator='=')
|
||||
|
||||
def __setup_softhsm(self):
|
||||
assert self.ods_uid is not None
|
||||
assert self.named_gid is not None
|
||||
@@ -186,23 +241,15 @@ class DNSKeySyncInstance(service.Service):
|
||||
'tokens_dir': paths.DNSSEC_TOKENS_DIR
|
||||
}
|
||||
logger.debug("Creating new softhsm config file")
|
||||
named_fd = open(paths.DNSSEC_SOFTHSM2_CONF, 'w')
|
||||
named_fd.seek(0)
|
||||
named_fd.truncate(0)
|
||||
named_fd.write(softhsm_conf_txt)
|
||||
named_fd.close()
|
||||
os.chmod(paths.DNSSEC_SOFTHSM2_CONF, 0o644)
|
||||
with open(paths.DNSSEC_SOFTHSM2_CONF, 'w') as f:
|
||||
os.fchmod(f.fileno(), 0o644)
|
||||
f.write(softhsm_conf_txt)
|
||||
|
||||
# setting up named to use softhsm2
|
||||
if not self.fstore.has_file(paths.SYSCONFIG_NAMED):
|
||||
self.fstore.backup_file(paths.SYSCONFIG_NAMED)
|
||||
|
||||
# setting up named and ipa-dnskeysyncd to use our softhsm2 config
|
||||
for sysconfig in [paths.SYSCONFIG_NAMED,
|
||||
paths.SYSCONFIG_IPA_DNSKEYSYNCD]:
|
||||
directivesetter.set_directive(sysconfig, 'SOFTHSM2_CONF',
|
||||
paths.DNSSEC_SOFTHSM2_CONF,
|
||||
quotes=False, separator='=')
|
||||
# setting up named and ipa-dnskeysyncd to use our softhsm2 and
|
||||
# openssl configs
|
||||
self.setup_named_openssl_conf()
|
||||
self.setup_named_sysconfig()
|
||||
self.setup_ipa_dnskeysyncd_sysconfig()
|
||||
|
||||
if (token_dir_exists and os.path.exists(paths.DNSSEC_SOFTHSM_PIN) and
|
||||
os.path.exists(paths.DNSSEC_SOFTHSM_PIN_SO)):
|
||||
@@ -231,23 +278,17 @@ class DNSKeySyncInstance(service.Service):
|
||||
entropy_bits=0, special=None, min_len=pin_length)
|
||||
|
||||
logger.debug("Saving user PIN to %s", paths.DNSSEC_SOFTHSM_PIN)
|
||||
named_fd = open(paths.DNSSEC_SOFTHSM_PIN, 'w')
|
||||
named_fd.seek(0)
|
||||
named_fd.truncate(0)
|
||||
named_fd.write(pin)
|
||||
named_fd.close()
|
||||
os.chmod(paths.DNSSEC_SOFTHSM_PIN, 0o770)
|
||||
# chown to ods:named
|
||||
os.chown(paths.DNSSEC_SOFTHSM_PIN, self.ods_uid, self.named_gid)
|
||||
with open(paths.DNSSEC_SOFTHSM_PIN, 'w') as f:
|
||||
# chown to ods:named
|
||||
os.fchown(f.fileno(), self.ods_uid, self.named_gid)
|
||||
os.fchmod(f.fileno(), 0o660)
|
||||
f.write(pin)
|
||||
|
||||
logger.debug("Saving SO PIN to %s", paths.DNSSEC_SOFTHSM_PIN_SO)
|
||||
named_fd = open(paths.DNSSEC_SOFTHSM_PIN_SO, 'w')
|
||||
named_fd.seek(0)
|
||||
named_fd.truncate(0)
|
||||
named_fd.write(pin_so)
|
||||
named_fd.close()
|
||||
# owner must be root
|
||||
os.chmod(paths.DNSSEC_SOFTHSM_PIN_SO, 0o400)
|
||||
with open(paths.DNSSEC_SOFTHSM_PIN_SO, 'w') as f:
|
||||
# owner must be root
|
||||
os.fchmod(f.fileno(), 0o400)
|
||||
f.write(pin_so)
|
||||
|
||||
# initialize SoftHSM
|
||||
|
||||
@@ -377,7 +418,7 @@ class DNSKeySyncInstance(service.Service):
|
||||
os.chown(dir_path, self.ods_uid, self.named_gid)
|
||||
for filename in files:
|
||||
file_path = os.path.join(root, filename)
|
||||
os.chmod(file_path, 0o770 | stat.S_ISGID)
|
||||
os.chmod(file_path, 0o660 | stat.S_ISGID)
|
||||
# chown to ods:named
|
||||
os.chown(file_path, self.ods_uid, self.named_gid)
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ class Backup(admintool.AdminTool):
|
||||
paths.OPENDNSSEC_KASP_FILE,
|
||||
paths.OPENDNSSEC_ZONELIST_FILE,
|
||||
paths.OPENDNSSEC_KASP_DB,
|
||||
paths.DNSSEC_OPENSSL_CONF,
|
||||
paths.DNSSEC_SOFTHSM2_CONF,
|
||||
paths.DNSSEC_SOFTHSM_PIN_SO,
|
||||
paths.IPA_ODS_EXPORTER_KEYTAB,
|
||||
|
||||
@@ -106,9 +106,9 @@ def install(api, replica_config, options, custodia):
|
||||
|
||||
# Restart apache for new proxy config file
|
||||
services.knownservices.httpd.restart(capture_output=True)
|
||||
# Restarted named-pkcs11 to restore bind-dyndb-ldap operation, see
|
||||
# Restarted named to restore bind-dyndb-ldap operation, see
|
||||
# https://pagure.io/freeipa/issue/5813
|
||||
named = services.knownservices.named # alias for named-pkcs11
|
||||
named = services.knownservices.named # alias for current named
|
||||
if named.is_running():
|
||||
named.restart(capture_output=True)
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ class OpenDNSSECInstance(service.Service):
|
||||
os.chown(dir_path, self.ods_uid, self.named_gid) # chown to ods:named
|
||||
for filename in files:
|
||||
file_path = os.path.join(root, filename)
|
||||
os.chmod(file_path, 0o770 | stat.S_ISGID)
|
||||
os.chmod(file_path, 0o660 | stat.S_ISGID)
|
||||
os.chown(file_path, self.ods_uid, self.named_gid) # chown to ods:named
|
||||
|
||||
finally:
|
||||
|
||||
@@ -660,6 +660,7 @@ class Service:
|
||||
]
|
||||
extra_config_opts.extend(config)
|
||||
|
||||
self.unmask()
|
||||
self.disable()
|
||||
|
||||
set_service_entry_config(
|
||||
|
||||
Reference in New Issue
Block a user