freeipa/ipatests/test_xmlrpc/test_group_plugin.py
Milan Kubik 0a64e9bd70 Applied tier0 and tier1 marks on unit tests and xmlrpc tests
Web UI tests were marked as tier1 tests.

The tier system is intended to be used together with CI system
to make sure the more complicated tests are being run only
when all of the basic functionality is working.

The system is using pytest's marker system. E.g. an invocation of
all tier1 tests with listing will look like:

    $ py.test -v -m tier1 ipatests

or in case of out of tree tests:

    $ ipa-run-tests -m tier1

Reviewed-By: Ales 'alich' Marecek <amarecek@redhat.com>
2015-11-09 11:49:17 +01:00

1351 lines
44 KiB
Python

# Authors:
# Rob Crittenden <rcritten@redhat.com>
# Pavel Zuna <pzuna@redhat.com>
#
# Copyright (C) 2008 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Test the `ipalib/plugins/group.py` module.
"""
import functools
import pytest
from ipalib import api, errors
from ipatests.test_xmlrpc import objectclasses
from xmlrpc_test import (Declarative, fuzzy_digits, fuzzy_uuid, fuzzy_set_ci,
add_sid, add_oc, XMLRPC_test, raises_exact)
from ipapython.dn import DN
from ipatests.test_xmlrpc.test_user_plugin import get_user_result
from ipatests.test_xmlrpc.ldaptracker import Tracker
from ipatests.test_xmlrpc.test_user_plugin import UserTracker
from ipatests.util import assert_deepequal
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 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'],
},
),
),
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'],
},
),
),
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],
'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],
'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'],
},
),
),
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],
),
),
]
@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'],
),
),
),
]
@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'),
'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'],
},
),
),
]
class GroupTracker(Tracker):
""" Class for host plugin like tests """
retrieve_keys = {u'dn', u'cn', u'gidnumber', u'member_user',
u'member_group'}
retrieve_all_keys = retrieve_keys | {u'ipauniqueid', u'objectclass'}
create_keys = retrieve_all_keys
update_keys = retrieve_keys - {u'dn'}
add_member_keys = retrieve_keys | {u'description'}
def __init__(self, name):
super(GroupTracker, self).__init__(default_version=None)
self.cn = name
self.dn = get_group_dn(name)
def make_create_command(self, nonposix=False, external=False,
force=True):
""" Make function that creates a group using 'group-add' """
return self.make_command('group_add', self.cn,
nonposix=nonposix, external=external)
def make_delete_command(self):
""" Make function that deletes a group using 'group-del' """
return self.make_command('group_del', self.cn)
def make_retrieve_command(self, all=False, raw=False):
""" Make function that retrieves a group using 'group-show' """
return self.make_command('group_show', self.cn, all=all)
def make_find_command(self, *args, **kwargs):
""" Make function that searches for a group using 'group-find' """
return self.make_command('group_find', *args, **kwargs)
def make_update_command(self, updates):
""" Make function that updates a group using 'group-mod' """
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']]
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']
return self.make_command('group_remove_member', self.cn, **options)
def make_detach_command(self):
""" Make function that detaches a managed group using
'group-detach' """
self.exists = True
return self.make_command('group_detach', self.cn)
def track_create(self):
""" Updates expected state for group creation"""
self.attrs = dict(
dn=get_group_dn(self.cn),
cn=[self.cn],
gidnumber=[fuzzy_digits],
ipauniqueid=[fuzzy_uuid],
objectclass=objectclasses.posixgroup,
)
self.exists = True
def check_create(self, result):
""" Checks 'group_add' command result """
assert_deepequal(dict(
value=self.cn,
summary=u'Added group "%s"' % self.cn,
result=self.filter_attrs(self.create_keys)
), result)
def check_delete(self, result):
""" Checks 'group_del' command result """
assert_deepequal(dict(
value=[self.cn],
summary=u'Deleted group "%s"' % self.cn,
result=dict(failed=[]),
), result)
def check_retrieve(self, result, all=False, raw=False):
""" Checks 'group_show' command result """
if all:
expected = self.filter_attrs(self.retrieve_all_keys)
else:
expected = self.filter_attrs(self.retrieve_keys)
assert_deepequal(dict(
value=self.cn,
summary=None,
result=expected
), result)
def check_find(self, result, all=False, raw=False):
""" Checks 'group_find' command result """
if all:
expected = self.filter_attrs(self.retrieve_all_keys)
else:
expected = self.filter_attrs(self.retrieve_keys)
assert_deepequal(dict(
count=1,
truncated=False,
summary=u'1 group matched',
result=[expected],
), result)
def check_update(self, result, extra_keys={}):
""" Checks 'group_mod' command result """
assert_deepequal(dict(
value=self.cn,
summary=u'Modified group "%s"' % self.cn,
result=self.filter_attrs(self.update_keys | set(extra_keys))
), result)
def check_add_member(self, result):
""" Checks 'group_add_member' command result """
assert_deepequal(dict(
completed=1,
failed={u'member': {u'group': (), u'user': ()}},
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']
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:
expected[u'failed'][u'member'][u'user'] = [(
self.adds[u'user'], u'no such entry')]
elif u'group' in self.adds:
expected[u'failed'][u'member'][u'group'] = [(
self.adds[u'group'], u'no such entry')]
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)
def check_detach(self, result):
""" Checks 'group_detach' command result """
assert_deepequal(dict(
value=self.cn,
summary=u'Detached group "%s" from user "%s"' % (
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