Kapitel 15

Verzeichnisdienstprotokoll LDAP

IN DIESEM KAPITEL

  • Baumartige, strukturierte Datenablage
  • Benutzerabfrage zentralisieren

Ein LDAP-Server liefert Daten und ist insofern vergleichbar mit einer Datenbank. Während relationale Datenbanken ihre Daten in Tabellen ablegen und sie so untereinander vernetzen, sind die Daten von LDAP hierarchisch geordnet, darum spricht man von einem Verzeichnisdienst.

Die Struktur der Datenbankeinträge sind durch die Tabelle geprägt, in der sie abgelegt sind. Die Einträge in einem Verzeichnisdienst können dagegen durch eine oder mehrere Klassen festgelegt werden. Sie können Klassen kombinieren und um eigene Elemente erweitern. Einige Klassen sind vorgefertigt und können für eigene Zwecke verwendet werden. Beispielsweise gibt es für den POSIX-Benutzer die Objektklasse posixAccount. Sie enthält die Felder uid, uidNumber und gidNumber und bildet so die Systemdatei /etc/passwd nach.

Solche Accounts sind für eine zentrale Verwaltung von Benutzern wertvoll. Darum findet man einen LDAP-Server in fast allen Netzwerken, in denen eine einheitliche Benutzerkennung erforderlich ist. Entsprechend verwenden viele Server und Anmelde-Clients die Option LDAP, um die lokale Anmeldung auszulagern.

Von allen LDAP-Implementationen dürfte OpenLDAP am weitesten verbreitet sein. Bevor Sie sich auf die Installation stürzen, sollten Sie noch ein paar grundlegende Erläuterungen ertragen.

Verzeichnisdienst

LDAP steht für Lightweight Directory Access Protocol und ist also ein Protokoll. Ein LDAP-Server ist also ein Server, der dieses Protokoll bedient.

Die Daten dieses Verzeichnisses (Directory) werden baumartig angelegt. Dabei können die Blätter eines solchen Baumes frei strukturiert werden. Die Informationen werden Attributen zugeordnet. Im Beispiel wird dem Attribut sn (surname) der Nachname und dem Attribut cn (common name) der vollständige Name zugeordnet. Der Vorname steht hinter dem Attribut givenName.

givenName:Arnold
sn: Willemer
cn: Arnold Willemer

Objektklassen

Es würde schnell kompliziert, wenn die Attributnamen bei jedem Objekt völlig frei definiert würden. Darum verwendet man Klassen, die bestimmte Attribute definieren, die Objektklassen (objectClass) genannt werden.

Die Objektklassen definieren einen Satz von Attributen und geben damit den Objekten Struktur. Beispielsweise enthält die Klasse posixAccount unter anderem die Attribute uid und gidNumber. Eine Objektklasse wird selbst wieder im LDIF-Format aufgeschrieben.

objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )

Diese Objektklasse person basiert auf der SUPerior Class top. Die Klasse top ist die Mutter aller Klassen. Mit STRUCTURAL wird beschrieben, dass sie eine Struktur von Attributen vorgibt. Dabei wird unter MUST festgelegt, dass jedes Objekt, dass eine ordentliche person sein will, auf jeden Fall das Attribut sn (surname, also Nachname) und das Attribut cn (common name) definieren muss. Erlaubt sind auch die Attribute userPassword, telephoneNumber, seeAlso und description, also alles was eine Person so gebrauchen könnte.

Einordnen in den Baum

Mit diesen Grundlagen lassen sich eigene Datenobjekte definieren, die gemeinsamen Objektklassen angehören. Dadurch sind die Attribute definiert, nach denen man suchen oder die man auswerten kann.

Alle diese Datenobjekte bevölkern einen Baum (DIT, Directory Inormation Tree), in dem diese eindeutig bestimmbar sein müssen. Als Identifikation wird ein Attribut dn (Distinguished Name) verwendet. Dieser wird zumeist aus mehreren Elementen zusammengesetzt. Im folgenden Beispiel beginnt mit dem eindeutige Schlüssel aus dem Attribut uid mit dem Wert paul. Dieser ist eindeutig im Raum dc=willemer, der wiederum eindeutig im Raum dc=edu ist. Davon ausgehend, dass es keine URL willemer.edu gibt, ist paul weltweit eindeutig und wir können diesen Baum in jeden beliebigen anderen Baum widerspruchsfrei integrieren.

dn: uid=paul,dc=willemer,dc=edu
objectClass: inetOrgPerson
objectClass: posixAccount
uid: paul
cn: Paul
sn: Willemer
uidNumber: 2002
gidNumber: 100
userPassword: {SSHA}fL402skgIMWc45mGL4PNq5LyJ1Waqqso
homeDirectory: /home/paul

Man sieht hier, dass paul die Attribute zweier Objektklassen, inetOrgPerson und posixAccount enthält. So muss auch uid noch einmal mit paul besetzt werden, obwohl es auf den ersten Blick wie eine Dopplung der dn wirkt.

Dieses Element beschreibt also das Datenobjekt paul in seiner Umgebung, mit den Objektklassen, auf denen es beruht und den Attributen, die für paul belegt werden. Diese textuelle Struktur nennt man LDAP Data Interchange Format (LDIF). In diesem Format werden Daten über das Lightweight Directory Access Protocol (LDAP) ausgetauscht.

Wir werden auf dieses Beispiel mit paul noch zurückkommen.

Installation eines LDAP-Servers

Um einen LDAP-Server zu installieren, benötigen Sie das Paket slapd. Vorher ist es immer wieder klug, die Paketlisten aktuell zu halten.

# apt update
# apt install slapd

Der Installationsassistenz wird Sie auffordern, das Administratorpasswort einzugeben und auf dem nächsten Dialog zu bestätigen. Dieses Passwort werden Sie wieder benötigen und es ist eine gute Idee, sich dieses zu merken.

OPENLDAP erstellt eine Standardkonfiguration, die Sie über Konfigurationsdateien anpassen können. Etwas einfacher wird es, wenn Sie eine Paket-Rekonfiguration durchführen:

# dpkg-reconfigure slapd

Dieser Befehl spornt den Assistenten dazu an, ein paar detailliertere Fragen zu stellen.

  • Die erste Frage, nämlich, ob Sie die OPENLDAP-Server-Konfiguration auslassen, beantworten Sie mit »Nein«. So wird eine neue Konfiguration und Datenbank angelegt.
  • DNS-Domainname: Hier wird die Domäne eingegeben, die für das lokale Netzwerk gilt. Ich verwende hier willemer.edu. Daraus wird LDAP dann dc=willemer,dc=edu generieren. Sie können und werden vermutlich eine eigene Domain verwenden wollen.
  • Organisation: Hier kann irgendetwas im Klartext erscheinen, auch gern noch einmal der Domain-Name.
  • Nun wird das LDAP-Administrationspasswort eingegeben und im nächsten Bildschirm bestätigt.
  • Datenbank: Hier sollte eine eventuell noch bestehende Datenbank vernichtet werden, also antworten Sie mit »Ja«. Und dann soll konsequenterweise die alte Datenbank verschoben werden.

Nun kann man den LDAP-Server starten und schauen, ob dieser auch tadellos läuft.

# systemctl restart slapd
# systemctl status slapd

Und schon kann man die erste Abfrage stellen. Dazu gibt es den Befehl ldapsearch, der durch die Installation schon zur Verfügung stehen sollte. Im Zweifelsfall müssten Sie das Paket ldap-utils nachinstallieren. Der Befehl testet zunächst, ob eine saubere Installation vorliegt.

# ldapsearch -x
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1

Verzeichnisaufbau per LDIF

Um LDAP besser verstehen zu können, ist ein konkretes Beispiel wichtig. Durch die Flexibilität des Konzepts verliert man sonst leicht den Überblick. Da LDAP allgemein gern für die Authentifizierung verwendet wird, soll ein Verzeichnis für Linux-Benutzer erstellt werden. Da ein Linux-Benutzer immer auch zu einer Gruppe gehört, sollte man die Gruppen gleich in das Konzept mit aufnehmen.

Um POSIX-User verwalten zu können, drängt es sich auf, Benutzer und Gruppen zu unterscheiden. Beide haben einen ordnenden Charakter und darum definieren wir sie als organizationalUnit.

Definitionen werden als LDIF an den Server übertragen und im Verzeichnis abgelegt. Es hat sich bewährt, diese Definition erst einmal in einer Datei niederzuschreiben und diese dann zu verschicken. So können Tippfehler in Ruhe beseitigt werden, bevor Sie im Server landen.

Wir erstellen eine Datei namens base-ou.ldif. Der Name ist natürlich beliebig. Unsere Datei base-ou.ldif enthält gleich zwei Einträge, einen Eintrag für Benutzer und einen für Gruppen. Beide müssen durch mindestens eine Leerzeile voneinander getrennt sein.

dn: ou=Benutzer,dc=willemer,dc=edu
objectClass: organizationalUnit
ou: Benutzer

dn: ou=Gruppen,dc=willemer,dc=edu
objectClass: organizationalUnit
ou: Gruppen

Diese Datei kann durch den Befehl ldapadd eingefügt werden. Die Option -D gibt an, unter welchem Account dieser Eintrag erfolgt. Wir tragen ihn als Administrator des LDAP-Servers ein. Der Administrator wird durch die Kombination cn=admin,dc=willemer,dc=edu eindeutig beschrieben. Es ist wichtig, dass dazwischen kein Leerzeichen gesetzt wird. Die Option -W bewirkt, dass das Passwort für den Administrator direkt in der Konsole eingetippt werden muss.

# ldapadd -x -D cn=admin,dc=willemer,dc=edu -W -f base-ou.ldif
Enter LDAP Password:
adding new entry “ou=Benutzer,dc=willemer,dc=edu”

adding new entry “ou=Gruppen,dc=willemer,dc=edu”

Wir legen nun eine Gruppe users an. Unter Linux benötigt ja jeder Benutzer eine Gruppe. Heute ist es üblich, jedem Benutzer eine eigene Gruppe zuzuordnen. In den guten alten Zeiten gab es einfach die Gruppe users für alle. Um uns das Leben etwas einfacher zu machen, reden wir uns auf diese Tradition heraus. Die Gruppe users gibt es noch heute. Sie ist in der Datei /etc/group unter der gid 100 zu finden. LDAP kennt für POSIX-Gruppen die Objektklasse posixGroup Den Eintrag der Gruppe users erledigen wir in einer Datei oc-users.ldif.

dn: cn=users,dc=willemer,dc=edu
objectClass: posixGroup
cn: users
gidNumber: 100

Auch diese Datei wird per ldapadd hinzugefügt.

# ldapadd -x -D cn=admin,dc=willemer,dc=edu -W -f oc-users.ldif
Enter LDAP Password:
adding new entry “cn=users,dc=willemer,dc=edu”

Jeder Benutzer wird ein Passwort benötigen. Da Administratoren spontan heftige Zahnschmerzen bekommen, wenn sie Passwörter im Klartext speichern oder über die Leitung senden sollen, müssen wir das Passwort vor dem Senden verschlüsseln. Dazu verwenden wir eine sichere Hash-Funktion, englisch als Secure Hash Algorithm (SHA) bekannt ist. Um ein so verschlüsseltes Passwort zu erzeugen, gibt es den Befehl slappasswd.

linux@mintmate:˜$ slappasswd
New password:
Re-enter new password:
{SSHA}fL402skgIMWc45mGL4PNq5LyJ1Waqqso

Nun ist alles bereit, um den Benutzer paul einzutragen. Wir erzeugen eine LDIF-Datei user-paul.ldif. Dort kopieren wir das erzeugte Passwort unter dem Attribut userPassword.

dn: uid=paul,dc=willemer,dc=edu
objectClass: inetOrgPerson
objectClass: posixAccount
uid: paul
cn: Paul
sn: Willemer
uidNumber: 2002
gidNumber: 100
userPassword: {SSHA}fL402skgIMWc45mGL4PNq5LyJ1Waqqso
homeDirectory: /home/paul

Nun wird der Benutzer paul mit dem Befehl ldapadd eingetragen.

# ldapadd -x -D cn=admin,dc=willemer,dc=edu -W -f user-paul.ldif
Enter LDAP Password:
adding new entry “uid=paul,dc=willemer,dc=edu”

Damit haben wir einen LDAP-Server erstellt, der sich für das Login eines Linux-Clients eignet. Durch den Einsatz verschiedener Objektklassen lassen sich die Daten nicht nur um Attribute erweitern, sondern auch völlig andere Informationen speichern.

LDAP-Client Login

Ein LDAP-Server kann für das Login eines Arbeitsplatzrechners verwendet werden. Damit reicht es, einen Benutzer einmal im Netzwerk zu definieren und er kann sich mit demselben Passwort an allen Arbeitsplätzen anmelden, ohne dass es einen Account für ihn auf diesem Rechner gibt. Als Beispiel wird Linux Mint mit der grafischen Oberfläche MATE verwendet. Es würde aber grundsätzlich mit allen POSIX-Systemen funktionieren.

Um das Einloggen im Netzwerk zu zentralisieren, bietet Linux zwei Mechanismen.

Um den Login mit LDAP zu ermöglichen, müssen die Libraries installiert werden, die dafür sorgen, dass NSS und PAM mit LDAP zusammenarbeiten können.

# apt update
# apt install libnss-ldapd libpam-ldapd

Die Installation fragt nach der URL des LDAP-Servers. Für den LDAP-Server, den wir im vorigen Abschnitt installiert haben, kann man einfach dessen IP-Nummer verwenden. Der LDAP-Server, mit dem ich getestet habe, hatte die IP-Adresse 192.168.109.199. Wenn Sie auf einen fremden LDAP-Server zugreifen wollen, müssen Sie dessen Adrese hier angeben.

ldap://192.168.109.199

Dann fordert die Installation den »Distinguished name of the search base«. Hier wird der DN des LDAP-Baums eingetragen, in dem die POSIX-Accounts gespeichert werden.

dc=willemer,dc=edu

Im nächsten Schritt wird gefragt, welche Namensdienste durch den NSS per LDAP zugegriffen werden soll. Für das Login werden auf jeden Fall passwd, group und shadow benötigt. Damit schließt die Installation.

Konfiguration des NSS

Sie können sicherheitshalber noch einmal prüfen, ob die richtigen Einträge in der Datei /etc/nslcd.conf stehen. Das kann in besonderen Konstruktionen schon einmal schiefgehen.

# The location at which the LDAP server(s) should be reachable.
uri ldap://192.168.109.199

# The search base that will be used for all queries.
base dc=willemer,dc=edu

Wenn Sie weitere Basen benötigen, können diese einfach untereinander geschrieben werden. Beispielsweise könnte es verschiedene Basen für Angestellte, Freiberufler und Kunden geben.

Der Blick in die Datei /etc/nsswitch.conf ist sehr aufschlussreich. Dort sind passwd, group und shadow um den Eintrag ldap ergänzt worden.

# /etc/nsswitch.conf
passwd: files systemd ldap
group: files systemd ldap
shadow: files ldap
gshadow: files
hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname
networks: files

Es wird auch die Reihenfolge festgelegt. Bei shadow wird zunächst in die lokale Datei geschaut und erst, wenn dort nichts steht LDAP gerufen.

Umgang mit dem Heimatverzeichnissen

Wenn alles klappt, wird LDAP melden, dass sich der Benutzer paul gern auf diesem System anmelden kann. Wenn aber paul dort kein Verzeichnis /home/paul vorfindet, wird die Anmeldung nicht glücken. Für dieses Problem gibt es zwei sehr unterschiedliche Lösungsansätze:

  1. Das Verzeichnis wird bei jeder Anmeldung von einem zentralen Server hinter dem lokalen Verzeichnis /home eingehängt. Das Handwerkzeug dafür heißt NFS und Automount. Beides wird im Kapitel 13 beschrieben.

    Dieser Ansatz hat den Charme, dass der Benutzer beliebig den Arbeitsplatz wechseln kann und überall die gleiche Arbeitsumgebung vorfindet.

  2. Das Verzeichnis wird bei der ersten Anmeldung erstellt und bleibt erhalten, wenn sich der Anwender ein weiteres Mal anmeldet.

    Dieser Ansatz hat den Vorteil, dass der Zugriff auf lokale Festplatten in der Regel schneller abläuft. In manchen Fällen ist ein Auslagern auch schwierig bis unmöglich.

Den ersten Ansatz können Sie in Kapitel 13 sehen, den zweiten werden wir gleich hier umsetzen.

Um das PAM dazu zu bringen, ein Verzeichnis für den angemeldeten Benutzer anzulegen, können Sie den Befehl pam-auth-update aufrufen. Nach dem Starten erscheint ein Dialog, in dem PAM-Profile freigeschaltet werden können. Eines davon lautet Create home directory on login. Dieses tut genau das Gewünschte und hat darum einen Haken verdient.

Als Konsequenz wird beim ersten erfolgreichen Login ein lokales Home-Verzeichnis angelegt. Bei späteren Logins findet der Anwender den letzten Stand vor.

Anmeldebildschirm konfigurieren

Wie fast immer bleibt noch etwas Handarbeit an unerwarteter Stelle. Der aktuelle Anmeldebildschirm von MATE zeigt für das Login alle Benutzer, die in der lokalen Datei /etc/passwd eingetragen sind. Damit stehen Benutzer, die nur im LDAP bekannt sind, vor verschlossener Tür, einfach weil man keinen unbekannten Benutzernamen eintippen kann.

Unter MATE finden Sie dem Menü SYSTEMVERWALTUNG den Punkt ANMELDEFENSTER. Ähnliche Konfigurationsmöglichkeiten gibt es auch bei anderen grafischen Desktops. Für eine Änderung benötigen Sie das Administrator-Passwort. Unter der Lasche BENUTZER gibt es einen Schalter »Manuelles Anmelden erlauben«. Dieser muss gesetzt sein. Leider ist das einer der wenigen Situationen, in denen Sie auch einen Linux-Rechner neustarten müssen, damit die Konfigurationsänderung wirksam wird.

Beim nächsten Anmelden erscheint ein zusätzliches Feld namens ANMELDEN. Wenn Sie dieses anklicken, erscheint ein Eingabefeld für einen beliebigen Benutzernamen und dann auch für das Passwort.

Passwort ändern

Der Benutzer kann auf der Konsole sein Passwort sogar selbst ändern. Dazu ruft er einfach den gewohnten Befehl passwd auf:

$ passwd
(current) LDAP Password:
Geben Sie ein neues Passwort ein:
Geben Sie das neue Passwort erneut ein:
passwd: Passwort erfolgreich geändert

Leider funktioniert die Passwortänderung nicht über die grafische Oberfläche von MATE. Aber irgendetwas ist ja immer…