diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index 9492ca418..1e88ba1d4 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -66,7 +66,7 @@ from ipapython import version from . import automount, timeconf, sssd from ipaclient import discovery -from .ipachangeconf import IPAChangeConf +from ipapython.ipachangeconf import IPAChangeConf NoneType = type(None) @@ -281,72 +281,6 @@ def is_ipa_client_installed(fstore, on_master=False): return installed -def configure_nsswitch_database(fstore, database, services, preserve=True, - append=True, default_value=()): - """ - Edits the specified nsswitch.conf database (e.g. passwd, group, sudoers) - to use the specified service(s). - - Arguments: - fstore - FileStore to backup the nsswitch.conf - database - database configuration that should be ammended, - e.g. 'sudoers' - service - list of services that should be added, e.g. ['sss'] - preserve - if True, the already configured services will be preserved - - The next arguments modify the behaviour if preserve=True: - append - if True, the services will be appended, if False, prepended - default_value - list of services that are considered as default (if - the database is not mentioned in nsswitch.conf), e.g. - ['files'] - """ - - # Backup the original version of nsswitch.conf, we're going to edit it now - if not fstore.has_file(paths.NSSWITCH_CONF): - fstore.backup_file(paths.NSSWITCH_CONF) - - conf = IPAChangeConf("IPA Installer") - conf.setOptionAssignment(':') - - if preserve: - # Read the existing configuration - with open(paths.NSSWITCH_CONF, 'r') as f: - opts = conf.parse(f) - raw_database_entry = conf.findOpts(opts, 'option', database)[1] - - # Detect the list of already configured services - if not raw_database_entry: - # If there is no database entry, database is not present in - # the nsswitch.conf. Set the list of services to the - # default list, if passed. - configured_services = list(default_value) - else: - configured_services = raw_database_entry['value'].strip().split() - - # Make sure no service is added if already mentioned in the list - added_services = [s for s in services - if s not in configured_services] - - # Prepend / append the list of new services - if append: - new_value = ' ' + ' '.join(configured_services + added_services) - else: - new_value = ' ' + ' '.join(added_services + configured_services) - - else: - # Preserve not set, let's rewrite existing configuration - new_value = ' ' + ' '.join(services) - - # Set new services as sources for database - opts = [ - conf.setOption(database, new_value), - conf.emptyLine(), - ] - - conf.changeConf(paths.NSSWITCH_CONF, opts) - logger.info("Configured %s in %s", database, paths.NSSWITCH_CONF) - - def configure_ipa_conf( fstore, cli_basedn, cli_realm, cli_domain, cli_server, hostname): ipaconf = IPAChangeConf("IPA Installer") @@ -948,9 +882,7 @@ def configure_sssd_conf( "Unable to activate the SUDO service in SSSD config.") sssdconfig.activate_service('sudo') - configure_nsswitch_database( - fstore, 'sudoers', ['sss'], - default_value=['files']) + tasks.enable_sssd_sudo(fstore) domain.add_provider('ipa', 'id') diff --git a/ipaclient/install/ipa_client_automount.py b/ipaclient/install/ipa_client_automount.py index a1dc2a18c..3a0896be3 100644 --- a/ipaclient/install/ipa_client_automount.py +++ b/ipaclient/install/ipa_client_automount.py @@ -41,7 +41,8 @@ from six.moves.urllib.parse import urlsplit # pylint: enable=import-error from optparse import OptionParser # pylint: disable=deprecated-module -from ipaclient.install import ipachangeconf, ipadiscovery +from ipapython import ipachangeconf +from ipaclient.install import ipadiscovery from ipaclient.install.client import ( CLIENT_NOT_CONFIGURED, CLIENT_ALREADY_CONFIGURED, @@ -177,44 +178,6 @@ def configure_xml(fstore): print("Configured %s" % authconf) -def configure_nsswitch(statestore, options): - """ - Point automount to ldap in nsswitch.conf. - This function is for non-SSSD setups only. - """ - conf = ipachangeconf.IPAChangeConf("IPA Installer") - conf.setOptionAssignment(':') - - with open(paths.NSSWITCH_CONF, 'r') as f: - current_opts = conf.parse(f) - current_nss_value = conf.findOpts( - current_opts, name='automount', type='option' - )[1] - if current_nss_value is None: - # no automount database present - current_nss_value = False # None cannot be backed up - else: - current_nss_value = current_nss_value['value'] - statestore.backup_state( - 'ipa-client-automount-nsswitch', 'previous-automount', - current_nss_value - ) - - nss_value = ' files ldap' - opts = [ - { - 'name': 'automount', - 'type': 'option', - 'action': 'set', - 'value': nss_value, - }, - {'name': 'empty', 'type': 'empty'}, - ] - conf.changeConf(paths.NSSWITCH_CONF, opts) - - print("Configured %s" % paths.NSSWITCH_CONF) - - def configure_autofs_sssd(fstore, statestore, autodiscover, options): try: sssdconfig = SSSDConfig.SSSDConfig() @@ -339,41 +302,8 @@ def uninstall(fstore, statestore): ] STATES = ['autofs', 'rpcidmapd', 'rpcgssd'] - if statestore.get_state( - 'ipa-client-automount-nsswitch', 'previous-automount' - ) is False: - # Previous nsswitch.conf had no automount database configured - # so remove it. - conf = ipachangeconf.IPAChangeConf("IPA automount installer") - conf.setOptionAssignment(':') - changes = [conf.rmOption('automount')] - conf.changeConf(paths.NSSWITCH_CONF, changes) - tasks.restore_context(paths.NSSWITCH_CONF) - statestore.delete_state( - 'ipa-client-automount-nsswitch', 'previous-automount' - ) - elif statestore.get_state( - 'ipa-client-automount-nsswitch', 'previous-automount' - ) is not None: - nss_value = statestore.get_state( - 'ipa-client-automount-nsswitch', 'previous-automount' - ) - opts = [ - { - 'name': 'automount', - 'type': 'option', - 'action': 'set', - 'value': nss_value, - }, - {'name': 'empty', 'type': 'empty'}, - ] - conf = ipachangeconf.IPAChangeConf("IPA automount installer") - conf.setOptionAssignment(':') - conf.changeConf(paths.NSSWITCH_CONF, opts) - tasks.restore_context(paths.NSSWITCH_CONF) - statestore.delete_state( - 'ipa-client-automount-nsswitch', 'previous-automount' - ) + if not statestore.get_state('autofs', 'sssd'): + tasks.disable_ldap_automount(statestore) if not any(fstore.has_file(f) for f in RESTORE_FILES) or not any( statestore.has_state(s) for s in STATES @@ -627,7 +557,7 @@ def configure_automount(): try: if not options.sssd: - configure_nsswitch(statestore, options) + tasks.enable_ldap_automount(statestore) configure_nfs(fstore, statestore, options) if options.sssd: configure_autofs_sssd(fstore, statestore, autodiscover, options) diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index 8aa9c5cd0..7fd7d5765 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -32,6 +32,7 @@ from pkg_resources import parse_version from ipaplatform.constants import constants from ipaplatform.paths import paths from ipapython import ipautil +from ipapython.ipachangeconf import IPAChangeConf logger = logging.getLogger(__name__) @@ -337,5 +338,157 @@ class BaseTaskNamespace: """ raise NotImplementedError + def configure_nsswitch_database(self, fstore, database, services, + preserve=True, append=True, + default_value=()): + """ + Edits the specified nsswitch.conf database (e.g. passwd, group, + sudoers) to use the specified service(s). + + Arguments: + fstore - FileStore to backup the nsswitch.conf + database - database configuration that should be ammended, + e.g. 'sudoers' + service - list of services that should be added, e.g. ['sss'] + preserve - if True, the already configured services will be + preserved + + The next arguments modify the behaviour if preserve=True: + append - if True, the services will be appended, if False, + prepended + default_value - list of services that are considered as default (if + the database is not mentioned in nsswitch.conf), + e.g. ['files'] + """ + + # Backup the original version of nsswitch.conf, we're going to edit it + # now + if not fstore.has_file(paths.NSSWITCH_CONF): + fstore.backup_file(paths.NSSWITCH_CONF) + + conf = IPAChangeConf("IPA Installer") + conf.setOptionAssignment(':') + + if preserve: + # Read the existing configuration + with open(paths.NSSWITCH_CONF, 'r') as f: + opts = conf.parse(f) + raw_database_entry = conf.findOpts(opts, 'option', database)[1] + + # Detect the list of already configured services + if not raw_database_entry: + # If there is no database entry, database is not present in + # the nsswitch.conf. Set the list of services to the + # default list, if passed. + configured_services = list(default_value) + else: + configured_services = raw_database_entry[ + 'value'].strip().split() + + # Make sure no service is added if already mentioned in the list + added_services = [s for s in services + if s not in configured_services] + + # Prepend / append the list of new services + if append: + new_value = ' ' + ' '.join(configured_services + + added_services) + else: + new_value = ' ' + ' '.join(added_services + + configured_services) + + else: + # Preserve not set, let's rewrite existing configuration + new_value = ' ' + ' '.join(services) + + # Set new services as sources for database + opts = [ + conf.setOption(database, new_value), + conf.emptyLine(), + ] + + conf.changeConf(paths.NSSWITCH_CONF, opts) + logger.info("Configured %s in %s", database, paths.NSSWITCH_CONF) + + def enable_sssd_sudo(self, fstore): + """Configure nsswitch.conf to use sssd for sudo""" + self.configure_nsswitch_database( + fstore, 'sudoers', ['sss'], + default_value=['files']) + + def enable_ldap_automount(self, statestore): + """ + Point automount to ldap in nsswitch.conf. + This function is for non-SSSD setups only. + """ + conf = IPAChangeConf("IPA Installer") + conf.setOptionAssignment(':') + + with open(paths.NSSWITCH_CONF, 'r') as f: + current_opts = conf.parse(f) + current_nss_value = conf.findOpts( + current_opts, name='automount', type='option' + )[1] + if current_nss_value is None: + # no automount database present + current_nss_value = False # None cannot be backed up + else: + current_nss_value = current_nss_value['value'] + statestore.backup_state( + 'ipa-client-automount-nsswitch', 'previous-automount', + current_nss_value + ) + + nss_value = ' files ldap' + opts = [ + { + 'name': 'automount', + 'type': 'option', + 'action': 'set', + 'value': nss_value, + }, + {'name': 'empty', 'type': 'empty'}, + ] + conf.changeConf(paths.NSSWITCH_CONF, opts) + + logger.info("Configured %s", paths.NSSWITCH_CONF) + + def disable_ldap_automount(self, statestore): + """Disable automount using LDAP""" + if statestore.get_state( + 'ipa-client-automount-nsswitch', 'previous-automount' + ) is False: + # Previous nsswitch.conf had no automount database configured + # so remove it. + conf = IPAChangeConf("IPA automount installer") + conf.setOptionAssignment(':') + changes = [conf.rmOption('automount')] + conf.changeConf(paths.NSSWITCH_CONF, changes) + self.restore_context(paths.NSSWITCH_CONF) + statestore.delete_state( + 'ipa-client-automount-nsswitch', 'previous-automount' + ) + elif statestore.get_state( + 'ipa-client-automount-nsswitch', 'previous-automount' + ) is not None: + nss_value = statestore.get_state( + 'ipa-client-automount-nsswitch', 'previous-automount' + ) + opts = [ + { + 'name': 'automount', + 'type': 'option', + 'action': 'set', + 'value': nss_value, + }, + {'name': 'empty', 'type': 'empty'}, + ] + conf = IPAChangeConf("IPA automount installer") + conf.setOptionAssignment(':') + conf.changeConf(paths.NSSWITCH_CONF, opts) + self.restore_context(paths.NSSWITCH_CONF) + statestore.delete_state( + 'ipa-client-automount-nsswitch', 'previous-automount' + ) tasks = BaseTaskNamespace() diff --git a/ipaplatform/redhat/paths.py b/ipaplatform/redhat/paths.py index 8ccd04bb5..15bdef60f 100644 --- a/ipaplatform/redhat/paths.py +++ b/ipaplatform/redhat/paths.py @@ -39,6 +39,7 @@ class RedHatPathNamespace(BasePathNamespace): AUTHCONFIG = '/usr/sbin/authconfig' AUTHSELECT = '/usr/bin/authselect' SYSCONF_NETWORK = '/etc/sysconfig/network' + NSSWITCH_CONF = '/etc/authselect/user-nsswitch.conf' paths = RedHatPathNamespace() diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index be0b6414a..e18f6fad5 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -744,4 +744,23 @@ class RedHatTaskNamespace(BaseTaskNamespace): return filenames + def enable_ldap_automount(self, statestore): + """ + Point automount to ldap in nsswitch.conf. + This function is for non-SSSD setups only. + """ + super(RedHatTaskNamespace, self).enable_ldap_automount(statestore) + + authselect_cmd = [paths.AUTHSELECT, "enable-feature", + "with-custom-automount"] + ipautil.run(authselect_cmd) + + def disable_ldap_automount(self, statestore): + """Disable ldap-based automount""" + super(RedHatTaskNamespace, self).disable_ldap_automount(statestore) + + authselect_cmd = [paths.AUTHSELECT, "disable-feature", + "with-custom-automount"] + ipautil.run(authselect_cmd) + tasks = RedHatTaskNamespace()