summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipatests/test_xmlrpc/test_group_plugin.py1756
-rw-r--r--ipatests/test_xmlrpc/test_stageuser_plugin.py4
-rw-r--r--ipatests/test_xmlrpc/tracker/group_plugin.py159
3 files changed, 754 insertions, 1165 deletions
diff --git a/ipatests/test_xmlrpc/test_group_plugin.py b/ipatests/test_xmlrpc/test_group_plugin.py
index 6eb57c12f..41d28f1cf 100644
--- a/ipatests/test_xmlrpc/test_group_plugin.py
+++ b/ipatests/test_xmlrpc/test_group_plugin.py
@@ -1,6 +1,7 @@
# Authors:
# Rob Crittenden <rcritten@redhat.com>
# Pavel Zuna <pzuna@redhat.com>
+# Filip Skola <fskola@redhat.com>
#
# Copyright (C) 2008 Red Hat
# see file 'COPYING' for use and warranty information
@@ -23,1141 +24,666 @@ Test the `ipalib/plugins/group.py` module.
import pytest
-from ipalib import api, errors
+from ipalib import errors
from ipatests.test_xmlrpc import objectclasses
from ipatests.test_xmlrpc.xmlrpc_test import (
- Declarative,
- fuzzy_digits,
- fuzzy_uuid,
- fuzzy_set_ci,
- add_sid,
- add_oc)
-from ipapython.dn import DN
-from ipatests.test_xmlrpc.test_user_plugin import get_user_result
+ fuzzy_digits, fuzzy_uuid, fuzzy_set_ci, add_oc,
+ XMLRPC_test, raises_exact
+)
+from ipatests.test_xmlrpc.tracker.group_plugin import GroupTracker
+from ipatests.test_xmlrpc.tracker.user_plugin import UserTracker
+from ipatests.util import assert_deepequal, get_group_dn
+
+notagroup = u'notagroup'
+renamedgroup1 = u'renamedgroup'
+invalidgroup1 = u'+tgroup1'
+external_sid1 = u'S-1-1-123456-789-1'
+
+
+@pytest.fixture(scope='class')
+def group(request):
+ tracker = GroupTracker(name=u'testgroup1', description=u'Test desc1')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def group2(request):
+ tracker = GroupTracker(name=u'testgroup2', description=u'Test desc2')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def managed_group(request, user):
+ user.ensure_exists()
+ tracker = GroupTracker(
+ name=user.uid, description=u'User private group for %s' % user.uid
+ )
+ tracker.exists = True
+ # Managed group gets created when user is created
+ tracker.track_create()
+ return tracker
+
+
+@pytest.fixture(scope='class')
+def user(request):
+ tracker = UserTracker(name=u'user1', givenname=u'Test', sn=u'User1')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def user_npg2(request, group):
+ """ User tracker fixture for testing users with no private group """
+ tracker = UserTracker(name=u'npguser2', givenname=u'Npguser',
+ sn=u'Npguser2', noprivate=True, gidnumber=1000)
+ tracker.track_create()
+ del tracker.attrs['mepmanagedentry']
+ tracker.attrs.update(
+ gidnumber=[u'1000'], description=[], memberof_group=[group.cn],
+ objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs')
+ )
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def admins(request):
+ # Track the admins group
+ tracker = GroupTracker(
+ name=u'admins', description=u'Account administrators group'
+ )
+ tracker.exists = True
+ tracker.track_create()
+ tracker.attrs.update(member_user=[u'admin'])
+ return tracker
+
+
+@pytest.fixture(scope='class')
+def trustadmins(request):
+ # Track the 'trust admins' group
+ tracker = GroupTracker(
+ name=u'trust admins', description=u'Trusts administrators group'
+ )
+ tracker.exists = True
+ tracker.track_create()
+ tracker.attrs.update(member_user=[u'admin'])
+ return tracker
-group1 = u'testgroup1'
-group2 = u'testgroup2'
-group3 = u'testgroup3'
-renamedgroup1 = u'testgroup'
-user1 = u'tuser1'
-
-invalidgroup1=u'+tgroup1'
-
-# When adding external SID member to a group we can't test
-# it fully due to possibly missing Samba 4 python bindings
-# and/or not configured AD trusts. Thus, we'll use incorrect
-# SID value to merely test that proper exceptions are raised
-external_sid1=u'S-1-1-123456-789-1'
-
-def get_group_dn(cn):
- return DN(('cn', cn), api.env.container_group, api.env.basedn)
+@pytest.mark.tier1
+class TestGroup(XMLRPC_test):
+ def test_create(self, group):
+ """ Create a group """
+ group.create()
+
+ def test_create_duplicate(self, group):
+ """ Try to create a duplicate group """
+ group.ensure_exists()
+ command = group.make_create_command()
+
+ with raises_exact(errors.DuplicateEntry(
+ message=u'group with name "%s" already exists' % group.cn)):
+ command()
+
+ def test_retrieve(self, group):
+ """ Retrieve a group """
+ group.retrieve()
+
+ def test_update(self, group):
+ """ Update a group with new description
+ and perform retrieve command to verify the update """
+ group.update(dict(description=u'New desc'))
+ group.retrieve()
+
+ def test_rename(self, group):
+ """ Rename a group and than rename it back """
+ origname = group.cn
+
+ command = group.make_command('group_mod', *[group.cn],
+ **dict(setattr=u'cn=%s' % renamedgroup1))
+ result = command()
+ group.attrs.update(cn=[renamedgroup1])
+ group.check_update(result)
+ group.cn = renamedgroup1
+
+ command = group.make_command('group_mod', *[group.cn],
+ **dict(setattr=u'cn=%s' % origname))
+ result = command()
+ group.attrs.update(cn=[origname])
+ group.check_update(result)
+ group.cn = origname
+
+ def test_convert_posix_to_external(self, group):
+ """ Try to convert a posix group to external """
+ command = group.make_update_command(dict(external=True))
+ with raises_exact(errors.PosixGroupViolation(
+ reason=u"""This is already a posix group and cannot
+ be converted to external one""")):
+ command()
+
+ def test_add_with_invalid_name(self, group):
+ """ Try to add group with an invalid name """
+ command = group.make_command(
+ 'group_add', *[invalidgroup1], **dict(description=u'Test')
+ )
+ with raises_exact(errors.ValidationError(
+ name='group_name',
+ error=u'may only include letters, numbers, _, -, . and $')):
+ command()
@pytest.mark.tier1
-class test_group(Declarative):
- cleanup_commands = [
- ('group_del', [group1], {}),
- ('group_del', [group2], {}),
- ('group_del', [group3], {}),
- ('group_del', [renamedgroup1], {}),
- ('user_del', [user1], {}),
- ]
-
- tests = [
-
- ################
- # create group1:
- dict(
- desc='Try to retrieve non-existent %r' % group1,
- command=('group_show', [group1], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
- dict(
- desc='Try to update non-existent %r' % group1,
- command=('group_mod', [group1], dict(description=u'Foo')),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
- dict(
- desc='Try to delete non-existent %r' % group1,
- command=('group_del', [group1], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
- dict(
- desc='Try to rename non-existent %r' % group1,
- command=('group_mod', [group1], dict(setattr=u'cn=%s' % renamedgroup1)),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
- dict(
- desc='Create non-POSIX %r' % group1,
- command=(
- 'group_add', [group1], dict(description=u'Test desc 1',nonposix=True)
- ),
- expected=dict(
- value=group1,
- summary=u'Added group "testgroup1"',
- result=dict(
- cn=[group1],
- description=[u'Test desc 1'],
- objectclass=objectclasses.group,
- ipauniqueid=[fuzzy_uuid],
- dn=get_group_dn('testgroup1'),
- ),
- ),
- ),
-
-
- dict(
- desc='Try to create duplicate %r' % group1,
- command=(
- 'group_add', [group1], dict(description=u'Test desc 1')
- ),
- expected=errors.DuplicateEntry(
- message=u'group with name "%s" already exists' % group1),
- ),
-
-
- dict(
- desc='Retrieve non-POSIX %r' % group1,
- command=('group_show', [group1], {}),
- expected=dict(
- value=group1,
- summary=None,
- result=dict(
- cn=[group1],
- description=[u'Test desc 1'],
- dn=get_group_dn('testgroup1'),
- ),
- ),
- ),
-
-
- dict(
- desc='Updated non-POSIX %r' % group1,
- command=(
- 'group_mod', [group1], dict(description=u'New desc 1')
- ),
- expected=dict(
- result=dict(
- cn=[group1],
- description=[u'New desc 1'],
- ),
- summary=u'Modified group "testgroup1"',
- value=group1,
- ),
- ),
-
-
- dict(
- desc='Retrieve %r to verify update' % group1,
- command=('group_show', [group1], {}),
- expected=dict(
- value=group1,
- result=dict(
- cn=[group1],
- description=[u'New desc 1'],
- dn=get_group_dn('testgroup1'),
- ),
- summary=None,
- ),
- ),
-
-
- # FIXME: The return value is totally different here than from the above
- # group_mod() test. I think that for all *_mod() commands we should
- # just return the entry exactly as *_show() does.
- dict(
- desc='Updated %r to promote it to a POSIX group' % group1,
- command=('group_mod', [group1], dict(posix=True)),
- expected=dict(
- result=dict(
- cn=[group1],
- description=[u'New desc 1'],
- gidnumber=[fuzzy_digits],
- ),
- value=group1,
- summary=u'Modified group "testgroup1"',
- ),
- ),
-
-
- dict(
- desc="Retrieve %r to verify it's a POSIX group" % group1,
- command=('group_show', [group1], {}),
- expected=dict(
- value=group1,
- result=dict(
- cn=[group1],
- description=(u'New desc 1',),
- dn=get_group_dn('testgroup1'),
- gidnumber=[fuzzy_digits],
- ),
- summary=None,
- ),
- ),
-
-
- dict(
- desc='Search for %r' % group1,
- command=('group_find', [], dict(cn=group1)),
- expected=dict(
- count=1,
- truncated=False,
- result=[
- dict(
- dn=get_group_dn(group1),
- cn=[group1],
- description=[u'New desc 1'],
- gidnumber=[fuzzy_digits],
- ),
- ],
- summary=u'1 group matched',
- ),
- ),
-
-
-
- ################
- # create group2:
- dict(
- desc='Try to retrieve non-existent %r' % group2,
- command=('group_show', [group2], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group2),
- ),
-
-
- dict(
- desc='Try to update non-existent %r' % group2,
- command=('group_mod', [group2], dict(description=u'Foo')),
- expected=errors.NotFound(reason=u'%s: group not found' % group2),
- ),
-
-
- dict(
- desc='Try to delete non-existent %r' % group2,
- command=('group_del', [group2], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group2),
- ),
-
-
- dict(
- desc='Create %r' % group2,
- command=(
- 'group_add', [group2], dict(description=u'Test desc 2')
- ),
- expected=dict(
- value=group2,
- summary=u'Added group "testgroup2"',
- result=dict(
- cn=[group2],
- description=[u'Test desc 2'],
- gidnumber=[fuzzy_digits],
- objectclass=objectclasses.posixgroup,
- ipauniqueid=[fuzzy_uuid],
- dn=get_group_dn('testgroup2'),
- ),
- ),
- ),
-
-
- dict(
- desc='Try to create duplicate %r' % group2,
- command=(
- 'group_add', [group2], dict(description=u'Test desc 2')
- ),
- expected=errors.DuplicateEntry(
- message=u'group with name "%s" already exists' % group2),
- ),
-
-
- dict(
- desc='Retrieve %r' % group2,
- command=('group_show', [group2], {}),
- expected=dict(
- value=group2,
- summary=None,
- result=dict(
- cn=[group2],
- description=[u'Test desc 2'],
- gidnumber=[fuzzy_digits],
- dn=get_group_dn('testgroup2'),
- ),
- ),
- ),
-
-
- dict(
- desc='Updated %r' % group2,
- command=(
- 'group_mod', [group2], dict(description=u'New desc 2')
- ),
- expected=dict(
- result=dict(
- cn=[group2],
- gidnumber=[fuzzy_digits],
- description=[u'New desc 2'],
- ),
- summary=u'Modified group "testgroup2"',
- value=group2,
- ),
- ),
-
-
- dict(
- desc='Retrieve %r to verify update' % group2,
- command=('group_show', [group2], {}),
- expected=dict(
- value=group2,
- result=dict(
- cn=[group2],
- description=[u'New desc 2'],
- gidnumber=[fuzzy_digits],
- dn=get_group_dn('testgroup2'),
- ),
- summary=None,
- ),
- ),
-
-
- dict(
- desc='Search for %r' % group2,
- command=('group_find', [], dict(cn=group2)),
- expected=dict(
- count=1,
- truncated=False,
- result=[
- dict(
- dn=get_group_dn('testgroup2'),
- cn=[group2],
- description=[u'New desc 2'],
- gidnumber=[fuzzy_digits],
- ),
- ],
- summary=u'1 group matched',
- ),
- ),
-
-
- dict(
- desc='Search for all groups',
- command=('group_find', [], {}),
- expected=dict(
- summary=u'6 groups matched',
- count=6,
- truncated=False,
- result=[
- {
- 'dn': get_group_dn('admins'),
- 'member_user': [u'admin'],
- 'gidnumber': [fuzzy_digits],
- 'cn': [u'admins'],
- 'description': [u'Account administrators group'],
- },
- {
- 'dn': get_group_dn('editors'),
- 'gidnumber': [fuzzy_digits],
- 'cn': [u'editors'],
- 'description': [u'Limited admins who can edit other users'],
- },
- {
- 'dn': get_group_dn('ipausers'),
- 'cn': [u'ipausers'],
- 'description': [u'Default group for all users'],
- },
- dict(
- dn=get_group_dn(group1),
- cn=[group1],
- description=[u'New desc 1'],
- gidnumber=[fuzzy_digits],
- ),
- dict(
- dn=get_group_dn(group2),
- cn=[group2],
- description=[u'New desc 2'],
- gidnumber=[fuzzy_digits],
- ),
- {
- 'dn': get_group_dn('trust admins'),
- 'member_user': [u'admin'],
- 'cn': [u'trust admins'],
- 'description': [u'Trusts administrators group'],
- },
- ],
- ),
- ),
-
- dict(
- desc='Search for non-POSIX groups',
- command=('group_find', [], dict(nonposix=True, all=True)),
- expected=dict(
- summary=u'2 groups matched',
- count=2,
- truncated=False,
- result=[
- {
- 'dn': get_group_dn('ipausers'),
- 'cn': [u'ipausers'],
- 'description': [u'Default group for all users'],
- 'objectclass': fuzzy_set_ci(objectclasses.group),
- 'ipauniqueid': [fuzzy_uuid],
- },
- {
- 'dn': get_group_dn('trust admins'),
- 'member_user': [u'admin'],
- 'cn': [u'trust admins'],
- 'description': [u'Trusts administrators group'],
- 'objectclass': fuzzy_set_ci(objectclasses.group),
- 'ipauniqueid': [fuzzy_uuid],
- },
- ],
- ),
- ),
-
- dict(
- desc='Search for non-POSIX groups with criteria filter',
- command=('group_find', [u'users'], dict(nonposix=True, all=True)),
- expected=dict(
- summary=u'1 group matched',
- count=1,
- truncated=False,
- result=[
- {
- 'dn': get_group_dn('ipausers'),
- 'cn': [u'ipausers'],
- 'description': [u'Default group for all users'],
- 'objectclass': fuzzy_set_ci(objectclasses.group),
- 'ipauniqueid': [fuzzy_uuid],
- },
- ],
- ),
- ),
-
- dict(
- desc='Search for POSIX groups',
- command=('group_find', [], dict(posix=True, all=True)),
- expected=dict(
- summary=u'4 groups matched',
- count=4,
- truncated=False,
- result=[
- add_sid({
- 'dn': get_group_dn('admins'),
- 'member_user': [u'admin'],
- 'gidnumber': [fuzzy_digits],
- 'cn': [u'admins'],
- 'description': [u'Account administrators group'],
- 'objectclass': fuzzy_set_ci(add_oc(
- objectclasses.posixgroup, u'ipantgroupattrs')),
- 'ipauniqueid': [fuzzy_uuid],
- }),
- add_sid({
- 'dn': get_group_dn('editors'),
- 'gidnumber': [fuzzy_digits],
- 'cn': [u'editors'],
- 'description': [u'Limited admins who can edit other users'],
- 'objectclass': fuzzy_set_ci(add_oc(
- objectclasses.posixgroup,
- u'ipantgroupattrs',
- check_sidgen=True)),
- 'ipauniqueid': [fuzzy_uuid],
- }, check_sidgen=True),
- dict(
- dn=get_group_dn(group1),
- cn=[group1],
- description=[u'New desc 1'],
- gidnumber=[fuzzy_digits],
- objectclass=fuzzy_set_ci(objectclasses.posixgroup),
- ipauniqueid=[fuzzy_uuid],
- ),
- add_sid(dict(
- dn=get_group_dn(group2),
- cn=[group2],
- description=[u'New desc 2'],
- gidnumber=[fuzzy_digits],
- objectclass=fuzzy_set_ci(add_oc(
- objectclasses.posixgroup, u'ipantgroupattrs')),
- ipauniqueid=[fuzzy_uuid],
- )),
- ],
- ),
- ),
-
-
- ###############
- # test external SID members for group3:
- dict(
- desc='Create external %r' % group3,
- command=(
- 'group_add', [group3], dict(description=u'Test desc 3',external=True)
- ),
- expected=dict(
- value=group3,
- summary=u'Added group "testgroup3"',
- result=dict(
- cn=[group3],
- description=[u'Test desc 3'],
- objectclass=objectclasses.externalgroup,
- ipauniqueid=[fuzzy_uuid],
- dn=get_group_dn(group3),
- ),
- ),
- ),
-
- dict(
- desc='Search for external groups',
- command=('group_find', [], dict(external=True, all=True)),
- expected=dict(
- summary=u'1 group matched',
- count=1,
- truncated=False,
- result=[
- dict(
- cn=[group3],
- description=[u'Test desc 3'],
- objectclass=fuzzy_set_ci(objectclasses.externalgroup),
- ipauniqueid=[fuzzy_uuid],
- dn=get_group_dn(group3),
- ),
- ],
- ),
- ),
-
-
- dict(
- desc='Convert posix group %r to support external membership' % (group2),
- command=(
- 'group_mod', [group2], dict(external=True)
- ),
- expected=errors.PosixGroupViolation(),
- ),
-
-
- dict(
- desc='Convert external members group %r to posix' % (group3),
- command=(
- 'group_mod', [group3], dict(posix=True)
- ),
- expected=errors.ExternalGroupViolation(),
- ),
-
-
- dict(
- desc='Add external member %r to %r' % (external_sid1, group3),
- command=(
- 'group_add_member', [group3], dict(ipaexternalmember=external_sid1)
- ),
- expected=lambda x, output: (type(x) == errors.ValidationError
- or type(x) == errors.NotFound
- or 'failed' in output),
- ),
-
-
- dict(
- desc='Remove group %r with external membership' % (group3),
- command=('group_del', [group3], {}),
- expected=dict(
- result=dict(failed=[]),
- value=[group3],
- summary=u'Deleted group "testgroup3"',
- ),
- ),
-
-
- ###############
- # member stuff:
- dict(
- desc='Add member %r to %r' % (group2, group1),
- command=(
- 'group_add_member', [group1], dict(group=group2)
- ),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn(group1),
- 'member_group': (group2,),
- 'gidnumber': [fuzzy_digits],
- 'cn': [group1],
- 'description': [u'New desc 1'],
+class TestFindGroup(XMLRPC_test):
+ def test_search(self, group):
+ """ Search for a group """
+ group.ensure_exists()
+ group.find()
+
+ def test_search_for_all_groups(self, group, group2):
+ """ Search for all groups """
+ group.ensure_exists()
+ group2.create()
+ command = group.make_command('group_find')
+ result = command()
+ assert_deepequal(dict(
+ summary=u'6 groups matched',
+ count=6,
+ truncated=False,
+ result=[
+ {
+ 'dn': get_group_dn('admins'),
+ 'member_user': [u'admin'],
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [u'admins'],
+ 'description': [u'Account administrators group'],
+ },
+ {
+ 'dn': get_group_dn('editors'),
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [u'editors'],
+ 'description':
+ [u'Limited admins who can edit other users'],
},
- ),
- ),
-
- dict(
- # FIXME: Shouldn't this raise a NotFound instead?
- desc='Try to add non-existent member to %r' % group1,
- command=(
- 'group_add_member', [group1], dict(group=u'notfound')
- ),
- expected=dict(
- completed=0,
- failed=dict(
- member=dict(
- group=[(u'notfound', u'no such entry')],
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn(group1),
- 'member_group': (group2,),
- 'gidnumber': [fuzzy_digits],
- 'cn': [group1],
- 'description': [u'New desc 1'],
+ {
+ 'dn': get_group_dn('ipausers'),
+ 'cn': [u'ipausers'],
+ 'description': [u'Default group for all users'],
},
- ),
- ),
-
- dict(
- desc='Remove member %r from %r' % (group2, group1),
- command=('group_remove_member',
- [group1], dict(group=group2)
- ),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn(group1),
- 'cn': [group1],
+ {
+ 'dn': get_group_dn(group.cn),
+ 'cn': [group.cn],
+ 'description': [u'Test desc1'],
'gidnumber': [fuzzy_digits],
- 'description': [u'New desc 1'],
},
- ),
- ),
-
- dict(
- # FIXME: Shouldn't this raise a NotFound instead?
- desc='Try to remove non-existent member from %r' % group1,
- command=('group_remove_member',
- [group1], dict(group=u'notfound')
- ),
- expected=dict(
- completed=0,
- failed=dict(
- member=dict(
- group=[(u'notfound', u'This entry is not a member')],
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn(group1),
- 'cn': [group1],
+ {
+ 'dn': get_group_dn(group2.cn),
+ 'cn': [group2.cn],
+ 'description': [u'Test desc2'],
'gidnumber': [fuzzy_digits],
- 'description': [u'New desc 1'],
},
- ),
- ),
-
-
- dict(
- desc='Rename %r' % group1,
- command=('group_mod', [group1], dict(setattr=u'cn=%s' % renamedgroup1)),
- expected=dict(
- value=group1,
- result=dict(
- cn=[renamedgroup1],
- description=[u'New desc 1'],
- gidnumber=[fuzzy_digits],
- ),
- summary=u'Modified group "%s"' % group1
- )
- ),
-
-
- dict(
- desc='Rename %r back' % renamedgroup1,
- command=('group_mod', [renamedgroup1], dict(setattr=u'cn=%s' % group1)),
- expected=dict(
- value=renamedgroup1,
- result=dict(
- cn=[group1],
- description=[u'New desc 1'],
- gidnumber=[fuzzy_digits],
- ),
- summary=u'Modified group "%s"' % renamedgroup1
- )
- ),
-
-
-
- ################
- # delete group1:
- dict(
- desc='Delete %r' % group1,
- command=('group_del', [group1], {}),
- expected=dict(
- result=dict(failed=[]),
- value=[group1],
- summary=u'Deleted group "testgroup1"',
- )
- ),
-
-
- dict(
- desc='Try to delete non-existent %r' % group1,
- command=('group_del', [group1], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
- dict(
- desc='Try to retrieve non-existent %r' % group1,
- command=('group_show', [group1], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
- dict(
- desc='Try to update non-existent %r' % group1,
- command=('group_mod', [group1], dict(description=u'Foo')),
- expected=errors.NotFound(reason=u'%s: group not found' % group1),
- ),
-
-
-
- ################
- # delete group2:
- dict(
- desc='Delete %r' % group2,
- command=('group_del', [group2], {}),
- expected=dict(
- result=dict(failed=[]),
- value=[group2],
- summary=u'Deleted group "testgroup2"',
- )
- ),
-
-
- dict(
- desc='Try to delete non-existent %r' % group2,
- command=('group_del', [group2], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group2),
- ),
-
-
- dict(
- desc='Try to retrieve non-existent %r' % group2,
- command=('group_show', [group2], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % group2),
- ),
-
-
- dict(
- desc='Try to update non-existent %r' % group2,
- command=('group_mod', [group2], dict(description=u'Foo')),
- expected=errors.NotFound(reason=u'%s: group not found' % group2),
- ),
-
- dict(
- desc='Test an invalid group name %r' % invalidgroup1,
- command=('group_add', [invalidgroup1], dict(description=u'Test')),
- expected=errors.ValidationError(name='group_name',
- error=u'may only include letters, numbers, _, -, . and $'),
- ),
-
- # The assumption on these next 4 tests is that if we don't get a
- # validation error then the request was processed normally.
- dict(
- desc='Test that validation is disabled on mods',
- command=('group_mod', [invalidgroup1], {}),
- expected=errors.NotFound(
- reason=u'%s: group not found' % invalidgroup1),
- ),
-
-
- dict(
- desc='Test that validation is disabled on deletes',
- command=('group_del', [invalidgroup1], {}),
- expected=errors.NotFound(
- reason=u'%s: group not found' % invalidgroup1),
- ),
-
-
- dict(
- desc='Test that validation is disabled on show',
- command=('group_show', [invalidgroup1], {}),
- expected=errors.NotFound(
- reason=u'%s: group not found' % invalidgroup1),
- ),
-
-
- ##### managed entry tests
- dict(
- desc='Create %r' % user1,
- command=(
- 'user_add', [], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add'),
- ),
- ),
-
-
- dict(
- desc='Verify the managed group %r was created' % user1,
- command=('group_show', [user1], {}),
- expected=dict(
- value=user1,
- summary=None,
- result=dict(
- cn=[user1],
- description=[u'User private group for %s' % user1],
- gidnumber=[fuzzy_digits],
- dn=get_group_dn(user1),
- ),
- ),
- ),
-
-
- dict(
- desc='Verify that managed group %r can be found' % user1,
- command=('group_find', [], {'cn': user1, 'private': True}),
- expected=dict(
- count=1,
- truncated=False,
- result=[
- dict(
- dn=get_group_dn(user1),
- cn=[user1],
- description=[u'User private group for %s' % user1],
- gidnumber=[fuzzy_digits],
- ),
- ],
- summary=u'1 group matched',
- ),
- ),
-
-
- dict(
- desc='Try to delete a managed group %r' % user1,
- command=('group_del', [user1], {}),
- expected=errors.ManagedGroupError(),
- ),
-
-
- dict(
- desc='Detach managed group %r' % user1,
- command=('group_detach', [user1], {}),
- expected=dict(
- result=True,
- value=user1,
- summary=u'Detached group "%s" from user "%s"' % (user1, user1),
- ),
- ),
-
-
- dict(
- desc='Now delete the unmanaged group %r' % user1,
- command=('group_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- value=[user1],
- summary=u'Deleted group "%s"' % user1,
- )
- ),
-
- dict(
- desc='Verify that %r is really gone' % user1,
- command=('group_show', [user1], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % user1),
- ),
-
- dict(
- desc='Delete %r' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "tuser1"',
- value=[user1],
- ),
- ),
-
- dict(
- desc='Create %r without User Private Group' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1', noprivate=True, gidnumber=1000)
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "tuser1"',
- result=get_user_result(
- user1, u'Test', u'User1', 'add',
- description=[],
- objectclass=add_oc(objectclasses.user_base,
- u'ipantuserattrs'),
- gidnumber=[u'1000'],
- omit=['mepmanagedentry'],
- ),
- ),
- ),
-
- dict(
- desc='Verify the managed group %r was not created' % user1,
- command=('group_show', [user1], {}),
- expected=errors.NotFound(reason=u'%s: group not found' % user1),
- ),
-
- dict(
- desc='Try to remove the admin user from the admins group',
- command=('group_remove_member', [u'admins'], dict(user=[u'admin'])),
- expected=errors.LastMemberError(key=u'admin', label=u'group',
- container='admins'),
- ),
-
- dict(
- desc='Add %r to the admins group' % user1,
- command=('group_add_member', [u'admins'], dict(user=user1)),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn('admins'),
- 'member_user': [u'admin', user1],
- 'gidnumber': [fuzzy_digits],
- 'cn': [u'admins'],
- 'description': [u'Account administrators group'],
+ {
+ 'dn': get_group_dn('trust admins'),
+ 'member_user': [u'admin'],
+ 'cn': [u'trust admins'],
+ 'description': [u'Trusts administrators group'],
+ },
+ ]), result)
+
+ def test_search_for_all_posix(self, group, group2):
+ """ Search for all posix groups """
+ command = group.make_command(
+ 'group_find', **dict(posix=True, all=True)
+ )
+ result = command()
+ assert_deepequal(dict(
+ summary=u'4 groups matched',
+ count=4,
+ truncated=False,
+ result=[
+ {
+ 'dn': get_group_dn('admins'),
+ 'member_user': [u'admin'],
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [u'admins'],
+ 'description': [u'Account administrators group'],
+ 'objectclass': fuzzy_set_ci(add_oc(
+ objectclasses.posixgroup, u'ipantgroupattrs')),
+ 'ipauniqueid': [fuzzy_uuid],
+ },
+ {
+ 'dn': get_group_dn('editors'),
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [u'editors'],
+ 'description':
+ [u'Limited admins who can edit other users'],
+ 'objectclass': fuzzy_set_ci(add_oc(
+ objectclasses.posixgroup, u'ipantgroupattrs')),
+ 'ipauniqueid': [fuzzy_uuid],
},
- ),
- ),
-
- dict(
- desc='Try to remove admin and %r from the admins group' % user1,
- command=('group_remove_member', [u'admins'],
- dict(user=[u'admin', user1])),
- expected=errors.LastMemberError(key=u'admin', label=u'group',
- container='admins'),
- ),
-
- dict(
- desc='Try to delete the admins group',
- command=('group_del', [u'admins'], {}),
- expected=errors.ProtectedEntryError(label=u'group',
- key='admins', reason='privileged group'),
- ),
-
-
- dict(
- desc='Try to rename the admins group',
- command=('group_mod', [u'admins'], dict(rename=u'loosers')),
- expected=errors.ProtectedEntryError(label=u'group',
- key='admins', reason='Cannot be renamed'),
- ),
-
- dict(
- desc='Try to rename the admins group via setattr',
- command=('group_mod', [u'admins'], {'setattr': u'cn=loosers'}),
- expected=errors.ProtectedEntryError(label=u'group',
- key='admins', reason='Cannot be renamed'),
- ),
-
- dict(
- desc='Try to modify the admins group to support external membership',
- command=('group_mod', [u'admins'], dict(external=True)),
- expected=errors.ProtectedEntryError(label=u'group',
- key='admins', reason='Cannot support external non-IPA members'),
- ),
-
- dict(
- desc='Try to delete the trust admins group',
- command=('group_del', [u'trust admins'], {}),
- expected=errors.ProtectedEntryError(label=u'group',
- key='trust admins', reason='privileged group'),
- ),
-
- dict(
- desc='Try to rename the trust admins group',
- command=('group_mod', [u'trust admins'], dict(rename=u'loosers')),
- expected=errors.ProtectedEntryError(label=u'group',
- key='trust admins', reason='Cannot be renamed'),
- ),
-
- dict(
- desc='Try to rename the trust admins group via setattr',
- command=('group_mod', [u'trust admins'], {'setattr': u'cn=loosers'}),
- expected=errors.ProtectedEntryError(label=u'group',
- key='trust admins', reason='Cannot be renamed'),
- ),
-
-
- dict(
- desc='Try to modify the trust admins group to support external membership',
- command=('group_mod', [u'trust admins'], dict(external=True)),
- expected=errors.ProtectedEntryError(label=u'group',
- key='trust admins', reason='Cannot support external non-IPA members'),
- ),
-
- dict(
- desc='Delete %r' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
- ]
+ {
+ 'dn': get_group_dn(group.cn),
+ 'cn': [group.cn],
+ 'description': [u'Test desc1'],
+ 'gidnumber': [fuzzy_digits],
+ 'objectclass': fuzzy_set_ci(add_oc(
+ objectclasses.posixgroup, u'ipantgroupattrs')),
+ 'ipauniqueid': [fuzzy_uuid],
+ },
+ {
+ 'dn': get_group_dn(group2.cn),
+ 'cn': [group2.cn],
+ 'description': [u'Test desc2'],
+ 'gidnumber': [fuzzy_digits],
+ 'objectclass': fuzzy_set_ci(add_oc(
+ objectclasses.posixgroup, u'ipantgroupattrs')),
+ 'ipauniqueid': [fuzzy_uuid],
+ },
+ ]), result)
@pytest.mark.tier1
-class test_group_remove_group_from_protected_group(Declarative):
- cleanup_commands = [
- ('group_del', [group1], {}),
- ]
- tests = [
- # Test scenario from ticket #4448
- # https://fedorahosted.org/freeipa/ticket/4448
- dict(
- desc='Add group %s' % group1,
- command=('group_add', [group1], dict(description=u'Test desc 1')),
- expected=dict(
- value=group1,
- summary=u'Added group "%s"' % group1,
- result=dict(
- cn=[group1],
- description=[u'Test desc 1'],
- objectclass=objectclasses.posixgroup,
- gidnumber=[fuzzy_digits],
- ipauniqueid=[fuzzy_uuid],
- dn=get_group_dn(group1),
- ),
- ),
- ),
-
- dict(
- desc='Add %s group to admins group' % group1,
- command=('group_add_member', [u'admins'], dict(group=group1)),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result=dict(
- dn=get_group_dn('admins'),
- member_user=[u'admin'],
- member_group=[group1],
- gidnumber=[fuzzy_digits],
- cn=[u'admins'],
- description=[u'Account administrators group'],
- ),
- ),
- ),
-
- dict(
- desc='Remove %s group from admins group' % group1,
- command=('group_remove_member', [u'admins'], dict(group=group1)),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result=dict(
- dn=get_group_dn(u'admins'),
- cn=[u'admins'],
- gidnumber=[fuzzy_digits],
- member_user=[u'admin'],
- description=[u'Account administrators group'],
- ),
- ),
- ),
- ]
+class TestNonexistentGroup(XMLRPC_test):
+ def test_retrieve_nonexistent(self, group):
+ """ Try to retrieve a non-existent group """
+ group.ensure_missing()
+ command = group.make_retrieve_command()
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % group.cn)):
+ command()
+
+ def test_update_nonexistent(self, group):
+ """ Try to update a non-existent group """
+ group.ensure_missing()
+ command = group.make_update_command(
+ updates=dict(description=u'hey'))
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % group.cn)):
+ command()
+
+ def test_delete_nonexistent(self, group):
+ """ Try to delete a non-existent user """
+ group.ensure_missing()
+ command = group.make_delete_command()
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % group.cn)):
+ command()
+
+ def test_rename_nonexistent(self, group):
+ """ Try to rename a non-existent user """
+ group.ensure_missing()
+ command = group.make_update_command(
+ updates=dict(setattr=u'cn=%s' % renamedgroup1))
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % group.cn)):
+ command()
@pytest.mark.tier1
-class test_group_full_set_of_objectclass_not_available_post_detach(Declarative):
- # https://fedorahosted.org/freeipa/ticket/4909#comment:1
- cleanup_commands = [
- ('group_del', [user1], {}),
- ('user_del', [user1], {}),
- ]
-
- tests = [
- dict(
- desc='Create %r' % user1,
- command=(
- 'user_add', [], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add'),
- ),
- ),
-
- dict(
- desc='Detach managed group %r' % user1,
- command=('group_detach', [user1], {}),
- expected=dict(
- result=True,
- value=user1,
- summary=u'Detached group "%s" from user "%s"' % (user1, user1),
- ),
- ),
-
- dict(
- desc='Show group - check objectclass',
- command=('group_show', [user1], dict(all=True)),
- expected=dict(
- value=user1,
- result={
- 'cn':[user1],
- 'description': [u'User private group for tuser1'],
- 'gidnumber': [fuzzy_digits],
- 'dn': get_group_dn('tuser1'),
+class TestNonposixGroup(XMLRPC_test):
+ def test_create_nonposix(self, group):
+ """ Create a non-posix group """
+ group.track_create()
+ command = group.make_create_command(**dict(nonposix=True))
+ result = command()
+
+ del group.attrs['gidnumber']
+ group.attrs.update(objectclass=objectclasses.group)
+ group.check_create(result)
+
+ def test_create_duplicate_to_nonposix(self, group):
+ """ Try to create a duplicate non-posix group """
+ group.ensure_exists()
+ command = group.make_create_command()
+
+ with raises_exact(errors.DuplicateEntry(
+ message=u'group with name "%s" already exists' % group.cn)):
+ command()
+
+ def test_retrieve_nonposix(self, group):
+ """ Retrieve a non-posix group """
+ group.retrieve()
+
+ def test_update_nonposix(self, group):
+ """ Update a non-posix group with new description
+ and perform retrieve command to verify the update """
+ group.update(dict(description=u'New desc'))
+ group.retrieve()
+
+ def test_search_for_all_nonposix(self, group):
+ """ Perform a search for all non-posix groups """
+ command = group.make_command(
+ 'group_find', **dict(nonposix=True, all=True)
+ )
+ result = command()
+ assert_deepequal(dict(
+ summary=u'3 groups matched',
+ count=3,
+ truncated=False,
+ result=[
+ {
+ 'dn': get_group_dn('ipausers'),
+ 'cn': [u'ipausers'],
+ 'description': [u'Default group for all users'],
+ 'objectclass': fuzzy_set_ci(objectclasses.group),
+ 'ipauniqueid': [fuzzy_uuid],
+ },
+ {
+ 'dn': get_group_dn(group.cn),
+ 'cn': [group.cn],
+ 'description': [u'New desc'],
+ 'objectclass': fuzzy_set_ci(objectclasses.group),
+ 'ipauniqueid': [fuzzy_uuid],
+ },
+ {
+ 'dn': get_group_dn('trust admins'),
+ 'member_user': [u'admin'],
+ 'cn': [u'trust admins'],
+ 'description': [u'Trusts administrators group'],
+ 'objectclass': fuzzy_set_ci(objectclasses.group),
'ipauniqueid': [fuzzy_uuid],
- 'objectclass': objectclasses.posixgroup,
},
- summary=None,
- ),
- ),
-
- dict(
- desc='Add member back to the detached group',
- command=('group_add_member', [user1], dict(user=user1)),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn('tuser1'),
- 'member_user': [user1],
- 'gidnumber': [fuzzy_digits],
- 'cn': [user1],
- 'description': [u'User private group for tuser1'],
+ ],
+ ), result)
+
+ def test_upgrade_nonposix_to_posix(self, group):
+ """ Update non-posix group to promote it to posix group """
+ group.attrs.update(gidnumber=[fuzzy_digits])
+ group.update(dict(posix=True), dict(posix=None))
+ group.retrieve()
+
+ def test_search_for_all_nonposix_with_criteria(self, group):
+ """ Search for all non-posix groups with additional
+ criteria filter """
+ command = group.make_command(
+ 'group_find', *[u'users'], **dict(nonposix=True, all=True)
+ )
+ result = command()
+ assert_deepequal(dict(
+ summary=u'1 group matched',
+ count=1,
+ truncated=False,
+ result=[
+ {
+ 'dn': get_group_dn('ipausers'),
+ 'cn': [u'ipausers'],
+ 'description': [u'Default group for all users'],
+ 'objectclass': fuzzy_set_ci(objectclasses.group),
+ 'ipauniqueid': [fuzzy_uuid],
},
- ),
- ),
- ]
+ ],
+ ), result)
+
+
+@pytest.mark.tier1
+class TestExternalGroup(XMLRPC_test):
+ def test_create_external(self, group):
+ """ Create a non-posix group """
+ group.track_create()
+ del group.attrs['gidnumber']
+ group.attrs.update(objectclass=objectclasses.externalgroup)
+ command = group.make_create_command(**dict(external=True))
+ result = command()
+ group.check_create(result)
+
+ def test_search_for_external(self, group):
+ """ Search for all external groups """
+ command = group.make_command(
+ 'group_find', **dict(external=True, all=True)
+ )
+ result = command()
+ group.check_find(result, all=True)
+
+ def test_convert_external_to_posix(self, group):
+ """ Try to convert an external group to posix """
+ command = group.make_update_command(dict(posix=True))
+ with raises_exact(errors.ExternalGroupViolation(
+ reason=u'This group cannot be posix because it is external')):
+ command()
+
+ def test_add_external_member_to_external(self, group):
+ """ Try to add an invalid external member to an external
+ group and check that proper exceptions are raised """
+ # When adding external SID member to a group we can't test
+ # it fully due to possibly missing Samba 4 python bindings
+ # and/or not configured AD trusts. Thus, we'll use incorrect
+ # SID value to merely test that proper exceptions are raised
+ command = group.make_command('group_add_member', *[group.cn],
+ **dict(ipaexternalmember=external_sid1))
+ try:
+ command()
+ except Exception as ex:
+ if type(ex) == errors.ValidationError:
+ pass
+ elif type(ex) == errors.NotFound:
+ pass
+ elif 'failed' in str(ex):
+ pass
+ else:
+ raise ex
+
+ def test_delete_external_group(self, group):
+ group.delete()
+
+
+@pytest.mark.tier1
+class TestGroupMember(XMLRPC_test):
+ def test_add_nonexistent_member(self, group):
+ """ Try to add non-existent member to a group """
+ group.create()
+ command = group.make_add_member_command(dict(group=notagroup))
+ result = command()
+ group.check_add_member_negative(result, dict(group=notagroup))
+
+ def test_remove_nonexistent_member(self, group):
+ """ Try to remove non-existent member from a group """
+ group.ensure_exists()
+ command = group.make_remove_member_command(dict(group=notagroup))
+ result = command()
+ group.check_remove_member_negative(result, dict(group=notagroup))
+
+ def test_add_member(self, group, group2):
+ """ Add member group to a group """
+ group.ensure_exists()
+ group2.ensure_exists()
+ group.add_member(dict(group=group2.cn))
+
+ def test_remove_member(self, group, group2):
+ """ Remove a group member """
+ group.ensure_exists()
+ group2.ensure_exists()
+ group.remove_member(dict(group=group2.cn))
+
+ def test_add_and_remove_group_from_admins(self, group, admins):
+ """ Add group to protected admins group and then remove it """
+ # Test scenario from ticket #4448
+ # https://fedorahosted.org/freeipa/ticket/4448
+ group.ensure_exists()
+ admins.add_member(dict(group=group.cn))
+ admins.remove_member(dict(group=group.cn))
+
+
+@pytest.mark.tier1
+class TestValidation(XMLRPC_test):
+ # The assumption for this class of tests is that if we don't
+ # get a validation error then the request was processed normally.
+
+ def test_validation_disabled_on_delete(self, group):
+ """ Test that validation is disabled on group deletes """
+ command = group.make_command('group_del', invalidgroup1)
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % invalidgroup1)):
+ command()
+
+ def test_validation_disabled_on_show(self, group):
+ """ Test that validation is disabled on group retrieves """
+ command = group.make_command('group_show', invalidgroup1)
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % invalidgroup1)):
+ command()
+
+ def test_validation_disabled_on_mod(self, group):
+ """ Test that validation is disabled on group mods """
+ command = group.make_command('group_mod', invalidgroup1)
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % invalidgroup1)):
+ command()
+
+
+@pytest.mark.tier1
+class TestManagedGroups(XMLRPC_test):
+ def test_verify_managed_created(self, managed_group):
+ """ Verify that managed group is created with new user """
+ managed_group.retrieve()
+
+ def test_verify_managed_findable(self, managed_group):
+ """ Verify that managed group can be found """
+ command = managed_group.make_find_command(
+ **dict(cn=managed_group.cn, private=True)
+ )
+ result = command()
+ managed_group.check_find(result)
+
+ def test_delete_managed(self, managed_group):
+ """ Try to delete managed group """
+ command = managed_group.make_delete_command()
+ with raises_exact(errors.ManagedGroupError()):
+ command()
+
+ def test_detach_managed(self, managed_group):
+ """ Detach managed group from a user """
+ command = managed_group.make_detach_command()
+ result = command()
+ managed_group.check_detach(result)
+
+ def test_delete_detached_managed(self, managed_group, user):
+ """ Delete a previously managed group that is now detached
+ and verify it's really gone """
+ managed_group.delete()
+ command = managed_group.make_retrieve_command()
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % managed_group.cn)):
+ command()
+ user.ensure_missing()
+
+ def test_verify_managed_missing_for_user_without_upg(self, user_npg2):
+ """ Create a user without user private group and
+ verify private group wasn't created """
+ user_npg2.attrs.update(memberof_group=[u'ipausers'])
+ command = user_npg2.make_create_command()
+ result = command()
+ user_npg2.check_create(result, [u'description', u'memberof_group'])
+ command = user_npg2.make_command('group_show', *[user_npg2.uid])
+ with raises_exact(errors.NotFound(
+ reason=u'%s: group not found' % user_npg2.uid)):
+ command()
+
+
+@pytest.mark.tier1
+class TestManagedGroupObjectclasses(XMLRPC_test):
+ def test_check_objectclasses_after_detach(self, user, managed_group):
+ """ Check objectclasses after user was detached from managed group """
+ # https://fedorahosted.org/freeipa/ticket/4909#comment:1
+ user.create()
+ user.run_command('group_detach', *[user.uid])
+ managed_group.retrieve(all=True)
+ managed_group.add_member(dict(user=user.uid))
+ managed_group.ensure_missing()
+ user.ensure_missing()
+
+
+@pytest.mark.tier1
+class TestAdminGroup(XMLRPC_test):
+ def test_remove_admin_from_admins(self, admins):
+ """ Remove the original admin from admins group """
+ command = admins.make_remove_member_command(
+ dict(user=u'admin')
+ )
+ with raises_exact(errors.LastMemberError(
+ key=u'admin', label=u'group', container=admins.cn)):
+ command()
+
+ def test_add_another_admin(self, admins, user):
+ """ Add second member to the admins group """
+ user.ensure_exists()
+ admins.add_member(dict(user=user.uid))
+
+ def test_remove_all_admins_from_admins(self, admins, user):
+ """ Try to remove both original and our admin from admins group """
+ command = admins.make_remove_member_command(
+ dict(user=[u'admin', user.uid])
+ )
+ with raises_exact(errors.LastMemberError(
+ key=u'admin', label=u'group', container=admins.cn)):
+ command()
+
+ def test_delete_admins(self, admins):
+ """ Try to delete the protected admins group """
+ command = admins.make_delete_command()
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=admins.cn, reason='privileged group')):
+ command()
+
+ def test_rename_admins(self, admins):
+ """ Try to rename the protected admins group """
+ command = admins.make_command('group_mod', *[admins.cn],
+ **dict(rename=renamedgroup1))
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=admins.cn, reason='Cannot be renamed')):
+ command()
+
+ def test_rename_admins_using_setattr(self, admins):
+ """ Try to rename the protected admins group using setattr """
+ command = admins.make_command('group_mod', *[admins.cn],
+ **dict(setattr=u'cn=%s' % renamedgroup1))
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=admins.cn, reason='Cannot be renamed')):
+ command()
+
+ def test_update_admins_to_support_external_membership(self, admins):
+ """ Try to modify the admins group to support external membership """
+ command = admins.make_command('group_mod', *[admins.cn],
+ **dict(external=True))
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=admins.cn,
+ reason='Cannot support external non-IPA members')):
+ command()
+
+
+@pytest.mark.tier1
+class TestTrustAdminGroup(XMLRPC_test):
+ def test_delete_trust_admins(self, trustadmins):
+ """ Try to delete the protected 'trust admins' group """
+ command = trustadmins.make_delete_command()
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=trustadmins.cn, reason='privileged group')):
+ command()
+
+ def test_rename_trust_admins(self, trustadmins):
+ """ Try to rename the protected 'trust admins' group """
+ command = trustadmins.make_command('group_mod', *[trustadmins.cn],
+ **dict(rename=renamedgroup1))
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=trustadmins.cn, reason='Cannot be renamed')):
+ command()
+
+ def test_rename_trust_admins_using_setattr(self, trustadmins):
+ """ Try to rename the protected 'trust admins' group using setattr """
+ command = trustadmins.make_command(
+ 'group_mod', *[trustadmins.cn],
+ **dict(setattr=u'cn=%s' % renamedgroup1)
+ )
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=trustadmins.cn, reason='Cannot be renamed')):
+ command()
+
+ def test_update_trust_admins_to_support_external_membership(
+ self, trustadmins
+ ):
+ """ Try to modify the 'trust admins' group to
+ support external membership """
+ command = trustadmins.make_command(
+ 'group_mod', *[trustadmins.cn],
+ **dict(external=True)
+ )
+ with raises_exact(errors.ProtectedEntryError(label=u'group',
+ key=trustadmins.cn,
+ reason='Cannot support external non-IPA members')):
+ command()
diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py
index b6744eb8e..689682c9d 100644
--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py
+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py
@@ -634,9 +634,7 @@ class TestGroups(XMLRPC_test):
def test_remove_preserved_from_group(self, user, group):
user.ensure_exists()
group.ensure_exists()
- command = group.make_add_member_command(options={u'user': user.uid})
- result = command()
- group.check_add_member(result)
+ command = group.add_member(options={u'user': user.uid})
command = group.make_retrieve_command()
result = command()
diff --git a/ipatests/test_xmlrpc/tracker/group_plugin.py b/ipatests/test_xmlrpc/tracker/group_plugin.py
index c47ce8ecf..9f399cad5 100644
--- a/ipatests/test_xmlrpc/tracker/group_plugin.py
+++ b/ipatests/test_xmlrpc/tracker/group_plugin.py
@@ -12,7 +12,7 @@ from ipatests.util import assert_deepequal, get_group_dn
class GroupTracker(Tracker):
""" Class for host plugin like tests """
retrieve_keys = {u'dn', u'cn', u'gidnumber', u'member_user',
- u'member_group'}
+ u'member_group', u'description'}
retrieve_all_keys = retrieve_keys | {u'ipauniqueid', u'objectclass'}
create_keys = retrieve_all_keys
@@ -20,16 +20,19 @@ class GroupTracker(Tracker):
add_member_keys = retrieve_keys | {u'description'}
- def __init__(self, name):
+ def __init__(self, name, description=u'Group desc'):
super(GroupTracker, self).__init__(default_version=None)
self.cn = name
- self.dn = get_group_dn(name)
+ self.description = description
+ self.dn = get_group_dn(self.cn)
def make_create_command(self, nonposix=False, external=False,
- force=True):
+ force=True, *args, **kwargs):
""" Make function that creates a group using 'group-add' """
return self.make_command('group_add', self.cn,
- nonposix=nonposix, external=external)
+ description=self.description,
+ nonposix=nonposix, external=external,
+ *args, **kwargs)
def make_delete_command(self):
""" Make function that deletes a group using 'group-del' """
@@ -48,23 +51,12 @@ class GroupTracker(Tracker):
return self.make_command('group_mod', self.cn, **updates)
def make_add_member_command(self, options={}):
- """ Make function that adds a member to a group
- Attention: only works for one user OR group! """
- if u'user' in options:
- self.attrs[u'member_user'] = [options[u'user']]
- elif u'group' in options:
- self.attrs[u'member_group'] = [options[u'group']]
+ """ Make function that adds a member to a group """
self.adds = options
-
return self.make_command('group_add_member', self.cn, **options)
def make_remove_member_command(self, options={}):
- """ Make function that removes a member from a group
- Attention: only works for one user OR group! """
- if u'user' in options:
- del self.attrs[u'member_user']
- elif u'group' in options:
- del self.attrs[u'member_group']
+ """ Make function that removes a member from a group """
return self.make_command('group_remove_member', self.cn, **options)
def make_detach_command(self):
@@ -78,12 +70,85 @@ class GroupTracker(Tracker):
self.attrs = dict(
dn=get_group_dn(self.cn),
cn=[self.cn],
+ description=[self.description],
gidnumber=[fuzzy_digits],
ipauniqueid=[fuzzy_uuid],
objectclass=objectclasses.posixgroup,
)
self.exists = True
+ def update(self, updates, expected_updates=None):
+ """Helper function to update the group and check the result
+
+ Overriding Tracker method for setting self.attrs correctly;
+ * most attributes stores its value in list
+ * the rest can be overridden by expected_updates
+ * allow deleting parametrs if update value is None
+ """
+ if expected_updates is None:
+ expected_updates = {}
+
+ self.ensure_exists()
+ command = self.make_update_command(updates)
+ result = command()
+
+ for key, value in updates.items():
+ if value is None:
+ del self.attrs[key]
+ else:
+ self.attrs[key] = [value]
+ for key, value in expected_updates.items():
+ if value is None:
+ del self.attrs[key]
+ else:
+ self.attrs[key] = value
+
+ self.check_update(
+ result,
+ extra_keys=set(updates.keys()) | set(expected_updates.keys())
+ )
+
+ def add_member(self, options):
+ """ Add a member (group OR user) and performs check """
+ if u'user' in options:
+ try:
+ self.attrs[u'member_user'] =\
+ self.attrs[u'member_user'] + [options[u'user']]
+ except KeyError as ex:
+ self.attrs[u'member_user'] = [options[u'user']]
+ elif u'group' in options:
+ try:
+ self.attrs[u'member_group'] =\
+ self.attrs[u'member_group'] + [options[u'group']]
+ except KeyError as ex:
+ self.attrs[u'member_group'] = [options[u'group']]
+
+ command = self.make_add_member_command(options)
+ result = command()
+ self.check_add_member(result)
+
+ def remove_member(self, options):
+ """ Remove a member (group OR user) and performs check """
+ if u'user' in options:
+ self.attrs[u'member_user'].remove(options[u'user'])
+ elif u'group' in options:
+ self.attrs[u'member_group'].remove(options[u'group'])
+
+ try:
+ if not self.attrs[u'member_user']:
+ del self.attrs[u'member_user']
+ except KeyError as ex:
+ pass
+ try:
+ if not self.attrs[u'member_group']:
+ del self.attrs[u'member_group']
+ except KeyError as ex:
+ pass
+
+ command = self.make_remove_member_command(options)
+ result = command()
+ self.check_remove_member(result)
+
def check_create(self, result):
""" Checks 'group_add' command result """
assert_deepequal(dict(
@@ -143,35 +208,48 @@ class GroupTracker(Tracker):
result=self.filter_attrs(self.add_member_keys)
), result)
- def check_add_member_negative(self, result):
- """ Checks 'group_add_member' command result when expected result
- is failure of the operation"""
- if u'member_user' in self.attrs:
- del self.attrs[u'member_user']
- elif u'member_group' in self.attrs:
- del self.attrs[u'member_group']
+ def check_add_member_negative(self, result, options={}):
+ """ Checks 'group_add_member' command result
+ when expected result is failure of the operation"""
+ expected = dict(
+ completed=0,
+ failed={u'member': {u'group': (), u'user': ()}},
+ result=self.filter_attrs(self.add_member_keys)
+ )
+ if not options:
+ try:
+ options = self.adds
+ except NameError:
+ pass
+ if u'user' in options:
+ expected[u'failed'][u'member'][u'user'] = [(
+ options[u'user'], u'no such entry')]
+ elif u'group' in options:
+ expected[u'failed'][u'member'][u'group'] = [(
+ options[u'group'], u'no such entry')]
+
+ assert_deepequal(expected, result)
+ def check_remove_member_negative(self, result, options):
+ """ Checks 'group_remove_member' command result
+ when expected result is failure of the operation"""
expected = dict(
completed=0,
failed={u'member': {u'group': (), u'user': ()}},
result=self.filter_attrs(self.add_member_keys)
)
- if u'user' in self.adds:
+ if u'user' in options:
expected[u'failed'][u'member'][u'user'] = [(
- self.adds[u'user'], u'no such entry')]
- elif u'group' in self.adds:
+ options[u'user'], u'This entry is not a member')]
+ elif u'group' in options:
expected[u'failed'][u'member'][u'group'] = [(
- self.adds[u'group'], u'no such entry')]
+ options[u'group'], u'This entry is not a member')]
assert_deepequal(expected, result)
def check_remove_member(self, result):
""" Checks 'group_remove_member' command result """
- assert_deepequal(dict(
- completed=1,
- failed={u'member': {u'group': (), u'user': ()}},
- result=self.filter_attrs(self.add_member_keys)
- ), result)
+ self.check_add_member(result)
def check_detach(self, result):
""" Checks 'group_detach' command result """
@@ -181,16 +259,3 @@ class GroupTracker(Tracker):
self.cn, self.cn),
result=True
), result)
-
- def make_fixture_detach(self, request):
- """Make a pytest fixture for this tracker
-
- The fixture ensures the plugin entry does not exist before
- and after the tests that use itself.
- """
- def cleanup():
- pass
-
- request.addfinalizer(cleanup)
-
- return self