From 47bddf4f458699f46b398d0969d5e3a348feed52 Mon Sep 17 00:00:00 2001 From: Sumedh Sidhaye Date: May 19 2020 13:11:54 +0000 Subject: Test for removing a subgroup Problem description: Removing an IPA sub-group should NOT remove the members from indirect parent that also belong to other subgroups The test: A user and three groups are created groupa,groupb,groupc 'groupc' should be a child of 'groupb' so that you have groupa->groupb->groupc user is direct member of 'groupa' and as a result member of 'groupb' and 'groupc'. Now when one adds a direct membership to 'groupb' nothing will change. If one removes the direct membership to 'groupb' again, nothing should change as well Pagure Link: https://pagure.io/SSSD/sssd/issue/3636 Signed-off-by: Sumedh Sidhaye Reviewed-By: Florence Blanc-Renaud Reviewed-By: Mohammad Rizwan Yusuf Reviewed-By: Fraser Tweedale Reviewed-By: Christian Heimes --- diff --git a/ipatests/test_integration/test_sssd.py b/ipatests/test_integration/test_sssd.py index f516e16..08b91c3 100644 --- a/ipatests/test_integration/test_sssd.py +++ b/ipatests/test_integration/test_sssd.py @@ -9,6 +9,7 @@ from __future__ import absolute_import import time from contextlib import contextmanager import re +import os import pytest import subprocess @@ -16,6 +17,7 @@ import textwrap from ipatests.test_integration.base import IntegrationTest from ipatests.pytest_ipa.integration import tasks +from ipatests.pytest_ipa.integration.tasks import clear_sssd_cache from ipatests.util import xfail_context from ipaplatform.tasks import tasks as platform_tasks from ipaplatform.osinfo import osinfo @@ -403,3 +405,178 @@ class TestSSSDWithAdTrust(IntegrationTest): assert 'no such user' in res.stderr_text # verify the user can be retrieved after re-enabling trustdomain self.master.run_command(['id', user]) + + +class TestNestedMembers(IntegrationTest): + num_clients = 1 + username = "testuser001" + userpasswd = 'Secret123' + + @classmethod + def install(cls, mh): + tasks.install_master(cls.master) + tasks.install_client(cls.master, cls.clients[0]) + + @pytest.fixture + def nested_group_setup(self, tmpdir): + """Setup and Clean up groups and user created""" + master = self.master + client = self.clients[0] + + # add a user and set password + tasks.create_active_user(master, self.username, self.userpasswd) + tasks.kinit_admin(master) + + privkey, pubkey = tasks.generate_ssh_keypair() + with open(os.path.join( + tmpdir, 'ssh_priv_key'), 'w') as fp: + fp.write(privkey) + + master.run_command([ + 'ipa', 'user-mod', self.username, '--ssh', "{}".format(pubkey) + ]) + + master.put_file_contents('/tmp/user_ssh_priv_key', privkey) + master.run_command(['chmod', '600', '/tmp/user_ssh_priv_key']) + + # add group groupa + cmd_output = master.run_command(['ipa', 'group-add', 'groupa']) + assert 'Added group "groupa"' in cmd_output.stdout_text + + # add group groupb + cmd_output = master.run_command(['ipa', 'group-add', 'groupb']) + assert 'Added group "groupb"' in cmd_output.stdout_text + + # add group groupc + cmd_output = master.run_command(['ipa', 'group-add', 'groupc']) + assert 'Added group "groupc"' in cmd_output.stdout_text + + client.put_file_contents('/tmp/user_ssh_priv_key', + privkey) + client.run_command(['chmod', '600', '/tmp/user_ssh_priv_key']) + yield + # test cleanup + for group in ['groupa', 'groupb', 'groupc']: + self.master.run_command(['ipa', 'group-del', group, '--continue']) + self.master.run_command(['ipa', 'user-del', self.username, + '--no-preserve', '--continue']) + tasks.kdestroy_all(self.master) + tasks.kdestroy_all(self.clients[0]) + + def test_nested_group_members(self, tmpdir, nested_group_setup): + """Nested group memberships should be honoured + + "groupc" should be a child of "groupb" + so that parent child relationship is as follows: + "groupa"->"groupb"->"groupc" + + testuser001 is direct member of "groupa" and as a result + member of "groupb" and "groupc"". + Now if one adds a direct membership to "groupb" + nothing will change. + + Now if one removes the direct membership to "groupb" + nothing should change, the memberships should be honored + Linked Issue: https://pagure.io/SSSD/sssd/issue/3636 + """ + master = self.master + client = self.clients[0] + + # add group members + cmd_output = master.run_command(['ipa', 'group-add-member', + 'groupb', '--groups', 'groupa']) + assert 'Group name: groupb' in cmd_output.stdout_text + assert 'Member groups: groupa' in cmd_output.stdout_text + assert 'Number of members added 1' in cmd_output.stdout_text + + cmd_output = master.run_command(['ipa', 'group-add-member', + 'groupc', '--groups', 'groupb']) + assert 'Group name: groupc' in cmd_output.stdout_text + assert 'Member groups: groupb' in cmd_output.stdout_text + assert 'Indirect Member groups: groupa' in cmd_output.stdout_text + + # add user to group 'groupa' + cmd_output = master.run_command(['ipa', 'group-add-member', + 'groupa', '--users', self.username]) + assert 'Group name: groupa' in cmd_output.stdout_text + assert_str = 'Member users: {}'.format(self.username) + assert assert_str in cmd_output.stdout_text + assert 'Member of groups: groupb' in cmd_output.stdout_text + assert 'Indirect Member of group: groupc' in cmd_output.stdout_text + + # clear sssd_cache + clear_sssd_cache(master) + + # user lookup + # at this point, testuser001 has the following group memberships + # Member of groups: groupa, ipausers + # Indirect Member of group: groupb, groupc + cmd_output = master.run_command(['ipa', 'user-show', self.username]) + assert 'groupa' in cmd_output.stdout_text + assert 'ipausers' in cmd_output.stdout_text + assert 'groupb' in cmd_output.stdout_text + assert 'groupc' in cmd_output.stdout_text + + clear_sssd_cache(client) + + cmd = ['ssh', '-i', '/tmp/user_ssh_priv_key', + '-q', '{}@{}'.format(self.username, client.hostname), + 'groups'] + cmd_output = master.run_command(cmd) + assert self.username in cmd_output.stdout_text + assert 'groupa' in cmd_output.stdout_text + assert 'groupb' in cmd_output.stdout_text + assert 'groupc' in cmd_output.stdout_text + + # add member + cmd_output = master.run_command(['ipa', 'group-add-member', + 'groupb', '--users', self.username]) + assert 'Group name: groupb' in cmd_output.stdout_text + assert_str = 'Member users: {}'.format(self.username) + assert assert_str in cmd_output.stdout_text + assert 'Member groups: groupa' in cmd_output.stdout_text + assert 'Member of groups: groupc' in cmd_output.stdout_text + assert 'Number of members added 1' in cmd_output.stdout_text + + # now check ssh on the client + clear_sssd_cache(client) + + # after adding testuser001 to b group + # testuser001 will have the following memberships + # Member of groups: groupa, ipausers, groupb + # Indirect Member of group: groupc + cmd = ['ssh', '-i', '/tmp/user_ssh_priv_key', + '-q', '{}@{}'.format(self.username, client.hostname), + 'groups'] + cmd_output = client.run_command(cmd) + assert self.username in cmd_output.stdout_text + assert 'groupa' in cmd_output.stdout_text + assert 'groupb' in cmd_output.stdout_text + assert 'groupc' in cmd_output.stdout_text + + # now back to server to remove member + cmd_output = master.run_command(['ipa', 'group-remove-member', + 'groupb', '--users', self.username]) + assert_str = 'Indirect Member users: {}'.format(self.username) + assert 'Group name: groupb' in cmd_output.stdout_text + assert 'Member groups: groupa' in cmd_output.stdout_text + assert 'Member of groups: groupc' in cmd_output.stdout_text + assert assert_str in cmd_output.stdout_text + assert 'Number of members removed 1' in cmd_output.stdout_text + + clear_sssd_cache(master) + + # now check ssh on the client again + # after removing testuser001 from b group + # testuser001 will have the following memberships + # Member of groups: groupa, ipausers + # Indirect Member of group: groupb, groupc + clear_sssd_cache(client) + cmd = ['ssh', '-i', '/tmp/user_ssh_priv_key', + '-q', '{}@{}'.format(self.username, client.hostname), + 'groups'] + cmd_output = client.run_command(cmd) + assert self.username in cmd_output.stdout_text + assert 'groupa' in cmd_output.stdout_text + assert 'groupb' in cmd_output.stdout_text + assert 'groupc' in cmd_output.stdout_text