Populate indirect members when showing a group object.

This is done by creating a new attribute, memberindirect, to hold this
indirect membership.

The new function get_members() can return all members or just indirect or
direct. We are only using it to retrieve indirect members currently.

This also:
* Moves all member display attributes into baseldap.py to reduce duplication
* Adds netgroup nesting
* Use a unique object name in hbacsvc and hbacsvcgroup

ticket 296
This commit is contained in:
Rob Crittenden 2010-10-04 17:45:40 -04:00 committed by Simo Sorce
parent 47629a604d
commit c25d62965a
15 changed files with 557 additions and 138 deletions

View File

@ -32,6 +32,93 @@ from ipalib import output
from ipalib.text import _
from ipalib.util import json_serialize
global_output_params = (
Str('member',
label=_('Failed members'),
),
Str('member_user?',
label=_('Member users'),
),
Str('member_group?',
label=_('Member groups'),
),
Str('member_host?',
label=_('Member hosts'),
),
Str('memberof_hostgroup?',
label=_('Member of host-groups'),
),
Str('memberof_taskgroup?',
label=_('Member of task-groups'),
),
Str('member_rolegroup?',
label=_('Member role-groups'),
),
Str('member_netgroup?',
label=_('Member netgroups'),
),
Str('memberof_netgroup?',
label=_('Member of netgroups'),
),
Str('member_service?',
label=_('Member services'),
),
Str('member_servicegroup?',
label=_('Member service groups'),
),
Str('memberof_servicegroup?',
label='Member of service groups',
),
Str('member_hbacsvcgroup?',
label=_('Member HBAC service groups'),
),
Str('memberof_hbacsvcgroup?',
label='Member of HBAC service groups',
),
Str('member_sudocmdgroup?',
label='Member SUDO command groups',
),
Str('member_sudocmd?',
label='Member SUDO commands',
),
Str('memberindirect_user?',
label=_('Indirect Member users'),
),
Str('memberindirect_group?',
label=_('Indirect Member groups'),
),
Str('memberindirect_host?',
label=_('Indirect Member hosts'),
),
Str('memberindirect_hostgroup?',
label=_('Indirect Member host-groups'),
),
Str('memberindirect_rolegroup?',
label=_('Indirect Member role-groups'),
),
Str('memberindirect_taskgroup?',
label=_('Indirect Member role-groups'),
),
Str('memberindirect_hbacsvc?',
label=_('Indirect Member HBAC service'),
),
Str('memberindirect_hbacsvcgrp?',
label=_('Indirect Member HBAC service group'),
),
Str('memberindirect_netgroup?',
label=_('Indirect Member netgroups'),
),
Str('memberindirect_sudocmdgroup?',
label='Indirect Member SUDO command groups',
),
Str('memberindirect_sudocmd?',
label='Indirect Member SUDO commands',
),
Str('externalhost?',
label=_('External host'),
),
)
def validate_add_attribute(ugettext, attr):
validate_attribute(ugettext, 'addattr', attr)
@ -273,6 +360,8 @@ class LDAPCreate(CallbackInterface, crud.Create):
for arg in super(crud.Create, self).get_args():
yield arg
has_output_params = global_output_params
def execute(self, *keys, **options):
ldap = self.obj.backend
@ -425,6 +514,7 @@ class LDAPRetrieve(LDAPQuery):
Retrieve an LDAP entry.
"""
has_output = output.standard_entry
has_output_params = global_output_params
takes_options = (
Flag('rights',
@ -502,6 +592,8 @@ class LDAPUpdate(LDAPQuery, crud.Update):
takes_options = _attr_options
has_output_params = global_output_params
def execute(self, *keys, **options):
ldap = self.obj.backend
@ -630,6 +722,8 @@ class LDAPDelete(LDAPMultiQuery):
"""
has_output = output.standard_delete
has_output_params = global_output_params
def execute(self, *keys, **options):
ldap = self.obj.backend
@ -765,11 +859,7 @@ class LDAPAddMember(LDAPModMember):
),
)
has_output_params = (
Str('member',
label=_('Failed members'),
),
)
has_output_params = global_output_params
def execute(self, *keys, **options):
ldap = self.obj.backend
@ -870,11 +960,7 @@ class LDAPRemoveMember(LDAPModMember):
),
)
has_output_params = (
Str('member',
label=_('Failed members'),
),
)
has_output_params = global_output_params
def execute(self, *keys, **options):
ldap = self.obj.backend
@ -989,6 +1075,8 @@ class LDAPSearch(CallbackInterface, crud.Search):
for option in super(LDAPSearch, self).get_options():
yield option
has_output_params = global_output_params
def execute(self, *args, **options):
ldap = self.obj.backend

View File

@ -83,12 +83,14 @@ class group(LDAPObject):
object_class_config = 'ipagroupobjectclasses'
search_attributes_config = 'ipagroupsearchfields'
default_attributes = [
'cn', 'description', 'gidnumber', 'member', 'memberof'
'cn', 'description', 'gidnumber', 'member', 'memberof',
'memberindirect',
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
'member': ['user', 'group'],
'memberof': ['group', 'netgroup', 'rolegroup', 'taskgroup'],
'memberindirect': ['user', 'group', 'netgroup', 'rolegroup', 'taskgroup'],
}
rdnattr = 'cn'
@ -114,14 +116,6 @@ class group(LDAPObject):
label=_('GID'),
doc=_('GID (use this option to set it manually)'),
),
Str('member_group?',
label=_('Member groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('member_user?',
label=_('Member users'),
flags=['no_create', 'no_update', 'no_search'],
),
)
api.register(group)

View File

@ -51,10 +51,10 @@ class hbacsvc(LDAPObject):
HBAC Service object.
"""
container_dn = api.env.container_hbacservice
object_name = 'service'
object_name_plural = 'services'
object_name = 'hbacsvc'
object_name_plural = 'hbacsvcs'
object_class = [ 'ipaobject', 'ipahbacservice' ]
default_attributes = ['cn', 'description']
default_attributes = ['cn', 'description', 'memberindirect',]
uuid_attribute = 'ipauniqueid'
label = _('Services')

View File

@ -53,14 +53,17 @@ class hbacsvcgroup(LDAPObject):
HBAC service group object.
"""
container_dn = api.env.container_hbacservicegroup
object_name = 'servicegroup'
object_name_plural = 'servicegroups'
object_name = 'hbacsvcgroup'
object_name_plural = 'hbacsvcgroups'
object_class = ['ipaobject', 'ipahbacservicegroup']
default_attributes = [ 'cn', 'description', 'member', 'memberof', ]
default_attributes = [ 'cn', 'description', 'member', 'memberof',
'memberindirect',
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
'member': ['hbacsvc', 'hbacsvcgroup'],
'memberof': ['hbacsvcgroup'],
'memberindirect': ['hbacsvc', 'hbacsvcgroup'],
}
label = _('HBAC Service Groups')
@ -77,18 +80,6 @@ class hbacsvcgroup(LDAPObject):
label=_('Description'),
doc=_('HBAC service group description'),
),
Str('member_service?',
label=_('Member services'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('member_servicegroup?',
label=_('Member service groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_servicegroup?',
label='Member of service groups',
flags=['no_create', 'no_update', 'no_search'],
),
)
api.register(hbacsvcgroup)

View File

@ -159,18 +159,6 @@ class host(LDAPObject):
label=_('Principal name'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_hostgroup?',
label=_('Member of host-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_netgroup?',
label=_('Member of net-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_rolegroup?',
label=_('Member of role-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
)
def get_dn(self, *keys, **options):

View File

@ -59,11 +59,14 @@ class hostgroup(LDAPObject):
object_name = 'hostgroup'
object_name_plural = 'hostgroups'
object_class = ['ipaobject', 'ipahostgroup']
default_attributes = ['cn', 'description', 'member', 'memberof']
default_attributes = ['cn', 'description', 'member', 'memberof',
'memberindirect'
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
'member': ['host', 'hostgroup'],
'memberof': ['hostgroup'],
'memberindirect': ['host', 'hostgroup'],
}
label = _('Host Groups')
@ -81,18 +84,6 @@ class hostgroup(LDAPObject):
label=_('Description'),
doc=_('A description of this host-group'),
),
Str('member_host?',
label=_('Member hosts'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('member_hostgroup?',
label=_('Member host-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_hostgroup?',
label=_('Member of host-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
)
api.register(hostgroup)

View File

@ -46,23 +46,6 @@ from ipalib.plugins.baseldap import *
from ipalib import _, ngettext
output_params = (
Str('memberuser_user?',
label='Member User',
),
Str('memberuser_group?',
label='Member Group',
),
Str('memberhost_host?',
label=_('Member Host'),
),
Str('memberhost_hostgroup?',
label='Member Hostgroup',
),
Str('externalhost?',
label=_('External host'),
),
)
class netgroup(LDAPObject):
"""
Netgroup object.
@ -72,13 +55,15 @@ class netgroup(LDAPObject):
object_name_plural = 'netgroups'
object_class = ['ipaobject', 'ipaassociation', 'ipanisnetgroup']
default_attributes = [
'cn', 'description', 'memberof', 'externalhost',
'nisdomainname', 'memberuser', 'memberhost',
'cn', 'description', 'memberof', 'externalhost', 'nisdomainname',
'memberuser', 'memberhost','member', 'memberindirect',
]
uuid_attribute = 'ipauniqueid'
rdn_attribute = 'ipauniqueid'
attribute_members = {
'member': ['netgroup'],
'memberof': ['netgroup'],
'memberindirect': ['netgroup'],
'memberuser': ['user', 'group'],
'memberhost': ['host', 'hostgroup'],
}
@ -116,7 +101,6 @@ class netgroup_add(LDAPCreate):
"""
Add a new netgroup.
"""
has_output_params = output_params
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
entry_attrs.setdefault('nisdomainname', self.api.env.domain)
return dn
@ -128,6 +112,7 @@ class netgroup_del(LDAPDelete):
"""
Delete a netgroup.
"""
msg_summary = _('Deleted netgroup "%(value)s"')
api.register(netgroup_del)
@ -136,7 +121,6 @@ class netgroup_mod(LDAPUpdate):
"""
Modify a netgroup.
"""
has_output_params = output_params
api.register(netgroup_mod)
@ -145,7 +129,6 @@ class netgroup_find(LDAPSearch):
"""
Search for a netgroup.
"""
has_output_params = output_params
api.register(netgroup_find)
@ -154,7 +137,6 @@ class netgroup_show(LDAPRetrieve):
"""
Display information about a netgroup.
"""
has_output_params = output_params
api.register(netgroup_show)
@ -163,8 +145,7 @@ class netgroup_add_member(LDAPAddMember):
"""
Add members to a netgroup.
"""
has_output_params = LDAPAddMember.has_output_params + output_params
member_attributes = ['memberuser', 'memberhost']
member_attributes = ['memberuser', 'memberhost', 'member']
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
completed_external = 0
# Sift through the host failures. We assume that these are all
@ -199,7 +180,6 @@ class netgroup_remove_member(LDAPRemoveMember):
"""
Remove members from a netgroup.
"""
has_output_params = LDAPRemoveMember.has_output_params + output_params
member_attributes = ['memberuser', 'memberhost']
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
# Run through the host failures and gracefully remove any defined as

View File

@ -70,10 +70,13 @@ class rolegroup(LDAPObject):
object_name = 'rolegroup'
object_name_plural = 'rolegroups'
object_class = ['groupofnames', 'nestedgroup']
default_attributes = ['cn', 'description', 'member', 'memberof']
default_attributes = ['cn', 'description', 'member', 'memberof',
'memberindirect'
]
attribute_members = {
'member': ['user', 'group', 'host', 'hostgroup'],
'memberof': ['taskgroup'],
'memberindirect': ['user', 'group', 'host', 'hostgroup'],
}
rdnattr='cn'
@ -91,18 +94,6 @@ class rolegroup(LDAPObject):
label=_('Description'),
doc=_('A description of this role-group'),
),
Str('member_group?',
label=_('Member groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('member_user?',
label=_('Member users'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_taskgroup?',
label=_('Member of task-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
)
api.register(rolegroup)

View File

@ -55,12 +55,13 @@ class sudocmdgroup(LDAPObject):
object_name_plural = 'sudocmdgroups'
object_class = ['ipaobject', 'ipasudocmdgrp']
default_attributes = [
'cn', 'description', 'member', 'memberof'
'cn', 'description', 'member', 'memberof', 'memberindirect',
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
'member': ['sudocmd', 'sudocmdgroup'],
'memberof': ['sudocmdgroup'],
'memberindirect': ['sudocmd', 'sudocmdgroup'],
}
label = _('Sudo Command Groups')

View File

@ -33,7 +33,6 @@ from ipalib.plugins.baseldap import *
from ipalib import api, _, ngettext
class taskgroup(LDAPObject):
"""
Taskgroup object.
@ -42,9 +41,12 @@ class taskgroup(LDAPObject):
object_name = 'taskgroup'
object_name_plural = 'taskgroups'
object_class = ['groupofnames']
default_attributes = ['cn', 'description', 'member', 'memberof']
default_attributes = ['cn', 'description', 'member', 'memberof',
'memberindirect'
]
attribute_members = {
'member': ['user', 'group', 'rolegroup'],
'memberindirect': ['user', 'group', 'rolegroup'],
# FIXME: taskgroup can be member of ???
}
rdnattr='cn'
@ -63,18 +65,6 @@ class taskgroup(LDAPObject):
label=_('Description'),
doc=_('Task-group description'),
),
Str('member_group?',
label=_('Member groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('member_user?',
label=_('Member users'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('member_rolegroup?',
label=_('Member role-groups'),
flags=['no_create', 'no_update', 'no_search'],
),
)
api.register(taskgroup)

View File

@ -139,22 +139,6 @@ class user(LDAPObject):
cli_name='street',
label=_('Street address'),
),
Str('memberof_group?',
label=_('Groups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_netgroup?',
label=_('Netgroups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_rolegroup?',
label=_('Rolegroups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('memberof_taskgroup?',
label=_('Taskgroups'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('telephonenumber*',
cli_name='phone',
label=_('Telephone Number') ),

View File

@ -49,6 +49,11 @@ from ipalib.encoder import Encoder, encode_args, decode_retval
from ipalib.request import context
# Group Member types
MEMBERS_ALL = 0
MEMBERS_DIRECT = 1
MEMBERS_INDIRECT = 2
# SASL authentication mechanism
SASL_AUTH = _ldap_sasl.sasl({}, 'GSSAPI')
@ -543,6 +548,13 @@ class ldap2(CrudBackend, Encoder):
if not res:
raise errors.NotFound(reason='no such entry')
if attrs_list and ('memberindirect' in attrs_list or '*' in attrs_list):
for r in res:
indirect = self.get_members(r[0], membertype=MEMBERS_INDIRECT,
time_limit=time_limit, size_limit=size_limit, normalize=normalize)
if len(indirect) > 0:
r[1]['memberindirect'] = indirect
return (res, truncated)
def find_entry_by_attr(self, attr, value, object_class, attrs_list=None,
@ -814,6 +826,65 @@ class ldap2(CrudBackend, Encoder):
# update group entry
self.update_entry(group_dn, group_entry_attrs)
def get_members(self, group_dn, attr_list=[], membertype=MEMBERS_ALL, time_limit=None, size_limit=None, normalize=True):
"""Do a memberOf search of groupdn and return the attributes in
attr_list (an empty list returns all attributes).
membertype = MEMBERS_ALL all members returned
membertype = MEMBERS_DIRECT only direct members are returned
membertype = MEMBERS_INDIRECT only inherited members are returned
Members may be included in a group as a result of being a member
of a group that is a member of the group being queried.
Returns a list of DNs.
"""
if membertype not in [MEMBERS_ALL, MEMBERS_DIRECT, MEMBERS_INDIRECT]:
return None
searchfilter = "(memberof=%s)" % group_dn
attr_list.append("member")
# We have to do two searches because netgroups are not within the
# accounts container.
try:
(results, truncated) = self.find_entries(searchfilter, attr_list,
api.env.container_accounts, time_limit=time_limit, size_limit = size_limit, normalize=normalize)
except errors.NotFound:
results = []
try:
(netresults, truncated) = self.find_entries(searchfilter, attr_list,
api.env.container_netgroup, time_limit=time_limit, size_limit = size_limit, normalize=normalize)
except errors.NotFound:
netresults = []
results = results + netresults
if membertype == MEMBERS_ALL:
entries = []
for e in results:
entries.append(e[0])
return entries
(dn, group) = self.get_entry(group_dn, ['dn', 'member'])
real_members = group.get('member')
if isinstance(real_members, basestring):
real_members = [real_members]
if real_members is None:
real_members = []
entries = []
for e in results:
if unicode(e[0]) not in real_members:
if membertype == MEMBERS_INDIRECT:
entries.append(e[0])
else:
if membertype == MEMBERS_DIRECT:
entries.append(e[0])
return entries
def set_entry_active(self, dn, active):
"""Mark entry active/inactive."""
assert isinstance(active, bool)

View File

@ -267,7 +267,7 @@ class test_hbac(XMLRPC_test):
assert 'hbacsvc' in failed['memberservice']
assert not failed['memberservice']['hbacsvc']
entry = ret['result']
assert_attr_equal(entry, 'memberservice_service', self.test_service)
assert_attr_equal(entry, 'memberservice_hbacsvc', self.test_service)
def test_a_hbac_remove_service(self):
"""

View File

@ -130,7 +130,7 @@ class test_hbacsvcgroup(Declarative):
'dn': dn1,
'cn': [hbacsvcgroup1],
'description': [u'Test hbacsvcgroup 1'],
'member_service': [hbacsvc1],
'member_hbacsvc': [hbacsvc1],
},
),
),
@ -144,7 +144,7 @@ class test_hbacsvcgroup(Declarative):
summary=None,
result={
'dn': dn1,
'member_service': [hbacsvc1],
'member_hbacsvc': [hbacsvc1],
'cn': [hbacsvcgroup1],
'description': [u'Test hbacsvcgroup 1'],
},
@ -162,7 +162,7 @@ class test_hbacsvcgroup(Declarative):
result=[
{
'dn': dn1,
'member_service': [hbacsvc1],
'member_hbacsvc': [hbacsvc1],
'cn': [hbacsvcgroup1],
'description': [u'Test hbacsvcgroup 1'],
},
@ -182,7 +182,7 @@ class test_hbacsvcgroup(Declarative):
result=dict(
cn=[hbacsvcgroup1],
description=[u'Updated hbacsvcgroup 1'],
member_service=[hbacsvc1],
member_hbacsvc=[hbacsvc1],
),
),
),
@ -196,7 +196,7 @@ class test_hbacsvcgroup(Declarative):
summary=None,
result={
'dn': dn1,
'member_service': [hbacsvc1],
'member_hbacsvc': [hbacsvc1],
'cn': [hbacsvcgroup1],
'description': [u'Updated hbacsvcgroup 1'],
},

View File

@ -0,0 +1,350 @@
# Authors:
# Rob Crittenden <rcritten@redhat.com>
#
# Copyright (C) 2010 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; version 2 only
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
Test group nexting an indirect members
"""
from ipalib import api, errors
from tests.test_xmlrpc import objectclasses
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
group1 = u'testgroup1'
group2 = u'testgroup2'
group3 = u'testgroup3'
user1 = u'tuser1'
user2 = u'tuser2'
class test_group(Declarative):
cleanup_commands = [
('group_del', [group1], {}),
('group_del', [group2], {}),
('group_del', [group3], {}),
('user_del', [user1], {}),
('user_del', [user2], {}),
]
tests = [
################
# create group1:
dict(
desc='Create %r' % group1,
command=(
'group_add', [group1], dict(description=u'Test desc 1')
),
expected=dict(
value=group1,
summary=u'Added group "testgroup1"',
result=dict(
cn=[group1],
description=[u'Test desc 1'],
objectclass=objectclasses.group + [u'posixgroup'],
ipauniqueid=[fuzzy_uuid],
gidnumber=[fuzzy_digits],
dn=u'cn=testgroup1,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
################
# create 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.group + [u'posixgroup'],
ipauniqueid=[fuzzy_uuid],
dn=u'cn=testgroup2,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Create %r' % group3,
command=(
'group_add', [group3], dict(description=u'Test desc 3')
),
expected=dict(
value=group3,
summary=u'Added group "testgroup3"',
result=dict(
cn=[group3],
description=[u'Test desc 3'],
gidnumber=[fuzzy_digits],
objectclass=objectclasses.group + [u'posixgroup'],
ipauniqueid=[fuzzy_uuid],
dn=u'cn=testgroup3,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Create %r' % user1,
command=(
'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
),
expected=dict(
value=user1,
summary=u'Added user "%s"' % user1,
result=dict(
gecos=[user1],
givenname=[u'Test'],
homedirectory=[u'/home/tuser1'],
krbprincipalname=[u'tuser1@' + api.env.realm],
loginshell=[u'/bin/sh'],
objectclass=objectclasses.user,
sn=[u'User1'],
uid=[user1],
uidnumber=[fuzzy_digits],
ipauniqueid=[fuzzy_uuid],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user1, api.env.basedn)
),
),
),
dict(
desc='Create %r' % user2,
command=(
'user_add', [user2], dict(givenname=u'Test', sn=u'User2')
),
expected=dict(
value=user2,
summary=u'Added user "%s"' % user2,
result=dict(
gecos=[user2],
givenname=[u'Test'],
homedirectory=[u'/home/tuser2'],
krbprincipalname=[u'tuser2@' + api.env.realm],
loginshell=[u'/bin/sh'],
objectclass=objectclasses.user,
sn=[u'User2'],
uid=[user2],
uidnumber=[fuzzy_digits],
ipauniqueid=[fuzzy_uuid],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user2, api.env.basedn)
),
),
),
###############
# member stuff
#
# Create 3 groups and 2 users and set the following membership:
#
# g1:
# member: g2
#
# g2:
# member: g3
# member: user1
#
# g3:
# member: user2
#
# So when we do a show it looks like:
#
# g1:
# member: g2
# indirect group: g3
# indirect users: user1, user2
#
# g2:
# member group: g3
# member user: tuser1
# indirect users: user2
# memberof: g1
#
# g3:
# member: user2
# memberof: g1, g2
dict(
desc='Add a group 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': u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn),
'member_group': (group2,),
'gidnumber': [fuzzy_digits],
'cn': [group1],
'description': [u'Test desc 1'],
},
),
),
dict(
desc='Add a group member %r to %r' % (group3, group2),
command=(
'group_add_member', [group2], dict(group=group3)
),
expected=dict(
completed=1,
failed=dict(
member=dict(
group=tuple(),
user=tuple(),
),
),
result={
'dn': u'cn=%s,cn=groups,cn=accounts,%s' % (group2, api.env.basedn),
'member_group': (group3,),
'memberof_group': (u'testgroup1',),
'gidnumber': [fuzzy_digits],
'cn': [group2],
'description': [u'Test desc 2'],
},
),
),
dict(
desc='Add a user member %r to %r' % (user1, group2),
command=(
'group_add_member', [group2], dict(user=user1)
),
expected=dict(
completed=1,
failed=dict(
member=dict(
group=tuple(),
user=tuple(),
),
),
result={
'dn': u'cn=%s,cn=groups,cn=accounts,%s' % (group2, api.env.basedn),
'member_user': (u'tuser1',),
'member_group': (group3,),
'memberof_group': (u'testgroup1',),
'gidnumber': [fuzzy_digits],
'cn': [group2],
'description': [u'Test desc 2'],
},
),
),
dict(
desc='Add a user member %r to %r' % (user2, group3),
command=(
'group_add_member', [group3], dict(user=user2)
),
expected=dict(
completed=1,
failed=dict(
member=dict(
group=tuple(),
user=tuple(),
),
),
result={
'dn': u'cn=%s,cn=groups,cn=accounts,%s' % (group3, api.env.basedn),
'member_user': (u'tuser2',),
'memberof_group': (u'testgroup2', u'testgroup1'),
'gidnumber': [fuzzy_digits],
'cn': [group3],
'description': [u'Test desc 3'],
},
),
),
dict(
desc='Retrieve group %r' % group1,
command=('group_show', [group1], {}),
expected=dict(
value=group1,
summary=None,
result=dict(
cn=[group1],
description=[u'Test desc 1'],
gidnumber= [fuzzy_digits],
memberindirect_group = (u'testgroup3',),
member_group = (u'testgroup2',),
memberindirect_user = (u'tuser1',u'tuser2',),
dn=u'cn=testgroup1,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Retrieve group %r' % group2,
command=('group_show', [group2], {}),
expected=dict(
value=group2,
summary=None,
result=dict(
cn=[group2],
description=[u'Test desc 2'],
gidnumber= [fuzzy_digits],
memberof_group = (u'testgroup1',),
member_group = (u'testgroup3',),
member_user = (u'tuser1',),
memberindirect_user = (u'tuser2',),
dn=u'cn=testgroup2,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Retrieve group %r' % group3,
command=('group_show', [group3], {}),
expected=dict(
value=group3,
summary=None,
result=dict(
cn=[group3],
description=[u'Test desc 3'],
gidnumber= [fuzzy_digits],
memberof_group = (u'testgroup2', u'testgroup1',),
member_user = (u'tuser2',),
dn=u'cn=testgroup3,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
]