mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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:
parent
d62b2d9be5
commit
8d00d7c130
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -498,4 +498,6 @@ class pwpolicy_find(LDAPSearch):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return truncated
|
||||
|
||||
api.register(pwpolicy_find)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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=(
|
||||
|
Loading…
Reference in New Issue
Block a user