Enforce sizelimit in permission-find, post_callback returns truncated

We actually perform two searches in permission-find. The first looks
for matches within the permission object itself. The second looks at
matches in the underlying aci.

We need to break out in two places. The first is if we find enough
matches in the permission itself. The second when we are appending
matches from acis.

The post_callback() definition needed to be modified to return
the truncated value so a plugin author can modify that value.

https://fedorahosted.org/freeipa/ticket/2322
This commit is contained in:
Rob Crittenden 2012-05-23 11:00:24 -04:00 committed by Martin Kosek
parent d62b2d9be5
commit 8d00d7c130
11 changed files with 110 additions and 11 deletions

View File

@ -1857,9 +1857,9 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
for callback in self.POST_CALLBACKS:
if hasattr(callback, 'im_self'):
callback(ldap, entries, truncated, *args, **options)
truncated = callback(ldap, entries, truncated, *args, **options)
else:
callback(self, ldap, entries, truncated, *args, **options)
truncated = callback(self, ldap, entries, truncated, *args, **options)
if self.sort_result_entries:
if self.obj.primary_key:
@ -1884,7 +1884,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
return (filters, base_dn, scope)
def post_callback(self, ldap, entries, truncated, *args, **options):
pass
return truncated
def exc_callback(self, args, options, exc, call_func, *call_args, **call_kwargs):
raise exc

View File

@ -132,7 +132,7 @@ EXAMPLES:
SRV record: 0 3 389 fast.example.com, 0 1 389 slow.example.com, 1 1 389 backup.example.com
Modify SRV record '0 3 389 fast.example.com'? Yes/No (default No):
Modify SRV record '0 3 389 fast.example.com'? Yes/No (default No):
Modify SRV record '0 1 389 slow.example.com'? Yes/No (default No): y
SRV Priority [0]: (keep the default value)
SRV Weight [1]: 2 (modified value)
@ -2589,6 +2589,8 @@ class dnsrecord_find(LDAPSearch):
for entry in entries:
self.obj.postprocess_record(entry[1], **options)
return truncated
api.register(dnsrecord_find)
class dns_resolve(Command):

View File

@ -461,6 +461,7 @@ class entitle_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if len(entries) == 0:
raise errors.NotRegisteredError()
return truncated
api.register(entitle_find)

View File

@ -769,7 +769,7 @@ class host_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
return
return truncated
for entry in entries:
(dn, entry_attrs) = entry
set_certificate_attrs(entry_attrs)
@ -785,6 +785,8 @@ class host_find(LDAPSearch):
output_sshpubkey(ldap, dn, entry_attrs)
return truncated
api.register(host_find)

View File

@ -182,10 +182,11 @@ class hostgroup_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
return
return truncated
for entry in entries:
(dn, entry_attrs) = entry
self.obj.suppress_netgroup_memberof(dn, entry_attrs)
return truncated
api.register(hostgroup_find)

View File

@ -351,7 +351,7 @@ class permission_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.pop('pkey_only', False):
return
return truncated
for entry in entries:
(dn, attrs) = entry
try:
@ -363,6 +363,15 @@ class permission_find(LDAPSearch):
attrs[attr] = aci[attr]
except errors.NotFound:
self.debug('ACI not found for %s' % attrs['cn'][0])
if truncated:
# size/time limit met, no need to search acis
return truncated
if 'sizelimit' in options:
max_entries = options['sizelimit']
else:
config = ldap.get_ipa_config()[1]
max_entries = config['ipasearchrecordslimit']
# Now find all the ACIs that match. Once we find them, add any that
# aren't already in the list along with their permission info.
@ -398,7 +407,12 @@ class permission_find(LDAPSearch):
dn = permission['dn']
del permission['dn']
if (dn, permission) not in entries:
entries.append((dn, permission))
if len(entries) < max_entries:
entries.append((dn, permission))
else:
truncated = True
break
return truncated
api.register(permission_find)

View File

@ -498,4 +498,6 @@ class pwpolicy_find(LDAPSearch):
except KeyError:
pass
return truncated
api.register(pwpolicy_find)

View File

@ -318,10 +318,11 @@ all=True)['result']
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
return
return truncated
for entry in entries:
(dn, attrs) = entry
self.obj._convert_seealso(ldap, attrs, **options)
return truncated
api.register(selinuxusermap_find)

View File

@ -399,11 +399,12 @@ class service_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
return
return truncated
for entry in entries:
(dn, entry_attrs) = entry
self.obj.get_password_attributes(ldap, dn, entry_attrs)
set_certificate_attrs(entry_attrs)
return truncated
api.register(service_find)

View File

@ -625,13 +625,14 @@ class user_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
return
return truncated
for entry in entries:
(dn, attrs) = entry
self.obj._convert_manager(attrs, **options)
self.obj.get_password_attributes(ldap, dn, attrs)
convert_nsaccountlock(attrs)
output_sshpubkey(ldap, dn, attrs)
return truncated
msg_summary = ngettext(
'%(count)d user matched', '%(count)d users matched', 0

View File

@ -386,6 +386,80 @@ class test_permission(Declarative):
),
dict(
desc='Search for %r with a limit of 1 (truncated)' % permission1,
command=('permission_find', [permission1], dict(sizelimit=1)),
expected=dict(
count=1,
truncated=True,
summary=u'1 permission matched',
result=[
{
'dn': lambda x: DN(x) == permission1_dn,
'cn': [permission1],
'member_privilege': [privilege1],
'type': u'user',
'permissions': [u'write'],
},
],
),
),
dict(
desc='Search for %r with a limit of 2' % permission1,
command=('permission_find', [permission1], dict(sizelimit=2)),
expected=dict(
count=2,
truncated=False,
summary=u'2 permissions matched',
result=[
{
'dn': lambda x: DN(x) == permission1_dn,
'cn': [permission1],
'member_privilege': [privilege1],
'type': u'user',
'permissions': [u'write'],
},
{
'dn': lambda x: DN(x) == permission2_dn,
'cn': [permission2],
'type': u'user',
'permissions': [u'write'],
},
],
),
),
# This tests setting truncated to True in the post_callback of
# permission_find(). The return order in LDAP is not guaranteed
# but in practice this is the first entry it finds. This is subject
# to change.
dict(
desc='Search for permissions by attr with a limit of 1 (truncated)',
command=('permission_find', [], dict(attrs=u'ipaenabledflag',
sizelimit=1)),
expected=dict(
count=1,
truncated=True,
summary=u'1 permission matched',
result=[
{
'dn': lambda x: DN(x) == DN(('cn', 'Modify HBAC rule'),
api.env.container_permission,api.env.basedn),
'cn': [u'Modify HBAC rule'],
'member_privilege': [u'HBAC Administrator'],
'permissions' : [u'write'],
'attrs': [u'servicecategory', u'sourcehostcategory', u'cn', u'description', u'ipaenabledflag', u'accesstime', u'usercategory', u'hostcategory', u'accessruletype', u'sourcehost'],
'subtree' : u'ldap:///ipauniqueid=*,cn=hbac,%s' % api.env.basedn,
'memberindirect': [u'cn=hbac administrator,cn=privileges,cn=pbac,%s' % api.env.basedn, u'cn=it security specialist,cn=roles,cn=accounts,%s' % api.env.basedn],
},
],
),
),
dict(
desc='Update %r' % permission1,
command=(