diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 17f10e6b6..ef894dd77 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -388,6 +388,7 @@ class BasePathNamespace: CERTMONGER = '/usr/sbin/certmonger' NETWORK_MANAGER_CONFIG_DIR = '/etc/NetworkManager/conf.d' NETWORK_MANAGER_IPA_CONF = '/etc/NetworkManager/conf.d/zzz-ipa.conf' + SYSTEMD_RESOLVED_IPA_CONF = '/etc/systemd/resolved.conf.d/zzz-ipa.conf' IPA_CUSTODIA_CONF_DIR = '/etc/ipa/custodia' IPA_CUSTODIA_CONF = '/etc/ipa/custodia/custodia.conf' IPA_CUSTODIA_KEYS = '/etc/ipa/custodia/server.keys' diff --git a/ipaplatform/base/services.py b/ipaplatform/base/services.py index ac1a3c89b..a17daa23c 100644 --- a/ipaplatform/base/services.py +++ b/ipaplatform/base/services.py @@ -57,7 +57,8 @@ wellknownservices = [ 'rpcidmapd', 'pki_tomcatd', 'chronyd', 'domainname', 'named', 'ods_enforcerd', 'ods_signerd', 'gssproxy', 'nfs-utils', 'sssd', 'NetworkManager', 'ipa-custodia', - 'ipa-dnskeysyncd', 'ipa-otpd', 'ipa-ods-exporter' + 'ipa-dnskeysyncd', 'ipa-otpd', 'ipa-ods-exporter', + 'systemd-resolved', ] # The common ports for these services. This is used to wait for the diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index ae3c47ea6..a39857e86 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -24,7 +24,9 @@ This module contains default platform-specific implementations of system tasks. from __future__ import absolute_import +import os import logging +import textwrap from pkg_resources import parse_version @@ -35,6 +37,17 @@ from ipapython.ipachangeconf import IPAChangeConf logger = logging.getLogger(__name__) +# TODO: Add other masters as FallbackDNS ? +RESOLVE1_IPA_CONF = textwrap.dedent(""" + # auto-generated by IPA installer + [Resolve] + # use local BIND instance + DNS=127.0.0.1 + # make local BIND default DNS server, add search suffixes + Domains=~. {searchdomains} +""") + + class BaseTaskNamespace: def restore_context(self, filepath, force=False): @@ -318,7 +331,21 @@ class BaseTaskNamespace: :param resolve1_enabled: is systemd-resolved enabled? :param fstore: optional file store for backup """ - raise NotImplementedError + if resolve1_enabled: + # break circular import + from ipaplatform.services import knownservices + + confd = os.path.dirname(paths.SYSTEMD_RESOLVED_IPA_CONF) + os.makedirs(confd, exist_ok=True) + + cfg = RESOLVE1_IPA_CONF.format( + searchdomains=" ".join(searchdomains) + ) + with open(paths.SYSTEMD_RESOLVED_IPA_CONF, "w") as f: + os.fchmod(f.fileno(), 0o644) + f.write(cfg) + + knownservices["systemd-resolved"].reload_or_restart() def unconfigure_dns_resolver(self, fstore=None): """Unconfigure global DNS resolver (e.g. /etc/resolv.conf) @@ -328,6 +355,12 @@ class BaseTaskNamespace: if fstore is not None and fstore.has_file(paths.RESOLV_CONF): fstore.restore_file(paths.RESOLV_CONF) + if os.path.isfile(paths.SYSTEMD_RESOLVED_IPA_CONF): + # break circular import + from ipaplatform.services import knownservices + + os.unlink(paths.SYSTEMD_RESOLVED_IPA_CONF) + knownservices["systemd-resolved"].reload_or_restart() def configure_pkcs11_modules(self, fstore): """Disable p11-kit modules diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index 6cf8a48e4..2b92c649b 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -44,7 +44,6 @@ from subprocess import CalledProcessError from pyasn1.error import PyAsn1Error from ipapython import directivesetter -from ipapython import dnsutil from ipapython import ipautil import ipapython.errors @@ -625,6 +624,13 @@ class RedHatTaskNamespace(BaseTaskNamespace): assert nameservers and isinstance(nameservers, list) assert searchdomains and isinstance(searchdomains, list) + super().configure_dns_resolver( + nameservers=nameservers, + searchdomains=searchdomains, + resolve1_enabled=resolve1_enabled, + fstore=fstore + ) + # break circular import from ipaplatform.services import knownservices @@ -632,7 +638,8 @@ class RedHatTaskNamespace(BaseTaskNamespace): fstore.backup_file(paths.RESOLV_CONF) nm = knownservices['NetworkManager'] - if nm.is_enabled(): + nm_enabled = nm.is_enabled() + if nm_enabled: logger.debug( "Network Manager is enabled, write %s", paths.NETWORK_MANAGER_IPA_CONF @@ -658,11 +665,13 @@ class RedHatTaskNamespace(BaseTaskNamespace): f.write(cfg) # reload NetworkManager nm.reload_or_restart() - else: - # no NM running, fall back to /etc/resolv.conf + + if not resolve1_enabled and not nm_enabled: + # no NM running, no systemd-resolved detected + # fall back to /etc/resolv.conf logger.debug( - "Network Manager is not enabled, write %s directly.", - paths.RESOLV_CONF + "Neither Network Manager nor systemd-resolved are enabled, " + "write %s directly.", paths.RESOLV_CONF ) cfg = [ "# auto-generated by IPA installer", @@ -678,12 +687,10 @@ class RedHatTaskNamespace(BaseTaskNamespace): :param fstore: optional file store for restore """ + super().unconfigure_dns_resolver(fstore=fstore) # break circular import from ipaplatform.services import knownservices - if fstore is not None and fstore.has_file(paths.RESOLV_CONF): - fstore.restore_file(paths.RESOLV_CONF) - nm = knownservices['NetworkManager'] if os.path.isfile(paths.NETWORK_MANAGER_IPA_CONF): os.unlink(paths.NETWORK_MANAGER_IPA_CONF)