OpenLDAP 2.4 mit qmail-Schema
In eigener Sache: Hm – die Fallhöhe zum vorangehenden Artikel ist schon krass… Erst eher Lyrisches, dann profan Technisches, aber nun denn…
Vorgeschichte
Unser Schulserver migriert zur Zeit auf leistungsfähigere Hardware: Hetzner bietet die Vorserie zu den aktuellen Modellen zur Zeit ohne Einrichtungsgebühr an. Integraler Bestandteil meines Setups ist dabei OpenLDAP (Das Pendant bei Kleinweich Fenster heißt ActiveDirectory – ist aber im Prinzip eine LDAP-Implementierung). So braucht jeder nur ein Passwort für alle Dienste, die die Schule zur Zeit anbietet. Prinzipiell ist das alles möglich, was mit LDAP spricht – und etwas anderes kommt mir eh nicht auf die Platte. Moodle, Mahara, WordPress, Egroupware, Elgg, MediaWiki usw. sprechen zumindest allesamt LDAP wie auch unser Mailsystem.
Es lag nahe, bei dem Umzug gleich auch die Serversoftware auf eine aktuelleren Stand zu bringen: Bisher nutzte ich Ubuntu 8.04 LTS (Hardy Heron) mit drei voneinander getrennten virtuellen Maschinen (eine für die Homepage, eine für Moodle & Co. und eine zum Spiele für die interessierten Kolleginnen und Kollegen.
Das Setup war Mist, weil sich drei (mit der domU sogar vier) unterschiedliche Maschinen schwer warten und sichern lassen. Außerdem verschluckte sich der Hypervisor stets, wenn mehr als zwei CPU-Kerne zu virtualisieren waren, sodass effektiv nur ein Kern nutzbar wurde. Daher schwenke ich nun um auf Ubuntu 10.04 LTS (Lucid) und fasse die virtuellen Maschinen zu einer zusammen – dann gibt es auch etwas mehr Power, wenngleich auch spätere Erziehungsmaßnahmen hin zur Nutzung von FTPS und eine strengere Policy für den Zugriff von Kollegen auf den Server auf Fileebene.
Der Kampf
Lucid kommt mit OpenLDAP 2.4 daher. Neu ist vor allem, dass slapd nun seine sämtlichen Konfigurationsdaten in einem separaten LDAP-Baum speichert und neu ist vor allem, dass das entsprechende Paket in Lucid nur sehr mager vorkonfiguriert ist – z.B. ist lediglich das core-Schema integriert. Ich brauche für meinen LDAP jedoch zusätzlich folgende Schemen: cosine, inetorgperson, qmail. Die Schemen müssen in die Datenbank. Freundlicherweise liefert Lucid eine Reihe von Schemen mit:
ldapadd ‑Y EXTERNAL ‑H ldapi:/// ‑f /etc/ldap/schema/cosine.ldif
ldapadd ‑Y EXTERNAL ‑H ldapi:/// ‑f /etc/ldap/schema/inetorgperson.ldif
… auf der Kommandozeile lösen schonmal die ersten zwei Probleme. Das qmail-Schema ist ein besonderer Kandidat. Es wird nicht mitgeliefert und ist auch im Web (noch?) nicht für Debianderivate zu finden, sodass ich die alte Schemadatei aus Hardy erst konvertieren musste. Da ich so gelitten habe – Fehlerausgaben lesen und Intuition waren hier als Kernkompetenzen gefragt, präsentiere ich hier einfach das Endergebnis in Form einer importierbaren LDIF- Datei: qmail.ldif. Das Attribut mailHost ließ sich jedoch nicht zur Mitarbeit mit OpenLDAP 2.4 überreden – ich brauche es nicht und vermute, dass mit dem Serial da etwas nicht stimmt. Ein beherztes
ldapadd ‑Y EXTERNAL ‑H ldapi:/// ‑f /etc/ldap/schema/qmail.ldif
fügte dann das Schema hinzu. Dann braucht es einen Adminaccount für OpenLDAP – also früher war das leichter, heute müssen auch diese Daten in Lucid per LDIF importiert werden – der Lucid-Installer fragt nichts ab, sondern hinterlässt eine Installation der 1000 Fragezeichen:
# Load dynamic backend modules
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulepath: /usr/lib/ldap
olcModuleload: back_hdb# Database settings
dn: olcDatabase=hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcSuffix: dc=schule,dc=tld
olcDbDirectory: /var/lib/ldap
olcRootDN: cn=admin,dc=schule,dc=tld
olcRootPW: secret
olcDbConfig: set_cachesize 0 2097152 0
olcDbConfig: set_lk_max_objects 1500
olcDbConfig: set_lk_max_locks 1500
olcDbConfig: set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcLastMod: TRUE
olcDbCheckpoint: 512 30
olcAccess: to attrs=userPassword by dn=„cn=admin,dc=schule,dc=tld“ write by anonymous auth by self write by * none
olcAccess: to attrs=shadowLastChange by self write by * read
olcAccess: to dn.base=““ by * read
olcAccess: to * by dn=„cn=admin,dc=schule,dc=tld“ write by * read
„schule“, „tld“ und „secret“ sind an die eigenen Bedürfnisse anzupassen. Die Datei dann als TXT unter dem Namen create_database.ldif speichern. Unten werden die Berechtigungen für den Zugriff „so wie früher“ gesetzt, d.h. z.B. Moodle kann die relevanten Daten per Anonymous Bind (ja, der LDAP-Port ist an localhost gebunden) auslesen ohne das Passwort eines Bindusers im Klartext durch die Gegend zu pusten. Mit
ldapadd ‑Y EXTERNAL ‑H ldapi:/// ‑f create_database.ldif
geht es dann ab in den LDAP-Baum. Im nächsten Schritt muss diese Datenbank noch initialisiert werden. Das geht – man erkennt eine gewisse Konsequenz – wieder über eine LDIF-Datei:
# Create top-level object in domain
dn: dc=schule,dc=tld
objectClass: top
objectClass: dcObject
objectclass: organization
o: Schule Organization
dc: schule
description: LDAP Example# Admin user.
dn: cn=admin,dc=schule,dc=tld
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword: secret
Diese Datei speichert man z.B. unter populate.ldif. Jetzt wird es ein wenig anders, da wir direkt an der Wurzeldatenbank mit slapd herumpfuschen wollen und er uns das nur mit einem echten Bind tun lässt – brav:
ldapadd ‑x ‑D cn=admin,dc=schule,dc=tld ‑W ‑f populate.ldif
Er fragt uns dann nach dem Passwort („secret“) aus der create_database.ldif. Wenn wir es im geben, ist danach alles so wie unter früheren slapd-Versionen mit einer schlichten Konfigurationsdatei statt eines config-Baumes.
phpldapadmin
phpldapadmin ist zwar feige, aber kann hübsch zur Kontrolle darüber verwendet werden, was man wieder einmal mit seinen Kommandozeilenscripten zum Befüllen des LDAP verbockt hat. Das Tool beherrscht noch nicht den Zugriff auf den Konfigurationsbaum (was doof ist). Deswegen müssen wir ihm den vermeintlichen Wurzelbaum in seiner config.php unterschieben:
/*********************************************/
/* Define your LDAP servers in this section */
/*********************************************/$servers = new Datastore();
/* $servers->NewServer(‚ldap_pla‘) must be called before each new LDAP server
declaration. */
$servers->newServer(‚ldap_pla‘);/* A convenient name that will appear in the tree viewer and throughout
phpLDAPadmin to identify this LDAP server to users. */
$servers->setValue(’server‘,’name‘,‚Schulname‘);/* Examples:
‚ldap.example.com‘,
‚ldaps://ldap.example.com/‘,
‚ldapi://%2fusr%local%2fvar%2frun%2fldapi‘
(Unix socket at /usr/local/var/run/ldap) */
$servers->setValue(’server‘,‚host‘,‚127.0.0.1‘);/* The port your LDAP server listens on (no quotes). 389 is standard. */
// $servers->setValue(’server‘,‚port‘,389);/* Array of base DNs of your LDAP server. Leave this blank to have phpLDAPadmin
auto-detect it for you. */
$servers->setValue(’server‘,‚base‘,array(‚dc=schule,dc=tld‘));$servers->setValue(‚login‘,‚bind_id‘,‚cn=admin,dc=schule,dc=tld‘);
Dann ist alles wie früher – zumindest bei mir. Auf jeden Fall sollten Tools wie phpldapadmin und phpmyadmin später immer mit http-auth (z.B. .htaccess) verrammelt werden.
Ich grüble jetzt daran herum, die Mailangaben mit unter den cn’s der Personen im LDAP zu verwalten – bisher lagen die in getrennten Unterbäumen. Die qmail-Attribute sind schließlich von inetorgperson abgeleitet. Hübsch wäre ja auch, wenn man sich eigene Mailaliase und ‑weiterleitungen setzen könnte. Dummerweise wird unser Serverldap nicht vom Schulldap repliziert, sondern der Datenaustausch erfolgt einmal täglich via LDIF, weil ich wirklich nur notwendige Daten unser SuS im Netz sehen wollte. Die zusätzlichen Userdaten aus dem Web müsste man also aus z.B. einer separaten Datenbank gewinnen oder ich leite einen Unterbaum aus dem bestehenden ab… Mal schauen – das läuft ja schon alles per Script.
Viel zu technisch für mich, ich bin froh, dass ich damit nichts zu tun habe.
Einerseits verstehe ich dich da voll und ganz – andererseits werkelt in einem LDAP unter der Haube z.B. auch sowas hier: http://www.herr-rau.de/wordpress/2009/10/einfach-verkettete-liste-rekursion-und-entdeckungen-bei-powerpoint.htm. Außerdem gibt es da Dinge wie Klassen (Schema), Objekte (z.B. Benutzer), Attribute (z.B. SSHA2-Passworthash), Methoden (löschen, modifizieren…).
Wir Administratoren haben oft den Eindruck, dass an einem Ende der Skala die (theoretische) Informatik steht und am anderen Ende die touchbare App. Das ist so lange gut, wie alles funktioniert, keine individuellen Anforderungen zu erfüllen sind oder jemand damit streitbare Dinge macht/zu machen überlegt (Easycash: http://www.spiegel.de/netzwelt/web/0,1518,723028,00.html, denn dann braucht man das riesengroße Loch dazwischen – das ist die Welt der informationstechnischen Kompetenzen, so wie ich sie definiere. Ohne LDAP (ein Verzeichnisdienst) gäbe es Dinge wie Single-Sign-On oder Zertifikat-Authorities nicht (also keine eID, kein SSL…). Das ginge alles auch relational – klar, aber wenn sich Daten nicht sehr oft ändern, ist ein DBMS oft Overkill.