diff options
Diffstat (limited to 'src/tests/multihost/basic')
-rw-r--r-- | src/tests/multihost/basic/mhc.yaml | 8 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_basic.py | 88 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_config.py | 114 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_files.py | 78 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_ifp.py | 37 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_kcm.py | 340 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_sssctl_config_check.py | 107 | ||||
-rw-r--r-- | src/tests/multihost/basic/test_sudo.py | 66 | ||||
-rw-r--r-- | src/tests/multihost/basic/utils_config.py | 32 |
9 files changed, 870 insertions, 0 deletions
diff --git a/src/tests/multihost/basic/mhc.yaml b/src/tests/multihost/basic/mhc.yaml new file mode 100644 index 0000000..24d5054 --- /dev/null +++ b/src/tests/multihost/basic/mhc.yaml @@ -0,0 +1,8 @@ +root_password: 'vagrant' +domains: +- name: tier0.tests + type: sssd + hosts: + - name: client + external_hostname: client.test + role: master diff --git a/src/tests/multihost/basic/test_basic.py b/src/tests/multihost/basic/test_basic.py new file mode 100644 index 0000000..72f092e --- /dev/null +++ b/src/tests/multihost/basic/test_basic.py @@ -0,0 +1,88 @@ +""" SSSD Sanity Test Cases + +:requirement: IDM-SSSD-REQ : KRB5 Provider +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" +import pytest +import time +import configparser as ConfigParser +from sssd.testlib.common.utils import sssdTools + + +class TestSanitySSSD(object): + """ Basic Sanity Test cases """ + @pytest.mark.converted('test_authentication.py', 'test_authentication__login') + @staticmethod + def test_ssh_user_login(multihost): + """ + :title: Login: Check ssh login as LDAP user with Kerberos credentials + :id: b7600a46-1827-486a-ae2e-cbedad6ddf41 + """ + client = sssdTools(multihost.master[0]) + ssh0 = client.auth_from_client("foo1", 'Secret123') == 3 + assert ssh0, "Authentication Failed as user foo1" + + @pytest.mark.converted('test_kcm.py', 'test_kcm__simple_kinit') + @staticmethod + def test_kinit(multihost): + """ + :title: Login: Verify kinit is successfull after user login + :id: 5e15e9e9-c559-49b8-a164-abe13d82d0fd + """ + user = 'foo2' + cmd = multihost.master[0].run_command( + f'su - {user} -c "kinit"', stdin_text='Secret123', + raiseonerr=False) + assert cmd.returncode == 0, "kinit failed!" + + cmd2 = multihost.master[0].run_command( + f'su - {user} -c "klist"', raiseonerr=False) + assert cmd2.returncode == 0, "klist failed!" + + @pytest.mark.converted('test_authentication.py', 'test_authentication__offline_login') + @staticmethod + def test_offline_ssh_login(multihost): + """ + :title: Login: Verify offline ssh login + :id: 90e9a834-a1f9-4bef-bdae-57a7b411cce4 + """ + multihost.master[0].transport.get_file('/etc/sssd/sssd.conf', + '/tmp/sssd.conf') + sssdconfig = ConfigParser.RawConfigParser() + sssdconfig.read('/tmp/sssd.conf') + domain_section = "%s/%s" % ('domain', 'EXAMPLE.TEST') + if domain_section in sssdconfig.sections(): + sssdconfig.set(domain_section, 'cache_credentials', 'True') + sssdconfig.set(domain_section, 'krb5_store_password_if_offline', + 'True') + sssdconfig.set('pam', 'offline_credentials_expiration', '0') + with open('/tmp/sssd.conf', "w") as file_d: + sssdconfig.write(file_d) + else: + print("Could not fetch sssd.conf") + assert False + multihost.master[0].transport.put_file('/tmp/sssd.conf', + '/etc/sssd/sssd.conf') + multihost.master[0].service_sssd('restart') + time.sleep(5) + client = sssdTools(multihost.master[0]) + user = 'foo4' + ssh0 = client.auth_from_client(user, password='Secret123') == 3 + assert ssh0, f"Initial ssh login as {user} failed." + + stop_dirsrv = 'systemctl stop dirsrv@example1' + stop_krb5kdc = 'systemctl stop krb5kdc' + multihost.master[0].run_command(stop_dirsrv) + multihost.master[0].run_command(stop_krb5kdc) + + ssh1 = client.auth_from_client(user, password='Secret123') == 3 + + start_dirsrv = 'systemctl start dirsrv@example1' + start_krb5kdc = 'systemctl start krb5kdc' + multihost.master[0].run_command(start_dirsrv) + multihost.master[0].run_command(start_krb5kdc) + + assert ssh1, f"Offline ssh login as {user} failed." diff --git a/src/tests/multihost/basic/test_config.py b/src/tests/multihost/basic/test_config.py new file mode 100644 index 0000000..8d4847b --- /dev/null +++ b/src/tests/multihost/basic/test_config.py @@ -0,0 +1,114 @@ +""" SSSD Configuration-related Test Cases + +:requirement: IDM-SSSD-REQ: Configuration merging +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" + +import pytest +from utils_config import remove_section, set_param + + +class TestSSSDConfig(object): + """ + Test cases around SSSD config management + """ + def _assert_config_value(self, multihost, section, key, value): + # This would really be much, much nicer to implement using python-ldb + # but at the moment, the multihost tests rely on a virtual environment + # where everything is pip-installed..and python-ldb is not present in + # pip + confdb_dn = 'cn=%s,cn=config' % (section) + ldb_cmd = 'ldbsearch -H /var/lib/sss/db/config.ldb -b %s' % (confdb_dn) + cmd = multihost.master[0].run_command(ldb_cmd) + check_str = '%s: %s' % (key, value) + assert check_str in cmd.stdout_text + + @pytest.mark.converted('test_config.py', 'test_config__change_config_while_sssd_running') + def test_sssd_genconf_sssd_running(self, multihost): + """ + :title: config: sssd --genconf is able to re-generate + the configuration even while SSSD is running + :id: 078721e9-536b-4fd8-a36d-bd94673228fc + """ + multihost.master[0].service_sssd('restart') + + self._assert_config_value(multihost, 'pam', 'debug_level', '9') + + set_param(multihost, 'pam', 'debug_level', '1') + multihost.master[0].run_command('/usr/sbin/sssd --genconf') + self._assert_config_value(multihost, 'pam', 'debug_level', '1') + + set_param(multihost, 'pam', 'debug_level', '9') + + @pytest.mark.converted('test_config.py', 'test_config__genconf_particular_section') + def test_sssd_genconf_section_only(self, multihost): + """ + :title: config: sssd --genconf-section only + refreshes those sections given on the command line + :id: 011bf2ad-4a2a-4350-adfa-7826349e262f + """ + multihost.master[0].service_sssd('restart') + + self._assert_config_value(multihost, 'pam', 'debug_level', '9') + self._assert_config_value(multihost, 'nss', 'debug_level', '9') + + set_param(multihost, 'pam', 'debug_level', '1') + set_param(multihost, 'nss', 'debug_level', '1') + multihost.master[0].run_command( + '/usr/sbin/sssd --genconf-section=pam') + + # We only told genconf to touch the pam section.. + self._assert_config_value(multihost, 'pam', 'debug_level', '1') + # ..so the NSS section shouldn't be updated at all + self._assert_config_value(multihost, 'nss', 'debug_level', '9') + + set_param(multihost, 'nss', 'debug_level', '9') + set_param(multihost, 'pam', 'debug_level', '9') + + @pytest.mark.converted('test_config.py', 'test_config__add_remove_section') + def test_sssd_genconf_add_remove_section(self, multihost): + """ + :title: config: sssd --genconf-section can not only modify + existing configuration sections, but also add a new section + :id: 8df66b51-aadc-456e-8f27-a1a787e61769 + """ + # Establish a baseline + multihost.master[0].service_sssd('restart') + self._assert_config_value(multihost, 'pam', 'debug_level', '9') + self._assert_config_value(multihost, 'nss', 'debug_level', '9') + + set_param(multihost, 'foo', 'bar', 'baz') + + multihost.master[0].run_command( + '/usr/sbin/sssd --genconf-section=foo') + + ldb_cmd = 'ldbsearch -H /var/lib/sss/db/config.ldb -b cn=foo,cn=config' + cmd = multihost.master[0].run_command(ldb_cmd) + assert 'bar: baz' in cmd.stdout_text + + remove_section(multihost, 'foo') + multihost.master[0].run_command( + '/usr/sbin/sssd --genconf-section=foo') + + ldb_cmd = 'ldbsearch -H /var/lib/sss/db/config.ldb -b cn=foo,cn=config' + cmd = multihost.master[0].run_command(ldb_cmd) + assert 'foo' not in cmd.stdout_text + # Also make sure the existing sections were intact + self._assert_config_value(multihost, 'pam', 'debug_level', '9') + self._assert_config_value(multihost, 'nss', 'debug_level', '9') + + @pytest.mark.converted('test_config.py', 'test_config__genconf_no_such_section') + def test_sssd_genconf_no_such_section(self, multihost): + """ + :title: config: Referencing a non-existant section must not fail + :id: 4e160dcc-9789-4f3f-b8d4-c67d27ef4a1c + :description: Referencing a non-existant section must not fail, + because we want to call this command from the systemd unit files + and by default the sections don't have to be present + """ + multihost.master[0].service_sssd('restart') + multihost.master[0].run_command( + '/usr/sbin/sssd --genconf-section=xyz') diff --git a/src/tests/multihost/basic/test_files.py b/src/tests/multihost/basic/test_files.py new file mode 100644 index 0000000..5a1c8c2 --- /dev/null +++ b/src/tests/multihost/basic/test_files.py @@ -0,0 +1,78 @@ +"""Files test provider cases + +:requirement: IDM-SSSD-REQ :: SSSD is default for local resolution +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" +import pytest + + +def have_files_provider(multihost): + cmd = multihost.master[0].run_command('man sssd-files | grep files', raiseonerr=False) + return cmd.returncode == 0 + + +def get_sss_entry(multihost, db, ent_name): + cmd = multihost.master[0].run_command('getent %s -s sss %s' % (db, ent_name), raiseonerr=False) + return cmd.returncode, cmd.stdout_text + + +def get_sss_user(multihost, username): + return get_sss_entry(multihost, 'passwd', username) + + +@pytest.mark.usefixtures('enable_files_domain', 'files_domain_users_class') +class TestImplicitFilesProvider(object): + """ + Test the files provider. This test runs the implicit files provider + together with another domain to stick close to what users use in Fedora + """ + @pytest.mark.converted('test_files.py', 'test_files__getent_does_not_handle_root') + def test_files_does_not_handle_root(self, multihost): + """ + :title: files: files provider does not handle root + :id: 5aa5165d-379f-4fc6-b4ed-b32b66406d4f + """ + if not have_files_provider(multihost): + pytest.skip("Files Provider support isn't available, skipping") + exit_status, _ = get_sss_user(multihost, 'root') + assert exit_status == 2 + + @pytest.mark.converted('test_files.py', 'test_files__simple_getent') + def test_files_sanity(self, multihost): + """ + :title: files: Test that the files provider can resolve a user + :id: 242cd094-b04d-4857-981a-8624573dde84 + """ + if not have_files_provider(multihost): + pytest.skip("Files Provider support isn't available, skipping") + exit_status, _ = get_sss_user(multihost, 'lcl1') + assert exit_status == 0 + + @pytest.mark.converted('test_files.py', 'test_files__enumeration') + def test_files_enumeration(self, multihost): + """ + :title: files: Verify files provider do not enumerate + :id: e6d922bf-3af2-4cea-8570-6dd9233da624 + :description: Since nss_files enumerates and libc would + concatenate the results, the files provider of SSSD should + not enumerate + """ + if not have_files_provider(multihost): + pytest.skip("Files Provider support isn't available, skipping") + cmd = multihost.master[0].run_command('getent passwd -s sss') + assert len(cmd.stdout_text) == 0 + + @pytest.mark.converted('test_files.py', 'test_files__user_modify') + def test_updated_homedir(self, multihost): + """ + :title: files: Test that homedir is updated + :id: a9a0a911-1818-40d1-b897-0397ef107fd4 + """ + if not have_files_provider(multihost): + pytest.skip("Files Provider support isn't available, skipping") + exit_status, output = get_sss_user(multihost, 'no_home_user') + assert exit_status == 0 + assert ":/tmp:" in output diff --git a/src/tests/multihost/basic/test_ifp.py b/src/tests/multihost/basic/test_ifp.py new file mode 100644 index 0000000..a8cf24b --- /dev/null +++ b/src/tests/multihost/basic/test_ifp.py @@ -0,0 +1,37 @@ +"""InfoPipe test cases + +:requirement: IDM-SSSD-REQ : Configuration and Service Management +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" +import pytest + + +class TestInfoPipe(object): + """ + Test the InfoPipe responder + """ + def test_ifp_extra_attributes_property(self, multihost): + """ + :title: ifp: requesting the extraAttributes property works + :id: 23b8c7e8-df4b-47ef-b38e-0503040e1d67 + see e.g. https://github.com/SSSD/sssd/issues/4891 + """ + # Note that this test needs dbus-tools package that + # is not implicitly installed here. + check_ifp = "libsss_simpleifp" in multihost.master[0].run_command("rpm -qa").stdout_text + if not check_ifp: + pytest.skip("libsss_simpleifp is not present, skipping test.") + dbus_send_cmd = \ + """ + dbus-send --print-reply --system \ + --dest=org.freedesktop.sssd.infopipe \ + /org/freedesktop/sssd/infopipe/Users/LDAP_2eTEST/123 \ + org.freedesktop.DBus.Properties.Get \ + string:"org.freedesktop.sssd.infopipe.Users.User" \ + string:"extraAttributes" + """ + cmd = multihost.master[0].run_command(dbus_send_cmd) + assert cmd.returncode == 0 diff --git a/src/tests/multihost/basic/test_kcm.py b/src/tests/multihost/basic/test_kcm.py new file mode 100644 index 0000000..8f527f6 --- /dev/null +++ b/src/tests/multihost/basic/test_kcm.py @@ -0,0 +1,340 @@ +""" KCM Responder Sanity Test Cases + +:requirement: IDM-SSSD-REQ :: SSSD KCM as default Kerberos CCACHE provider +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" +import os +import re +import pytest +from pexpect import pxssh +from utils_config import set_param +from sssd.testlib.common.utils import sssdTools + + +class TestSanityKCM(object): + """ KCM Sanity Test cases """ + def _kcm_service_op(self, multihost, svc_op): + systemd_kcm_op = 'systemctl %s sssd-kcm' % (svc_op) + multihost.master[0].run_command(systemd_kcm_op) + + def _start_kcm(self, multihost): + self._kcm_service_op(multihost, 'start') + + def _stop_kcm(self, multihost): + self._kcm_service_op(multihost, 'stop') + + def _restart_kcm(self, multihost): + self._kcm_service_op(multihost, 'restart') + + def _remove_kcm_log_file(self, multihost): + multihost.master[0].run_command('rm -f /var/log/sssd/sssd_kcm.log') + + def _kcm_log_length(self, multihost): + basename = 'sssd_kcm.log' + kcm_log_file = '/var/log/sssd/' + basename + local_kcm_log_file = '/tmp/kcm.log' + try: + multihost.master[0].transport.get_file(kcm_log_file, + local_kcm_log_file) + except FileNotFoundError: + return 0 + + nlines = sum(1 for line in open(local_kcm_log_file)) + os.remove(local_kcm_log_file) + return nlines + + def _remove_secret_db(self, multihost): + multihost.master[0].run_command( + 'rm -f /var/lib/sss/secrets/secrets.ldb') + self._restart_kcm(multihost) + + @pytest.mark.usefixtures("enable_kcm") + def test_kinit_kcm(self, multihost): + """ + :title: kcm: Run kinit with KRB5CCNAME=KCM + :id: 245eecf6-04b9-4c9f-8685-681d184fbbcf + """ + self._start_kcm(multihost) + + user = 'foo3' + cmd = multihost.master[0].run_command( + f'su - {user} -c "KRB5CCNAME=KCM:; kinit"', stdin_text='Secret123', + raiseonerr=False) + assert cmd.returncode == 0, "kinit failed!" + + cmd2 = multihost.master[0].run_command( + f'su - {user} -c "KRB5CCNAME=KCM:; klist"', raiseonerr=False) + assert cmd2.returncode == 0, "klist failed!" + assert 'Ticket cache: KCM:14583103' in cmd2.stdout_text + + @staticmethod + @pytest.mark.usefixtures("enable_kcm") + def test_ssh_login_kcm(multihost): + """ + :title: kcm: Verify ssh logins are successuful with kcm as default + :id: 458ed1e4-b908-40d3-b2fd-392e8d2dcf4b + """ + # pylint: disable=unused-argument + client = sssdTools(multihost.master[0]) + ssh0 = client.auth_from_client("foo4", 'Secret123') == 3 + if not ssh0: + multihost.master[0].run_command( + 'journalctl -u sssd -n 50 --no-pager') + assert ssh0, "Authentication Failed as user foo4" + + @pytest.mark.usefixtures("enable_kcm") + def test_kcm_debug_level_set(self, multihost): + """ + :title: kcm: After kcm section with debug + level set restaring sssd-kcm service enables kcm debugging + :id: 31c74bfc-69d5-46bd-aef8-a5581970832e + :description: Test that just adding a [kcm] section and restarting + the kcm service enables debugging without having to restart the + whole sssd + """ + # Start from a known-good state where the configuration is refreshed + # by the monitor and logging is completely disabled + multihost.master[0].service_sssd('stop') + self._stop_kcm(multihost) + self._remove_kcm_log_file(multihost) + set_param(multihost, 'kcm', 'debug_level', '0') + multihost.master[0].service_sssd('start') + self._start_kcm(multihost) + + log_lines_pre = self._kcm_log_length(multihost) + + # Debugging is disabled, kinit and make sure that no debug messages + # were produced + user = 'foo3' + client = sssdTools(multihost.master[0]) + ssh0 = client.auth_from_client(user, 'Secret123') == 3 + assert ssh0, f"Authentication Failed as user {user}." + + multihost.master[0].run_command( + f'su - {user} -c "kdestroy"', raiseonerr=False) + + log_lines_nodebug = self._kcm_log_length(multihost) + assert log_lines_nodebug == log_lines_pre + + # Enable debugging, restart only the kcm service, make sure some + # debug messages were produced + set_param(multihost, 'kcm', 'debug_level', '9') + self._restart_kcm(multihost) + + ssh1 = client.auth_from_client(user, 'Secret123') == 3 + assert ssh1, f"Authentication Failed as user {user}." + + multihost.master[0].run_command( + f'su - {user} -c "kdestroy"', raiseonerr=False) + + log_lines_debug = self._kcm_log_length(multihost) + assert log_lines_debug > log_lines_pre + 100 + + @staticmethod + @pytest.mark.usefixtures("enable_kcm") + def test_kdestroy_retval(multihost): + """ + :title: kcm: Test that destroying an empty cache does + not return a non-zero return code + :id: 2826097f-e6d7-4d99-ac85-3ee081aa681a + """ + + user = 'foo3' + client = sssdTools(multihost.master[0]) + ssh0 = client.auth_from_client(user, 'Secret123') == 3 + assert ssh0, f"Authentication Failed as user {user}." + + kd1 = multihost.master[0].run_command( + f'su -l {user} -c "kdestroy"', raiseonerr=False) + assert kd1.returncode == 0, "First kdestroy failed!" + + # Run the command again in case there was something in the ccache + # previously + kd2 = multihost.master[0].run_command( + f'su -l {user} -c "kdestroy"', raiseonerr=False) + assert kd2.returncode == 0, "Second kdestroy failed!" + + @staticmethod + @pytest.mark.usefixtures("enable_kcm") + def test_ssh_forward_creds(multihost): + """ + :title: kcm: Test that SSH can forward credentials with KCM + :id: f4b0c785-a895-48a1-a55e-7519cf221393 + :ticket: https://github.com/SSSD/sssd/issues/4863 + """ + ssh = pxssh.pxssh(options={"StrictHostKeyChecking": "no", + "UserKnownHostsFile": "/dev/null"}) + ssh.force_password = True + try: + ssh.login(multihost.master[0].sys_hostname, 'foo3', 'Secret123') + ssh.sendline('kdestroy -A -q') + ssh.prompt(timeout=5) + ssh.sendline('kinit foo9') + ssh.expect('Password for .*:', timeout=10) + ssh.sendline('Secret123') + ssh.prompt(timeout=5) + ssh.sendline('klist') + ssh.prompt(timeout=5) + klist = str(ssh.before) + ssh.sendline(f'ssh -v -o StrictHostKeyChecking=no -K -l foo9 ' + f'{multihost.master[0].sys_hostname} klist') + ssh.prompt(timeout=30) + ssh_output = str(ssh.before) + ssh.logout() + except pxssh.ExceptionPxssh as ex: + pytest.fail(ex) + # Note: The cache is based on uid so for foo3 it is 14583103 and + # for foo9 it is 14583109 (see create_posix_usersgroups fixture) + assert 'KCM:14583103' in klist, "kinit did not work!" + assert 'KCM:14583109' in ssh_output, "Ticket not forwarded!" + + @staticmethod + @pytest.mark.usefixtures("enable_kcm") + def test_kvno_display(multihost): + """ + :title: kcm: Test kvno correctly displays version numbers of principals + :id: 7c9178e6-fea5-44a1-b473-76667624cee2 + :ticket: https://github.com/SSSD/sssd/issues/4763 + """ + host_princ = f'host/{multihost.master[0].sys_hostname}@EXAMPLE.TEST' + kvno_cmd = f'kvno {host_princ}' + + client = sssdTools(multihost.master[0]) + client.auth_from_client('foo4', 'Secret123') + + kvno = multihost.master[0].run_command( + f'su -l foo4 -c "{kvno_cmd}"', raiseonerr=False) + assert kvno.returncode == 0, "kvno failed!" + + for line in kvno.stdout_text.splitlines(): + kvno_check = re.search(r'%s: kvno = (\d+)' % host_princ, line) + if kvno_check: + print(kvno_check.group()) + else: + pytest.fail("kvno display was improper") + + @pytest.mark.usefixtures("enable_kcm", "create_many_user_principals") + def test_kcm_peruid_quota(self, multihost): + """ + :title: kcm: Make sure the quota limits a client, but only that client + :id: 3ac8f62e-05e4-4ca7-b588-145fd6258c2a + """ + # It is easier to keep these tests stable and independent from others + # if they start from a clean slate + self._remove_secret_db(multihost) + + client = sssdTools(multihost.master[0]) + client.auth_from_client('foo2', 'Secret123') + client.auth_from_client('foo3', 'Secret123') + + # The loop would request 63 users, plus there is foo3 we authenticated + # earlier, so this should exactly deplete the quota, but should succeed + for i in range(1, 64): + username = "user%04d" % i + kinit = multihost.master[0].run_command( + f'su -l foo3 -c "kinit {username}"', + stdin_text='Secret123', raiseonerr=False) + assert kinit.returncode == 0 + + # this kinit should be exactly one over the peruid limit + kinit_f = multihost.master[0].run_command( + 'su -l foo3 -c "kinit user0064"', + stdin_text='Secret123', raiseonerr=False) + assert kinit_f.returncode != 0 + + # Since this is a per-uid limit, another user should be able to kinit + # just fine + # this kinit should be exactly one over the peruid limit + kinit_o = multihost.master[0].run_command( + 'su -l foo2 -c "kinit user0064"', + stdin_text='Secret123', raiseonerr=False) + assert kinit_o.returncode == 0 + + # kdestroy as the original user, the quota should allow a subsequent + # kinit + multihost.master[0].run_command( + 'su -l foo3 -c "kdestroy -A"', raiseonerr=False) + kinit_p = multihost.master[0].run_command( + 'su -l foo3 -c "kinit user0064"', + stdin_text='Secret123', raiseonerr=False) + assert kinit_p.returncode == 0 + + multihost.master[0].run_command( + 'su -l foo2 -c "kdestroy -A"', raiseonerr=False) + + multihost.master[0].run_command( + 'su -l foo3 -c "kdestroy -A"', raiseonerr=False) + + @pytest.mark.usefixtures("enable_kcm", "create_many_user_principals") + def test_kcm_peruid_quota_increase(self, multihost): + """ + :title: kcm: Quota increase + :id: 0b3cab49-befb-4ab2-bb12-b102d94249aa + :description: Increasing the peruid quota allows a client to store + more data + """ + # It is easier to keep these tests stable and independent from others + # if they start from a clean slate + self._remove_secret_db(multihost) + user = 'foo3' + client = sssdTools(multihost.master[0]) + client.auth_from_client(user, 'Secret123') + + # The loop would request 63 users, plus there is foo3 we authenticated + # earlier, so this should exactly deplete the quota, but should succeed + for i in range(1, 64): + username = "user%04d" % i + kinit = multihost.master[0].run_command( + f'su -l {user} -c "kinit {username}"', + stdin_text='Secret123', raiseonerr=False) + assert kinit.returncode == 0 + + # this kinit should be exactly one over the peruid limit + kinit_f = multihost.master[0].run_command( + f'su -l {user} -c "kinit user0064"', + stdin_text='Secret123', raiseonerr=False) + assert kinit_f.returncode != 0 + + set_param(multihost, 'kcm', 'max_uid_ccaches', '65') + self._restart_kcm(multihost) + + # Now the kinit should work as we increased the limit + kinit_p = multihost.master[0].run_command( + f'su -l {user} -c "kinit user0064"', + stdin_text='Secret123', raiseonerr=False) + assert kinit_p.returncode == 0 + + multihost.master[0].run_command( + f'su -l {user} -c "kdestroy -A"', raiseonerr=False) + + @pytest.mark.usefixtures("enable_kcm") + def test_kcm_payload_low_quota(self, multihost): + """ + :title: kcm: Quota enforcement + :id: cb3daadb-c5e7-48f8-b419-11c616f0d602 + :description: Set a prohibitive quota for the per-ccache payload + limit and make sure it gets enforced + """ + # It is easier to keep these tests stable and independent from others + # if they start from a clean slate + self._remove_secret_db(multihost) + user = 'foo3' + client = sssdTools(multihost.master[0]) + client.auth_from_client(user, 'Secret123') + + multihost.master[0].run_command( + f'su -l {user} -c "kdestroy -A"', raiseonerr=False) + + set_param(multihost, 'kcm', 'max_ccache_size', '1') + self._restart_kcm(multihost) + + # We use kinit to exceed the maximum ccache size as it creates payload + # of 1280 bytes by acquiring tgt and also some control credentials. + # SSH authentication is not sufficient as it stores only tgt. + kv_p = multihost.master[0].run_command( + f'su -l foo3 -c "kinit {user}@EXAMPLE.TEST"', + stdin_text='Secret123', raiseonerr=False) + assert kv_p.returncode != 0 diff --git a/src/tests/multihost/basic/test_sssctl_config_check.py b/src/tests/multihost/basic/test_sssctl_config_check.py new file mode 100644 index 0000000..1ada5c7 --- /dev/null +++ b/src/tests/multihost/basic/test_sssctl_config_check.py @@ -0,0 +1,107 @@ +"""sssctl config-check Test Cases + +:requirement: IDM-SSSD-REQ: Status utility +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" + +import re + +import pytest + + +class TestSssctlConfigCheck(object): + @pytest.mark.converted('test_sssctl.py', 'test_sssctl__check_typo_option_name') + def test_verify_typo_option_name(self, multihost): + """ + :title: sssctl: Verify typos in option name (not value) + of configuration file + :id: 4089f5d6-cdeb-4bcb-9028-cabd97d43045 + """ + cfgget = '/etc/sssd/sssd.conf' + cfgput = '/tmp/sssd.conf.backup' + multihost.master[0].run_command(['/bin/cp', + '-a', cfgget, cfgput], + raiseonerr=False) + sssdcfg = multihost.master[0].get_file_contents(cfgget) + + # replacing ldap_search_base option with search_base + sssdcfg = re.sub(b"ldap_search_base", + b"search_base", sssdcfg) + multihost.master[0].put_file_contents(cfgget, sssdcfg) + sssctl_cmd = 'sssctl config-check' + cmd = multihost.master[0].run_command(sssctl_cmd, raiseonerr=False) + if cmd.returncode == 1: + log = re.compile(r'Attribute\s.search.base.\sis\snot\sallowed.*') + if log.search(cmd.stdout_text): + assert True + else: + assert False + else: + assert False + multihost.master[0].run_command(['/bin/cp', '-a', cfgput, cfgget], + raiseonerr=False) + + @pytest.mark.converted('test_sssctl.py', 'test_sssctl__typo_domain_name') + def test_verify_typo_domain_name(self, multihost): + """ + :title: sssctl: Verify typos in domain name of configuration file + :id: a5d3a3a5-f832-4fc6-a628-9165dab69dd2 + """ + cfgget = '/etc/sssd/sssd.conf' + cfgput = '/tmp/sssd.conf.backup' + multihost.master[0].run_command(['/bin/cp', + '-a', cfgget, cfgput], + raiseonerr=False) + sssdcfg = multihost.master[0].get_file_contents(cfgget) + + # replacing the domain name with typo + sssdcfg = re.sub(b"domain/EXAMPLE.TEST", + b"domain/", sssdcfg) + multihost.master[0].put_file_contents(cfgget, sssdcfg) + sssctl_cmd = 'sssctl config-check' + cmd = multihost.master[0].run_command(sssctl_cmd, raiseonerr=False) + if cmd.returncode == 1: + log = re.compile(r'Section\s\[domain\/\]\sis\snot\sallowed.*') + if log.search(cmd.stdout_text): + assert True + else: + assert False + else: + assert False + multihost.master[0].run_command(['/bin/cp', '-a', cfgput, cfgget], + raiseonerr=False) + + @pytest.mark.converted('test_sssctl.py', 'test_sssctl__misplaced_option') + def test_misplaced_option(self, multihost): + """ + :title: sssctl: Verify misplace options in default configuration file + :id: ed814158-dea5-4f62-8500-fe62087332f9 + """ + cfgget = '/etc/sssd/sssd.conf' + cfgput = '/tmp/sssd.conf.backup' + sssdcfg = multihost.master[0].get_file_contents(cfgget) + + # adding services option under domain section + sssdcfg = re.sub(b"services = nss, pam, sudo, ifp", + b"#services = nss, pam, sudo, ifp", sssdcfg) + sssdcfg = re.sub(b".domain/EXAMPLE.TEST.", + b"[domain/EXAMPLE.TEST]" + b"\nservices = nss, pam, sudo, ifp", sssdcfg) + multihost.master[0].put_file_contents(cfgget, sssdcfg) + sssctl_cmd = 'sssctl config-check' + cmd = multihost.master[0].run_command(sssctl_cmd, + raiseonerr=False) + if cmd.returncode == 1: + log = re.compile( + r'.Attribute\s.services.\sis\snot\sallowed\sin\ssection\s.*') + if log.search(cmd.stdout_text): + assert True + else: + assert False + else: + assert False + multihost.master[0].run_command(['/bin/cp', '-a', cfgput, cfgget], + raiseonerr=False) diff --git a/src/tests/multihost/basic/test_sudo.py b/src/tests/multihost/basic/test_sudo.py new file mode 100644 index 0000000..35861de --- /dev/null +++ b/src/tests/multihost/basic/test_sudo.py @@ -0,0 +1,66 @@ +""" SUDO responder sanity Test Cases + +:requirement: sudo +:casecomponent: sssd +:subsystemteam: sst_idm_sssd +:upstream: yes +:status: approved +""" + +import time +import pytest +from sssd.testlib.common.utils import sssdTools + + +class TestSanitySudo(object): + """ Basic Sanity Test cases for sudo service in sssd """ + @staticmethod + @pytest.mark.converted('test_sudo.py', 'test_sudo__case_sensitive_false') + @pytest.mark.usefixtures( + "case_sensitive_sudorule", "enable_sss_sudo_nsswitch", + "set_case_sensitive_false") + def test_case_senitivity(multihost): + """ + :title: sudo: Verify case sensitivity in sudo responder + :id: 64ab80be-17fd-4c3b-9d9b-7d07c6279975 + """ + user = 'capsuser-1' + # Test ssh login + client = sssdTools(multihost.master[0]) + ssh_result = client.auth_from_client(user, 'Secret123') == 3 + cmd = multihost.master[0].run_command( + f'su - {user} -c "sudo -l"', raiseonerr=False) + rule_result = cmd.returncode == 0 and \ + '(root) NOPASSWD: /usr/bin/less' in cmd.stdout_text + rule2_result = cmd.returncode == 0 and \ + '(root) NOPASSWD: /usr/bin/more' in cmd.stdout_text + assert ssh_result, f"Ssh failed for user: {user}." + assert rule_result, f"Rules missing for user: {user}." + assert rule2_result, f"Rules missing for user: {user}." + + @staticmethod + @pytest.mark.converted('test_sudo.py', 'test_sudo__rules_refresh') + @pytest.mark.usefixtures("enable_sss_sudo_nsswitch", "generic_sudorule", + "set_entry_cache_sudo_timeout") + def test_refresh_expired_rule(multihost): + """ + :title: sudo: Verify refreshing expired sudo rules + do not crash sssd_sudo + :id: 532513b2-15bc-46ac-8fc9-19fd0bf485c4 + """ + + user = 'foo1' + # Test ssh login + client = sssdTools(multihost.master[0]) + ssh_result = client.auth_from_client(user, 'Secret123') == 3 + cmd = multihost.master[0].run_command( + f'su - {user} -c "sudo -l"', raiseonerr=False) + time.sleep(30) + cmd2 = multihost.master[0].run_command( + f'su - {user} -c "sudo -l"', raiseonerr=False) + + assert ssh_result, f"Ssh failed for user: {user}." + assert cmd.returncode == 0, \ + f"First sudo -l failed for user: {user}." + assert cmd2.returncode == 0, \ + f"Second sudo -l failed for user: {user}." diff --git a/src/tests/multihost/basic/utils_config.py b/src/tests/multihost/basic/utils_config.py new file mode 100644 index 0000000..11b718e --- /dev/null +++ b/src/tests/multihost/basic/utils_config.py @@ -0,0 +1,32 @@ +""" Various utilities for manipulating SSSD configuration """ +import configparser as ConfigParser + + +def set_param(multihost, section, key, value): + multihost.master[0].transport.get_file('/etc/sssd/sssd.conf', + '/tmp/sssd.conf') + sssdconfig = ConfigParser.ConfigParser() + sssdconfig.read('/tmp/sssd.conf') + if section not in sssdconfig.sections(): + sssdconfig.add_section(section) + + sssdconfig.set(section, key, value) + with open(str('/tmp/sssd.conf'), "w") as sssconf: + sssdconfig.write(sssconf) + + multihost.master[0].transport.put_file('/tmp/sssd.conf', + '/etc/sssd/sssd.conf') + + +def remove_section(multihost, section): + multihost.master[0].transport.get_file('/etc/sssd/sssd.conf', + '/tmp/sssd.conf') + sssdconfig = ConfigParser.ConfigParser() + sssdconfig.read('/tmp/sssd.conf') + sssdconfig.remove_section(section) + + with open(str('/tmp/sssd.conf'), "w") as sssconf: + sssdconfig.write(sssconf) + + multihost.master[0].transport.put_file('/tmp/sssd.conf', + '/etc/sssd/sssd.conf') |