ipa user-find --manager does not find matches

The manager LDAP attribute is a dn pointing inside the user
container. When passed on the command it is typically a bare user
uid. The search filter will only succeed if the bare uid is converted
to a full dn because that is what is stored in the value for the
manager attribute.

The search failure is solved by calling _normalize_manager() which
does the conversion to a dn (if not already a dn).

It feels like this type of conversion should be performed in the pre
callback which allows one to modify the filter. But when the pre
callback is invoked it's complex string with the manager attribute
already inserted. This is because the LDAPSearch.execute() method
processes the options dict and constructs a filter component for each
key/value in the options dict prior to invoking the pre callback. If
we wanted to modify the manager value in the filter in the pre
callback we would have to decompose the filter string, perform dn
checking and then reassemble the filter. It's much cleaner to perform
the dn operations on the manager value before it gets embedded into
what otherwise might be a very complex filter. This is the reason why
the normalization is perfored in the execute method as opposed to the
pre callback. Other classes do similar things in their execute methods
as opposed to their callbacks's, selinuxusermap_find is one example.

Patch also introduces new unit test to verify.

https://fedorahosted.org/freeipa/ticket/2264
This commit is contained in:
John Dennis 2012-09-03 18:05:17 +02:00 committed by Martin Kosek
parent 7e9eb9caad
commit 557b260550
2 changed files with 34 additions and 0 deletions

View File

@ -628,6 +628,13 @@ class user_find(LDAPSearch):
), ),
) )
def execute(self, *args, **options):
# assure the manager attr is a dn, not just a bare uid
manager = options.get('manager')
if manager is not None:
options['manager'] = self.obj._normalize_manager(manager)
return super(user_find, self).execute(self, *args, **options)
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options): def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options):
assert isinstance(base_dn, DN) assert isinstance(base_dn, DN)
if options.get('whoami'): if options.get('whoami'):

View File

@ -662,6 +662,33 @@ class test_user(Declarative):
), ),
), ),
dict(
desc='Search for "%s" with manager "%s"' % (user2, user1),
command=(
'user_find', [user2], {'manager': user1}
),
expected=dict(
result=[
dict(
dn=get_user_dn(user2),
givenname=[u'Test'],
homedirectory=[u'/home/tuser2'],
loginshell=[u'/bin/sh'],
sn=[u'User2'],
uid=[user2],
nsaccountlock=False,
has_keytab=False,
has_password=False,
uidnumber=[fuzzy_digits],
gidnumber=[fuzzy_digits],
manager=[user1],
),
],
summary=u'1 user matched',
count=1,
truncated=False,
),
),
dict( dict(
desc='Delete %r and %r at the same time' % (user1, user2), desc='Delete %r and %r at the same time' % (user1, user2),