LDAP (Schwerpunkt OpenLDAP)
Lightweight Directory Access Protocol (LDAP) ist ein Anwendungsprotokoll aus der Computertechnik. Es erlaubt die Abfrage und die Modifikation von Informationen eines Verzeichnisdienstes (eine im Netzwerk verteilte hierarchische Datenbank: absoluter Pfad kennzeichnet Datensatz) über das TCP/IP Netzwerk. Die aktuelle Version ist in RFC 4511 spezifiziert.
Das LDAP-Protokoll wird in vielen bekannten Verzeichnisdiensten (und Servern) benutzt:
- Slapd (University of Michigan, Openldap)
- Netscape Directory Server
- Microsoft Active Directory (AD)
- Microsoft Exchange
- Novell Directory Services (NDS)
- Lotus Domino
- Sun Directory Services (SDS)
- Lucent’s Internet Directory Server (IDS).
LDAP ist für relativ einfache Lesezugriffe optimiert. Man kann zwar mit boolschen Ausdrücken arbeiten, es findet aber keine Sortierung durch den LDAP-Server statt. D.h. die Datensätze kommen in beliebiger Reihenfolge, da die LDAP-Entwickler der Meinung sind, so etwas gehört auf dem Client implementiert (auch um die Serverlast zu minimieren).
Der LDAP-Server hat ein sog. Schema (=genormte und ggf. erweiterte Struktur), das das Format der Datensätze (Entrys) mit ihren Attributen definiert.
Das Schema legt die Regeln für gespeicherten Daten fest (benötigte und erlaubte Attribute) und hilt so die Daten konsistent zu halten. Dabei sollte man sich aus Kompatibilitätsgründen möglichst an vordefinierte Schemata halten bzw. bei sog. Schemaerweiterungen möglichst ein vorhandenes erweitern. Vordefinierte Objektklassen stehen in der Datei /etc/openldap/schema/core.schema
.
Ein Datensatz (Entry) hat eine oder mehrere Objektklassen (Objectclass) die zum gruppieren der Informationen benutzt werden und benötigte und erlaubte Attribute festlegt. Der Datensatz ist ein Knoten im Baum (DIT: directory information unit).
Zusätzlich können Aliase (Eintrag mit Objektklasse Alias, Attribut namens „aliasedObjectName“ die auf den DN verweist) angelegt werden.
LDAP ist flexibler als das angegraute NIS: Dieses ist formatgebunden, wenig Möglichkeiten bei den Zugriffsrechten (ACLs) und kann keine Verschlüsselung. Zudem wird autofs als NIS-Ersatz benutzt.
LDAP-User-IDs (UIDs) mit gutem Abstand zu den System UIDs anlegen (falls man später noch lokale Benutzer anlegen will).
Authentifizierung kann auch von Kerberos vorgenommen werden.
Einsatz
LDAP kann sehr gut bei klassischen Einsatzzwecken eines Verzeichnisdienstes eingesetzt werden: Bei verteilten Daten wie Adressbücher für Anwendungen und MUAs (Thunderbird, ..), fingerd, … .
Die Integration in Programme erfolgt entweder über die Shell-Befehle (Änderungsanweisungen im LDIF-Format), Bibliotheken und native Funktionen.
LDIF-Format
Das LDIF-Format
- repräsentiert LDAP-Einträge in (menschenlesbarer) Textform
- erlaubt eine einfache Datenänderung
- ist nützlich für Massenänderungen: DB in LDIF, Skript drüber jagen, importieren
- kann Vorlagen benutzen
- dient zum Backup und zum Datentransfer zu anderen Systemen
dn: uid=user1,ou=People, dc=mycompany,dc=com uid: user1 cn: User One objectclass: account objectclass: posixAccount objectclass: top loginshell: /bin/bash uidnumber: 500 gidnumber: 120 homedirectory: /mnt/home/bmarshal gecos: Brad Marshall,,,, userpassword: {crypt}KDnOoUYN7Neac
Anmerkung zu „userpassword“ hier wird der verwendete Hash (crypt) in geschweiften Klammern angegeben. Es sind serverseitig mehrere Hash-Algorithmen möglich, die dann auch vom Server verwaltet werden und eine spätere Migration zu einem anderen Hash-Algorithmus problemlos möglich machen (ohne dass alle sofort ihre Passwörter ändern müssen).
Datenbank zu LDIF und zurück
- ldbmcat & slapcat: ldbm Datenbank zu LDIF
- ldif2ldbm & slapadd: LDIF zu ldbm Datenbabk
Begriffe
Beispiel: uid=bmarshal,ou=People,dc=mycompany,dc=com
DN | distinguished name Eindeutiger Name bzw. der Pfad zu einem Objekt: uid=user1,ou=People,dc=mycompany,dc=com |
RDN | Relative Distinuished Name der relative Name in Verhätlnis zu einem Objekt: uid=user1 |
Base DN | Der „Basiseinsprungspunkt“: ou=People,dc=mycompany,dc=com . Am besten den schon vorhandenen DNS-Namen benutzen. |
DIT | Directory Information Tree |
LDIF | LDAP Data Interchange Format: Format zum Datenaustausch, kann auch für den Austausch der Konfiguration benutzt werden |
Objekte
- Containerobjekte sind objekte die weitere enthalten, z.B. CN, OU, O und DC.
- Blattobjekte
Attribute
Der Datensatz setzt sich aus Attributen zusammen, die wiederum Werte eines bestimmten (Daten-) Typs enthalten. Attribute haben
- einen Namen
- eine OID (siehe Tabelle)
- eine Syntax (Datentyp und wie die Wert verglichen können)
- eine Anweisung ein oder mehrere Werte zu enthalten
Attributname | Bedeutung |
---|---|
C | Country (= Land) |
CN | Common Name der Name des Objektes unter dem das Objekt gewöhnlich angesprochen wird |
DC | Domain Component |
DESC | Description, menschenlesbare Beschreibung |
L | Location, Bezeichnung eines geografischen Ortes |
OID | Objectidentifier, String der aus einer (von Punkten unterbrochenen) Folge von Dezimalzahlen, z.B. hat Microsoft die OID 1.2.840.113556.* und man kann sich die durch RFC 1065 reservierten OIDs 1.3.6.1 nehmen. Als Firma beispielweise die 1.3.6.1.4.1.* . Eine eigene OID benötigt man, wenn sich eigene Atrributtypen definieren möchte und man sich weltweit vernetzt (IPv6?). OIDs werden kostenlos durch die IANA vergeben. |
SN | Surname (=Nachnahme) |
O | Organisation (=Name der Organisation/Firma) |
OU | Organisational Unit (=Organisationseinheit, z.B. Abteilung) |
ST | State (=Bundesstaat) |
UID | user id (=Benutzername) |
Siehe RFC2256 - A Summary of the X.500(96) User Schema for use with LDAPv3
Regeln
Verwaltungstools
- Die mitgelieferten (kommandozeilenbasierten-) Such-/Bearbeitungstools: ldapsearch, -modify, …
- Luma - LDAP browser + utility (Python, PyQt und python-ldap)
- phpLDAPadmin (PHP)
- GQ - LDAP client (GTK+)
- LDAP Browser/Editor (Java)
- JXplorer - A Java Ldap Browser
- Softerra LDAP Browser (Freeware, Windows)
- GOsa² - Der GONICUS System Administrator (GPL, web)
OpenLDAP
OpenLDAP läuft auf den meisten UNIX-basierten Systemen: FreeBSD, Linux, NetBSD, OpenBSD und Windows (http://lucas.bergmans.us/hacks/openldap/|Homepage des Ports). . Siehe OpenLDAP Homepage.
OpenLDAP arbeitet mit den Modulen
- nss_ldap (für weniger sensible Daten)
- pam_ldap (authentication und Passwortänderungen)
nss_ldap
nss_ldap eignet sich nur für wenig sensible Daten: user-id, shell, …
Es wird in der Datei /etc/nsswitch.conf
konfiguriert.
passwd: files ldap shadow: files ldap hosts: files dns
Eine Delegation von Unterbereichen ist möglich (man kann Teile mounten). Der Datenaustausch wird in den Formaten
- LDIF (Einträge der Form „Attribut: Wert“ in einer Textdatei)
- ?
pam_ldap
Für sensible Daten wie Passwörter eignet sich eher pam_ldap
.
Die Abfragen beschränken sich meist auf:
- ldap_simple (zum Passwortüberprüfen; ohne SASL-Schicht): Klartext (aber über TLS), der Hash wird vom Server berechnet (transparent für den Client)
- SASL external (beide Zertifikate: Server und Client) ohne SASL
Lesezugriff über LDAP-URLs
RFC 2255 - LDAP URL Format (ersetzt RFC1959): Format für LDAP-Urls und mit Lesezugriff.
Aufbau LDAP-URL, vereinfacht:
- Protokoll ldap / ldaps (verschlüsselt)
- Servername und Portnummer
- BASE-DN (Einsprungspunkt)
- auszulesende Attr.
- Suchbereich (scope)
- Boolscher Filterausdruck
- Erweiterungen
Also z.B.: ldaps://ldap.mycompany.com/dc=bar,dc=com?cn?sub?uid=user1
Komplett aus RFC 2255:
ldapurl = scheme "://" [hostport] ["/" [dn ["?" [attributes] ["?" [scope] ["?" [filter] ["?" extensions]]]]]] scheme = "ldap" attributes = attrdesc *("," attrdesc) scope = "base" / "one" / "sub" dn = distinguishedName from Section 3 of [1] hostport = hostport from Section 5 of RFC 1738 [5] attrdesc = AttributeDescription from Section 4.1.5 of [2] filter = filter from Section 4 of [4] extensions = extension *("," extension) extension = ["!"] extype ["=" exvalue] extype = token / xtoken exvalue = LDAPString from section 4.1.2 of [2] token = oid from section 4.1 of [3] xtoken = ("X-" / "x-") token
Suchfilter und Suchbereich
Suchfilter | |
---|---|
Operatoren | Wirkung |
& | and (=und) |
| | or (=oder) |
! | |
̃= | approx equal (=vorraussichtl. gleich) |
>= | greater than or equal (=größer gleich) |
⇐ | less than or equal (=kleiner gleich) |
* | any (=alle) |
Suchbereich | |
---|---|
base | beschränkt auf den Basisbereich |
onelevel | beschränkt auf den direkten Nachfolgelevel |
sub | durchsucht den kompletten Unterbaum |
Zugriffsrechte (ACLs)
Zugriffsrechte lassen sich fein granular zuweisen.
access to dn.sub="ou=, .." by self write by * auth
by * auth: nur fragen
Die erste zutreffende Regel gilt!
beiligte "Schichten"
- Datenbank-Backend (meist Berkeley DB = BDB, andere möglich: SQL etc., wenn man keinen guten Grund hat: beibehalten; An Indices und Caches denken!)
- Anwendung
- SASL
- TLS
- TCP/IP
Replikation
Durch ein Replication-Logfile (Übertragung mit slurpd) ist auch ein Backupserver (Slave) möglich, das delegieren einzelner Teile bleibt ebenfalls möglich.
Damit wird die
- Verlässlichkeit
- Verfügbarkeit (durch mehrere Server, master:lesen+schreiben und slaves=Backupserver:nur-lesen; Eleminierung des „single point of failure“)
- Geschwindigkeit: Sowohl durch örtliche Nähe (langsame Verbindungen) als auch durch Lastverteilung (Suchanfragen)
erhöht.
Temporäre Inkonsistenzen sind ok, geschrieben wird eh nicht allzu oft.
Replikationsablauf: Verweise (Referrals)
- Client sendet Änderungen an den slave-Server
- slave-Server gibt den Verweis an den master zurück
- Client sendet Änderungen diesmal an den master-Server
- master-Server gibt das Änderungsergebnis an den Client zurück
- master-Server gibt die Änderungen an den slave-Server weiter
Replikationsablauf: Verketten (Chaining)
- Client sendet Änderungen an den slave-Server
- slave-Server leitet den Änderungswunsch an den master weiter
- master-Server gibt das Änderungsergebnis an den slave-Server zurück
- slave-Server schickt Ergebnis an den Client weiter
- master-Server gibt die Änderungen an den slave-Server weiter
Links
Hilfen / Anleitungen
- openldap.org (Doku, FAQ)
Die mitgelieferten man-pages (Hileseiten)
man slapd.conf
man slapd.access
man slapd
Probleme
- nur ein master catalog server zu einer Zeit pro domain (noch aktuell? )
- Da OpenLDAP (vor allem beim Server) sehr aktiv entwickelt wird, ist die Doku (vor allem die man-pages) oft hinterher (z.B. werden veraltete Funktionen beschrieben) wenn man aus dem Quellcode kompiliert. Deshalb sollte man nicht allzu oft upgraden. Wenn man eine vorkompilierte Version einer Distribution (z.B. aus Debian) benutzt, wird das Problem (hoffentlich) geringer ausfallen, da auf einer stabilen Version verblieben wird und der Paketbetreuer (maintainer) sich mehr drum kümmern sollte.
- kryptische Fehlermeldungen
- ACL erst „nach und nach“ machen (und testen!)
- NICHT für viele Schreibzugriffe geeignet!
- komplexe Abfrage und Strukturänderungen sind ein großes Problem
- keine Transaktionen (add / modify sind aber atomar) / kein Locking
best-practises
- Backups machen und/oder Daten replizieren
- man kann komplette Server migrieren/replizieren durch „dump“ der Konfiguration und Daten
- Server mit persönlichen Daten vor Zugriff schützen (Slave-Server öffentlich (ro), Master-Server intern)
- DB-Strukturen sorgfältig planen, Attribute (z.B. „memberOf:“), möglichst vordefinierte (Kompatibilität)
- Keep it simple!
- keine Schreibzugriff durch Applikationen
Links
Installation
Authentifizierung an LDAP
Administration
Anwendungen
Linux Journal LDAP-Serie
SSSD
Firewalling:
- 53 (udp/tcp) dns → AD
- 88 (udp+udp) kerberos
- 389 (tcp+udp) LDAP
- 445 tcp AD GPOs
- 464 (udp+udp) kpasswd
- 636 (tcp) LDAP TLS
- 3268 (tcp) Ad global catalog
- 3269 (tcp)
SASL
SASL Bind (RFC 2829)
PHP-Code
LDAP Funktionen von PHP. Benutzer mit PHP gegen ein Active Directory (LDAP) authentifizieren Webzentriert - Zugriff auf LDAP-Daten mit PHP
Sonderwünsche
- Overlays: zwischen dem Datenbank-backend und Anwendungsschicht kann man eigene Overlays einfügen die dann Anfragen modifizieren, abkürzen usw.
Beispiel: eigene eMail-Adresse mit Verfallsdatum und Signatur modifizieren:
bbmail: http://www.best-before.qipc.org