From dc8e3fcdd6807974122e47ff97e9bbd3be16557f Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 3 Oct 2017 16:55:40 +0200 Subject: [PATCH 08/79] TESTS: Add integration tests for the auto_private_groups option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related: https://pagure.io/SSSD/sssd/issue/1872 Reviewed-by: Fabiano Fidêncio Reviewed-by: Pavel Březina --- src/tests/intg/test_enumeration.py | 79 +++++++++++++- src/tests/intg/test_ldap.py | 214 +++++++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+), 3 deletions(-) diff --git a/src/tests/intg/test_enumeration.py b/src/tests/intg/test_enumeration.py index fdb8d376879f756957f8f25fd28b37d7178aeff5..c7d78155c64dc6c85cb4dc070b205bdcfceff6af 100644 --- a/src/tests/intg/test_enumeration.py +++ b/src/tests/intg/test_enumeration.py @@ -237,9 +237,7 @@ def sanity_rfc2307(request, ldap_conn): create_sssd_fixture(request) return None - -@pytest.fixture -def sanity_rfc2307_bis(request, ldap_conn): +def populate_rfc2307bis(request, ldap_conn): ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) ent_list.add_user("user1", 1001, 2001) ent_list.add_user("user2", 1002, 2002) @@ -266,6 +264,11 @@ def sanity_rfc2307_bis(request, ldap_conn): [], ["one_user_group1", "one_user_group2"]) create_ldap_fixture(request, ldap_conn, ent_list) + + +@pytest.fixture +def sanity_rfc2307_bis(request, ldap_conn): + populate_rfc2307bis(request, ldap_conn) conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) create_conf_fixture(request, conf) create_sssd_fixture(request) @@ -695,3 +698,73 @@ def test_vetoed_shells(vetoed_shells): shell="/bin/default") ) ) + + +@pytest.fixture +def sanity_rfc2307_bis_mpg(request, ldap_conn): + populate_rfc2307bis(request, ldap_conn) + + ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) + ent_list.add_group_bis("conflict1", 1001) + ent_list.add_group_bis("conflict2", 1002) + create_ldap_fixture(request, ldap_conn, ent_list) + + conf = \ + format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) + \ + unindent(""" + [domain/LDAP] + auto_private_groups = True + """).format(**locals()) + create_conf_fixture(request, conf) + create_sssd_fixture(request) + return None + + +def test_ldap_auto_private_groups_enumerate(ldap_conn, + sanity_rfc2307_bis_mpg): + """ + Test the auto_private_groups together with enumeration + """ + passwd_pattern = ent.contains_only( + dict(name='user1', passwd='*', uid=1001, gid=1001, gecos='1001', + dir='/home/user1', shell='/bin/bash'), + dict(name='user2', passwd='*', uid=1002, gid=1002, gecos='1002', + dir='/home/user2', shell='/bin/bash'), + dict(name='user3', passwd='*', uid=1003, gid=1003, gecos='1003', + dir='/home/user3', shell='/bin/bash') + ) + ent.assert_passwd(passwd_pattern) + + group_pattern = ent.contains_only( + dict(name='user1', passwd='*', gid=1001, mem=ent.contains_only()), + dict(name='user2', passwd='*', gid=1002, mem=ent.contains_only()), + dict(name='user3', passwd='*', gid=1003, mem=ent.contains_only()), + dict(name='group1', passwd='*', gid=2001, mem=ent.contains_only()), + dict(name='group2', passwd='*', gid=2002, mem=ent.contains_only()), + dict(name='group3', passwd='*', gid=2003, mem=ent.contains_only()), + dict(name='empty_group1', passwd='*', gid=2010, + mem=ent.contains_only()), + dict(name='empty_group2', passwd='*', gid=2011, + mem=ent.contains_only()), + dict(name='two_user_group', passwd='*', gid=2012, + mem=ent.contains_only("user1", "user2")), + dict(name='group_empty_group', passwd='*', gid=2013, + mem=ent.contains_only()), + dict(name='group_two_empty_groups', passwd='*', gid=2014, + mem=ent.contains_only()), + dict(name='one_user_group1', passwd='*', gid=2015, + mem=ent.contains_only("user1")), + dict(name='one_user_group2', passwd='*', gid=2016, + mem=ent.contains_only("user2")), + dict(name='group_one_user_group', passwd='*', gid=2017, + mem=ent.contains_only("user1")), + dict(name='group_two_user_group', passwd='*', gid=2018, + mem=ent.contains_only("user1", "user2")), + dict(name='group_two_one_user_groups', passwd='*', gid=2019, + mem=ent.contains_only("user1", "user2")) + ) + ent.assert_group(group_pattern) + + with pytest.raises(KeyError): + grp.getgrnam("conflict1") + ent.assert_group_by_gid(1002, dict(name="user2", mem=ent.contains_only())) diff --git a/src/tests/intg/test_ldap.py b/src/tests/intg/test_ldap.py index f2467f1ffe9890049ad73bba6432102d029510e8..a6659b1b78df4d72eb98c208d67ee5d10c9c88ea 100644 --- a/src/tests/intg/test_ldap.py +++ b/src/tests/intg/test_ldap.py @@ -1169,3 +1169,217 @@ def test_nss_filters_cached(ldap_conn, sanity_nss_filter_cached): res, _ = call_sssd_getgrgid(0) assert res == NssReturnCode.NOTFOUND + + +@pytest.fixture +def mpg_setup(request, ldap_conn): + ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) + ent_list.add_user("user1", 1001, 2001) + ent_list.add_user("user2", 1002, 2002) + ent_list.add_user("user3", 1003, 2003) + + ent_list.add_group_bis("group1", 2001) + ent_list.add_group_bis("group2", 2002) + ent_list.add_group_bis("group3", 2003) + + ent_list.add_group_bis("two_user_group", 2012, ["user1", "user2"]) + ent_list.add_group_bis("one_user_group1", 2015, ["user1"]) + ent_list.add_group_bis("one_user_group2", 2016, ["user2"]) + + create_ldap_entries(ldap_conn, ent_list) + create_ldap_cleanup(request, ldap_conn, None) + + conf = \ + format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) + \ + unindent(""" + [domain/LDAP] + auto_private_groups = True + """).format(**locals()) + create_conf_fixture(request, conf) + create_sssd_fixture(request) + return None + + +def test_ldap_auto_private_groups_direct(ldap_conn, mpg_setup): + """ + Integration test for auto_private_groups + + See also ticket https://pagure.io/SSSD/sssd/issue/1872 + """ + # Make sure the user's GID is taken from their uidNumber + ent.assert_passwd_by_name("user1", dict(name="user1", uid=1001, gid=1001)) + # Make sure the private group is resolvable by name and by GID + ent.assert_group_by_name("user1", dict(gid=1001, mem=ent.contains_only())) + ent.assert_group_by_gid(1001, dict(name="user1", mem=ent.contains_only())) + + # The group referenced in user's gidNumber attribute should be still + # visible, but it's fine that it doesn't contain the user as a member + # as the group is currently added during the initgroups operation only + ent.assert_group_by_name("group1", dict(gid=2001, mem=ent.contains_only())) + ent.assert_group_by_gid(2001, dict(name="group1", mem=ent.contains_only())) + + # The user's secondary groups list must be correct as well + # Note that the original GID is listed as well -- this is correct and expected + # because we save the original GID in the SYSDB_PRIMARY_GROUP_GIDNUM attribute + user1_expected_gids = [1001, 2001, 2012, 2015] + (res, errno, gids) = sssd_id.call_sssd_initgroups("user1", 1001) + assert res == sssd_id.NssReturnCode.SUCCESS + + assert sorted(gids) == sorted(user1_expected_gids), \ + "result: %s\n expected %s" % ( + ", ".join(["%s" % s for s in sorted(gids)]), + ", ".join(["%s" % s for s in sorted(user1_expected_gids)]) + ) + + # Request user2's private group by GID without resolving the user first. + # This must trigger user resolution through by-GID resolution, since the GID + # doesn't exist on its own in LDAP + ent.assert_group_by_gid(1002, dict(name="user2", mem=ent.contains_only())) + + # Test supplementary groups for user2 as well + user1_expected_gids = [1002, 2002, 2012, 2016] + (res, errno, gids) = sssd_id.call_sssd_initgroups("user2", 1002) + assert res == sssd_id.NssReturnCode.SUCCESS + + assert sorted(gids) == sorted(user1_expected_gids), \ + "result: %s\n expected %s" % ( + ", ".join(["%s" % s for s in sorted(gids)]), + ", ".join(["%s" % s for s in sorted(user1_expected_gids)]) + ) + + # Request user3's private group by name without resolving the user first + # This must trigger user resolution through by-name resolution, since the + # name doesn't exist on its own in LDAP + ent.assert_group_by_name("user3", dict(gid=1003, mem=ent.contains_only())) + + # Remove entries and request them again to make sure they are not + # resolvable anymore + cleanup_ldap_entries(ldap_conn, None) + + if subprocess.call(["sss_cache", "-GU"]) != 0: + raise Exception("sssd_cache failed") + + with pytest.raises(KeyError): + pwd.getpwnam("user1") + with pytest.raises(KeyError): + grp.getgrnam("user1") + with pytest.raises(KeyError): + grp.getgrgid(1002) + with pytest.raises(KeyError): + grp.getgrnam("user3") + + +@pytest.fixture +def mpg_setup_conflict(request, ldap_conn): + ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) + ent_list.add_user("user1", 1001, 2001) + ent_list.add_user("user2", 1002, 2002) + ent_list.add_user("user3", 1003, 1003) + ent_list.add_group_bis("group1", 1001) + ent_list.add_group_bis("group2", 1002) + ent_list.add_group_bis("group3", 1003) + ent_list.add_group_bis("supp_group", 2015, ["user3"]) + create_ldap_fixture(request, ldap_conn, ent_list) + + conf = \ + format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) + \ + unindent(""" + [domain/LDAP] + auto_private_groups = True + """).format(**locals()) + create_conf_fixture(request, conf) + create_sssd_fixture(request) + return None + + +def test_ldap_auto_private_groups_conflict(ldap_conn, mpg_setup_conflict): + """ + Make sure that conflicts between groups that are auto-created with the + help of the auto_private_groups option and between 'real' LDAP groups + are handled in a predictable manner. + """ + # Make sure the user's GID is taken from their uidNumber + ent.assert_passwd_by_name("user1", dict(name="user1", uid=1001, gid=1001)) + # Make sure the private group is resolvable by name and by GID + ent.assert_group_by_name("user1", dict(gid=1001, mem=ent.contains_only())) + ent.assert_group_by_gid(1001, dict(name="user1", mem=ent.contains_only())) + + # Let's request the group with the same ID as user2's private group + # The request should match the 'real' group + ent.assert_group_by_gid(1002, dict(name="group2", mem=ent.contains_only())) + # But because of the GID conflict, the user cannot be resolved + with pytest.raises(KeyError): + pwd.getpwnam("user2") + + # This user's GID is the same as the UID in this entry. The most important + # thing here is that the supplementary groups are correct and the GID + # resolves to the private group (as long as the user was requested first) + user3_expected_gids = [1003, 2015] + ent.assert_passwd_by_name("user3", dict(name="user3", uid=1003, gid=1003)) + (res, errno, gids) = sssd_id.call_sssd_initgroups("user3", 1003) + assert res == sssd_id.NssReturnCode.SUCCESS + + assert sorted(gids) == sorted(user3_expected_gids), \ + "result: %s\n expected %s" % ( + ", ".join(["%s" % s for s in sorted(gids)]), + ", ".join(["%s" % s for s in sorted(user3_expected_gids)]) + ) + # Make sure the private group is resolvable by name and by GID + ent.assert_group_by_gid(1003, dict(name="user3", mem=ent.contains_only())) + ent.assert_group_by_name("user3", dict(gid=1003, mem=ent.contains_only())) + + +@pytest.fixture +def mpg_setup_no_gid(request, ldap_conn): + ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) + ent_list.add_user("user1", 1001, 2001) + + ent_list.add_group_bis("group1", 2001) + ent_list.add_group_bis("one_user_group1", 2015, ["user1"]) + + create_ldap_entries(ldap_conn, ent_list) + create_ldap_cleanup(request, ldap_conn, None) + + conf = \ + format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) + \ + unindent(""" + [domain/LDAP] + auto_private_groups = True + ldap_user_gid_number = no_such_attribute + """).format(**locals()) + create_conf_fixture(request, conf) + create_sssd_fixture(request) + return None + + +def test_ldap_auto_private_groups_direct_no_gid(ldap_conn, mpg_setup_no_gid): + """ + Integration test for auto_private_groups - test that even a user with + no GID assigned at all can be resolved including their autogenerated + primary group. + + See also ticket https://pagure.io/SSSD/sssd/issue/1872 + """ + # Make sure the user's GID is taken from their uidNumber + ent.assert_passwd_by_name("user1", dict(name="user1", uid=1001, gid=1001)) + # Make sure the private group is resolvable by name and by GID + ent.assert_group_by_name("user1", dict(gid=1001, mem=ent.contains_only())) + ent.assert_group_by_gid(1001, dict(name="user1", mem=ent.contains_only())) + + # The group referenced in user's gidNumber attribute should be still + # visible, but shouldn't have any relation to the user + ent.assert_group_by_name("group1", dict(gid=2001, mem=ent.contains_only())) + ent.assert_group_by_gid(2001, dict(name="group1", mem=ent.contains_only())) + + # The user's secondary groups list must be correct as well. This time only + # the generated group and the explicit secondary group are added, since + # there is no original GID + user1_expected_gids = [1001, 2015] + (res, errno, gids) = sssd_id.call_sssd_initgroups("user1", 1001) + assert res == sssd_id.NssReturnCode.SUCCESS + + assert sorted(gids) == sorted(user1_expected_gids), \ + "result: %s\n expected %s" % ( + ", ".join(["%s" % s for s in sorted(gids)]), + ", ".join(["%s" % s for s in sorted(user1_expected_gids)]) + ) -- 2.15.1