Filter groups by type (POSIX, non-POSIX, external)

Added flag for each groups type: --posix, --nonposix, --external to group-find command.

Group types:
* non-POSIX: not posix, not external
* POSIX: with objectclass posixgroup
* external: with objectclass ipaexternalgroup

https://fedorahosted.org/freeipa/ticket/3483
This commit is contained in:
Petr Vobornik
2013-03-11 12:37:29 +01:00
committed by Martin Kosek
parent 3f053437c9
commit e64db8cbc2
5 changed files with 151 additions and 3 deletions

View File

@@ -1307,11 +1307,12 @@ output: Output('result', <type 'bool'>, None)
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('value', <type 'unicode'>, None)
command: group_find
args: 1,24,4
args: 1,27,4
arg: Str('criteria?', noextrawhitespace=False)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('cn', attribute=True, autofill=False, cli_name='group_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=False)
option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
option: Flag('external', autofill=True, cli_name='external', default=False)
option: Int('gidnumber', attribute=True, autofill=False, cli_name='gid', minvalue=1, multivalue=False, query=True, required=False)
option: Str('group*', cli_name='groups', csv=True)
option: Str('in_group*', cli_name='in_groups', csv=True)
@@ -1321,12 +1322,14 @@ option: Str('in_role*', cli_name='in_roles', csv=True)
option: Str('in_sudorule*', cli_name='in_sudorules', csv=True)
option: Str('no_group*', cli_name='no_groups', csv=True)
option: Str('no_user*', cli_name='no_users', csv=True)
option: Flag('nonposix', autofill=True, cli_name='nonposix', default=False)
option: Str('not_in_group*', cli_name='not_in_groups', csv=True)
option: Str('not_in_hbacrule*', cli_name='not_in_hbacrules', csv=True)
option: Str('not_in_netgroup*', cli_name='not_in_netgroups', csv=True)
option: Str('not_in_role*', cli_name='not_in_roles', csv=True)
option: Str('not_in_sudorule*', cli_name='not_in_sudorules', csv=True)
option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('posix', autofill=True, cli_name='posix', default=False)
option: Flag('private', autofill=True, cli_name='private', default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Int('sizelimit?', autofill=False, minvalue=0)

View File

@@ -328,10 +328,35 @@ class group_find(LDAPSearch):
cli_name='private',
doc=_('search for private groups'),
),
Flag('posix',
cli_name='posix',
doc=_('search for POSIX groups'),
),
Flag('external',
cli_name='external',
doc=_('search for groups with support of external non-IPA members from trusted domains'),
),
Flag('nonposix',
cli_name='nonposix',
doc=_('search for non-POSIX groups'),
),
)
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
# filter groups by pseudo type
filters = []
if options['posix']:
search_kw = {'objectclass': ['posixGroup']}
filters.append(ldap.make_filter(search_kw, rules=ldap.MATCH_ALL))
if options['external']:
search_kw = {'objectclass': ['ipaExternalGroup']}
filters.append(ldap.make_filter(search_kw, rules=ldap.MATCH_ALL))
if options['nonposix']:
search_kw = {'objectclass': ['posixGroup' , 'ipaExternalGroup']}
filters.append(ldap.make_filter(search_kw, rules=ldap.MATCH_NONE))
# if looking for private groups, we need to create a new search filter,
# because private groups have different object classes
if options['private']:
@@ -351,6 +376,9 @@ class group_find(LDAPSearch):
cflt = ldap.make_filter(search_kw, exact=False)
filter = ldap.combine_filters((oflt, cflt), rules=ldap.MATCH_ALL)
elif filters:
filters.append(filter)
filter = ldap.combine_filters(filters, rules=ldap.MATCH_ALL)
return (filter, base_dn, scope)
api.register(group_find)

View File

@@ -46,6 +46,7 @@ group = [
]
externalgroup = group + [u'ipaexternalgroup']
posixgroup = group + [u'posixgroup']
host = [
u'ipasshhost',

View File

@@ -23,7 +23,8 @@ Test the `ipalib/plugins/group.py` module.
from ipalib import api, errors
from tests.test_xmlrpc import objectclasses
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
from tests.util import Fuzzy
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid, fuzzy_set_ci
from ipapython.dn import DN
group1 = u'testgroup1'
@@ -248,7 +249,7 @@ class test_group(Declarative):
cn=[group2],
description=[u'Test desc 2'],
gidnumber=[fuzzy_digits],
objectclass=objectclasses.group + [u'posixgroup'],
objectclass=objectclasses.posixgroup,
ipauniqueid=[fuzzy_uuid],
dn=get_group_dn('testgroup2'),
),
@@ -382,6 +383,98 @@ class test_group(Declarative):
),
),
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=[
{
'dn': get_group_dn('admins'),
'member_user': [u'admin'],
'gidnumber': [fuzzy_digits],
'cn': [u'admins'],
'description': [u'Account administrators group'],
'objectclass': fuzzy_set_ci(objectclasses.posixgroup),
'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(objectclasses.posixgroup),
'ipauniqueid': [fuzzy_uuid],
},
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],
),
dict(
dn=get_group_dn(group2),
cn=[group2],
description=[u'New desc 2'],
gidnumber=[fuzzy_digits],
objectclass=fuzzy_set_ci(objectclasses.posixgroup),
ipauniqueid=[fuzzy_uuid],
),
],
),
),
###############
# test external SID members for group3:
dict(
@@ -402,6 +495,25 @@ class test_group(Declarative):
),
),
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),

View File

@@ -83,6 +83,10 @@ fuzzy_dergeneralizedtime = Fuzzy('^[0-9]{14}Z$')
# match any string
fuzzy_string = Fuzzy(type=basestring)
# case insensitive match of sets
def fuzzy_set_ci(s):
return Fuzzy(test=lambda other: set(x.lower() for x in other) == set(y.lower() for y in s))
try:
if not api.Backend.xmlclient.isconnected():
api.Backend.xmlclient.connect(fallback=False)