Bug 40652 - replace self.lo.search() with getAttr() or get (uldap) if the search is meant to return attributes for a specific object
replace self.lo.search() with getAttr() or get (uldap) if the search is meant...
Status: CLOSED FIXED
Product: UCS
Classification: Unclassified
Component: UDM (Generic)
UCS 3.2
Other Linux
: P5 normal (vote)
: UCS 3.2-8-errata
Assigned To: Felix Botner
Florian Best
:
Depends on: 40651
Blocks: 41518
  Show dependency treegraph
 
Reported: 2016-02-12 16:46 CET by Daniel Orrego
Modified: 2017-01-26 12:58 CET (History)
4 users (show)

See Also:
What kind of report is it?: ---
What type of bug is this?: ---
Who will be affected by this bug?: ---
How will those affected feel about the bug?: ---
User Pain:
Enterprise Customer affected?:
School Customer affected?:
ISV affected?:
Waiting Support:
Flags outvoted (downgraded) after PO Review:
Ticket number:
Bug group (optional):
Max CVSS v3 score:


Attachments
my udm test (creates/removes/modifies various udm objects) (3.36 KB, text/x-python)
2016-02-23 15:16 CET, Felix Botner
Details
patch (1.11 KB, patch)
2016-02-24 11:30 CET, Florian Best
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Orrego univentionstaff 2016-02-12 16:46:42 CET
(Clone for UCS 3.2)

+++ This bug was initially created as a clone of Bug #40651 +++

In setups with big databases and sldap size limits, creating a users fails:

udm users/user create ...
LDAP Error: Administrative limit exceeded


 uldap.search filter=(objectClass=*) base=cn=Domain Users,cn=groups,o=in8,o=orange scope=sub attr=['gidNumber'] unique=0 required=0 timeout=-1 sizelimit=0
12.02.16 15:49:51.490  ADMIN       ( ERROR   ) : Post-modify operation failed:   File "/usr/lib/pymodules/python2.6/univention/admin/handlers/__init__.py", line 781, in _create
    self._ldap_post_create()

  File "/usr/lib/pymodules/python2.6/univention/admin/handlers/users/user.py", line 1887, in _ldap_post_create
    self.__primary_group()

  File "/usr/lib/pymodules/python2.6/univention/admin/handlers/users/user.py", line 1701, in __primary_group
    searchResult=self.lo.search(base=self['primaryGroup'], attr=['gidNumber'])

  File "/usr/lib/pymodules/python2.6/univention/admin/uldap.py", line 355, in search
    raise univention.admin.uexceptions.ldapError, _err2str(msg)
12.02.16 15:50:42.808  ADMIN       ( ERROR   ) : Post-modify operation failed:   File "/usr/lib/pymodules/python2.6/univention/admin/handlers/__init__.py", line 781, in _create
    self._ldap_post_create()

The problem is this:

 self.lo.search(base=self['primaryGroup'], attr=['sambaSID'])

This search uses the ldap filter filter=(objectClass=*). Seems that slapd applies the filter and than checks the limits (before filtering the search base).

The search works with a proper scope "scope=base" but we may better use uldap.get or uldap.getAttr instead.

Attached a patch that fixes this problem for "udm users/user create" (with scope=base). But there are much more of those searches in our udm handlers.
Comment 1 Felix Botner univentionstaff 2016-02-23 15:15:32 CET
fixed in univention-directory-manager-modules 9.0.76-40.1369.201602231508

Replaced the lo.search(base=...) requests (without a ldap filter) with lo.get/lo.getAttr.

svn r67641

Index: modules/univention/admin/handlers/users/user.py
Index: modules/univention/admin/handlers/groups/group.py
Index: modules/univention/admin/handlers/computers/domaincontroller_backup.py
Index: modules/univention/admin/handlers/computers/macos.py
Index: modules/univention/admin/handlers/computers/ubuntu.py
Index: modules/univention/admin/handlers/computers/domaincontroller_slave.py
Index: modules/univention/admin/handlers/computers/windows_domaincontroller.py
Index: modules/univention/admin/handlers/computers/domaincontroller_master.py
Index: modules/univention/admin/handlers/computers/windows.py
Index: modules/univention/admin/handlers/computers/memberserver.py
Index: modules/univention/admin/handlers/computers/linux.py
Index: modules/univention/admin/handlers/shares/printergroup.py
Index: modules/univention/admin/handlers/shares/printer.py
Index: modules/univention/admin/handlers/__init__.py

to reproduce:

* only with mdb backend!!
* create 1000 users
* ucr set ldap/sizelimit='100'
* ucr set ldap/limits='users time.soft=-1 time.hard=-1 size.unchecked=100'
* /etc/init.d/slapd restart

import univention.admin.uldap
import univention.config_registry
lo, pos = univention.admin.uldap.getMachineConnection()
ucr = univention.config_registry.ConfigRegistry()
ucr.load()
print lo.search(base='cn=Domain Users,cn=groups,%s' % ucr['ldap/base'], attr=['gidNumber'])

-> univention.admin.uexceptions.ldapError: Administrative limit exceeded
Comment 2 Felix Botner univentionstaff 2016-02-23 15:16:47 CET
Created attachment 7498 [details]
my udm test (creates/removes/modifies various udm objects)
Comment 3 Florian Best univentionstaff 2016-02-24 11:06:55 CET
Please add required=True to the getAttr calls. Otherwise no exception is raised if the object doesn't exists which results in unexpected behavior as the gidNumber '9999' is used then.
Comment 4 Florian Best univentionstaff 2016-02-24 11:30:52 CET
Created attachment 7499 [details]
patch

Please use the code style from the patch.
Comment 5 Florian Best univentionstaff 2016-02-24 12:22:49 CET
REOPEM: the changes in simpleComputer.primary_group() causes that the attribute oldPrimaryGroupDn is not set anymore.
Comment 6 Florian Best univentionstaff 2016-02-24 12:59:57 CET
(In reply to Florian Best from comment #5)
> REOPEM: the changes in simpleComputer.primary_group() causes that the
> attribute oldPrimaryGroupDn is not set anymore.
same goes for users/user.py __primary_group()
Comment 7 Felix Botner univentionstaff 2016-02-25 13:18:33 CET
fixed 

scope: ucs_3.2-0-errata3.2-8
src: univention-directory-manager-modules
fix: 9.0.76-41.1372.201602251311
Comment 8 Florian Best univentionstaff 2016-02-25 13:42:37 CET
This looks very much better now and the unification improved code quality a lot. Thank you!

REOPEN: The required=True parameter is missing in the following places:

groups/group.py:
+               searchResult = self.lo.get(self.dn, attr=['uniqueMember','memberUid'])
+               searchResult = self.lo.get(self.dn, attr=['uniqueMember','memberUid'])

+                       searchResult = self.lo.getAttr(member_dn, 'univentionGroupType')

+                       searchResult = self.lo.getAttr(member_dn, 'univentionGroupType')

shares/printer.py:
+                               member_list = self.lo.get(pg_dn, attr=['univentionPrinterGroupMember','cn'])


shares/printergroup.py:
+                               member_list = self.lo.get(pg_dn, attr=['univentionPrinterGroupMember','cn'])


users/user.py
+                       if 'samba' in self.options and not self.lo.getAttr(self['primaryGroup'], 'sambaSID'):

Best would be also to raise an human readable exception (something inheriting from uexceptions.base) in case of ldap.NO_SUCH_OBJECT.
Comment 9 Felix Botner univentionstaff 2016-02-25 14:57:33 CET
(In reply to Florian Best from comment #8)
> This looks very much better now and the unification improved code quality a
> lot. Thank you!
> 
> REOPEN: The required=True parameter is missing in the following places:
> 
> groups/group.py:
> +               searchResult = self.lo.get(self.dn,
> attr=['uniqueMember','memberUid'])
> +               searchResult = self.lo.get(self.dn,
> attr=['uniqueMember','memberUid'])

no, why, what is if there are no members

> 
> +                       searchResult = self.lo.getAttr(member_dn,
> 'univentionGroupType')
> 
> +                       searchResult = self.lo.getAttr(member_dn,
> 'univentionGroupType')

no, if there is no univentionGroupType attribute _has_universal_member() and _has_domain_local_member return False (as before), i think this is ok

> 
> shares/printer.py:
> +                               member_list = self.lo.get(pg_dn,
> attr=['univentionPrinterGroupMember','cn'])
> 
> 
> shares/printergroup.py:
> +                               member_list = self.lo.get(pg_dn,
> attr=['univentionPrinterGroupMember','cn'])
> 

no, as far as i understand, univentionPrinterGroupMember is optional

> 
> users/user.py
> +                       if 'samba' in self.options and not
> self.lo.getAttr(self['primaryGroup'], 'sambaSID'):

no, we want to raise univention.admin.uexceptions.primaryGroupWithoutSamba in the case the primary group has no sid. So just check with self.lo.getAttr() and raise if not return value


> Best would be also to raise an human readable exception (something
> inheriting from uexceptions.base) in case of ldap.NO_SUCH_OBJECT.
Comment 10 Florian Best univentionstaff 2016-02-29 13:32:59 CET
(In reply to Felix Botner from comment #9)
oh yes, this was my mistake.

New search behavior: OK
Code-Review: OK
Error handling: OK
YAML: OK
Comment 11 Janek Walkenhorst univentionstaff 2016-03-02 14:35:02 CET
<http://errata.software-univention.de/ucs/3.2/406.html>