Bug 28361 - nscd + libnss-ldap Gruppenauflösung
nscd + libnss-ldap Gruppenauflösung
Status: CLOSED FIXED
Product: UCS
Classification: Unclassified
Component: nscd
UCS 3.0
Other Linux
: P5 critical (vote)
: UCS 3.1
Assigned To: Stefan Gohmann
Felix Botner
: interim-1
Depends on:
Blocks: 28401 28413 56127
  Show dependency treegraph
 
Reported: 2012-08-29 12:22 CEST by Stefan Gohmann
Modified: 2023-06-08 11:51 CEST (History)
2 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): UCS Performance
Max CVSS v3 score:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Gohmann univentionstaff 2012-08-29 12:22:18 CEST
Aktuell in bei einem Kunden aufgetreten (Ticket #2012082821001308) aber auch in einer Testumgebung mit 30.000 Benutzern in Domain Users.

Der nscd schafft es nicht die Daten in den lokalen Cache zu bekommen. Dabei ist es egal, ob die Daten aus dem LDAP per libnss-ldap oder aus der lokalen Datei bezogen werden.

Stehen alle Gruppen in der lokalen Datei, so kann Domain Users nicht zuverlässig aufgelöst werden, zwei "ls -la /home"-Befehle direkt nacheinander:

root@master141:~/eglibc-2.11.3/nscd# ls -la /home
total 16
drwxr-xr-x  4 root root         4096 Apr 27 16:12 .
drwxr-xr-x 24 root root         4096 Apr 27 13:57 ..
drwxr-xr-x  2 root Domain Users 4096 Apr 27 16:12 a
drwxr-xr-x  2 root root         4096 Apr 26 13:25 groups
root@master141:~/eglibc-2.11.3/nscd# ls -la /home
total 16
drwxr-xr-x  4 root root 4096 Apr 27 16:12 .
drwxr-xr-x 24 root root 4096 Apr 27 13:57 ..
drwxr-xr-x  2 root 5001 4096 Apr 27 16:12 a
drwxr-xr-x  2 root root 4096 Apr 26 13:25 groups

Aus der Logdatei:
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:43 AM CEST - 6007:        GETFDPW
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:43 AM CEST - 6007:        GETPWBYUID (0)
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: Haven't found "0" in password cache!
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: add new entry "0" of type GETPWBYUID for passwd to cache (first)
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: add new entry "root" of type GETPWBYNAME for passwd to cache
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: short write in cache_addpw: Success
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:43 AM CEST - 6007:        GETFDGR
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:43 AM CEST - 6007:        GETGRBYGID (0)
Sat 28 Apr 2012 06:12:43 AM CEST - 6007: Haven't found "0" in group cache!
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: add new entry "0" of type GETGRBYGID for group to cache (first)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: add new entry "root" of type GETGRBYNAME for group to cache
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: short write in cache_addgr: Success
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: Haven't found "5001" in group cache!
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: Haven't found "5001" in group cache!
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: add new entry "5001" of type GETGRBYGID for group to cache (first)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: add new entry "Domain Users" of type GETGRBYNAME for group to cache
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: short write in cache_addgr: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: add new entry "5001" of type GETGRBYGID for group to cache (first)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: add new entry "Domain Users" of type GETGRBYNAME for group to cache
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: short write in cache_addgr: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Resource temporarily unavailable
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: handle_request: request received (Version = 2) from PID 6017
Sat 28 Apr 2012 06:12:44 AM CEST - 6007:        GETGRBYGID (5001)
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Resource temporarily unavailable
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Broken pipe
Sat 28 Apr 2012 06:12:44 AM CEST - 6007: cannot write result: Broken pipe

Weitere Tests haben ergeben, dass libnss-ldap in Bezug auf die Gruppenauflösung extrem langsam ist, ohne nscd:

root@master141:~# time getent group >group.getent

real    1m50.711s
user    1m22.533s
sys     0m4.036s

Das gleiche mit einem Python Skript, welches auch auf Gruppen in Gruppen und Rekursionen prüft:

root@master141:~# time ./dump-groups.py >group.python

real    0m4.217s
user    0m2.104s
sys     0m0.208s

Wenn die Daten aus dem python Skript an /etc/group ergänzt werden, so ist der Zugriff sehr schnell:
root@master141:~# time getent group | wc -l
2802

real    0m0.015s
user    0m0.020s
sys     0m0.000s


Eine mögliche Lösung:

- deaktivieren des nscd Cache für Gruppen

- libnss-ldap für Gruppen entfernen

- ein neues nss-Modul schreiben, welches die Gruppen aus einer lokalen Datei (/etc/group.ldap) ausliest, siehe libnss-passwdcache

- in regelmäßigen konfigurierbaren Abständen die Datei (/etc/group.ldap) neu generieren, zum einen per Cron, aber auch aus dem Listener heraus, siehe auch UCR Variable nscd/group/invalidate_cache_on_changes

Eine Alternative wäre es libnss-ldapd zu verwenden, allerdings fehlt dort derzeit die Gruppen in Gruppen Auflösung.
Comment 1 Stefan Gohmann univentionstaff 2012-08-29 12:33:29 CEST
(In reply to comment #0)
> root@master141:~# time getent group >group.getent
> 
> real    1m50.711s
> user    1m22.533s
> sys     0m4.036s
> 
> Das gleiche mit einem Python Skript, welches auch auf Gruppen in Gruppen und
> Rekursionen prüft:
> 
> root@master141:~# time ./dump-groups.py >group.python
> 
> real    0m4.217s
> user    0m2.104s
> sys     0m0.208s

libnss-ldap benötigt so lange, weil jedes Gruppenmitglied nochmal gesucht wird. In dem python-Skript wird derzeit uid= direkt als Benutzer eingetragen.
Comment 2 Stefan Gohmann univentionstaff 2012-08-30 12:34:04 CEST
(In reply to comment #0)
> - ein neues nss-Modul schreiben, welches die Gruppen aus einer lokalen Datei
> (/etc/group.ldap) ausliest, siehe libnss-passwdcache

Dafür kann und sollte libnss-extrausers verwendet werden.
Comment 3 Stefan Gohmann univentionstaff 2012-08-30 17:42:28 CEST
Das ist in einer ersten Version im Paket univention-pam umgesetzt. Beim Update wird automatisch der nscd Cache für die Gruppen deaktiviert und die nss-Auflösung per ldap für die Gruppen wird ebenfalls deaktiviert.

Das Tool /usr/lib/univention-pam/ldap-group-to-file.py wir jetzt entweder per Cron alle 15 Minuten aufgerufen oder per Listener Modul nss.py, dort aber nur wenn der Listener 15 Sekunden nichts mehr zu tun hat.
Beides ist per UCR konfigurierbar:
 nss/group/cachefile/invalidate_on_changes
 nss/group/cachefile/invalidate_interval
Das Tool schreibt die Änderungen in die Datei /var/lib/extrausers/group, diese wird vom nss-Modul extrausers ausgelesen.

Das bisherige Verhalten kann so wieder hergestellt werden:
 ucr set nss/group/cachefile=no nscd/group/enabled=true
 /etc/init.d/nscd restart

Weitere Tests stehen noch aus. Zusätzlich sollen die Pakete für UCS 3.0 in einem Scope bereitgestellt werden.
Comment 4 Moritz Muehlenhoff univentionstaff 2012-08-31 09:31:04 CEST
Das Listener-Modul, das den Gruppencache invalidiert muss ebenfalls angepasst werden, so dass es nichts macht wenn die Option aktiviert ist.
Comment 5 Stefan Gohmann univentionstaff 2012-08-31 10:24:25 CEST
Das ist jetzt soweit für UCS 3.1 umgesetzt. Die Pakete stehen ebenfalls als Backport für UCS 3.0 zur Verfügung. Dort können sie wie folgt eingebunden werrden:

 ucr set repository/online/component/groupcache=true \
   repository/online/component/groupcache/server=apt.univention.de \
   repository/online/component/groupcache/parts=unmaintained

 apt-get update && apt-get -u dist-upgrade

Das System wird dann direkt so umkonfiguriert, dass die Gruppenauflösung nicht mehr per libnss-ldap und nscd gemacht wird, sondern über ein Tool, welches die Daten in eine lokale Datei schreibt.

Das alte Verhalten kann so wieder hergestellt werden:
  ucr set nss/group/cachefile=no nscd/group/enabled=true
  invoke-rc.d nscd restart
  invoke-rc.d univention-directory-listener restart
 Je nach Status vor dem Update müsste die Cache Invalidierung ebenfalls wieder hergestellt werden:
  ucr nscd/group/invalidate_cache_on_changes=true
  invoke-rc.d univention-directory-listener restart

Getestet habe ich bisher:
- Umgebung mit > 30000 Benutzern
- Diverse Gruppenverschachtelungen
- Ungültige Gruppenmitglieder
- Beendeter LDAP Server
- Doppelte Gruppenmitglieder über Gruppen in Gruppen
- Rekursionen

In der QA bitte nochmal die 3.0 und 3.1 Pakete testen.
Comment 6 Arvid Requate univentionstaff 2012-09-03 17:59:05 CEST
Verified:
 * Gruppen in Gruppen, invalid users, Umlaute
 * i386 und amd64
 * UCS 3.0 und UCS 3.1
 * Wird auch bei Neuinstallation standardmäßig aktiviert.
 * postrun delay funktioniert, Cronjob funktioniert.
 * Changelog OK


Neue UCR Variablen:
  nss/group/cachefile?yes
  nss/group/cachefile/invalidate_on_changes?yes
Geänderte Defaults:
  nscd/group/enabled?no
  nscd/group/invalidate_cache_on_changes=false


Eigenheiten der neuen Lösung:

 * Gruppenmitlieder, die lokal nicht per getent passwd aufgelöst werden, werden
   als Gruppenmitglieder aufgeführt (getent group $gruppenname). Bei nss_ldap
   wurden diese herausgefiltert und nicht angezeigt. Dafür gibt es jetzt
   Bug 28401.

 * Wenn man viele Gruppen jeweils im Abstand von <15 sek. anlegt, dann wird der groupcache längere Zeit nicht geschrieben, weil die postrun-Funktion des neuen nss-Listeners nicht aktiv wird. Der Cron-Job läuft aber alle 15 min.

 * Der Name von Gruppen mit Umlaut wird jetzt in der Ausgabe von 'getent group' mit Umlauten dargestelt, mit nss_ldap wurde da jeder Umlaut als zwei escapte hex-Bytes ausgegeben. In der Praxis scheint das keinen Unterschied zu machen. Insbesondere treten in der Ausgabe von "getent group grüppe" und in der Ausgabe von "id user1" weiterhin die Hex-bytes auf.

 * In einem Fall verwendete 'getent group group1' nach dem Update auf die neue Lösung weiterhin den nscd (strace zeigt das). Daher ist nach dem Update ein Reboot zu empfehlen, zumindest aber ein '/etc/init.d/nscd stop; getent group guests; /etc/init.d/nscd start'.
Comment 7 Stefan Gohmann univentionstaff 2012-09-04 10:25:22 CEST
Gerade bei der Bearbeitung von Bug #25656 aufgefallen. libnss-ldap + nscd funktionieren case-insensitive, libnss-extrausers hingegen case-sensitive.

Neu:
SG@master52:~$ getent group domain\ users
SG@master52:~$ getent group Domain\ Users
Domain Users:*:5001:test1,Administrator,SG2,SG
SG@master52:~$ 

Alt:
SG@master52:~$ getent group domain\ users
Domain Users:*:5001:test1,Administrator,SG2,SG
SG@master52:~$ getent group Domain\ Users
Domain Users:*:5001:test1,Administrator,SG2,SG
SG@master52:~$
Comment 8 Stefan Gohmann univentionstaff 2012-09-04 11:19:37 CEST
Ist angepasst und gebaut. Die Anpassung ist für den groupcache Scope noch nicht veröffentlicht.
Comment 9 Arvid Requate univentionstaff 2012-09-04 17:23:29 CEST
Verifed:
 * libnss-extrausers verhält sich jetzt case insensitive
 * Advisory muss nicht upgedatet werden

root@master:~# getent group UpperGroup1
UpperGroup1:*:7234:user1
root@master:~# getent group uppergroup1
UpperGroup1:*:7234:user1
root@master:~# getent group übergroup1
\C3\9CberGroup1:*:7235:user1
root@master:~# getent group Übergroup1
\C3\9CberGroup1:*:7235:user1
root@master:~# getent group ÜberGroup1
\C3\9CberGroup1:*:7235:user1
root@master:~# getent group UPPERGROUP1
UpperGroup1:*:7234:user1
Comment 10 Stefan Gohmann univentionstaff 2012-09-04 20:16:42 CEST
(In reply to comment #9)
> Verifed:
>  * libnss-extrausers verhält sich jetzt case insensitive
>  * Advisory muss nicht upgedatet werden

groupcache Scope für UCS 3.0 wurde auch aktualisiert.
Comment 11 Janis Meybohm univentionstaff 2012-09-13 15:51:03 CEST
(In reply to comment #10)
> (In reply to comment #9)
> > Verifed:
> >  * libnss-extrausers verhält sich jetzt case insensitive
> >  * Advisory muss nicht upgedatet werden
> 
> groupcache Scope für UCS 3.0 wurde auch aktualisiert.

libnss-extrausers ist nicht im 3.0 Scope nicht für amd64 gebaut/veröffentlicht.
Comment 12 Stefan Gohmann univentionstaff 2012-09-13 16:54:02 CEST
Das amd64 war nicht vorhanden. Paket für amd64 neu gebaut und veröffentlicht:

  http://apt.univention.de/3.0/unmaintained/component/groupcache/amd64/
Comment 13 Stefan Gohmann univentionstaff 2012-09-13 16:54:53 CEST
(In reply to comment #12)
> Das amd64 war nicht vorhanden. Paket für amd64 neu gebaut und veröffentlicht:

Das amd64-Verzeichnis war nicht vorhanden. Paket für amd64 neu gebaut und veröffentlicht:
Comment 14 Stefan Gohmann univentionstaff 2012-09-13 20:29:28 CEST
Da die Anpassung nur den 3.0 Backport betraf, habe ich den Bug wieder auf Verified gesetzt.
Comment 15 Felix Botner univentionstaff 2012-09-14 11:57:48 CEST
Wenn /tmp und /var nicht auf der gleichen Partition liegen, kommt es in ldap-group-to-file.py zu einem Traceback.

Traceback (most recent call last):
  File "/usr/lib/univention-pam/ldap-group-to-file.py", line 124, in <module>
    os.rename(fdname, options.file)
OSError: [Errno 18] Invalid cross-device link
Restarting bind9 daemon: .
done.

os.rename kann wahrscheinlich nicht über Partitionsgrenzen hinweg arbeiten.
Comment 16 Felix Botner univentionstaff 2012-09-14 12:02:34 CEST
Ich habe es bei mir nun mit 

(fdtemp, fdname) = tempfile.mkstemp(dir=os.path.dirname(options.file))

behoben.
Comment 17 Stefan Gohmann univentionstaff 2012-09-14 12:41:08 CEST
Ist angepasst.
Comment 18 Felix Botner univentionstaff 2012-09-14 12:43:57 CEST
ok, es wird nun shutil zum Verschieben verwendet.

-> /usr/lib/univention-pam/ldap-group-to-file.py --check_member
debug shutil.move(/tmp/tmpPxyWxQ, /var/lib/extrausers/group)
Comment 19 Stefan Gohmann univentionstaff 2012-12-12 21:07:43 CET
UCS 3.1-0 has been released: 
 http://forum.univention.de/viewtopic.php?f=54&t=2125

If this error occurs again, please use "Clone This Bug".