From 8b0f3595fd94a31a0e2d5a83dc74a430c973325b Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Nov 07 2018 15:28:35 +0000 Subject: Allow ipaapi user to access SSSD's info pipe For smart card authentication, ipaapi must be able to access to sss-ifp. During installation and upgrade, the ipaapi user is now added to [ifp]allowed_uids. The commit also fixes two related issues: * The server upgrade code now enables ifp service in sssd.conf. The existing code modified sssd.conf but never wrote the changes to disk. * sssd_enable_service() no longer fails after it has detected an unrecognized service. Fixes: https://pagure.io/freeipa/issue/7751 Signed-off-by: Christian Heimes Reviewed-By: Rob Crittenden --- diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index fe15901..fe3f0bb 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -33,6 +33,7 @@ from configparser import RawConfigParser from urllib.parse import urlparse, urlunparse from ipalib import api, errors, x509 +from ipalib.constants import IPAAPI_USER from ipalib.install import certmonger, certstore, service, sysrestore from ipalib.install import hostname as hostname_ from ipalib.install.kinit import kinit_keytab, kinit_password @@ -912,7 +913,7 @@ def configure_sssd_conf( domain = sssdconfig.new_domain(cli_domain) if options.on_master: - sssd_enable_service(sssdconfig, 'ifp') + sssd_enable_ifp(sssdconfig) if ( (options.conf_ssh and os.path.isfile(paths.SSH_CONFIG)) or @@ -1016,21 +1017,47 @@ def configure_sssd_conf( return 0 -def sssd_enable_service(sssdconfig, service): +def sssd_enable_service(sssdconfig, name): try: - sssdconfig.new_service(service) + sssdconfig.new_service(name) except SSSDConfig.ServiceAlreadyExists: pass except SSSDConfig.ServiceNotRecognizedError: logger.error( - "Unable to activate the %s service in SSSD config.", service) + "Unable to activate the '%s' service in SSSD config.", name) logger.info( "Please make sure you have SSSD built with %s support " - "installed.", service) + "installed.", name) logger.info( - "Configure %s support manually in /etc/sssd/sssd.conf.", service) + "Configure %s support manually in /etc/sssd/sssd.conf.", name) + return None - sssdconfig.activate_service(service) + sssdconfig.activate_service(name) + return sssdconfig.get_service(name) + + +def sssd_enable_ifp(sssdconfig): + """Enable and configure libsss_simpleifp plugin + """ + service = sssd_enable_service(sssdconfig, 'ifp') + if service is None: + # unrecognized service + return + + try: + uids = service.get_option('allowed_uids') + except SSSDConfig.NoOptionError: + uids = set() + else: + uids = {s.strip() for s in uids.split(',') if s.strip()} + # SSSD supports numeric and string UIDs + # ensure that root is allowed to access IFP, might be 0 or root + if uids.isdisjoint({'0', 'root'}): + uids.add('root') + # allow IPA API to access IFP + uids.add(IPAAPI_USER) + service.set_option('allowed_uids', ', '.join(sorted(uids))) + sssdconfig.save_service(service) def change_ssh_config(filename, changes, sections): diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index 96c95b7..698afd3 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -23,7 +23,7 @@ import SSSDConfig import ipalib.util import ipalib.errors from ipaclient.install import timeconf -from ipaclient.install.client import sssd_enable_service +from ipaclient.install.client import sssd_enable_ifp from ipaplatform import services from ipaplatform.tasks import tasks from ipapython import ipautil, version @@ -1408,6 +1408,22 @@ def set_sssd_domain_option(option, value): sssdconfig.write(paths.SSSD_CONF) +def sssd_update(): + sssdconfig = SSSDConfig.SSSDConfig() + sssdconfig.import_config() + # upgrade domain + domain = sssdconfig.get_domain(str(api.env.domain)) + domain.set_option('ipa_server_mode', 'True') + domain.set_option('ipa_server', api.env.host) + sssdconfig.save_domain(domain) + # enable and configure IFP plugin + sssd_enable_ifp(sssdconfig) + # write config and restart service + sssdconfig.write(paths.SSSD_CONF) + sssd = services.service('sssd', api) + sssd.restart() + + def remove_ds_ra_cert(subject_base): logger.info('[Removing RA cert from DS NSS database]') @@ -2017,15 +2033,8 @@ def upgrade_configuration(): cainstance.ensure_ipa_authority_entry() migrate_to_authselect() - set_sssd_domain_option('ipa_server_mode', 'True') - set_sssd_domain_option('ipa_server', api.env.host) - sssdconfig = SSSDConfig.SSSDConfig() - sssdconfig.import_config() - sssd_enable_service(sssdconfig, 'ifp') - - sssd = services.service('sssd', api) - sssd.restart() + sssd_update() krb = krbinstance.KrbInstance(fstore) krb.fqdn = fqdn diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py index 640eacf..1aa1bb3 100644 --- a/ipatests/test_integration/test_commands.py +++ b/ipatests/test_integration/test_commands.py @@ -20,6 +20,8 @@ import pytest from cryptography.hazmat.backends import default_backend from cryptography import x509 +from ipalib.constants import IPAAPI_USER + from ipaplatform.paths import paths from ipatests.test_integration.base import IntegrationTest @@ -28,6 +30,7 @@ from ipatests.create_external_ca import ExternalCA logger = logging.getLogger(__name__) + class TestIPACommand(IntegrationTest): """ A lot of commands can be executed against a single IPA installation @@ -429,3 +432,31 @@ class TestIPACommand(IntegrationTest): x509.load_pem_x509_certificate(data, backend=default_backend()) self.master.run_command(['rm', '-f', filename]) + + def test_sssd_ifp_access_ipaapi(self): + # check that ipaapi is allowed to access sssd-ifp for smartcard auth + # https://pagure.io/freeipa/issue/7751 + username = 'admin' + # get UID for user + result = self.master.run_command(['ipa', 'user-show', username]) + mo = re.search(r'UID: (\d+)', result.stdout_text) + assert mo is not None, result.stdout_text + uid = mo.group(1) + + cmd = [ + 'dbus-send', + '--print-reply', '--system', + '--dest=org.freedesktop.sssd.infopipe', + '/org/freedesktop/sssd/infopipe/Users', + 'org.freedesktop.sssd.infopipe.Users.FindByName', + 'string:{}'.format(username) + ] + # test IFP as root + result = self.master.run_command(cmd) + assert uid in result.stdout_text + + # test IFP as ipaapi + result = self.master.run_command( + ['sudo', '-u', IPAAPI_USER, '--'] + cmd + ) + assert uid in result.stdout_text