Opensuse 12.1 – LDAP V

Im letzten Beitrag “Opensuse 12.1 – LDAP IV” hatten wir uns mit Password Policy Objekten auf dem LDAP Server befasst. Nun wollen wir einen weiteren Schritt in Richtung auf eine LDAP-basierte Userverwaltung in einem (kleinen) Opensuse-basierten Netzwerk gehen. Ich setze hierbei die Lektüre der früheren Beiträge “LDAP I” bis “LDAP IV” voraus.

Wir haben in den vorhergehenden Beiträgen erkundet, was man tun muss, um User mittels YaST2 auf dem LDAP-Server anzulegen und zu verwalten. Wir hatten auch gesehen, dass und wie wir uns über Binds vom LDAP-Server für einen Login auf anderen Hosts im Netzwerk authentisieren und autorisieren lassen können . Das lokale PAM auf dem jeweiligen Host sorgt dabei – wenn erforderlich – für die Anlage eines Home-Verzeichnisses bei einem initialen Login. Zudem hatten wir uns damit auseinandersetzt, wie eine zentrale LDAP Password Policy mit den lokalen PAM-Prüfmodulen auf den Netzwerk-Hosts zusammenwirkt.

Noch nicht geklärt haben wir dagegen, was wir tun müssen, um den Zugang von einzelnen Usern auf definierte Hosts im Netzwerk zu begrenzen. U.a. soll sich ja nicht jeder User auf dem sicherheitsrelevanten LDAP-Server einloggen können. Es geht uns also um eine host-bezogene Zugangsautorisierung über LDAP. Interessiert sind wir dabei an einer Politik, die nicht zulässt, was nicht explizit erlaubt ist.

In unserem Muster-Scenario gibt es   – wie in den früheren Beiträgen auch –   einen OpenLDAP-Server “vms2” auf Basis von Opensuse 12.1 und einen weiteren Opensuse 12.1-Host “vms1” im Netzwerk, auf dem unsere gewöhnlichen User arbeiten sollen. Das letztere System repräsentiert einen beliebigen Opensuse-Host in unserem Netzwerk. Das Setup der beiden Systeme hatten wir in den Beiträgen “LDAP I” bis “LDAP IV” ausführlich besprochen.

Ein simpler, aber unzureichender Ansatz für die Zugangsbeschränkung zum Server

Im Beitrag “LDAP II” hatten wir uns die Erweiterung der “/etc/passwd” um den Verweis auf NIS/LDAP-Accounts angesehen. Nun könnte man zum Schutz des LDAP-Servers “vms2” auf den Gedanken kommen, jeglichen Login von Usern, die über LDAP verwaltet werden, durch ein “/sbin/nologin” oder /bin/false” zu unterbinden, indem man aus der letzten Zeile der “/etc/passwd” auf “vms2”

+::::::

ein

+::::::/sbin/nologin

oder ein

+::::::/bin/false

macht.

Das ist sehr wirksam, aber eben auch nur auf diesen Server begrenzt und dort bzgl. der User nicht besonders selektiv. Ggf. will man auch einem über LDAP verwalteten User Zugriff auf den LDAP_Server gewähren. Wir belassen unsere “/etc/passwd”-Einträge daher lieber in der ursprünglichen Form.

Auf einem anderen Host als “vms2” nutzt uns das beschrieben Verfahren sowieso herzlich wenig:
Auf den normalen Hosts sollen sich ja gerade zumindest einige der über LDAP verwalteten User einloggen dürfen. Wenn auch vielleicht nicht alle …

Wir brauchen im Netz also ein Verfahren, bei dem userspezifisch entschieden werden kann, zu welchem Host ein User Zugang erhält und zu welchem nicht.

Zwei LDAP-basierte Standardverfahren zur Zugriffssteuerung

In diesem Artikel bespreche ich deshalb zwei einfache Methoden, mit deren Hilfe man es in einem kleinen Netzwerk schafft, Usern, die über einen zentralen LDAP-Server verwaltet werden, einen Zugang nur auf vordefinierte Hosts zu gewähren. Die Host-User-Relationen, die erlaubt sind, werden dabei auf dem LDAP-Server selbst hinterlegt.

Kennzeichnend für diese Verfahren ist Folgendes:

  • Verfahren 1: Im Verfahren 1 analysiert der LDAP-Server im Auftrag des “pam_ldap”-Moduls eines Netzwerk-Hosts den Inhalt eines Zusatzfeldes “host”, das man den Useraccounts auf dem LDAP-Server hinzufügen muss. Über diesen Feldtyp werden explizit alle Hosts aufgelistet, zu denen der User Zugang erhalten soll. Man baut in diesem Verfahren also eine (1:n)-Relation der Form “User >> hosts” auf und betrachtet die Zugangserlaubnis aus Sicht des Users.
  • Verfahren 2: Das zweite Verfahren basiert dagegen auf dem Aufbau einer Host-Verwaltung in einem dafür geeigneten Ast – z.B. ou=hosts – des LDAP-Verzeichnisbaum. Jedem Hosteintrag wird dann über ein spezielles Feld “uniquemember” eine Liste von registrierten Usern aus dem Zweig “ou=people” zugeordnet. Man baut in diesem Verfahren also eine (1:n)-Relation der Form “host >> user” auf und betrachtet die Zugangserlaubnis aus Sicht des Hosts.

Welches Verfahren man bevorzugt, ist mehr eine Frage der Philosophie und der Pflege-Technik. Die Anzahl der einzutragenden Sätze bleibt letztlich gleich:

Für jeden User und jeden Host, zu dem der Zugang erlaubt werden soll, muss in beiden Verfahren explizit ein Eintrag angelegt werden. Beim ersten Verfahren kann man die Host-Zuordnung jedoch bereits während der Useranlage mit erledigen. Im zweiten Verfahren muss der Administrator bei der Anlage neuer User dagegen explizit daran denken, den User danach auch bei ausgewählten Host-Objekten des LDAP-Baums explizit zu hinterlegen.

Ich persönlich finde die zweite Variante in einem kleinen Netzwerk etwas besser:

Erstens ist die Anlage einer Liste von Hosts auf dem LDAP-Server auch für andere Zwecke – wie etwa die LDAP-Unterstützung von Samba etc. – eine sehr gute Idee. Zweitens zwingt sie einen regelmäßig dazu, darüber nachzudenken, wer eigentlich auf welchem Rechner werkeln soll. Und wenn man tatsächlich mal einen Eintrag für einen Host vergessen sollte – es schadet nicht wirklich. Die User rühren sich bestimmt.

Bei beiden Verfahren ist es übrigens so, dass man die LDAP-Client-Konfiguration auf allen zu schützenden Hosts um bestimmte Einträge erweitern muss. Wir werden weiter unten zudem sehen, dass beide Verfahren dabei sogar kombiniert werden können.

Verfahren 1: Zugangskontrolle über das Attribut “pam_check_host_attr”

Der LDAP-Server soll in diesem Verfahren bei einem Login-Versuch auf einem Host von eben diesem Host aufgefordert werden, einen “host”-Eintrag in den LDAP-Daten des Users zu kontrollieren. Hierzu sind einerseits Änderungen an der Datei “/etc/ldap.conf” auf dem betroffenen Host erforderlich. Andererseits muss das “host”-Feld in den Userdaten des LDAP-Servers vorhanden und gefüllt sein.

Wie aber ergänzen wir nun auf dem LDAP-Server die User-Einträge unter dem Zweig   “ou=people”   um das benötigte “host”-Feld? Ein Blick mit dem YaST2-LDAP-Browser zeigt uns nämlich schnell, dass dieses Feld bisher leider nicht angelegt worden ist.

Bis zu diesem Zeitpunkt hatte uns YaST2 weitgehend von solchen “Niederungen” des Umgangs mit dem LDAP-Server abgeschirmt. Nutzen wir YaST2 zur Userverwaltung, so werden neue User-Einträge im Zweig “ou=people, dc=anracona,dc=de” unseres LDAP-Servers “vms2” fix und fertig aufbereitet angelegt. Nun sind wir auch als eventuelle LDAP-Beginner gezwungen, ein wenig über den Tellerrand von YaST hinausblicken.

Die Felder, die zu jedem Objekt im LDAP-Baum erfasst werden können, entsprechen den Möglichkeiten, die sich aus einer Kombination von “LDAP-Objektklassen” ergeben. Letztere werden wiederum über LDAP-Schemata bereitgestellt, die auf unserem LDAP-Server geladen sein müssen. Wie man sich mit YaST2 ein Übersicht über die auf dem LDAP-Server installierten Schemata verschaffen kann, hatte ich u.a. im Beitrag “LDAP IV” gezeigt.

Ein konkretes Objekt des LDAP-Baumes erhält seine Felddefinitionen also aus einer für das Objekt getroffenen Festlegung hinsichtlich seiner konstituierenden Objektklassen. Diese Festlegung wird im Objekt selbst hinterlegt. Die Felddefinitionen einer einzelnen Klasse sind dabei eindeutig. Es gibt unter den Feldern einer Objektklasse – wie in anderen Datenbanken auch – in der Regel einige Mussfelder, die man bei der Anlage eines konkreten Objektes mit einem Wert belegt muss.

Für ein neues, weiteres Feld muss man einem LDAP-Objekt daher eine neue Objektklasse zuordnen, die im Rahmen eines der auf dem Server geladenen Schemata definiert ist. Daneben gibt es noch die Möglichkeit, ein konkretes Objekt zu einem sog. “Extensible Object” zu machen. Einem solchen Objekt können dann einzelne weitere Felder aus dem Schema-Vorrat hinzugefügt werden.

In unserem Fall benötigen wir zusätzlich zu den Feldern, die unsere User-Einträge bisher aufweisen, nur noch genau ein Feld – nämlich eines des Typs “host”.

An dieser Stelle unserer Überlegungen prüfen wir über YaST2’s LDAP Browser mal, welche Objektklassen die YaST2 “User- und Gruppenverwaltung” unseren Usereinträgen bei deren Anlage im LDAP-Baum eigentlich zugewiesen hat:

ldap 97

Wir erkennen die Klassen

  • “top”,
  • “PosixAccount”,
  • “InetOrgPerson”.

Diese Kombination wurde sicher nicht ohne Grund von SuSE’s Entwicklern ausgewählt. Daran wollen wir vorsichtshalber auch nichts verändern. Allerdings kann ein Festhalten an einer Objektklassen-Kombination dann problematisch werden, wenn sich eine weitere, zusätzliche Objektklasse nicht mit den genannten vertragen sollte.

Das benötigte Feld “host” ist über das “cosine.schema” definiert und taucht in der Objektklasse “account” auf. Das “cosine.schema” ist bei der Anlage unseres OpenLDAP-Servers mittels YaST2 übrigens automatisch bereitgestellt worden.

Die Objektklasse “account” harmoniert gut mit der Klasse “PosixAccount”. Beide Klassen setzen das Feld “uid” ein und dieses ist im übrigen auch das einzige “Muss”-Feld der Klasse “account”. Leider ergeben sich jedoch Probleme zwischen den Klassen “InetOrgPerson” und “account”. Wie kann man das sehen ?

Nachfolgend werden wir bei Experimenten mit dem LDAP-Verzeichnisbaum statt YaST2’s “LDAP Browser” öfter mal den LDAP-Browser “gq” einsetzen, da wir nun langsam an die Grenzen der YaST-Tools geraten.

“gq” ist bei Opensuse schnell über ein RPM-Paket installiert. Die erforderliche Konfiguration des Zugangs zum Server über Binds (z.B. mit der rootdn – in unserem Testscenario: “cn=Administrator,dc=anracona,dc=de”) sollte zumindest auf dem LDAP-Server “vms2” einfach von der Hand gehen. Die notwendigen Default-Einträge macht unter dem Menüpunkt “File >> Preferences”.

Mit “gq” kann man in der Ansicht zu den Feldern eines Objektes im LDAP-Baum schnell weitere Einträge für bestimmte Feldtypen anlegen. Neue Einträge werden über die rechts außen liegenden größeren Tasten mit dem nach unten gerichteten Pfeil erzeugt. Feldinhalte wählt man ggf. über die Combobox-Tasten am rechten Rand der Felder aus.

Nachfolgend sieht man das Ergebnis eines Versuches auf dem “vms2”, mittels “gq” ein User-Objekt um die Objektklasse “account” zu erweitern.

Das ging so richtig schief !

Einige weitere Tests, bei denen wir systematisch mit LDIF-Dateien und dem Kommando “ldapmodify” neue Objekte mit unterschiedlichen Objektklassenkombinationen anlegen, zeigen, dass man entweder auf die Objektklasse “inetOrgperson” oder die Klasse “account” verzichten muss. Das hier im Einzelnen darzustellen, erspare ich mir. (Leser, für die der Umgang mit LDIF-Dateien etwas Neues darstellt, sollten bei dieser Gelegenheit anfangen, sich damit auseinanderzusetzen. Das Studium der zugehörigen “man”-Seiten hilft dabei.)

Um in unseren User-Objekten im Zweig “ou=people,dc=anracona,dc=de” trotz der Probleme mit der “account”-Klasse noch ein “host”-Feld unterzubringen, greifen wir zu dem oben bereits angedeuteten Umweg:

Wir machen versuchsweise unseren Test-User “tarja” zu einem “Extensible Object” ! Wir ergänzen dazu mit “gq” und seinen Tasten die Einträge des Feldtyps “objectClass” um eine weitere Objektklasse, nämlich die Klasse “extensibleObject”:

ldap 99

Wir drücken dann auf den “Apply”-Button und danach auf “Refresh”.

Im nächsten Schritt fügen wir unserem modifzierten Objekt mit einer weiteren “gq”-Methode unser gewünschtes “host”-Feld hinzu. Dazu drücken wir auf das “gelbe” Symbol links oberhalb der Felddarstellung. Dieses öffnet den Dialog für die Felderweiterung eines “Extensible Objects”:

ldap 100

Wir drücken in kleineren Dialog zunächst auf “OK” und danach auf “Apply” und erhalten tatsächlich unser neues Feld:

ldap 101

Dieses füllen wir durch Editieren gleich mit einem Host-Eintrag für unser System “vms1”. Hier gibt man den FQDN des Hosts an, unter dem der Host im Netzwerk gefunden werden kann.

Für diejenigen, die statt mit “gq” lieber mit LDIF-Dateien sowie “ldapadd” und “ldapmodify” arbeiten wollen, hier der Inhalt einer LDIF-Datei, die unserem “tarja”-Datensatz entspricht:

dn: uid=tarja,ou=people,dc=anracona,dc=de
cn: tarja Turunen
gidNumber: 100
givenName: tarja
homeDirectory: /home/tarja
loginShell: /bin/bash
objectClass: top
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: extensibleObject
sn: Turunen
uid: tarja
uidNumber: 1010
userPassword: {ssha}PTvGho95jW9reNdggxgJUWRDxTBNQktKTg==
host: vms1.anracona.de

Für unseren Testuser “tarja” heißt das, dass wir ihm/ihr den Zugang zum Host “vms1” gewähren wollen.

Das ist zwar nett von uns, doch wir hatten ja im letzten Beitrag “LDAP IV” schon mehrfach von der Tatsache Gebrauch gemacht, dass “tarja” Zugang zu diesem Host hatte. Warum sollte sich daran jetzt etwas durch den zusätzlichen Eintrag auf dem LDAP-Server geändert haben verändert haben?

Hat sich auch nicht ! Der User “tarja” hat – wie im übrigen auch alle anderen User in unserem LDAP Zweig “ou=people” – nach wie vor Zugang zu “vms1”. Bislang ist der Zugang für unsere Accounts, die über LDAP verwaltet werden, ja in keiner Weise (außer über das Passwort) eingeschränkt. Das kann der Leser gerne selber testen.

Dieser Zustand ändert sich erst, wenn wir an der LDAP-Client-Konfiguration von “vms1” etwas ändern. Künftig soll der PAM-LDAP-Client auf “vms1” unser “host”-Feld durch den LDAP-Server abfragen lassen, bevor er einen Zugang gewährt. Welcher Eintrag ist dafür notwendig?

Ein Studium der Erläuterungstexte zu den vielen auskommentierten Statements in der Datei   “/etc/ldap.conf”   auf “vms1”
macht uns auf folgende Zeile aufmerksam, von der wir nach der Lektüre mutig den Kommentar entfernen:

# Check the "host" attribute for access control
# Default is no; if set to yes, and user has no
# value for the host attribute, and pam_ldap is
# configured for account management (authorization)
# then the user will not be allowed to login.
pam_check_host_attr    yes

Wenn dieser Eintrag tatsächlich das bewirkt, was sein Erläuterungstext verspricht, so sollte sich nun außer dem User “tarja” kein weiterer User, der auf dem LDAP-Server gepflegt ist, auf “vms1” einloggen können.

Wir machen diesen Negativtest mit dem User “tuxer”, den wir im letzten Beitrag schon öfter bemüht haben. In seinem LDAP-Eintrag existiert bislang ja nicht einmal ein zusätzliches Feld “host”. Das Ergebnis ist:

ldap 102

Genau so hatten wir uns das vorgestellt !

Analog geht es mit allen anderen Testusern unter “ou=people,dc=anracona,dc=de” – außer “tarja”.

Der Positivtest mit “tarja” verläuft dagegen, wie wir das erhofft haben, tatsächlich positiv:

ldap 103

Unser erstes Verfahren funktioniert also schon mal.

Wenn man nun dem User “tarja” Zugang zu mehreren Hosts gewähren will, so ergänzt man den Datensatz für “tarja” auf dem LDAP-Server z.B. per “gq” einfach um weitere Feldeinträge des Typs “host”:

ldap 104

Oder man nutzt eine LDIF-Datei der Form:

dn: uid=tarja,ou=people,dc=anracona,dc=de
cn: tarja Turunen
gidNumber: 100
givenName: tarja
homeDirectory: /home/tarja
loginShell: /bin/bash
objectClass: top
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: extensibleObject
sn: Turunen
uid: tarja
uidNumber: 1010
userPassword: {ssha}PTYGho95jW9reNdxUdgJUWRDxTBNQktMTg==
host: vms1.anracona.de
host: vmsx.anracona.de
host: vmsy.anracona.de

Hinweis : Natürlich muss man dann auf den anderen Hosts auch die Dateien “/etc/ldap.conf” um den Eintrag

pam_check_host_attr    yes

ergänzen!

Das genannte Verfahren führt man dann sukzessive für alle User durch. Bei größeren Installatinen wird man dabei um ein wenig Scripting, den Einsatz von “ldapsearch” und “ldapmodify” nicht herumkommen.

Auf einen YaST2-Unterstützung können wir bei diesem Verfahren auf Opensuse-Systemen also nicht mehr zählen!

Verfahren 2 – Zugangskontrolle durch User-Einträge in “host”-Objekten des LDAP-Baums

Für unser zweites Verfahren müssen wir Host-Einträge im LDAP-Verzeichnisbaum unterbringen. YaST2 können wir hierfür abschreiben – mir ist zumindest keine Möglichkeit bekannt, mit YaST2’s LDAP-Tools eine Host-Verwaltung auf einem LDAP-Server vorzunehmen und damit auch noch Zugriffsberechtigungen für User zu organisieren.

Damit unsere “host”-Einträge im LDAP-Baum aufgeräumt sind, wollen wir einen neuen Zweig des LDAP-Baums eröffnen:

ou=hosts,dc=anracona,dc=de

In diesem Zweig wollen wir als ersten Eintrag gleich unseren LDAP-Server unterbringen. Hier stellt sich erneut die Frage der Objektklassen-Zuordnung für die gewünschten Einträge.

Ich greife zu folgenden Klassen, die aus meiner Sicht die notwendigsten Felder zur Beschreibung eines Hosts enthalten:

  • objectClass: posixGroup
  • objectClass: groupOfUniqueNames
  • objectClass: extensibleObject
  • objectClass: ipHost

Wie beim ersten Verfahren sehen wir hier aus Flexibilitätsgründen den Einsatz der Klasse “extensibleObject” vor. Zwingend erforderlich ist diese Klasse diesmal aber nicht.

Es ergibt sich folgende Struktur einer LDIF-Datei, die wir auf dem Server zur Ausführung bringen müssen:

LDIF-Datei für die Anlage des neuen Zweiges und eines Hosteintrags für “vms2”:

dn: ou=hosts,dc=anracona,dc=de
objectClass: organizationalUnit
ou: hosts

dn: cn=vms2,ou=hosts,dc=anracona,dc=de
objectClass: posixGroup
objectClass: groupOfUniqueNames
objectClass: extensibleObject
objectClass: ipHost
ipHostNumber: 192.168.0.12
cn: vms2.anracona.de
cn: vms2
gidNumber: 1
uniqueMember: uid=tuxer,ou=people,dc=anracona,dc=de

Man erkennt an der letzten Zeile, dass wir dem Host-Eintrag gleich auch noch einen ersten User mitgegeben haben !

Aufgrund unserer Objektklassenzusammenstellung ergeben sich in diesem Fall einige Muss-Felder, für die ein Eintrag zwingend vorzunehmen ist, nämlich:

  • cn    ( für die Bezeichnung des Hosts)
  • gidNumber    ( für die Zugehörigkeit zu einer Gruppe von Hosts)
  • ipHostNumber    ( für die IP-Adresse des Hosts)
  • uniqueMember    ( mindestens einen User des Hosts)

Wem diese Mussfelder zuviel sind oder wen im Besonderen das Mussfled “uniqueMember” stört, kann für die Hosteinträge auch folgende Alternative verwenden:

LDIF-Alternative für Host-Einträge :

dn: cn=vms2,ou=hosts,dc=anracona,dc=de
objectClass: device
objectClass: ipHost
objectClass: extensibleObject
ipHostNumber: 192.168.0.12
cn: vms2.anracona.de
cn: vms2
member: uid=tuxer,ou=people,dc=anracona,dc=de

Hinweise zur Alternative:

  • Um dem Host Feldeinträge vom Typ “member” zuordnen zu können, ist die Klasse “extensibleObject” zwingende Voraussetzung.
  • Das Feld “member” ist dann kein Mussfeld. Man kann es daher auch leer lassen.
  • Man muss bei Verwendung dieser Alternative weiter unten bei der Einrichtung der LDAP-Clients auf den Hosts aufpassen und als zu untersuchendes Feld “member” statt “uniqueMember” angeben.

Unsere Vorgaben bringen wir nun in einer Datei “host_vms2.ldif” in einem Verzeichnis unserer Wahl auf “vms2” unter. In diesem Verzeichnis führen wir nun diese Datei für den LDAP-Server aus:

vms2:~ # ldapadd -D "cn=Administrator,dc=anracona,dc=de" -w MY_LDAP_PASSWD -x -a -f hosts_vms2.ldif

Danach kontrollieren wir das Erreichte über “gq”:

ldap 106

Der aufmerksame Leser erkennt, das ich auf meinem Testserver “vms2” zwischenzeitlich schon mal dem User “rmo” Zugang gewährt hatte.

Gemäß des LDAP-Eintrags für unseren Server “vms2” dürfte sich jetzt also auch unser User “tuxer” dort einloggen.

Bisher ist auf dem Server der Zugang von Usern, die per LDAP erfasst wurden, aber noch gar nicht beschränkt worden, weil wir auf dem System “vms2” noch keine Änderung unserer ursprünglichen LDAP-Client-Konfiguration vorgenommen haben!

Für die Anwendung unseres Verfahrens 2 müssen die Einträge in der Datei “/etc/ldap.conf” auf “vms2” folgendermaßen aussehen:

# Group to enforce membership of
#pam_groupdn cn=PAM,ou=Groups,dc=example,dc=com
pam_groupdn cn=vms2,ou=hosts,dc=anracona,dc=de

# Group member attribute
#pam_member_attribute uniquemember
pam_member_attribute uniquemember

oder im Fall der angesprochenen Alternative:

# Group to enforce membership of
#pam_groupdn cn=PAM,ou=Groups,dc=example,dc=com
pam_groupdn cn=vms2,ou=hosts,dc=anracona,dc=de

#pam_groupdn - Eintrag
pam_member_attribute member

Nachdem wir unseren LDAP-Server hiermit ausgestattet haben, versuchen wir einen Positiv-Test mit dem User “tuxer”:

ldap 107

Hm, das ging so halb. Was soll aber die Meldung bzgl. des Home-Verzeichnisses? Hier bitte ich den Leser, noch einmal einen Blick in den Beitrag “LDAP IV” zu werfen. Aha, dort hatte ich die automatische Anlage von “home”-Verzeichnissen ja explizit ausgeschlossen ! Daher ist die Meldung nicht verwunderlich.

Für meinen User “tuxer” mache ich testweise mal eine Ausnahme :

vms2:~ # cp -r /etc/skel /home/tuxer
vms2:~ # chown -R tuxer.users /home/tuxer
vms2:~ #

Danach sieht die Sache schon besser aus:

ldap 108

Alles OK also mit unserem User “tuxer” ! Er hat nun die Ehre, sich auf unserem LDAP-Server einloggen zu dürfen. Unser Positiv-Test war offenbar erfolgreich.

Nun müssen wir aber noch einen Negativtest machen. Hierzu verwenden wir den User “tarja”:

ldap 109

Genauso wollen wir das !

Kombination beider Verfahren auf einem Host

Abschließend schauen wir uns interesserhalber an, was auf “vms1” passiert, wenn wir beide Verfahren kombinieren. Dazu erfassen wir den Host “vms1” zunächst mit Hilfe einer geeigneten LDIF-Datei “vms1.ldif” im Zweig “ou=hosts,dc=anracona,dc=de” des LDAP-Baums:

dn: cn=vms1,ou=hosts,dc=anracona,dc=de
# objectClass: device
objectClass: posixGroup
objectClass: groupOfUniqueNames
objectClass: extensibleObject
objectClass: ipHost
ipHostNumber: 192.168.0.11
cn: vms1.anracona.de
cn: vms1
uniqueMember: uid=tuxer,ou=people,dc=anracona,dc=de
gidNumber: 1

Diese Datei bringen wir auf “vms2” zur Anwendung:

vms2:~ # ldapadd -D "cn=Administrator,dc=anracona,dc=de" -w MY_LDAP_PASSWD -x -a -f hosts_vms1.ldif
adding new entry "cn=vms1,ou=hosts,dc=anracona,dc=de"

Der Check mit “gq” zeigt:

ldap 110

Auf “vms1” ändern wir nun die Datei “/etc/ldap.conf” so ab, dass (hoffentlich) auch Verfahren 2 zur
Anwendung kommt:

# Group to enforce membership of
#pam_groupdn cn=PAM,ou=Groups,dc=example,dc=com
pam_groupdn cn=vms1,ou=hosts,dc=anracona,dc=de

# Group member attribute
#pam_member_attribute uniquemember
pam_member_attribute uniquemember

Bislang war ein Login von “tarja” auf “vms1” zwar nach dem ersten Verfahren zugelassen, aber nicht nach dem zweiten ! Dagegen ist unser User “tuxer” zwar nach dem zweiten Verfahren zugelassen, nicht aber nach dem ersten !

Wir erwarten daher, dass sich keiner der beiden User mehr auf “vms1” einloggen darf. Und tatsächlich:

ldap 111

Tarja darf nicht mehr auf “vms1” zugreifen. Und “tuxer” ?

ldap 112

Der darf auch nicht ! Ganz offenbar werden bei einer Kombination beider Verfahren also beide Zugangsberechtigungen geprüft !

Nun fügen wir “tarja” auf dem LDAP-Server auch dem “vms1”-Host-Eintrag als “uniquemember” hinzu:

ldap 113

Dann versuchen wir erneut, “tarja” auf “vms1” einzuloggen :

ldap 114

Alles wieder OK !

Abschließende Anmerkungen

Ich hoffe, dieser Ausflug in die LDAP-Welt unter Opensuse hat gezeigt, was man mit Yast2’s Hausmitteln machen kann und was nicht mehr.

Ein Server ist schnell angelegt, Hosts lassen sich auch relativ schnell als LDAP-Clients konfigurieren. Bei einer einfachen Useranlage unterstützt YaST2 hinreichend. Ebenso hilft YaST2 beim Umgenag mit einer zentralen Password Policy.

Bei der Konfiguration von Zugangsbeschränkungen für Hosts beißt es dann aber aus! Hier würde ich mir wünschen, dass YaST2 erweitert wird, damit auch User, die keine LDAP-Profis sind, eine Chance haben, LDAP sinnvoll in einem kleinen Netz einzusetzen.

Opensuse 12.1 – LDAP IV

In den Beiträgen “Opensuse 12 LDAP I” bis “LDAP III” hatte ich zwei Systeme mit Opensuse 12.1 als Betriebssystem betrachtet:

Ein System “vms2” wurde als LDAP-Server vorgesehen. Ein weiteres, unabhängiges System “vms1” im Netzwerk fungierte als typischer Arbeitsplatzrechner oder weiterer Server, auf dem unsere Opensuse-Endanwender sich einloggen und arbeiten sollen. Gewöhnliche unpriviligierte Useraccounts von “vms1” sollen nicht lokal hinterlegt, sondern auf dem LDAP-Server mit Hilfe von YaST2 verwaltet werden.

Anhand dieser zwei Beispielsysteme hatten wir bereits folgende Punkte diskutiert:

  • Einrichtung eines LDAP-Servers auf einem Opensuse 12.1 System – hier auf “vms2”
  • Vorbereitung des LDAP-Servers “vms2” auf TLS-gesicherte Verbindungen von externen ( – aber auch von internen) LDAP-Clients.
  • Konfiguration wichtiger LDAP-Clients – nämlich PAM, NSSWITCH und LDAP-Kommandozeilen-Tools – auf dem Server (“vms2”) selbst und vor allem auch auf anderen Opensuse-Systemen (hier “vms1”) des Netzwerks.
  • Konfiguration der LDAP-Clients (auf “vms1” und auch auf “vms2”) für TLS-Verbindungen zum zentralen LDAP-Server (“vms2”).
  • Konfiguration der YaST2-Userverwaltung auf Opensuse-Systemen im Netzwerk (hier “vms1”), so dass die wichtigsten User-Account-Daten auf dem zentralen LDAP-Server hinterlegt werden können.
  • Konfiguration von PAM und NSSWITCH, so dass ein Login-Vorgang auf einem Opensuse-System des Netzwerks (hier “vms1”) über den zentralen LDAP-Server (“vms2”) autorisiert wird.
  • Anlage eines LDAP-verwalteten Users auf einem Opensuse-System im Netz (hier “vms1”) mittels des dortigen YaST2 und Test des Logins eines solchen Users auf diesem System.

Zur Erledigung all dieser Aufgaben konnten wir auf dem LDAP-Server (“vms2”) und auch auf dem anderen Opensuse-System (hier “vms1”) bislang YaST2-Tools einsetzen.

Bevor wir uns nun weiter in die Möglichkeiten einer zentralen Userverwaltung von Opensuse-Systemen mittels LDAP einarbeiten, müssen wir noch einen Punkt nachtragen, den wir im Beitrag    “Opensuse 12.1 – LDAP III”    noch nicht genauer betrachtet hatten.

Zentrale User-Anlage auf “vms2” und erster Login auf einem anderen für LDAP konfigurierten Opensuse-System

Der oder die Testuser, die wir im Laufe des letzten Beitrag “LDAP III” auf dem System “vms1” angelegt hatten, wurden mit den YaST2-Modulen des Systems “vms1” (!) angelegt.

Bei der dortigen “LDAP Client”-Konfiguration hatten wir explizit vorgegeben, dass im Zuge der Account-Erstellung auch ein Homeverzeichnis auf dem lokalen System erstellt werden soll.

Ein Klick auf den Hilfebutton dieser Maske belehrt uns darüber, dass diese Vorgabe für die YaST2-Module des Systems (“vms1”) zur Useranlage von Bedeutung ist, da diese Module automatisch Homeverzeichnisse einrichten können. So geschah es denn auch, und das hat uns nicht weiter verwundert.

Das entspricht jedoch nicht der normalen Situation bei der Userverwaltung mit Hilfe eines LDAP-Servers.

Der Admin wird – wenn er denn überhaupt YaST2 verwendet – den User direkt auf dem LDAP-Server “vms2” mit dem dortigen YaST2 anlegen. Dann ergibt sich folgende Frage:

Was passiert eigentlich, wenn sich ein solcher User erstmalig an einem anderen System (wie “vms1”) anmeldet?
Dort existiert ja dann noch kein Home-Verzeichnis für
diesen User!

Der Reihe nach:

Schon aus Sicherheitsgründen wollen wir bei der künftigen Useranlage auf dem System “vms2” nicht, dass dort für einen neuen normalen User ein Homeverzeichnis erstellt wird.

Aus diesem Grunde wählen wir auf “vms2” die lokale Einrichtung eines Home-Verzeichnisses in der LDAP-Client-Konfiguration für die Zukunft ab:

ldap 84

Hinweis: Die Einträge im unteren Feld zur Passwort-Politik werden wir am Ende dieses Artikels verstehen. Im Moment können wir sie ignorieren.

Zur Sicherheit stellen wir auch noch sicher, dass es auf “vms2” in der Datei    “/etc/pam.d/common-session”    keinen (!) Eintrag der Form

session   optional   pam_mkhomedir.so

gibt.

Nun legen wir auf “vms2” mittels des dortigen YaST2 einen neuen User – z.B. “tuxer” an. Ein anschließender Blick in das Verzeichnis “/home” auf “vms2” zeigt uns dann hoffentlich, dass für diesen neuen User tatsächlich kein Home-Verzeichnis angelegt wurde.

Nun probieren wir, uns mit diesem User auf dem System “vms1” einzuloggen. Grundsätzlich sollte das funktionieren, denn PAM hatten wir dort für die Nutzung des LDAP-Servers konfiguriert.

Aber was geschieht bzgl. des dort nicht vorhandenen Home-Verzeichnisses ?

ldap 85

Offenbar wurde es auf meinem “vms1” generiert!

Was auf meinem System “vms1” ist dafür verantwortlich? Der Leser sehe einmal im Beitrag “LDAP III” nach. Meine PAM-Konfiguration auf “vms1” enthielt in der Datei “/etc/pam.d/common-session” einen Eintrag

session   optional   pam_mkhomedir.so

Dieses Modul erledigt das für uns. Informationen hierzu findet man z.B. unter folgenden Links:

http://manpages.ubuntu.com/manpages/maverick/man8/pam_mkhomedir.8.html
http://www.debian-administration.org/articles/403

Nebenbei: Lesenswert sind auch die Kommentare zum letzteren Artikel!

Den genannten Eintrag zu    “pam_mkhomedir.so”    kann man übrigens auf manchen Systemen auch in anderen PAM-Dateien und nicht nur in der Datei für   “sessions”    finden.

Hinweis zum graphischen Login: Unter Opensuse funktioniert nach der Generierung des Home-Verzeichnisses per PAM übrigens auch der graphische Login (z.B. für einen KDE-Desktop). Warum, mag der geneigte Leser selber erforschen.

ldap 89

Gegenprobe:
Wir machen nun mal die Gegenprobe, melden “tuxer” ab und löschen das Verzeichnis “/home/tuxer” auf “vms1”. Ferner kommentieren wir die oben dargestellte Zeile mit    “pam_mkhomedir.so”    in der Datei    “/etc/pam.d/common-session”    aus.

Versuchen wir danach, uns wieder als “tuxer” auf “vms1” einzuloggen, so geschieht Folgendes:

ldap 86

Ein graphischer Login geht allerdings nicht mehr. Der Leser möge das selbst probieren.

Wir lernen daraus zweierlei:

  • Für die Anlage des Verzeichnisses ist auf unserem “vms1” tatsächlich der oben diskutierte “pam_mkhomedir.so”-Eintrag in der Datei “/etc/pam.d/common-session” verantwortlich.
  • Der
    jungfräuliche User “tuxer” kann sich auf “vms1” einloggen, obwohl er kein Homeverzeichnis besitzt !

Der letztere Punkt erschreckt uns dann doch ein wenig:

Denn das was für “vms1” gilt, gilt ja vermutlich auch für “vms2” ! Auch dort hatten wir ja früher mittels YaST2 die LDAP-Clients konfiguriert und Opensuse hatte damals auch eine brauchbare PAM-Konfiguration für uns vorgenommen.

Also selbst wenn wir auf “vms2” kein Modul    “pam_mkhomedir.so”    in der PAM-Konfiguration eingetragen haben und auch die Erzeugung eines Home-Verzeichnisses in der “YaST2-LDAP-Client”-Konfiguration von “vms2” unterbunden haben, so wird sich ein per LDAP verwalteter User “tuxer” auf dem “vms2” zwar nicht graphisch, aber doch über ein tty einloggen können:

ldap 87

Ja, das ist also tatsächlich der Fall !

Nun könnte man spekulieren, was denn passiert, wenn man die Zeilen mit “pam_ldap.so” aus der PAM-Konfiguration des “vms2” wieder entfernt. Das ist interessant auszuprobieren. Ich überlasse das dem Leser, weise aber auf folgendes hin:

Es ist nicht unwahrscheinlich, dass es künftig ein paar User geben muss, die wir über LDAP verwalten wollen und die neben einem Zugang zu anderen Systemen auch einen direkten tty-Zugang zum “vms2” erhalten sollen. Dann brauchen wir auf “vms2” die LDAP-Client-Konfiguration!
 
Wir müssen also im Verlauf unserer LDAP-Experimente noch eine andere Lösung für die Zugangsbeschränkung zum LDAP-Server finden, als die PAM-LDAP-Funktionalität auf “vms2” abzuschalten.

Wir fassen das Ergebnis unserer bisherigen Tests zusammen:

  • User, die direkt im LDAP-Verzeichnis eines LDAP-Servers (hier “vms2”) angelegt wurden, können sich auf anderen Opensuse-Systemen (hier “vms1”) einloggen, wenn die dortigen PAM-LDAP-Clients für den Zugriff auf den LDAP-Server konfiguriert wurden.
  • Falls dort (auf “vms1” oder auf einem ähnlichen System) das Home-Verzeichnis des neuen Users noch nicht existieren sollte, wird es beim ersten Login automatisch angelegt ‐ wenn denn die PAM-Konfiguration geeignete “pam_mkhomedir.so” ‐ Einträge in der    “common-session”   ‐ Datei enthält.
  • Auf Opensuse-12.1-Systemen klappt danach auch der graphische Login.
  • User können sich auf dem LDAP-Server selbst aber auch einloggen, wenn der dortige LDAP-Client funktionstüchtig eingerichtet ist. Dies gilt auch dann, wenn auf dem LDAP-Server gar kein Homeverzeichnis für den User angelegt wurde und kein    “pam_mkhomedir.so”   ‐ Modul in PAM aktiv ist ! Dies stellt ein gewisses Sicherheitsrisiko dar !

Während die ersten drei Punkte unsere LDAP-User-Verrwaltung im Opensuse-Netzwerk erleichtern, müssen wir uns um den letzten Punkt wohl noch im Detail kümmern !

Immerhin ist jetzt trotz dieser Einschränkung relativ klar, wie man mit YaST2-Mitteln eine zentrale LDAP-basierte User-Verwaltung in einem kleinen Opensuse-Netzwerk aufziehen kann:

Der LDAP-Server muss mit YaST2 eingerichtet und auf TLS vorbereitet werden. Auf den übrigen Systemen sind die Konfigurationsdateien für die wichtigsten LDAP-Clients  ‐  u.a. PAM und NSSWITCH  ‐  für die LDAP‐Anbindung und deren TLS-Absicherung anzupassen. Das lokale YaST2 des jeweiligen Opensuse-Systems unterstützt auch dabei.

Das war es schon – beinahe zumindest ….

Weiterhin offene Fragen

Selbst für eine Userverwaltung in einem kleineren Netz wollen wir uns mit dem bisher Erreichten
nicht zufrieden geben. Uns fehlen noch Antworten auf folgende Fragen:

  • Wie kann ich unter Opensuse auf dem LDAP-Server eine zentrale Passwort-Politik hinterlegen, die für alle LDAP-User gleichermaßen gelten soll?
  • Wie schütze ich den zentralen Server oder auch andere Systeme im Netzwerk gegen den Zugriff von x-beliebigen Usern, die wir im LDAP-Verzeichnis per YaST2 von irgendeinem bestimmten Client-System aus angelegt haben ? Wie begrenze ich den Zugriff eines im LDAP erfassten Users oder einer Gruppe auf bestimmte Hosts ?

Beim Schreiben dieses Beitrags musste ich leider feststellen, dass beide Themen zuviel für einen Artikel sind. Ich muss die Leser bzgl. des zweiten Punktes also nochmals auf einen kommenden Beitrag “LDAP V” vertrösten. Sorry!

Wir machen in diesem Beitrag also “nur” einen Ausflug in die Untiefen einer zentralen “Password Policy” auf dem LDAP-Server. Dabei werden wir feststellen, dass das Konzept der sogenannten “Policy”-Objekte, das die Vorgabe zentraler “Password Constraints uf dem LDAP-Server ermöglicht, zwar grundsätzlich funktioniert.

Im heutigen OpenLDAP-Standard wird ein Passwort durch Policy-Objekte jedoch nicht im gleichen Umfang auf seine Stärke abgeprüft, wie dies mit dem PAM-Modul   “pam_cracklib.so”   möglich ist. Möglichkeiten jenseits des Standards verfolge ich in diesem Beitrag nicht, gebe aber weiter unten Links für Interessierte an.

Wer also meint, man könne nach der Lektüre dieses Beitrags die PAM-Konfiguration für Passwort-Änderungen auf den unterschiedlichen Systemen im Netz drastisch vereinfachen und auf die Prüffunktionen des LDAP-Systems beschränken, täuscht sich.

Vielmehr dient die zentrale LDAP-Politik im Moment mehr als eine Art letzter Hürde bei Passwortänderungen, die zusätzlich zu den PAM-Prüfungen aufgebaut werden kann. Eine Konsistenz zwischen den PAM-Prüfmodulen und der zentralen Politik muss im Interesse des Endanwenders allerdings hergestellt werden. Das Leben des Admins wird durch die Einführung einer zentralen LDAP Password Policy also nicht wirklich einfacher sondern eher noch ein wenig komplizierter.

Ich hoffe dennoch, dass der Blick auf OpenLDAPs Password Policy interessant ist – u.a. auch deshalb, weil wir dabei die Wechselwirkung der zentralen Regeln mit den lokalen PAM-Regeln zur Passwortänderung auf einem Opensuse-System studieren können.

Zentrale “Password Policy” mit OpenLDAP

Im Beitrag   “Opensuse 12.1 – LDAP III”   hatten wir beschrieben, wie wir von einem System “vms1” aus User-Account-Daten mittels YaST2 auf einem zentralen LDAP-Server hinterlegen können. Eine zentrale Passwortpolitik wurde dadurch aber nicht implementiert.

Die Betonung liegt hier wirklich auf “zentral”, denn lokal auf einem System (hier “vms1”) wird die Passwort-Politik ja durch diverse Parameter der (lokalen) PAM-Konfiguration gesteuert.

Ändert man etwa auf unserem Opensuse-System “vms1” im Yast2-Modul “Security Center and Hardening” über den Menüpunkt “Password Settings” die minimale Länge des Passwortes auf 8 Character ab, so führt dies zu folgender Einstellung in der ersten Zeile der Datei   “/etc/pam.d/common-password-pc”   bzw. der verlinkten Datei   “/etc/pam.d/common-password” :

password    requisite    pam_cracklib.so    minlen=8
 
password    optional    pam_gnome_keyring.so    use_authtok
password    sufficient    pam_unix2.so    use_authtok nullok

password    required    pam_ldap.so  &
nbsp; try_first_pass    use_authtok

Informationen zu den grundlegenden Fähigkeiten und Möglichkeiten des “pam_cracklib.so”-Moduls findet man z.B. hier:

http://www.deer-run.com/~hal/sysadmin/pam_cracklib.html
http://linux.die.net/man/8/pam_cracklib

Opensuse’s Default-Einstellungen für das Betriebssystem und auch YaST2 sorgen über die PAM-Konfiguration und den Einsatz der “cracklib” also auf jedem einzelnen System dafür, dass dort ein Minimum an lokalen (!) Regularien bzgl. der Passwortqualität eingehalten wird. Wir kommen weiter unten noch auf Details zurück.

Aber wir wollen in einem Rechnerverbund natürlich auch systemübergreifende Regeln implementieren – möglichst über das LDAP-System. Eine Modifikation der PAM-Regeln auf dem LDAP-Server (“vms2”) selbst nutzt in diesem Zusammenhang nichts, denn die beziehen sich ja nur auf Passwortvergaben, die dort lokal vorgenommen werden. Wir bzw. die späteren User wollen ja aber von jedem anderen Linux-System aus Passwort-Änderungen vornehmen können, die zentralen Kriterien genügen.

Bzgl. der minimalen Passwortlänge hatten wir im Beitrag LDAP III übrigens bereits einen Weg gesehen, wie man unter Opensuse eine erste zentrale Vorgabe auf dem LDAP-Server verankern kann. Dieser Weg führte über die Einrichtung des “yast”-LDAP-Schemas und die Einrichtung der Standardtemplates für die User-Anlage.

Man sehe sich auf dem LDAP-Server “vms2” im LDAP-Browser nochmals den Zweig “cn=userconfiguration,ou=ldapconfig,dc=anracona,dc=de” an:

ldap58

Hier ist zentral eine minimale Passwortlänge hinterlegt worden, die YaST2 bei der Useranlage per YaST2-Skripts auch kontrolliert. Diese Vorgabe ist aber eben SuSE- und leider auch nur tool-spezifisch:

Sie gilt nur für YaST2’s “User- und Gruppenverwaltung” – und auch dort führt das Vorgehen lediglich zu einer Warnung an den Administrator, die root natürlich auch ignorieren kann !

Zudem gilt :

  • Es gibt eine Reihe weiterer Punkte einer Passwortpolitik, wie etwa der Gültigkeitszeitraum eines Passworts, die durch Suses “yast”-LDAP-Schema gar nicht erfasst werden.
  • Neben lokalen Tools, die der PAM-Kontrolle unterliegen und die mit LDAP-Zusatz-Features ausgestattet werden, gibt es ggf. weitere Tools wie etwa “ldappasswd”, mit denen man die lokalen PAM-Einschränkungen an neue Passwörter umgehen kann.
  • Zu den potentiellen Umgehern von PAM-Richtlinien sind auch Programme zu rechnen, die z.B. unter Java, PERL, Python oder PHP erstellt wurden und die mit dem LDAP-Server kommunizieren können. Wir wollen nicht, dass solche Werkzeuge eine gewünschte zentrale Passwort-Politik unterlaufen können.

Für das Thema zentrale Passwort-Politik im Zusammenhang mit LDAP wurde deshalb bereits im Jahr 2005 eine Lösung vorgeschlagen. Siehe hierzu folgendes, immer noch im Zustand eines Drafts befindliche Dokument:

RFC draft draft-behera-ldap-password-policy-09.txt.

Der Ansatz, Passwort-Einschränkungen zu erzwingen, bezog und bezieht sich dabei primär auf eine Absicherung des LDAP-Zugriffs selbst   –   also auf die Absicherung von LDAP-Binds.

Im Fokus der Absicherung stehen dabei Anforderungen an Passwörter der LDAP-Accounts für Benutzer sowie die Änderungs- und Verfallspolitik zu diesen Passwörtern. Passwort-Felder sind von den LDAP-Backends (LDAP-Datenbanken) über die Schema-Definitionen eindeutig identifizierbar.

Nun erfolgt aber auch eine PAM- und LDAP-basierte User-Authentifizierung und – Autorisierung von Anwendern, die sich auf einem Opensuse-
System wie “vms1” einloggen wollen, gerade über die erfolgreiche Durchführung von LDAP-Binds zum LDAP-Server, auf dem User-Passwörter verwaltet werden.

D.h., eine über das LDAP-Backend verankerte LDAP-Passwort-Politik wirkt sich natürlich direkt auf die Passwort-Qualität all jener Linux-User aus, die im Netz über das LDAP-System verwaltet werden. Damit kann – zumindest in der Theorie – eine zentral im LDAP-System definierte Passwort-Politik auch auf anderen Systemen im Netz zum Tragen kommen.

Ferner kann eine der Mindest-Qualitäten eines Passwortes – nämlich die Länge – auch unabhängig von den jeweils lokalen Prozessen, für die PAM Einschränkungen an die Passwortfestlegung oder -Änderung kontrolliert, erwirkt werden.

Password Policy am LDAP-Server per “Overlay”

Auf dem aktuellen Stand der Entwicklung implementiert man eine zentrale “LDAP Password Policy” über sogenannte “Extensions” oder “Overlays” des LDAP-Datenbank-Backends. Dadurch werden softwaretechnische “Hooks” definiert, die entsprechende LDAP-Erweiterungen bei der Manipulation der Dateneinträge nutzen können. Siehe hierzu etwa:

http://www.openldap.org/doc/admin24/overlays.html
http://www.highlandsun.com/hyc/ldapguide/overlays.html
http://onlamp.com/onlamp/2007/09/13/an-openldap-update.html
http://www.openldap.org/faq/data/cache/1169.html

Overlays erlauben es, Datenbankinhalte gemäß vorgegebener Regeln zu modifizieren oder zu prüfen, ohne die Datenbankstruktur des Backends selbst oder ein Schema ändern zu müssen. Ein spezielles Beispiel eines Overlays ist das “ppolicy”-Overlay. Schon der Name verrät, dass es sich um ein Overlay zur Kontrolle von Passwörtern handelt.

http://www.zytrax.com/books/ldap/ch6/#overlay
http://www.zytrax.com/books/ldap/ch6/ppolicy.html
www.dpunkt.de/leseproben/2104/Kapitel_17.pdf     (siehe dort Kap. 17.3)

Aus den angegebenen Quellen erahnen wir, dass eine händische Einrichtung des Overlays “ppolicy” mehrere Schritte erfordern würde. Wir benutzen der Einfachheit halber deshalb die YaST2-eigenen Tools.

Dazu öffnen wir auf dem LDAP-Server “vms2” (!) das YaST2-Modul “LDAP-Server” und prüfen dort zunächst die installierten LDAP-Schemata:

ldap59

(Hinweis für die, die genauer hinsehen: Dieses Bild habe ich faktisch von einem etwas jungfräulicheren Server als unserem “vms2” entliehen. Daher die deutsche Beschriftung).

Neben-Hinweis:

Nebenbei merken wir uns für die spätere Administration des Servers, dass es auf dieser Maske zwei Buttons “Hinzufügen” oder “Add” sowie “Löschen” oder “Delete” gibt, die dazu dienen, die vom Server geladene Schema-Palette um weitere Schemata zu erweitern oder zu verkleinern. Aus meiner praktischen Erfahrung sind diese YaST2-Werkzeuge auf einem LDAP-Testsystem insbesondere dann nützlich, wenn man mal mit Inkompatibilitäten verschiedener LDAP-Schemata zu kämpfen hat und man diese schnell und systematisch durch das Laden und Entfernen ganz bestimmter Schemata untersuchen will.

Danach wechseln wir zum Punkt “Databases >> dc=anracona,dc=de >> Password Policy Configuration”:

ldap 63

und aktivieren dort die Passwort-Richtlinien (Password Policy).

Die “Hash”-Vorgabe könnten wir eigentlich ignorieren, da wir über Opensuse’s “yast”-Schema und den Einsatz von YaST2-Tools bzw. über unsere Konfiguration von PAM (Option “pam_password exop”) sowieso alle Passwörter per SSHA-Hash verschlüsselt ablegen, wenn wir auf Systemen wie “vms1” Passwörter unter PAM-Kontrolle ändern.
Aber auch hier sollten wir uns daran erinnern, dass es andere Tools geben mag, die das anders handhaben.

Ein Abhaken der “ppolicy-Option” schadet zur Sicherheit also nichts.

Hinweis: SSHA ist der LDAP-Server-Default für exop-Clients: “exop” in der PAM-Konfiguration der LDAP-Clients sorgt dafür, dass die Hash-Verschlüsselung am Server mit dem dort festgelegten Hash-Verfahren erfolgt. Hat man bei der Serverkonfiguration nicht explizit etwas anderes angegeben, so ist der Default “SSHA”. Siehe hierzu auch den Beitrag “LDAP III”. Ich habe den Artikel nachträglich um diesbzgl. Anmerkungen ergänzt.

Man beachte auch, dass die Opensuse-spezifischen Festlegungen im LDAP-Zweig

“cn=userconfiguration,ou=ldapconfig,dc=anracona,dc=de”

für die YaST2-Userverwaltung ggf. andere und vom Server-Deafult abweichende Hash-Regeln festlegen. Spätestens jetzt wird es also Zeit, sich über die Konsistenz der verschiedenen Einstellungen Gedanken zu machen !

Die Einstellung zur   “Default Policy DN”   in der obigen Maske lassen wir unverändert :

Diese Einstellung führt zur Anlage eines zentralen “Policy-Objekts”, in dem wir Default-Passwort-Richtlinien hinterlegen und bei der Userpflege per YaST2 oder LDIF-Dateien neuen Usern zuordnen können. Wir werden weiter unten über das Default-Objekt hinaus noch zusätzliche, eigene “Password Policy-Objekte” in separaten Zweigen der LDAP-Datenstruktur anlegen.

Abschließend lassen wir die gewünschten Änderungen an unserer LDAP-Server-Konfiguration durch Drücken der OK-Taste durchführen. Ein erneuter Blick auf die installierten Schemata zeigt, dass dabei ein neues Schema “ppolicy” integriert wurde.

ldap 62

Ein weiterer Blick im LDAP-Browser auf die Verzeichnisstruktur zeigt die Anlage des “Objekts” zur Default Policy im LDAP-Baum:

ldap 64

An dieser Stelle ist es interessant, sich anzusehen, wie YaST2 das Overlay in den LDAP-Server-Konfigurationsdateien verankert hat. Also setzen wir mal folgendes Kommando ab:

vms2:/etc # grep -d recurse ppolicy ./openldap/
./openldap/slapd.d/cn=config/cn=schema/cn={5}ppolicy.ldif:dn: cn={5}ppolicy
./openldap/slapd.d/cn=config/cn=schema/cn={5}ppolicy.ldif:cn: {5}ppolicy
./openldap/slapd.d/cn=config/olcDatabase={1}hdb/olcOverlay={0}ppolicy.ldif:dn: olcOverlay={0}ppolicy
./openldap/slapd.d/cn=config/olcDatabase={1}hdb/olcOverlay={0}ppolicy.ldif:olcOverlay: {0}ppolicy
vms2:/etc #

Die ersten beiden Einträge entsprechen der Erweiterung der Liste der geladenen LDAP-Schemata. Die letzten beiden Einträge repräsentieren das Hinzufügen des Overlays “ppolicy” zur hier verwendeten hdb-Variante der BDB (s. zur “hdb” und zur “bdb” den Beitrag “Opensuse 12.1 – LDAP I“).

Wie man die letzten beiden Einträge händisch per LDIF-Datei hätte anlegen müssen, findet man hier

www.zytrax.com/books/ldap/ch6/slapd-config.html#use-overlays.

Einstellung der “Default Password Policy”

Natürlich ist es per Yast2 möglich, die Einstellungen der “Default Policy” zu ändern. Hierzu klickt man in der zuletzt geöffneten Maske von YaST2’s “LDAP-Server-Modul” (s. die vorletzte Abbildung) auf den Button “Edit Policy”.

Danach gelangt man zunächst zu folgender Maske für die “Password Change Policy”:

ldap 65

In ihr und in den Masken, die sich hinter den weiteren Reitern “Password Aging Policies” und “Lockout Policies” verbergen, kann man nun seine Einstellungen für die einzelnen Password Policies hinterlegen.

Kurzinformationen zur Bedeutung der Felder liefern der “Help”-Button der jeweiligen YaST2-Maske. Weiterführende Informationen erhält man aus den Internet-Artikeln zum “ppolicy”-Overlay, auf die wir oben verwiesen haben.

Nachfolgend wollen wir beispielhaft für andere Einstellungen eine zentrale Vorgabe für die Passwort-Länge testen. Die “Minimum Password Length” setzen wir hierfür in der oben abgebildeten Maske auf den Wert “7”.

Hinweis: Den Haken bei “Old Password Required for Password Change” lassen wir dagegen weg. Warum besprechen wir weiter unten.

Will man sich bei den nachfolgenden Tests nicht unnötig mit der “cracklib” und ihren Anforderungen an Passwort-Änderungen herumschlagen, setzt man besser auch die “Maximum Number of Passwords Stored in History” auf den Wert “0”.

Ein Test unseres “Constraints” bzgl. der Passwort-Länge ist u.a. deshalb interessant, weil wir uns dabei ansehen können, wie die zentrale Vorgabe auf “vms2” mit den lokalen Einstellungen für PAM auf dem System “vms1” interferiert. Tests anderer Einstellungen überlassen wir dem Leser.

(Kein) Test der LDAP-“ppolicy” – genauer der Default Policy – mit YaST2’s Userverwaltung

Als erstes wollen wir uns ansehen, ob die oben getroffene Längen-Einschränkung an ein Passwort überhaupt zieht, wenn man per YaST2 das Passwort eines Users (zurück-) setzt.

Hierzu öffnen wir auf “vms1” (!) mal das dortige YaST2-Modul zur “User- und Gruppen-Verwaltung”. Dort lassen wir uns per “Filter” die auf dem LDAP-Server “vms2” eingetragenen User anzeigen und ändern für einen unserer zwischenzeitlichen angelegten Testuser – hier “tarja” – das Passwort.

ldap 67

In unserem Beispiel nehme ich mit Absicht das Passwort “drei”. Dieses hat nur 4 Buchstaben und kollidiert daher mit einer ganzen Reihe von Festlegungen – u.a. auch mit der “Default Password Policy”, in der wir oben die “Minimum Password Length” auf den Wert 7 gesetzt hatten.

Es kollidiert aber auch mit den opensuse-spezifischen Festlegungen für die Anlage von Usern, die wir per YaST2 im LDAP-Zweig “cn=userconfiguration,ou=ldapconfig,dc=anracona,dc=de” des Servers hinterlegt hatten:

ldap 69

(Wer den entsprechenden Schritt inzwischen vergessen hat, möge mal im Beitrag “Opensuse 12.1 LDAP – III” nachsehen.) Dort hatten wir den Wert für die minimale Passwort-Länge auf “5” gesetzt (Parameter: suseMinPasswordLength). Natürlich fragt unser YaST2-Programm zur User-Modifikation diesen Wert ab.

Wir erhalten deshalb von YaST2 prompt eine Warnung:

ldap 68

Im Warnungstext wird explizit auf die Festlegung “5” in den opensuse-spezifischen Festlegungen des LDAP Eintrags verwiesen. Wir setzen uns über die Warnung hinweg – wir sind root und dürfen das – und drücken auf “Yes”.

Jetzt erwarten wir eigentlich, dass die Festlegung in der “ppolicy” zieht und uns vom Speichern des Passwortes abhält.

Aber nein !! YaST2 schluckt unser kurzes Passwort ohne Probleme und speichert es tatsächlich im LDAP-Baum ab.

Dass das neue und zu kurze Passwort tatsächlich vom Testuser “tarja” verwendbar ist, zeigt ein Login-Versuch auf “vms1”, den ich in meiner virtualisierten KVM-Testumgebung auf einer KVM-VNC-Konsole durchgeführt habe:

ldap 70

Das ist doch irgendwie frustrierend! Was nützt uns unter diesen Umständen eigentlich die ganze hübsche zentrale “ppolicy”? Zumindest YaST2’s User-Modul ignoriert unsere “ppolicy”-Einträge offenbar!

Misstrauisch geworden sehen wir uns ein wenig um und editieren noch einmal den Testuser “tarja”. Dort gehen wir nun auf den bislang nicht beachteten Reiter “Plug-Ins”.

ldap 71

Hier klicken wir zunächst auf den Eintrag “Edit Password Policy” und dann auf den Button “Launch”.

ldap 72

Dort setzen wir – falls nicht schon aktiviert – den Haken bei “Use Default Password Policy” und drücken solange auf “OK”-Buttons bis die Änderung gespeichert wird. Danach führen wir unseren Test erneut durch.

Es ergibt sich aber das gleiche Ergebnis wie zuvor :

Root kann mit YaST2s Benutzerverwaltung ein viel zu kurzes Passwort in die LDAP-Datenbank schreiben!

Offenbar ist der Zweck der zuletzt benutzen interessanten Maske ein anderer als die Beachtung der “ppolicy”-Einstellungen zu erzwingen. Wir kommen hierauf weiter unten zurück.

Warum um alles in der Welt durften wir das im Vergleich zu den “ppolicy”-Festlegungen zu kurze Passwort in die LDAP-Bank schreiben? Der Grund ist relativ einfach:

LDAP-Aktionen, die mit einem “rootdn”-Bind auf dem LDAP-Server ausgeführt werden, können “ppolicy”-Einschränkungen umgehen !

Der Grund für das Ignorieren der “ppolicy” liegt darin, dass bei der Benutzung der YaST2-Module die “rootdn” für einen LDAP-Bind benutzt wird. Bei der Anlage des LDAP-Servers hatten wir die “rootdn” auf

cn=Administrator,dc=anracona,dc=de

gesetzt. Wir erkennen den entsprechenden Bind-String im Text des PopUp-Dialogs wieder, in den wir das Passwort für die “rootdn” eingeben müssen, wenn wir im YaST-Tool die User bzgl. LDAP filtern :

ldap 73

Die YaST2-Benutzerverwaltung führt auch nachfolgend alle Operationen mit einem “rootdn”-Bind durch. Die “rootdn” hat auf dem LDAP-Server aber aus prinzipiellen Gründen sehr weitgehende Schreiberlaubnis und ist “ppolicy”-Einschränkungen nicht unterworfen. Siehe hierzu etwa den einleitenden Text von

https://linux.die.net/man/5/slapo-ppolicy

oder die Ausführungen in folgenden Forumsdiskussionen zu Fällen, in denen die LDAP-“ppolicy” auch “ignoriert” wurde:

http://www.openldap.org/lists/openldap-technical/201203/msg00375.html
http://www.openldap.org/lists/openldap-technical/201102/msg00261.html

Also:

Mit YaST2 können wir das Einhalten der zentralen “ppolicy” nicht testen! Auch
händische LDAP-Kommandos der folgenden Art, die ein gewiefter LDAP-Profi vielleicht am Prompt von “vms2” ausprobieren würde, würden nur ergeben, dass die “rootdn” Passwörter setzen darf, die die “ppolicy” verletzen :

vms2:/etc # ldappasswd -e ppolicy -W -x -D "cn=Administrator,dc=anracona,dc=de" \
>  -H ldap://127.0.0.1/ -A -S "uid=tarja,ou=people,dc=anracona,dc=de"

Wenden wir uns deshalb lieber unserem User “tarja” und seinen Möglichkeiten zu. Letztlich sollen ja nicht “root” und sein LDAP-Pendant “rootdn” sondern normale User daran gehindert werden, zentrale Constraints auf dem LDAP-Server zu umgehen.

Test der ppolicy – Default Policy – mit “/usr/bin/passwd” und PAM

Im Beitrag “LDAP III” hatten wir den Client “vms1” so konfiguriert, dass NSSWITCH und PAM den LDAP-Server nutzen. Ein Tool, das den PAM-Einschränkungen folgt, ist das Kommando   “/usr/bin/passwd”  , das ein User normalerweise zur Änderung seines Passwortes einsetzt.

Bevor wir dieses Kommando als User “tarja” auf dem “vms1” benutzen, werfen wir zur Sicherheit nochmal einen Blick auf folgende Einträge in der PAM-LDAP-Konfigurationsdatei   “/etc/ldap.conf”   auf “vms1”:

# Search the root DSE for the password policy (works
# with Netscape Directory Server). Make use of
# Password Policy LDAP Control (as in OpenLDAP)
pam_lookup_policy   yes

# Use the OpenLDAP password change
# extended operation to update the password.
pam_password   exop

Hinweis: Beide (!) Einträge sind notwendig, um die zentrale “ppolicy” in die Durchführung der von PAM kontrollierten Aktionen einzubinden (siehe den Beitrag LDAP III).

Welche Prüfungen von PAM bei einer Passwort-Änderung der Reihe nach auf “vms1” durchgeführt werden, offenbart die dortige Datei

/etc/pam.d/passwd

welche wiederum die Datei

/etc/pam.d/common-password

einbindet. Letztere ist übrigens ein Link auf die Datei “/etc/pam.d/common-password-pc”. Je nach Systemeinstellungen sieht die etwa so aus:

password    requisite    pam_cracklib.so    minlen=8
password    optional    pam_gnome_keyring.so    use_authtok
password    sufficient    pam_unix2.so    use_authtok    nullok
password    required    pam_ldap.so    try_first_pass    use_authtok

Man sieht hier erneut, dass auf meinem “vms1” ein neues Password zuerst vom PAM-Modul “pam_cracklib.so” geprüft wird. Ganz am Ende findet dann ein Einsatz des “pam_ldap”-Moduls statt, das nach unseren Anweisungen in der “/etc/ldap.conf” hoffentlich die “ppolicy” zum Zuge bringen wird.

Die Optionen “requisite” und “required” im obigen Beispiel sorgen dafür, dass in jedem Fall eine Fehlermeldung generiert wird, wenn die jeweilige Prüfung fehlschlägt. (Bei “requisite” wird die Kontrolle direkt ans aufrufende Programm – hier passwd – zurückgegeben.)

Der Parameter   “minlen=8”   führt – wie schon weiter oben diskutiert – zu einer Überprüfung einer “Mindestlänge” des Passwortes – hier 8 Zeichen.

Auf Opensuse-Systemen mit Standardeinstellungen findet man vor einer Manipulation durch YaST2-LDAP-Programme oft auch einen Eintrag der Form

password  
  requisite    pam_pwcheck.so    nullok    cracklib

vor. Von dieser Standard-Einstellung kommt man zur oben dargestellten “vms1”-Konfiguration z.B. durch die Anwendung folgender Konfigurations-Kommandos als root:

# pam-config    −d    −−pwcheck
# pam-config    −a    −−cracklib    −−cracklib-minlen=8

Auf die Syntax und die Optionen von /usr/sbin/pam-config” kann ich hier nicht genauer eingehen. Informationen zum Kommando “pam-config” findet man aber unter

http://www.linuxtopia.org/online_books/opensuse_guides/opensuse11.1_reference_guide/sec_pam_pam-config.html

Einfache Parameter wie “minlen” kann man auf einem Opensuse-System auch über die Änderung von Security-Einstellungen mittels des YaST2-Moduls   “Security Center and Hardening”   ändern:

ldap 76

Ich ziehe für komplexere Konfigurationen aber das Kommando   “/usr/sbin/pam-config”   vor, weil man bei dessen Einsatz auch Rückmeldungen zu problematischen Modul- und Options-Kombinationen (wie z.B. zur Kombination von pam_pwcheck und pam_cracklib mit zusätzlichen Credit-Parametern) bekommt.

Jetzt mag sich der Leser fragen, was denn in diesem Zusammenhang ein Verweis auf “Credits” soll.

Leider müssen wir für eine Vergleichbarkeit der Passwort-Prüfungen, die in unserem Test auf “vms1”

  • einerseits lokal von der “pam_cracklib.so” und
  • andererseits von “pam_ldap.so” gegenüber der “ppolicy” auf dem LDAP-Server “vms2”

durchgeführt werden sollen, noch ein wenig ins Detail gehen. Die “minlen”-Einstellung ist nämlich mit Vorsicht zu genießen, und das offenbart die eben gezeigt einfache YaST2-Oberfläche leider nicht.

Das PAM-cracklib-Modul lässt sog. “Credits” in puncto Komplexität eines Passwortes zu. Ein “Credit” bezieht sich dabei auf die Passwortlänge und erlaubt Einsparungen an Zeichen. Das bedeutet in der Praxis, dass das Modul “pam_cracklib.so” trotz des “minlen” Parameters kürzere Passwörter zulässt, wenn diese neben Kleinbuchstaben auch Kombinationen von Sonderzeichen, Zahlen, Großbuchstaben enthalten.

Gesteuert werden “Credits” – mögliche Einsparungen von einem oder sogar mehreren Zeichen – durch vier weitere Parameter: “lcredit, ucredit, dcredit und ocredit”.

Ferner lässt die “cracklib” grundsätzlich keine Passwörter mit einer Länge unter 6 Zeichen zu. Siehe zu diesen Besonderheiten der “cracklib” auch:

http://www.deer-run.com/~hal/sysadmin/pam_cracklib.html
http://www.linux-faqs.info/security/force-strong-passwords

Nun weiß unsere zentrale LDAP-“ppolicy” aber leider gar nichts von solchen subtilen Feinheiten!

Dort – also auf dem LDAP-Server – bedeutet “Minimum Password Length” wirklich die Anzahl der Zeichen (zumindest solange Sie keine deutschen Umlaute verwenden). Damit wir eine konsistente Behandlung der Passwortlänge erhalten, modifizieren unsere erste PAM-cracklib-Prüfung daher wie folgt:

password    required    pam_cracklib.so    minlen=6    lcredit=0    ucredit=0    dcredit=0    ocredit=0

Dies erreicht man entweder durch direktes Editieren der Datei   “/etc/pam.d/common-
password-pc”   (auf “vms1”) oder mittels   “pam-config” :

vms1:~ # pam-config   −a   −−cracklib   −−cracklib-minlen=6   −−cracklib-lcredit=0   −−cracklib-ucredit=0  
−−cracklib-dcredit=0   −−cracklib-ocredit=0

Man beachte das geänderte “minlen=6” :

Cracklib soll für unseren nachfolgenden Test also Passwörter zulassen, die kleiner sind als die Länge “7”, die unsere “ppolicy” verlangt.

Nachdem wir das sichergestellt haben, loggen wir uns wieder mit dem zu kurzen Passwort “drei” als User “tarja” auf “vms1” ein und führen einen “passwd”-Dialog durch, bei dem wir ein Passwort mit genau 6 Zeichen eingeben.

Wir erwarten, dass cracklib das Passwort passieren lässt, wenn es nicht zu leicht zu “cracken” ist. Aber wir erwarten auch, dass wir anschließend an der LDAP-“ppolicy” scheitern:

ldap 77

Erläuterung der Schritte:

  • Auf die Frage nach dem alten LDAP-Passwort geben wir natürlich das alte Passwort “drei” an.
  • Als neues Passwort verwenden wir testweise die 6 Zeichen lange ASCII-Kombination “%45zz6”, das cracklib auch anstandslos schluckt.
    (Es ist heutzutage gar nicht mehr so leicht, eine passende Zeichenkombination zu finden, die cracklib
    akzeptiert 🙂 ).
  • Auf die obligatorische Rückfrage geben wir das neue Passwort erneut ein.
  • Wir scheitern dann tatsächlich bei den Prüfungen gegen die LDAP-“ppolicy”, obwohl die Fehlermeldung zur “Constraint Violation” beim “LDAP Password Update” uns keine Auskunft über die genauere Art des Fehler gibt.

Das ist dennoch ein schöner Erfolg :

Wir haben erstmalig eine zentrale LDAP-“ppolicy” auf “vms2” beim Versuch, ein Passwort auf “vms1” zu ändern, zur Wirkung gebracht !

Nun machen wir noch den Positiv-Test:

ldap 79

Erläuterung der Schritte:

  • Auf die Frage nach dem alten LDAP-Passwort geben wir wieder das alte Passwort “drei” an. Es wurde ja beim vorhergehenden Versuch nicht geändert.
  • Als neues Passwort verwenden wir nun die 7 Zeichen lange ASCII-Kombination “%45zz67”. Sie wird von cracklib akzeptiert.
  • Auf die obligatorische Rückfrage geben wir das neue Passwort erneut ein.
  • Nun akzeptiert auch das Modul “pam_ldap.so” unser Passwort! Es erfüllt ja das Längen-Kriterium unserer “ppolicy”.

In ähnlicher Weise kann man auch andere Constraints der “ppolicy” testen. Ggf. wird man dabei feststellen, dass die PAM-LDAP-Kombinatione nicht immer so informativ ist, wie man sich das wünschen würde. Zudem wird man wie ich über die eine oder andere kleinere Falle im Zusammenhang mit der Ablaufzeit von Passwörtern stolpern, für deren Aufklärung man das Internet zu Rate ziehen muss. Aber im Kern funktioniert die Sache.

Test der LDAP Default Password Policy – mit dem Tool “ldappasswd”

Wir haben ja auf unserem “vms1” neben “passwd” auch andere Tools – nämlich z.B. das LDAP-Kommandozeilentool “ldappasswd” – zur Verfügung, um ein Passwort zu ändern.

Wir vergegenwärtigen uns zudem, dass wir an der zugehörigen Konfigurationsdatei für LDAP-Clients auf
unserem “vms1” – nämlich in diesem Fall an der Datei   “/etc/openldap/ldap.conf”   – keine Änderungen vorgenommen haben, um eine “ppolicy” zu berücksichtigen. Diese Datei weist immer noch dieselben Inhalte auf, die wir bereits im Beitrag “LDAP III” gesehen hatten:

base    dc=anracona,dc=de
uri    ldap://vms2.anracona.de
ldap_version   3
ssl   start_tls
TLS_CACERTDIR   /etc/openldap
TLS_CACERT   /etc/openldap/anracona_vms2.pem
TLS_REQCERT   demand

Der Kommandozeilenbefehl   “ldappasswd”   kommt also theoretisch dafür in Frage, unsere zentrale “ppolicy” auszuhebeln. Zu den Optionen des Kommandos sehe man sich die Man-Seiten an.

Ein sinnvoller Befehl zur Änderung des Passwortes von “tarja” vom “vms1” aus ist dementsprechend:

ldappasswd   −W   −x   −D   “uid=tarja,ou=people,dc=anracona,dc=de” \
> −H   ldap://vms2   −S   “uid=tarja,ou=people,dc=anracona,dc=de”

Wir versuchen uns zunächst mit einem Positiv-Test und arbeiten uns durch folgenden Dialog auf unserem “vms1”:

ldap 78

Erläuterung der Schritte:

  • Auf die Frage nach dem alten LDAP-Passwort geben wir natürlich das alte Passwort “%45zz67” aus unserem letzten Test an.
  • Als neues Passwort verwenden wir die 7 Zeichen lange ASCII-Kombination “%hjurtx”, die cracklib akzeptiert.
  • Auf die obligatorische Rückfrage geben wir das neue Passwort erneut ein.
  • Das läuft auch beim Modul   “pam_ldap.so”   durch wie geschmiert, denn unser Passwort erfüllt ja das Kriterium der “ppolicy”.

Nun der Negativ-Test:

Versucht man eine erneute Änderung des Passwortes mit der Zeichenkombination “%93gg6”, die zu kurz ist, erleben wir Folgendes:

ldap 80

Super ! Das freut uns, denn auch hier schlägt offenbar wieder der Constraint unserer LDAP-“ppolicy” zu.

Konsistenz der lokalen und der globalen Passwort-Politik?

Was haben wir erreicht?

  • Wir können eine zentrale LDAP-Passwort-Politik unabhängig von einer lokalen PAM-Politik auf unseren SuSE-Systemen als letzten Rettungsanker benutzen, um eine definierte Qualität der Passwörter hinsichtlich ihrer Länge durchzusetzen.
  • Durch die zentrale Politik werden auch Umgehungsversuche durch andere Tools (wie etwa LDAP-Tools für die Kommando-Zeile) abgefangen.

Was wir jedoch nicht können, sind Dinge wie die Passwortstärke jenseits der Länge an zentraler Stelle zu überprüfen. Dies gibt der aktuelle “ppolicy”-Mechanismus im Gegensatz zur “cracklib” unter PAM nicht her   –   zumindest nicht ohne weitere Hilfsmittel und einige Anstrengungen :

Um eine tiefergehende Passwort-Prüfung auf dem Server zu erreichen, müsste ein “cracklib”-Modul vom LDAP-Server in die von außen initiierte Passwort-Transaktionen eingebunden werden. Hier bewegen wir uns jenseits dessen, was heute zusammen mit OpenLDAP 2.4 als Standard ausgeliefert wird.

“PPolicy” ist aber grundsätzlich schon auf ein solches Verfahren ausgelegt. So ist eine entsprechende Schnittstelle zu Programmen auf dem LDAP-Server vorbereitet, die Passwörter checken können. Konfiguriert wird das auf
dem Server durch ein zusätzliches Attribut   “pwdCheckModule”. Siehe hierzu die Dokumentation unter

https://linux.die.net/man/5/slapo-ppolicy.

Und tatsächlich gibt es Leute, die an dieser “non-standard extension to the LDAP password policy proposal ” basteln. Wer sich dafür interessiert, kann einen Blick in folgende Webseiten werfen:

http://www.calivia.com/blog/mike/openldap-check_password-password-policy-module
http://ltb-project.org/wiki/documentation/openldap-ppolicy-check-password
https://github.com/onyxpoint/ppolicy-check-password

Ich werde diese Wege hier aber nicht beschreiten. Ich warte lieber auf OpenLDAP 2.5. Vielleicht wird ein entsprechendes Feature zur Einbindung der “cracklib” dort schon mit ausgeliefert.

Fürs erste müssen wir uns deshalb hinsichtlich der Passwortstärke noch auf die lokalen cracklib-Module und eine vernünftige PAM-Konfiguration auf unseren Linux-Systemen verlassen. Das ist irgendwie ein großer Wehmutstropfen, den wir beim aktuellen Zustand von OpenLDAP hinnehmen müssen.

Durch die obigen Tests ist vermutlich auch klar geworden, dass eine Kombination der PAM-Module   “pam_pwcheck.so”   oder   “pam_cracklib.so”   mit einer nachfolgenden   “ppolicy”-Prüfung durch   “pam_ldap.so” &nsp; für den Anwender undurchsichtig werden kann !

So wurde die Eingabe zu kurzer Passwörter durch “cracklib” in unseren Testfällen aufgrund der lokalen Einstellungen ja zunächst akzeptiert. Erst danach kam die die Fehlermeldung vom LDAP-Server. Das kann irritierend wirken. Zudem sind die Fehlermeldungen der Cracklib auch bzgl. der Passwortlänge etwas aussagekräftiger als die LDAP-Rückmeldung.

Dies bedeutet aus meiner Sicht, dass der Administrator bis auf weiteres gut daran tut, die lokale PAM-Politik mit der LDAP-“ppolicy” auf konsistente Weise abzustimmen!

Dies betrifft einerseits die Beseitigung von Unterschieden, die es in der PAM-Konfiguration verschiedener Systeme im Netz geben mag.

Es betrifft – wie wir gesehen haben – aber auch Unterschiede im genauen Prüfungsverhalten der etablierten PAM-Routinen bzgl. der Passwort-Länge im Vergleich zum LDAP-System. Zur Etablierung gleicher Passwortkriterien, die zur zentralen “ppolicy” passen, muss man letztlich entsprechende “pam-config”-Kommandos auf allen Systemen, die sich des zentralen LDAP-Servers bedienen, absetzen. Dafür kann man z.B. Tools wie die “dsh” (distributed shell) nutzen.

“ppolicy mit pwdSafeModify” – Probleme und Fehler im LDAP-Client

Nun möchte ich noch auf zwei Fallen hinweisen, in die man im Zusammenhang mit “ppolicy” schnell und in bester Absicht stolpern kann. Bislang hatten wir nur eine einfache Art der Passwortänderung auf dem Server verlangt. Was aber, wenn der Server vor einer Änderung auch noch das alte Passwort prüfen soll?

Beim Einsatz von “passwd” nimmt uns das PAM ab. Aber bei anderen Tools und LDAP?

Der aufmerksame Leser erinnert sich jetzt an die YaST2-Maske   “Password Policy Configuration”   zur Einstellung der   “Default Password Policy”   auf dem LDAP-Server. Dort hatten wir vor unseren Tests keinen Haken bei   “Old Password Required for Password Change”   gesetzt!

Der Punkt hört sich aber doch sehr sinnvoll an, und deswegen probieren wir dies jetzt einmal aus:

ldap 66

Ein Blick in den LDAP-Browser auf “vms2”
zeigt hier übrigens, dass dies den Wert des Parameters “pwdSafeModify” unseres “ppolicy”-Objekts von FALSE auf TRUE setzt:

ldap 82

Nun machen wir wieder einen “passwd”-Test als User “tarja”. Dabei geben wir als neues Passwort zunächst eines mit passender Länge – nämlich mit 7 Buchstaben – und mit einer bunten Mischung aus Buchstaben und Zahlen an (z.B.”d4b3c9a”). Und laufen dann – obwohl “cracklib” nicht mosert – auf eine unerwartete Fehlermeldung vom LDAP-Server:

“Must supply old password to be changed as well as new one”.

ldap 74

Tja, hier haben wir es mit einer ersten Tücke zu tun, vor der uns YaST2 bei der “ppolicy”-Konfiguration leider nicht warnt.

Mit YaST2 setzt man auf dem Server schnell den Haken, aber man muss danach auch noch etwas auf den Clients ändern!

Irgendwie wird in unserem Test wohl das alte Passwort von der passwd/PAM-Kombination nicht an den LDAP-Server übermittelt. Um herauszufinden, an welcher Client-Einstellung das liegen mag , muss man ein wenig suchen. Den richtigen Hinweis findet man z.B. unter

https://linux.die.net/man/5/pam_ldap

bei der Beschreibung des Parameters “pam_password”:

pam_password      Specifies the password change protocol to use. The following protocols are supported:
 
exop
     Change password using the RFC 3062 password modify extended operation (only the new password is sent).
 
exop_send_old
     Change password using the RFC 3062 password modify extended operation (both the old and new passwords are sent).

Kurzanleitungen zur LDAP-Konfiguration von Clients wie etwa die unter

“http://karmak.org/archive/2003/02/ldap/ldap-linux.htm”

verschweigen meist, dass es zwei Varianten der “exop”-Einstellung gibt !

Mutig ändern wir nun auf “vms1” in der Datei “/etc/ldap.conf” den Eintrag zum Parameter “pam_password” wie folgt ab:

# Use the OpenLDAP password change
# extended operation to update the password.
pam_password     exop_send_old

Danach führen wir unseren Test wieder durch – mit einem Passwort, das die Länge von 7 Buchstaben hat und auch die Anforderungen der “cracklib” erfüllt.

ldap 75

Erfolg! Das klappt nun schon mal.

Nun führen wir aber gegenüber der “ppolicy” erneut auch den Negativ-Test mit dem zu kurzen Passwort “%45zz6” (6 Zeichen) durch und erleben folgende Überraschung:

ldap 81

Nach dem hier dargestellten Ablauf zu urteilen, ist die Passwortänderung durchgeführt worden!

Ist das Passwort tatsächlich auf dem LDAP-Server abgelegt worden ? Haben wir den “Constraint” der LDAP-“ppolicy” bzgl. der Länge zuletzt doch noch umgehen können ?

Nein, dies ist entgegen den obigen Meldungen nicht der Fall ! Man logge sich aus und versuche, sich mit dem neuen Passwort “%45zz6” wieder einzuloggen. Dies schlägt fehl! Ein Login mit dem alten Passwort   “%hjurtx”   funktioniert dagegen.

Was lernen wir daraus? Die “ppolicy” hält auch in diesem Fall – aber das Zusammenspiel der PAM-LDAP-Clients mit dem LDAP-Server wird bei Einsatz der Konfigurationsoption

pam_password     exop_send_old

in der Datei “/etc/ldap.conf” (hier auf “vms1”) buggy. Leider! Die Fehlermeldung vom LDAP-Server wird offenbar nicht mehr an den User auf “vms1” durchgereicht.

Tja, mich bringt diese ernüchternde Erfahrung völlig davon ab, die zusätzliche Prüfung des alten Passwortes auf dem Server zu verlangen. Ich mache deshalb diesen Punkt der Server-Konfiguration wieder rückgängig. Natürlich setze ich auf “vms1” auch die   “pam_password”-Option wieder zurück auf   “exop” !

Letzteres ist unbedingt notwendig, denn sonst bleibt das fehlerhafte Verhalten auf “vms1” nämlich unabhängig von der geänderten Servereinstellung bestehen.

So ist das halt – es ist nicht alles Gold, was auf den ersten Blick glänzt.

Zu Recht kann man an dieser Stelle die Frage stellen, ob eine Prüfung des alten Passwortes denn überhaupt und unbedingt notwendig ist. Ein erfolgreicher LDAP-Bind des Users ist für eine erfolgreiche Passwortänderung ja eine zwingende Voraussetzung. Und dabei wird ja gerade das alte Passwort geprüft.

Aber ich gebe gerne zu, dass ich nicht überblicke, ob es nicht doch Szenarien gibt, bei denen die zusätzliche Übermittlung des alten Psswortes nicht nur Beiwerk sondern ein echtes Sicherheitsfeature darstellen würde.

Anlegen weiterer spezieller “Password Policy”-Objekte und Zuweisung an einzelne User

Zum Schluss unseres Ausflugs in die “ppolicy”-Gefilde widmen wir uns der Frage, was man tun muss, wenn man für unterschiedliche Gruppen an Usern auch unterschiedliche “Passwort-Policies” hinterlegen will.

Dies kann z.B. deshalb erforderlich sein, weil man auf bestimmten Systemen/Servern des Netzes härtere Passwort-Bedingungen durchsetzen will. Dann muss man eigentlich schon bei der Useranlage eine Möglichkeit haben, dem User auf dem LDAP-Server eine andere “Password Policy” als die bislang benutzte “Default Policy” zuzuordnen.

Was man dafür zu tun hat, erschließt sich indirekt aus folgendem Text, den man

http://linux.die.net/man/5/slapo-ppolicy

entnehmen kann. Er betrifft einen Eintrag, den man pro User anlegen muss:

pwdPolicySubentry
 
This attribute refers directly to the pwdPolicy subentry that is to be used for this particular directory user. If pwdPolicySubentry exists, it must contain the DN of a valid pwdPolicy object. If it does not exist, the ppolicy module will enforce the default password policy rules on the user associated with this authenticating DN. If there is no default, or the referenced subentry does not exist, then no policy rules will be enforced.
 

Und in http://www.openldap.org/doc/admin24/overlays.html#Password%20Policies finden wir:

You can create additional policy objects as needed.
 
There are two ways password policy can be applied to individual objects:
 
1. The pwdPolicySubentry in a user’s object – If a user’s object has a pwdPolicySubEntry attribute specifying the DN of a policy object, then the policy defined by that object is applied.
 
2. Default password policy – If there is no specific pwdPolicySubentry set for an object, and the password policy module was configured with the DN of a default policy object and if that object exists, then the policy defined in that object is applied.
 

Unter OpenLDAP wird unser Problem also dadurch gelöst, dass man weitere spezifische “Password Policy Objekte” im LDAP-Baum anlegt und diese dann individuellen “User”-Einträgen über einen Eintrag “pwdPolicySubentry” zuordnet.

Hilft uns Yast2 auch hierbei? Ja, etwas, aber letztlich nicht so, wie ich mir das wünsche:

Man kann neue “Password Policy”-Objekte auf dem LDAP-Server “vms2” unter YaST2 zwar grundsätzlich über das “LDAP-Client”-Modul und dort über die Maske

“Advanced Configuration” >> “Administration Settings” > > Button “Add”   (unter der Tabelle)

anlegen.

ldap 90

Das Problem ist aber, dass YaST2 dies direkt unter der LDAP-Wurzel tun will – also dort, wo auch schon das “Default Policy”-Objekt gemäß der Standardeinstellungen von YaST2 untergebracht wurde. Da hört bei mir jetzt ein wenig das Verständnis auf; ich finde es blöd, den Hauptast des LDAP-Baumes mit Einzelobjekten zuzupflastern.

Um das Ganze wenigstens etwas besser zu strukturieren, erzeugen wir uns mittels einer LDIF-Datei einen neuen Zweig

ou=policies,dc=anracona,dc=de

zur Unterbringung unserer Policy-Objekte im LDAP-Baum. Und bei der Gelegenheit legen wir uns gleich auch noch ein Policy-Objekt der Klasse “objectClass: pwdPolicy” an, das wir mit “norm” bezeichnen:

cn=standard,ou=policies,dc=anracona,dc=de

Eine entsprechende LDOF-Datei, die ich hier “ppolicy.ldif” nenne und in einem Verzeichnis   “/root/ldapadmin/ldifs/”  anlege, hat dann folgenden Inhalt:

 
dn: ou=policies,dc=anracona,dc=de
objectclass: organizationalUnit
ou:policies
 
dn: cn=norm,ou=policies,dc=anracona,dc=de
objectClass: namedObject
objectClass: pwdPolicy
pwdAttribute: userPassword
pwdCheckQuality: 2
pwdMinLength: 8
pwdMustChange: FALSE
 

Dann führen wir diese Datei mit folgendem Kommando auf dem LDAP-Server “vms2” aus:

vms2:~ #    ldapadd    -D    “cn=Administrator,dc=anracona,dc=de”    -W    -x    -a    -f    ./ldapadmin/ldifs/ppolicy.ldif

Mit YaST2’s LDAP-Browser überzeugen wir uns vom Ergebnis:

ldap 91

Wir haben ein neues spezielles “ppolicy”-Objekt angelegt, das sich von unserem “Default Policy”-Objekt im Moment nur dadurch unterscheidet, dass es eine Passwort-Länge von “8” Zeichen verlangt.

Dieses Policy-Objekt wollen wir nun einem unserer User zuordnen. Dies können wir unter YaST2 über die User- und Gruppenverwaltung tun:

Wir editieren zunächst unseren Testuser “tarja”

ldap 93

und klicken dort auf den Reiter “Plug-Ins”.

ldap 94

Dort launchen wir die “Passwor Policy Settings”, wählen auf der nächsten Maske die Standard Policy ab und klicken schließlich auf den “Browse”-Button.

Im sich öffnenden LDAP-Browser wählen wir unser neu angelegtes “norm”-“Policy Objekt” und weisen es dem User durch Klicken auf die übliche Kaskade von “OK”-Buttons zu.

ldap 95

Das Ganze funktioniert allerdings nur auf einer “pro User”-Basis. Diese Einschränkung liegt natürlich schon am “ldapmodify”.

Auf großen Systemen sollte man für Operationen, bei denen man viele User gleichzeitig modifizieren muss, mit einer Kombination aus Scripting und LDAP-Kommandozeilentools arbeiten. Typischerweise sucht man erst nach
LDAP-Einträgen, lädt das Ergebnis in ein File, welches man anschließend durch ein “sed”-Script manipuliert und schließlich als Eingabe für ldapmodify verwendet. Schade, dass Opensuse hier nichts passendes anbietet.

Leider wird man unter YaST2 nun auch vergeblich nach einer Maske suchen, über die man auf einfache Weise die Zuordnung von Policies zu Usereinträgen erkennen könnte.

Der Grund hierfür ist, dass es sich bei den “pwdSubEntry” – Einträgen um sogenannte “administrative” Einträge handelt, die auch “System-” oder “Directory”-Attribute genannt werden. Die allermeisten LDAP-Browser zeigen solche Einträge nicht an, da sie User-Manipulationen nicht zugänglich sein sollen. Hiervon macht auch der YaST2-LDAP-Browser keine Ausnahme. Mit “gq” kommt man auch nicht weiter.

Bleibt man bei YaST2, so muss man für den User, dessen Einstellungen einen interessieren, erneut die eben schon geöffnete YaST2-Maske in der User- und Gruppenverwaltung “launchen”, die der Verwaltung des “ppolicy”-Plug-Ins dient. Dort sieht man dann die aktuelle Zuordnung des gewählten Policy-Objekts zum User. Dieses Vorgehen führt aber pro User über mehrere Masken und ist deshalb unbequem.

Tja, so verlassen wir nun langsam die Möglichkeiten von YaST2. Über das Kommandozeilen-Tool   “ldapsearch”   bekommen wir jedoch die Information, die wir haben wollen:

ldap 96

Das Testen, ob nun bei einem spezifischen User statt der   “Default Policy”   die Constraints des jeweiligen speziellen “Policy”-Objektes ziehen, überlassen wir dem Leser. Man geht dabei genauso vor, wie bereits oben beschrieben.

Nun bleibt dem Admin noch die mühsame Aufgabe, auf dem LDAP-Server weitere Policy-Objekte anzulegen und sie seinen Usern zuzuweisen. Dazu wird er die User typischerweise in Gruppen einteilen.

Zusammenfassung

In diesem Beitrag haben wir gesehen, wie man einem über LDAP verwalteten User-Account mit Hilfe der YaST2-Tools ein “Password-Policy”-Objekt des LDAP-Directories zuordnet. Wir hatten auch diskutiert, dass man die Einstellungen für die unter PAM aufgerufenen “cracklib”-Prüfungen auf den Systemen des Netzwerkes mit den zentralen Passworteinschränkungen in Einklang bringen sollte.

Der findige User wird aufgrund des oben Dargestellten nun sicher auch einen eigenen Weg finden, alle angelegten “Policy Objekte” – und auch das Default Policy”-Objekt – in einem dafür geeigneten Zweig des LDAP-Baums aufzuräumen.

Für Leute, die von dem Thema immer noch nicht genug haben, sei abschließend auf einen Artikel verwiesen, der zeigt, wie man die “ppolicy”-Technik von OpenLDAP mit SSH zusammenbringt:

http://directory.fedoraproject.org/wiki/Howto:PAM

Viel Spaß nun beim Anwenden zentraler LDAP Password Policies !

 

Opensuse 12.1 – LDAP III

In den letzten zwei Beiträgen zur LDAP-Installation unter Opensuse 12.1 hatte ich auf einem Testsystem “vms2.anracona.de” einen LDAP-Server installiert und diesen TLS-fähig gemacht.

Ferner hatte ich auf diesem Server die YaST2-Clients zur Anwenderverwaltung eingerichtet. In diesem Zusammenhang hatten wir neben der Konfigurationsdatei

“/etc/openldap/ldap.conf”

auch die wichtige Konfigurationsdatei

“/etc/ldap.conf”

für PAM und NSS betrachtet. Allerdings haben wir die User- und Gruppenverwaltung bislang nur lokal auf dem LDAP-Server selbst durchgeführt und getestet. Server- und Client-System waren also identisch.

Letztlich wollen wir aberr erreichen, dass mit Hilfe des zentralen LDAP-Systems eine Authentifizierung von Usern, die sich an einem beliebigen Host im Netzwerk einloggen, gewährleistet wird. Ferner soll über das LDAP-Verzeichnis neben der Authentifizierung auch eine userspezifische Autorisierung des Zugangs zu ganz bestimmten Hosts verwaltet und bei jedem Login-Vorgang vorgenommen werden. Es ist klar, dass hierzu während eines Login-Vorgangs auf einem Host eine Kommunikation zwiuschen dem Host und dem zentralen LDAP-System ablaufen muss. Da hierbei sicherheitsrelevante Information ausgetauscht wird, muss die Kommunikationsverbindung durch Verschlüsselung (TLS/SSL) abgesichert werden.

In diesem Beitrag erinnern wir deshalb an die Skizze am Anfang des LDAP II-Artikels. Unser nächstes Ziel ist es, einen Zugriff auf den LDAP-Server von einem echten Opensuse 12.1-Client-System aus zu realisieren. Dieser Client sei im lokalen Testnetz unter der Adresse “vms1.anracona.de” erreichbar.

LDAP_vms2_vms1

Wir wollen auf dem System “vms1” natürlich auch wieder die YaST2-Tools zur Anlage von User- und Gruppenaccounts benutzen. Diese Accounts sollen aber nicht lokal, sondern auf dem LDAP-Server hinterlegt werden. Wir benötigen also einen TLS-geschützten Zugriff von LDAP-Clients des Systems “vms1” auf den LDAP-Server “vms2”.

Die im letzten Beitrag bereits durchgeführte Einrichtung der YaST2-LDAP-Client-Module sowie der YaST2-User- und Gruppen-Verwaltung auf dem Server sah sehr generisch aus. Wir vermuten daher zu Recht:

Auf dem System “vms1” können wir im Prinzip ähnlichen Schritten zur Einrichtung der YaST2-LDAP-Module folgen wie bei der Einrichtung des YaST2-LDAP-Clients und der YaST2-Benutzerverwaltung auf dem LDAP-Server selbst.

Damit wir dabei aber auch etwas Neues kennenlernen, werden wir uns in diesem Beitrag zusätzlich folgende Punkte genauer ansehen:

  • Templateartige und opensuse-spezifische Vorgaben für die Anlage von Usern- und Gruppen. Zentrale Hinterlegung der Vorgaben auf dem LDAP-Server und Ort der entsprechenden Einträge im LDAP-Verzeichnisbaum. Änderung der Vorgaben per YaST2.
  • LDAP-Einträge in den Konfigurationsdateien für PAM und NSS

Ein später nachfolgender Beitrag “LDAP IV” widmet sich dagegen einer zentralen Passwort-Politik, die wir auf dem LDAP-Server einrichten sowie Fragen der Absicherung des Servers gegenüber Logins von beliebigen Usern, die im LDAP-System hinterlegt wurden.

Konfiguration des YaST-LDAP-Clients auf dem externen System “vms1”

Schritt 1: Beschaffung des CA-Zertifikats

Wir gehen hier unter YaST2 völlig analog zu den Schritten vor, die ich im Beitrag LDAP I unter dem Schritt 4 und im Beitrag LDAP II unter dem dortigen Schritt 3 beschrieben habe. Im Unterschied zur Ersteinrichtung der LDAP-Clients auf dem Server (s. LDAP I) berücksichtigen wir hier aber von vornherein die Nutzung von TLS.

Die auszufüllenden
Masken geben wir hier nicht erneut vollständig wieder. Wir betrachten nur die wichtigsten:

ldap 47

Unser Server ist in unserem Beispiel natürlich nach wie vor das System “vms2.anracona.de” (und nicht “vms1” !). Auch die “LDAP Base DN” ist natürlich identisch zu der, die wir bei der Client-Einrichtung auf dem Server eingetragen hatten.

Eine wichtige Ausnahme zum bisherigen Vorgehen gibt es allerdings auf der Maske

“Advanced Configuration >> Reiter Administration Settings”

des LDAP-Clients:

Ldap 46

Wichtiger Hinweis 1:
Der Haken bei “Home Directories on This Machine” ist unbedingt erforderlich. Wir wollen ja, dass die Home-Verzeichnisse definitiv auf dem System “vms1” angelegt werden – und nicht sonst wo (etwa auf dem LDAP-Server “vms2”) oder evtl. gar nicht.

Wichtiger Hinweis 2:
Wir setzen keinen Haken beim Punkt “Create Default Configuration Objects” ! Dadurch würden wir auf dem Server “vms2” bereits durchgeführte Konfigurationen zur Anlage von User- und Gruppen Accounts ggf. überschreiben. Was das bedeutet, werden ich weiter unten (s. Schritt 1.4) beschreiben.

Erwartungsgemäß benötigen wir für den Aufbau von TLS-Verbindungen der YaST2-LDAP-Clients und der PAM/NSS-Komponenten vom System “vms1” zum Server “vms2” auch Kopien von Zertifikaten. Der Ablageort dieser Zertifikate muss natürlich auch auf dem System “vms1” in die Konfigurationsmasken eingetragen werden. Wir nehmen der Einfachheit halber auch hier das lokale Verzeichnis “/etc/openldap” (auf “vms1”):

ldap 48

Welche Art von Zertifikatsdateien benötigen wir? Brauchen wir überhaupt mehrere?

Ohne großes Nachdenken tippen wir mal darauf, dass uns der LDAP-Server im Rahmen des TLS- Verschlüsselungsdialogs sein eigenes Server-Zertifikat übermitteln wird, damit wir auf “vms1” seine Authentizität überprüfen können. In unserem Beispiel liegt das Server-Zertifikat auf dem Server “vms2” – und dort in der Datei “/etc/openldap/vms2_cert.pem”. Dieses Zertifikat wird auf dem Client-System nicht benötigt.

Für die Überprüfungsprozesse, die LDAP-Client-Module auf “vms1” bzgl. des Server-Zertifikats von “vms2” durchführen, müssen wir jedoch angeben, welchen CA-Authorities (bis hin zu Root-CA) das System “vms1” dabei vertrauen soll.

Hinweis:
Dies ist in unserem Testbeispiel umso wichtiger, als es sich bei “vms2_cert.pem” im Kern ja um ein “self-signed” Zertifikat für den LDAP-Server handelt. Denn es wurde ja gerade von einer Root-CA ausgestellt, die auf dem LDAP-Server “vms2” beheimatet ist.

Dieser Root-CA muss unser Client-System im Testnetz also explizit vertrauen. Wodurch identifizieren wir auf dem Client aber die CA? Natürlich durch ihr eigenes Zertifikat! Wir benötigen also das Zertifikat “anracona_vms2.pem” unserer Root-CA. Genauer müsste man eigentlich sagen: Die Zertifikate der für das Serverzertifikat “vms2_cert.pem” des LDAP-Server ausschlaggebenden CA-Authorities. Wären in einem realistischeren Beispiel mehrere hierarchische CAs involviert gewesen, so würden wir alle Zertifikate der CA-Kette benötigen!

In unserem einfachen Fall müssen wir also die Datei “/etc/openldap/anracona_vms2.pem” vom Server auf unser Clientsystem kopieren. Wir können dies z.B. mit “scp” erledigen, wenn wir openssh auf beiden Systemen installiert haben.

Auf dem Server “vms2”:

vms2:~ # scp /etc/openldap/anracona_vms2.pem root@vms1.anracona.de:/etc/openldap/

Im realen Leben würden wir das Zertifikat der Root-CA
dagegen für unseren Client von einem LDAP-Server herunterladen. Danach versehen wir die Zertifikatsdatei auf dem Clientsystem “vms1” mit passenden Zugriffsrechten:

vms1:~ #: chown ldap.ldap /etc/openldap/anracona_vms2.pem
vms1:~ #: chmod 644 /etc/openldap/anracona_vms2.pem

Schritt 2: Die Datei “/etc/openldap/ldap.conf”

Wir erinnern uns, dass die Einstellungen, die YaST2 bei der Einrichtung der LDAP-Client-Fähigkeit vornimmt, sich an mehreren Stellen auf die Konfiguration des Opensuse-Systems auswirken (u.a. in den Dateien “/etc/openldap/ldap.conf” und “/etc/ldap.conf”).

Zunächst sehen wir uns mal die benötigten Einträge in der Datei “/etc/openldap/ldap.conf” des Clients “vms1” an.

Diese Datei steuert systemweit Standard-LDAP-Zugriffsverfahren (vergl. mit dem Beitrag LDAP II). Hier Auszüge aus dem Datei-Inhalt für das System “vms1”:

/etc/openldap/ldap.conf

base dc=anracona,dc=de
uri ldap://vms2.anracona.de
ldap_version 3
ssl start_tls
TLS_CACERTDIR /etc/openldap
TLS_CACERT /etc/openldap/anracona_vms2.pem
TLS_REQCERT allow

Über den Parameter “uri” wird die Adresse des LDAP-Servers angegeben. Einen speziellen Port geben wir dabei nicht an. Stattdessen sorgt die Zeile

ssl start_tls”

dafür, dass eine TLS-geschützte Verbindung über den Standard-LDAP-Port 389 initialisiert wird. Bzgl. der übrigen Parameter werfen wir zur Vervollständigung unseres Wissens auch mal einen Blick in die man-Seiten. Es folgen Ausschnitte:

URI <ldap[si]://[name[:port]] …>
Specifies the URI(s) of an LDAP server(s) to which the LDAP library should connect. The URI scheme may be any of ldap, ldaps or ldapi, which refer to LDAP over
TCP, LDAP over SSL (TLS) and LDAP over IPC (UNIX domain sockets), respectively.
Each server’s name can be specified as a domain-style name or an IP address lit-
eral. Optionally, the server’s name can followed by a ‘:’ and the port number the
LDAP server is listening on. If no port number is provided, the default port for
the scheme is used (389 for ldap://, 636 for ldaps://).

 
TLS_CACERT <filename>
Specifies the file that contains certificates for all of the Certificate
Authorities the client will recognize.

 
TLS_CACERTDIR <path>
Specifies the path of a directory that contains Certificate Authority certificates in separate individual files. The TLS_CACERT is always used
before TLS_CACERTDIR. This parameter is ignored with GnuTLS.

 
TLS_REQCERT <level>
Specifies what checks to perform on server certificates in a TLS session, if any. The can be specified as one of the following keywords:
 
never The client will not request or check any server certificate.
 
allow The server certificate is requested. If no certificate is provided,
the session proceeds normally. If a bad certificate is provided, it
will be ignored and the session
proceeds normally.
 
try The server certificate is requested. If no certificate is provided,
the session proceeds normally. If a bad certificate is provided, the
session is immediately terminated.
 
demand | hard
These keywords are equivalent. The server certificate is requested.
If no certificate is provided, or a bad certificate is provided, the
session is immediately terminated. This is the default setting.

Aha, an den Werten für den Parameter “TLS_REQCERT” erkennen wir, dass es durchaus unterschiedliche “Level” für den Umgang mit dem Zertifikat des Servers gibt. Wir können in unser Testkonfiguration nun durchaus mal die Einstellung “demand” ausprobieren und sehen, ob auf dem Client “vms1” das Absetzen eines Kommandos der Art:

vms1:~ # ldapsearch -b dc=anracona,dc=de uid=* -x -D “cn=Administrator,dc=anracona,dc=de” -W -xLLL -ZZ

funktioniert. Bzgl. der Parameter siehe die man-Seiten zu “ldapsearch”. (Zitat: “-Z[Z] Issue StartTLS (Transport Layer Security) extended operation. If you use -ZZ, the command will require the operation to be successful.” / Zum Beobachten des Zertifikatsaustausches kann man die Option -d2 anschließen.)

Die Durchführung des “ldapsearch-Kommandos” sollte in unserer Testkonfiguration anstandslos Ergebnisse für die bereits eingetragenen User liefern. Damit haben wir auch gleich unseren ersten Test für die Client-Anbindung hinter uns gebracht. Normale LDAP-Operationen funktionieren zwischen unseren Opensuse-Systemen bereits.

Schritt 3: Die Datei “/etc/ldap.conf”

Wir erinnern uns daran (siehe Beitrag “LDAP II), dass diese Datei unter Opensuse 12 für die Anbindung von PAM und NSS an LDAP zu steuern. Wir sehen uns nur die Parameter an, die von Standardeinstellungen abweichen. Weitere Informationen zu den einzelnen Parametern liefern die man-Seiten zu “/etc/ldap.conf”.

/etc/ldap.conf

# The distinguished name of the search base.
base dc=anracona,dc=de
 
# Reconnect policy:
# soft: return immediately on server failure
bind_policy soft
 
# Search the root DSE for the password policy (works
# with Netscape Directory Server). Make use of
# Password Policy LDAP Control (as in OpenLDAP)
pam_lookup_policy yes
 
# Use the OpenLDAP password change
# extended operation to update the password.
pam_password exop
 
# returns NOTFOUND if nss_ldap’s initgroups() is called
# for users specified in nss_initgroups_ignoreusers
# (comma separated)
nss_initgroups_ignoreusers root,ldap
 
# Enable support for RFC2307bis (distinguished names in group
# members)
nss_schema rfc2307bis
 
# configure –enable-nds is no longer supported.
# NDS mappings
nss_map_attribute uniqueMember member
 
# OpenLDAP SSL mechanism
# start_tls mechanism uses the normal LDAP port, LDAPS typically 636
ssl start_tls
uri ldap://vms2.anracona.de
ldap_version 3
pam_filter objectClass=posixAccount
 
# OpenLDAP SSL options
# Require and verify server certificate (yes/no)
# Default is to use libldap’s default behavior, which can be configured in
# /etc/openldap/ldap.conf using the TLS_REQCERT setting. The default for
# OpenLDAP 2.0 and earlier is “no”, for 2.1 and later is “yes”.
#tls_checkpeer yes
 
# CA
certificates for server certificate verification
# At least one of these are required if tls_checkpeer is “yes”
tls_cacertdir /etc/openldap
tls_cacertfile /etc/openldap/anracona_vms2.pem

Einige Einträge sind offenkundig ganz ähnlich zu den Einträgen in der “/etc/openldap/ldap.conf”. Einige sind jedoch auch spezifisch:

Die Einstellung “soft” des Parameters “bind_policy” bedeutet nach den man-Seiten und der Quelle “http://linux.die.net/man/5/nss_ldap“, dass kein Reconnect (mit erheblicher Zeitverzögerung) versucht wird, wenn ein (initialer) Connect-Versuch gemäß der NSS-Anweisungen fehlschlägt.

bind_policy <hard_open|hard_init|soft>
Specifies the policy to use for reconnecting to an unavailable LDAP server. The default is hard_open, which reconnects if opening the connection to the directory server failed. By contrast, hard_init reconnects if initializing the connection failed. Initializing may not actually contact the directory server, and it is possible that a malformed configuration file will trigger reconnection. If soft is specified, then nss_ldap will return immediately on server failure. All "hard" reconnect policies block with exponential backoff before retrying.

“Hard”-Einstellungen für diesen Parameter können also problematisch werden; siehe auch :
http://www.held.org.il/blog/2008/09/ldap-default-bindhard-policy-is-problematic/
http://unix.derkeiler.com/Mailing-Lists/FreeBSD/questions/2008-02/msg01126.html
https://bugzilla.redhat.com/show_bug.cgi?id=502072

Ganz unten sehen wir wieder die Einstellungen für die Zertifikate, denen zu vertrauen ist. Bzgl. des “tls_cacertdir”-Wertes siehe die entsprechenden Ausführungen im früheren Beitrag LDAP II.

Die Bedeutung des Parameters “tls_checkpeer” ergibt sich aus der in der Datei unmittelbar darüber stehenden Erläuterung. Wir können das Kommentarzeichen vor diesem Parameter in unserer Testumgebung auch mal versuchsweise entfernen und den Wert auf “yes” setzen. Das sollte zu keinen Problemen führen.

Interessanter sind die Parameter “pam_password” und “pam_lookup_policy”.

Unter der Web-Adresse http://karmak.org/archive/2003/02/ldap/ldap-linux.htm

lesen wir:

“The directive “pam_password exop” tells pam-ldap to change passwords in a way that allows OpenLDAP to apply the hashing algorithm specified in /etc/ldap/slapd.conf, instead of attempting to hash locally and write the result directly into the database.”

Tja, nun hatten wir ja schon früher gesehen, dass es die “slapd.conf”-Konfigurationsdatei unter Opensuse gar nicht mehr gibt!

Jetzt könnte man unbedarft versuchen, auf dem Opensuse LDAP-Server in dessen modularen Konfigurationsdateien einen Eintrag für ein Standard-Hash-Verfahren des LDAP-Servers zu finden. Also einen Eintrag der Art “password-hash {SHA},{SSHA}”, wie es ihn früher in der guten alten “slapd.conf” gab.

Eine Suche der Art

vms2:/etc # grep  -d recurse hash /etc/openldap/

liefert aber nur Kommentarzeilen aus diversen Schema-Dateien. Deshalb stellen sich jetzt folgende Fragen:

  • Woher wissen die Yast2-Userverwaltung auf “vms1” und der LDAP-Server eigentlich, welches Passwort-Verschlüsselungsverfahren bei der Anlage der Userdaten auf einem LDAP-Server angewendet werden soll?
  • Woher kennt die YaST-Userverwaltung für LDAP auf “vms1” eigentlich die nächste lfd. UID-Nummer, die bei der Anlage eines neuen Users verwendet werden soll, wenn die Nummern der bisher angelegten User doch auf dem LDAP-Server liegen?
  • Woher erfährt das YaST2-Modul zur Anlage von Usern eigentlich das Skeleton-Verzeichnis oder andere Standarddaten, die bei der Neuanlage eines Users berücksichtigt werden sollen?
  • Wie zentralisiert man eigentlich die Standarddaten für die Anlage von Useracounts über mehrere Systeme hinweg?
  • Wo wurde eigentlich festgelegt, dass User-Daten auf unserem Testsystem im LDAP-Baum unter “ou=people,dc=anracona,dc=de” angelegt werden sollen ?

Vielleicht ist man nun durch diese Fragen verunsichert worden und bezweifelt, dass die YaST2-Benutzerverwaltung auf dem System “vms1” überhaupt funktioniert. Höchste Zeit also für die testweise Anlage einiger Testuser auf dem System “vms1”.

Die Möglichkeit zur YaST2-gestützten Useranlage unter Hinzuziehung des LDAP-Servers erhalten wir, wie in den früheren Beiträgen beschrieben, auch auf dem System “vms1” über folgende Maske der YaST2-Benutzerverwaltung und die Wahl des Filters “LDAP-Users”:

ldap_56

Dort drücken wir auf den Button “Add” und nehmen in den nachfolgenden Masken die erforderlichen Einträge vor. Auf der Maske “Details” erkennen wir dabei übrigens, dass auf wundersame Weise automatisch die nächste freie Nummer für den Testuser gewählt wird.

Ohne hier alle Schritte vorzuführen, endet unser Test der Useranlage mit YaST2 auch auf “vms1” erfolgreich:

  • die Kommunikation unserer YaST2-Benutzerverwaltung auf “vms1” mit dem LDAP-Server “vms2” funktioniert,
  • unter dem Zweig “ou=people,dc=anracona,dc=de” werden im LDAP-Verzeichnis auf “vms2” die erforderlichen User-Einträge angelegt,
  • auf “vms1” (und nicht etwa auf vms2) werden die Home-Verzeichnisse für die neuen User korrekt angelegt und
  • jeder neu mit YaST2 von “vms1” aus angelegte User kann sich auf “vms1” auch einloggen.

Der Leser möge speziell den letzten Punkt – nämlich den erfolgreichen Login auf dem Host “vms1” an dieser Stelle selbst ausprobieren. In den Beiträgen “LDAP IV” und “LDAP V” werden wir solche Login-Vorgänge explizit und ausführlich an mehreren Userbeispielen betrachten. Wir zeigen dies hier für einen Test-User “tarja”:

ldap 70

Offenbar haben wir “vms1” richtig konfiguriert. Ein Blick mit dem LDAP-Browser auf “vms2” zeigt denn auch die angelegten Testuser an:

ldap_57

Als nächstes sehen wir uns ein Detail der User-Einträge, die YaST2 für uns auf dem LDAP-Server vornimmt, genauer an.

Studiert man nun die User-Einträge unter dem Ast “ou=people,dc=anracond,dc=de” des LDAP-Verzeichnisses genauer, so findet man bzgl. der Passwortverschlüsselung Feldeinträge der Form:

userPassword {ssha}dMU9M69W………

Es wurde also SSHA als Hash-Verfahren für die Passwortverschlüsselung herangezogen. Gehen wir dagegen auf die Passworteinstellungen der YaST2-Userverwaltung (Expert-Options >> Password Encryption) auf dem System “vms1”, so finden wir dort überraschenderweise jedoch Folgendes:

ldap 49

Opensuses’s YaST ist nach einer Standardinstallation eigentlich auf MD5 als Hashverfahren eingestellt! Unser Fragenkatalog von oben erweitert sich also um die Frage:

  • Woher also kommt also die SSHA-Einstellung für das LDAP-System?

Auf diese Frage gibt es eine Antwort, die allein aber nicht hinreichend ist:

Die erste Antwort ist, dass der LDAP-Server eine Standardeinstellung zieht, wenn die Option “exop” gesetzt ist. Wir zitieren nach
http://www.zytrax.com/books/ldap/ch6/#passwordhash:

olcPasswordHash (password-hash)
Allows definition of one or more hash methods used when storing a new password in userPassword with an Extended Modify Password Operation (RFC 3602). Format:
 
# OLC (cn=config) form
olcPasswordHash: {hash}[,{hash} [, …]]
# slapd.conf form
password-hash {hash}[,{hash} [, …]]
The value of hash must be one of the supported methods {SSHA}, {SHA}, {SMD5}, {MD5}, {CRYPT}, or {CLEARTEXT}. The default value is {SSHA}. … When used with OLC (cn=config) this attribute appears in/is added to the olcDatabase={-1}frontend,cn=config entry not the global (cn=config) entry.

SSHA ist also der Standard, der gezogen wird, wenn in der Datei “/etc/ldap.conf” der Parameter “pam_password exop” gesetzt ist, und in die Datei “olcDatabase={-1}frontend.ldif” kein Eintrag der Form “olcPasswordHash: {hash}” eingefügt wurde. Wie es bei uns der Fall ist.

Dennoch könnte es ja so sein, dass die Module, die YaST2 einsetzt, um User anzulegen, explizit andere Einstellungen für die Verschlüsselung der Passwörter verwenden – wie eben MD5. Die Schemata, deren Felddefinitionen einen User-Datensatz festlegen, lassen eine individuelle Festlegung des Verschlüsselungsverfahrens für das Feld “userPasswort” ja durchaus zu.

Wo befinden sich also die Vorgaben für die YaST2-Module zur Useranlage? Um diese Frage und auch die anderen offen gebliebenen Fragen zu beantworten, müssen wir nun auf einen Punkt aus dem Beitrag “LDAP I” zurückkommen, der SuSE-spezifisch ist und auf den wir bislang nicht eingegangen sind.

Schritt 4: Opensuse-spezifische Konfigurationsvorgaben und Templates für die Anlage von Usern und Gruppen

Im Beitrag “LDAP I” hatten wir in folgender Maske zur Einrichtung der YaST2-LDAP-Clients auf “vms2”

ldap_11

die Option “Create Default Configuration Objects” gesetzt.

Lässt man dies bei der Einrichtung eines anderen LDAP-Servers testweise weg und legt später User an, so wird man u.a. feststellen, dass die User Accounts dann keineswegs unter dem LDAP-Verzeichniszweig

“ou=people,dc=anracona,dc=de”

angelegt werden. Diesen Zweig gibt es dann nicht einmal ! Im LDAP-Baum würde die Anlage von Informationen zu User Accounts in einer solchen Situation vielmehr direkt unter der Base-DN erfolgen, was aus einer Reihe von Gründen natürlich nicht erstrebenswert wäre.

Die Option “Create Default Configuration Objects” bei der Konfiguration des LDAP-Clients scheint also dazu zu führen, dass YaST2 während der Einrichtung des LDAP-Clients auf dem LDAP-Server (!) einige Standardeinstellungen vornimmt und dabei auch bestimmte Äste des LDAP-Baums einrichtet.

Ein Blick mit dem YaST2-LDAP-Browser offenbart denn auch, was so alles während unserer LDAP-Einrichtung angelegt wurde:

ldap 51

Zunächst stellen wir fest, dass es drei interessante “ou-Zweige” gibt:

  • ou=people
  • ou=ldapconfig
  • ou=group

(Der darüber liegende Eintrag “cn=Default Policy” ist übrigens kein Standardeintrag. Wie dieser Eintrag auf meinem Testsystem “vms2” entstanden ist, bespreche ich im Beitrag “LDAP IV”.)

Unter dem Zweig “ou=people” hinterlegt die YaST-Userverwaltung offenbar die Informationen zu User Accounts, unter “ou=group” die Informationen zu Group Accounts. Für die User hatten wird dies im Beitrag “LDAP II” bereits explizit gesehen. Dass das auch für Gruppen gilt, kann jeder selbst durch Anlegen entsprechender Test-Accounts für Gruppen verifizieren.

Von größerem Interesse ist aber der Bereich “ou=ldapconfig”. Dort wurden von YaST2 bei unserer initialen Konfiguration des “LDAP-Clients” auf dem System “vms2” (s. LDAP I) offenbar schablonen- und templateartige Informationen als Vorgaben für die Anlage von User- und Group-Accounts angelegt. Ein Blick auf die Felder der “cn”-Einträge

  • cn=groupconfiguration
  • cn=grouptemplate
  • cn=userconfiguration
  • cn=usertemplate

ist wirklich ganz instruktiv. Man erkennt sofort, dass die Inhalte tatsächlich in etwa den Informationen entsprechen, die man bei einer manuellen Verwendung von “useradd” bzw. “usermodify” auf Standardsystemen auch anlegen bzw. modifizieren würde.

U.a. finden wir in den genannten LDAP-Einträgen auch die vorhin gesuchte Vorgabe zur Verwendung von SSHA als Hash-Verfahren für die User-Passwörter sowie eine Vorgabe für das Skeleton-Verzeichnis. Beide Informationen werden von YaST2 verwendet, wenn ein neuer User-Account angelegt wird.

Wichtiger Hinweis:
An dieser Stelle sollte durch Vergleich zur weiter oben gemachten Anmerkung für den Hash-Standard des Servers klar sein, dass man zwischen den Einstellungen in Opensuse’s “userconfiguration”-Eintrag und dem Serverstandard, der in den Server-Konfigurationsdateien eingestellt wird, für Konsistenz sorgen muss, wenn man nicht ein kunterbuntes Durcheinander an Passwort-Hashes riskieren will. Denn löst man sich irgendwann von YaST2 und nutzt andere Tools oder direkt LDIF-Dateien für die User-Anlage, so ist je nach verwendeten Einstellungen für Uneinheitlichkeit viel Platz. Aber das nur nebenbei.

Offenbar werden bei der Anlage neuer Accounts auf dem LDAP-System auch Informationen zur nächsten freien UID-Nr und GID-Nr. in entsprechenden Feldern der Zweige “userconfiguration” und “groupconfiguration” überschrieben (suseNextUniqueID). Darauf greifen die YaST-Module bei der Anlage des nächsten Users zurück.

Die Struktur der Einträge entspricht übrigens einem spezifischen LDAP-Schema, das bei der Einrichtung des LDAP-Servers von YaST2 mit angelegt wurde, nämlich dem “yast”-Schema.

Dies bestätigen ein Blick in das Konfigurationsverzeichnis “/etc/openldap/slapd.d/ ”

ldap 54

sowie zusätzliche Blicke in die Dateien

  • /etc/openldap/slapd.d/cn=config/cn=schema/cn={4}yast.ldif” und
  • /etc/openldap/schema/yast.schema

Was sagt uns das alles?

  • Opensuses’ YaST erstellt schablonenartige Vorgaben zur Erstellung von User- und Group-Accounts. Während der Einrichtung der YaST2-LDAP-Clients für die User-Verwaltung werden diese Vorgaben im LDAP-System selbst unter dem Zweig “ou=ldapconfig” unterhalb der Base-DN hinterlegt! Dies ist der Sinn der oben erwähnten Option “Create Default Configuration Objects
    “.
  • Die YaST2-Client-Anwendungen zur Userverwaltung holen sich diese Daten im Vorfeld einer Account-Einrichtung oder -Änderung also vom LDAP-Server selbst ab. (Faktisch geschieht dies bei der Setzung des Filters für das Account-Backend auf “LDAP User” oder “LDAP Group” (Button “Set Filter” in den Masken zur User- und Gruppenverwaltung).

Die Antworten auf die oben gestellten Fragen liegen also in den Tiefen von YaST2 und den dort in ycp-Scripts verankerten Ideen von Opensuse zur Account-Verwaltung und einem spezifischen “yast”-LDAP-Schema.

YaST’s ycp-Scripts fragen im Zuge der User- und Gruppen-Verwaltung im LDAP-System dort hinterlegte Instruktionen zur User- und Gruppen-Anlage ab. Bei der Konfiguration des YaST2-LDAP-Clients hingegen werden durch ycp-Scripts auf dem LDAP-Server bestimmte Verzeichnis-Zweige angelegt und Einträge mit Vorgaben zur User- und Gruppen-Anlage hinterlegt.

Tatsächlich findet man nach ein wenig Recherche in der Datei “/usr/share/YaST2/modules/Ldap.ycp” auch die Codezeilen für diejenigen Informationen, die bei der initialen Anlage der Vorgaben zu User- und Gruppenaccounts unter “ou=ldapconfig” von den YaST2-Konfigurationsskripts herangezogen werden:

ldap 52

Nun fragt man sich als nächstes, ob und wo man diese Standardeinstellungen für die account-bezogenen Configuration- und Template-Vorgaben ändern kann.

Auch dies geschieht natürlich über YaST2 und zwar im YaST2-Modul “LDAP-Client”.

Auf der Einstiegsmaske “LDAP Client Configuration” nutzt man den Button “Advanced Configuration”, geht auf der nächsten Maske in den Reiter “Administration Settings” und klickt dort auf den Button “Configure User Management Settings”. Auf der nachfolgenden Maske hat man alle Möglichkeiten zum Überschreiben der Werte für die User- und auch der Gruppenkonfiguration sowie der zugehörigen “Templates” :

ldap 53

Diese Änderungen kann per YaST2 man von jedem System aus vornehmen, das den LDAP-Server als Backend für die User- und Gruppenverwaltung verwendet.

Inzwischen wird wohl auch ein wenig klar, wie man mittels YaST2 und LDAP eine (in diesem Stadium einfache!) systemübergreifende User- und Gruppenverwaltung hinbekommt, die zumindest elementaren Bedürfnissen ganz gut gerecht wird.

Grundsätzlich finde ich das Opensuse-Vorgehen zur User- und Gruppenverwaltung mit YaST2 und LDAP ja für eine Basisausstattung und einfache Situationen hinreichend und clever. Aber zwei Dinge stören mich doch ganz erheblich:

  • Weder aus den YaST-Masken selbst noch aus den zugehörigen Hilfeseiten ist ersichtlich, was die “Default Configuration Objects” sind und wo sie hinterlegt werden. Die Bezeichnung “LDAP Client” verführt geradezu zu der Annahme, dass auch hierbei nur Einstellungen auf dem Client vorgenommen werden – was aber offenkundig falsch ist.
  • Wenn man den LDAP-Server als Backend für die User- und Gruppenverwaltung von mehreren Systemen aus verwendet, so kann man mit dem YaST”-LDAP-Client-Modul von jedem System aus die Vorgaben unter “ou=ldapconfig” auf dem zentralen Server überschreiben.

    Blöderweise gilt dies auch während der initialen Konfiguration des YaST2 LDAP-Client Moduls auf einem jeden neuen System, das an den LDAP-Server angebunden werden soll. Setzt man hier versehentlich den Haken bei der Option “Create Default Configuration Objects”, so werden die bisherigen, auf dem LDAP-Server gepflegten User- und Gruppen-Konfigurationsoptionen erneut durch die Default-Einstellungen überschrieben.

    Daher ist mein obiger Hinweis, diesen Haken bei der Einrichtung von “vms1” nicht zu setzen, wichtiger als man zunächst vielleicht meinen
    möchte!

NSS und PAM auf dem System “vms1” und ihr Zusammenspiel mit LDAP

Weiter oben hatten wir den erfolgreichen Login eines Testusers auf “vms1” als Beleg für die richtige Konfiguration des Zusammenspiels unseres Hosts “vms1” mit dem LDAP-Server “vms2” angesehen. Für Details des Login-Vorgangs hatten wir uns dabei aber noch nicht interessiert. Unser Fokus lag auf den Konfigurationseinstellungen.

Bereits aus dem beitrag “LDAP II” wissen wir aber, dass Login-Vorgänge und zugehörige Authentifizierungsvorgänge auf aktuellen Linux-Systemen vom PAM-Mechanismus überwacht und gesteuert werden. Es ist daher an der Zeit, sich das Zusammenspiel von PAM mit LDAP auf unserem Host “vms1” etwas genauer anzusehen. In diesem Beitrag sehen wir uns einige Konfigurationsdateien an. Vertieft wird das Verständnis der Interaktion zwischen PAM auf einem Host “vms1” mit einem zentralen LDAP-Server aber vor allem im folgenden Beitrag LDAP IV.

NSS-Konfigurationsdatei für LDAP

Bereits im Beitrag LDAP II hatten wir festgestellt, dass das YaST2-Module “LDAP Client” offenbar auch Einstellungen für PAM und NSS vornimmt. Bislang hatten wir nur die Datei “/etc/ldap.conf” betrachtet. Es ist aber auch ganz lehrreich, mal einen Blick in ein paar andere NSS- und PAM-spezifische Dateien auf dem System “vms1” zu werfen.

Sehen wir als erstes in die Datei “/etc/nsswitch.conf”:

/etc/nsswitch.conf

passwd: compat
group: files ldap
 
hosts: files mdns4_minimal [NOTFOUND=return] dns
networks: files dns
 
services: files ldap
protocols: files
rpc: files
ethers: files
netmasks: files
netgroup: files ldap
publickey: files
 
bootparams: files
automount: files nis
aliases: files ldap
passwd_compat: ldap

Grundlegende Informationen zum Aufbau dieser Konfigurationsdatei zum NSS-Service findet man unter:

http://cims.nyu.edu/cgi-systems/man.cgi?section=4&topic=nsswitch.conf
http://serverfault.com/questions/289933/pam-nsswitch-and-ldap-configuration
http://cims.nyu.edu/cgi-systems/man.cgi?section=4&topic=passwd

Wir stellen fest, dass Opensuse bereits (vorsorglich?) für einige der eingetragenen Punkte “ldap” vorgemerkt hat, obwohl z.T. noch gar keine entsprechenden Informationen im LDAP-Baum vorhanden sind. Dadurch lassen wir uns nicht beunruhigen. Wir kümmern uns zunächst um die Einträge

  • passwd: compat
  • group: files ldap
  • passwd_compat: ldap

Hierzu ist zu sagen, dass Opensuse – vermutlich aus Rücksichtnahme auf Installationen mit vorhandenem NIS eine ältere Variante des Zugriffs auf “ldap” hinsichtlich der Passwörter über den Parameter “passwd: compat” und ein anschließendes “passwd_compat: ldap” vornimmt.

Der NSS-Service erwartet dann in der Datei “/etc/passwd” eine Zeile der Form

+::::::

und in “/etc/shadow” eine Zeile

+

vorzufinden, was tatsächlich auch der Fall ist.

Die Platzhalter stehen für Einträge aus NIS und eben auch LDAP-Quellen.

Zur Prüfung, dass die Abfrage-Kette

  • Durchsuche die Datei “/etc/passwd/” und
  • gehe dann zusätzlich auf LDAP

funktioniert, bietet sich auf “vms1” das Absetzen des Befehls “getent passwd” an. Man bekommt dann alle passwd-Einträge, aber auch alle Einträge auf dem LDAP-Server aufgelistet:

vms1:~ # getent passwd
at:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bash



rmx:x:1000:100:rmx:/home/rmx:/bin/bash
rmo:*:1004:100:rmo:/home/rmo:/bin/bash
rmu:*:1005:100:rmu rmu:/home/rmu:/bin/bash
rmv:*:1006:100:rmx rmx:/home/rmv:/bin/bash
vms1:~ #

Der einzige auf dem Test-System regulär eingetragene User ist rmx, die anderen User-Einträge kommen vom LDAP-Server “vms2”.

Alternativ hätte es natürlich auch die etwas modernere Variante gegeben, in der Datei “nsswitch.conf” den LDAP-Zugriff für “passwd” zu gestalten, nämlich:

passwd:	files ldap

Das funktioniert auf einem System ohne NIS genauso, nur sollte man dann auch die Platzhalterzeilen “+::::::” bzw. “+” in “/etc/passwd” bzw. “/etc/shadow” eliminieren. Das mag jeder mal selbst ausprobieren.

Interessant ist, dass Opensuse im Gegensatz zu früheren Veröffentlichungen

http://www.pks.mpg.de/~mueller/docs/suse10.0/suselinux-manual_de/manual/sec.ldap.yast.client.html

oder

http://www.linuxtopia.org/online_books/suse_linux_guides/SLES10/suse_enterprise_linux_server_installation_admin/sec_ldap_yast_client.html)

für die Gruppen einen analoge “compat”-Politik nicht mehr verfolgt. Hier wird das modernere Verfahren eingesetzt.

In professionellen Umgebungen mit vielen hundert Usern würde es laufend entsprechend viele Netzwerkzugriffe auf den LDAP-Server geben. Um das zu vermeiden, sollte man auf den Systemen den Daemon für den sog. “Name Service Cache”-Service – kurz “NSCD” – starten. Unter Opensuse ist das vorkonfiguriert. Die zugehörige Konfigurationsdatei findet man auf “vms1” unter “/etc/nscd.conf”. Ob der Dienst läuft, kann man mit “rcnscd status” prüfen.

PAM-Konfigurationsdateien für LDAP auf “vms1”

Wir setzen nachfolgend ein Grundverständnis von PAM voraus. Eine erste Übersicht gibt
http://www.comptechdoc.org/os/linux/howlinuxworks/linux_hlpam.html

Einen instruktiven Foliensatz findet man unter
http://www.linuxcampus.net/component/remository/func-startdown/56/?Itemid=186

Für PAM allgemein und für die PAM-Konfiguration zu SSHD findet man erste Übersichtsinformationen unter
http://www.mpipks-dresden.mpg.de/~mueller/docs/suse10.0/suselinux-manual_de/manual/cha.pam.html

Details zu einigen PAM-Modulen entnimmt man dem “Linux-PAM System Administrators’ Guide”
http://webapp5.rrz.uni-hamburg.de/SuSe-Dokumentation/packages/pam/pdf/Linux-PAM_SAG.pdf

Die wichtigsten PAM-Konfigurationsdateien für sicherheitsrelevante Services findet man im Verzeichnis “/etc/pam.d”. Welche dieser Konfigurationsdateien enthalten Einträge bzgl. LDAP?

Unter Opensuse werden einige zentrale Dateien in die Konfigurationsdateien der einzelnen sicherheitsrelevanter Services inkludiert. Diese zentralen Dateien (meist als Link auf eine weitere Datei ausgelegt) sind die folgenden:

  • /etc/pam.d/common-auth
  • /etc/pam.d/common-account
  • /etc/pam.d/common-password
  • /etc/pam.d/common-session

Uns verwundert es daher nicht, dass LDAP-Module genau in diesen Dateien aufgerufen werden:

vms1:~ # grep -d recurse ldap /etc/pam.d/

/etc/pam.d/common-auth:auth    required    pam_ldap.so    use_first_pass
/etc/pam.d/common-auth-pc:auth    required    pam_ldap.so    use_first_pass
/etc/pam.d/common-account-pc:account    required    pam_ldap.so    use_first_pass
/etc/pam.d/common-password-pc:password    required    pam_ldap.so    try_first_pass use_authtok

/etc/pam.d/common-password:password    required    pam_ldap.so    try_first_pass use_authtok
/etc/pam.d/common-session-pc:session    optional    pam_ldap.so
/etc/pam.d/common-session:session    optional    pam_ldap.so
/etc/pam.d/common-account:account    required    pam_ldap.so    use_first_pass
vms1:~ #

Hier wird also an verschiedenen Stellen auf die Shared Object Library “pam_ldap.so” zurückgegriffen, die offenbar die erforderlichen Abfragen und die Kommunikation mit dem LDAP-System (auf Basis der “/etc/ldap.conf”-Regeln) für PAM erledigt. Wir halten fest:

Das PAM-Modul “pam_ldap.so” ist entscheidend für die zentrale LDAP-basierte Authentifizierung und Autorisierung eines Users, der sich auf einem Host (hier “vms1”) unseres Netzwerks einloggen will und der über das LDAP-Verzeichnis verwaltet wird.

Ich komme darauf gleich noch einmal detaillierter zurück. Es ist jedenfalls kaum überraschend, dass die oben genannten PAM-Dateien des Opensuse-Systems unter “/etc/pam.d/” u.a. in den PAM-Konfigurationsdateien für die Kontrolle des gewöhnlichen Login-Mechanismus (/etc/pam.d/login) oder einer SSH-verbindung (/etc/pam.d/sshd) benutzt werden.

Wir betrachten auf unserem Clientsystem als Beispiel mal die Datei “/etc/pam.d/login”:

/etc/pam.d/login

#%PAM-1.0
auth    requisite    pam_nologin.so
auth    [user_unknown=ignore success=ok ignore=ignore auth_err=die default=bad]    pam_securetty.so
auth    include    common-auth
account    include    common-account
password    include    common-password
session    required    pam_loginuid.so

session    include    common-session
session    optional    pam_lastlog.so    nowtmp showfailed

session    optional    pam_mail.so standard
session    optional    pam_ck_connector.so

Opensuse wartet hier nicht mit besonderen Überraschungen auf. Eine kurze, prägnante Erklärung zum Aufbau einer PAM-Konfigurationsdatei für den Login-Mechanismus bietet etwa
http://www.selflinux.de/selflinux/html/grundlagen_sicherheit05.html

Man erkennt in unser Datei sofort Elemente der im gerade genannten Link beschriebenen Struktur wieder:

Zuerst wird überprüft, ob die Datei “/etc/nologin” existiert und nur root Zugang zum System haben darf. Danach wird der Root-Zugang über sichere TTYs geregelt. Anschließend wird die Authentizität des Users anhand seiner Credentials überprüft – dies geschieht durch die Elemente der Datei “common-auth”. Diese steuert die Abfolge möglicher Authentifizierungsvorgänge:

/etc/pam.d/common-auth

auth    required    pam_env.so
auth    optional    pam_gnome_keyring.so
auth    sufficient    pam_unix2.so
auth    required    pam_ldap.so    use_first_pass

Man erkennt hier, dass eine Anfrage an des LDAP-System gestartet wird, falls eine lokale Prüfung durch das “pam_unix2”-Modul nicht erfolgreich ist (Check Anmeldename und Passwort gegen “/etc/passwd” und “/etc/shadow”). Durch “use_first_pass” ist dafür gesorgt, dass das bereits eingegebene Password an das LDAP-Modul weitergereicht und nicht neu beim User abgefragt wird.

Was genau macht nun eigentlich das zentrale Modul “pam_ldap.so” für uns bei seiner Interaktion mit dem LDAP-Server ?

Wir zitieren hierzu aus der Quelle http://linux.die.net/man/5/pam_ldap, die das sehr prägnant beschreibt:

When authenticating or authorizing a user, pam_ldap first maps the user's login name to a distinguished name by searching the directory server. This must be possible using the local system's identity, specified in pam_ldap.conf. (Note that presently only simple authentication is supported for authenticating in this initial step.)
To authenticate a user, pam_ldap attempts to bind to the directory server using the distinguished name of the user (retrieved previously). Both simple and SASL authentication mechanisms are supported; in the former case, one should take care to use transport security to prevent the user's password being transmitted in the clear. 

Hier lohnt es sich, ein wenig tiefer über den zweiten Satz (“This must be possible …”) nachzudenken. Ich überlasse es dem Leser herauszufinden,

  • warum das Durchsuchen des LDAP-Baumes erlaubt ist
  • und unter welcher Identität sich PAM initial für den ersten Schritt am LDAP-Server anmeldet

Der erste Punkt hat damit zu tun, welche Zugriffsrechte bzgl. der Zweige des LDAP-Baums gesetzt wurden. Bislang haben wir uns darum nicht explizit gekümmert. YaST2 hat uns während der früheren Schritte entsprechende Festlegungen abgenommen. Leser, die hier mehr wissen wollen, sollten sich nun z.B. unter folgenden Adressen zur Vergabe von Zugriffsrechten auf einem LDAP-Server kundig machn:

http://www.openldap.org/doc/admin24/access-control.html
http://www.mpipks-dresden.mpg.de/~mueller/docs/suse10.3/opensuse-manual_de/manual/sec.ldap.slapd.html
www.linux-info-tag.de/62/image/LDAP.pdf

Danach lohnt sich ein Blick in die Server-Konfigurationsdatei

/etc/openldap/slapd.d/cn=config/olcDatabase={-1}frontend.ldif

Dort findet man die Rechte, die von YaST2 bei der Serverkonfiguration und bei der Einrichtung der Userverwaltung gesetzt wurden.

Bzgl. des zweiten Punktes ist erstens ein Blick auf einige bisher von uns nicht beachtete
Einträge der PAM-relevanten Datei “/etc/ldap.conf” interessant. Wir zitieren wieder nach http://linux.die.net/man/5/pam_ldap:

binddn
     Specifies the distinguished name with which to bind to the directory server(s). This option is optional; the default is to bind anonymously.
bindpw
     Specifies the cleartext credentials with which to bind. This option is only applicable when used with binddn above. The default is no credential (anonymous bind). When binding to the directory using SASL or other authentication mechanisms apart from simple binds, this option is not used.
rootbinddn
This option has the same syntax and effect as the binddn option above, except it applies when the effective user ID is zero. If not specified, then the identity specified in binddn is used instead. Because the configuration file may be readable by many users, the root bind DN credentials are stored in the pam_ldap.secret file instead. This file is usually in the same directory as the configuration file.

Nun kann man sich mal genauer ansehen, was YaST2 hier z.B. auf dem Host “vms1” für Eintragungen vorgenommen hat.

Die Aussagen zum zweiten Schritt dessen, was “pam_ldap.so” macht, sind jedenfalls klar. Die Authentifizierung erfolgt über einen erfolgreich durchgeführten Bind. Bzgl. des Hinweises zur Verbindungsabsicherung haben wir durch unsere TLS-Konfiguration bereits hinreichende Vorkehrungen getroffen.

Nachdem wir das Prinzip einer User-Authentifizierung duch und am LDAP-Server nun verstanden haben, wenden wir uns wieder dem Ablauf der PAM-Kontrolle eines Login-Vorgangs zu:

Im nächsten Schritt werden gemäß der Datei “/etc/pam.d/login” Zugangsberechtigungen untersucht, die mit dem Account zusammenhängen – u.a., ob keine Zeitbeschränkungen des Accounts verletzt sind. Die Schlüsselfrage ist: “Gibt es diesen Benutzer im System und darf er sich anmelden?” Ein Blick in “common-account” zeigt auch hier die Abfrage des LDAP-Systems an:

/etc/pam.d/common-account

account    requisite    pam_unix2.so
account    sufficient    pam_localuser.so
account    required    pam_ldap.so    use_first_pass

Damit die erste Bedingung erfüllt wird, müssen die weiter oben erläuterten Verweis-Einträge im NIS-Format in den Dateien “/etc/passwd” und “/etc/shadow” vorhanden sein !

LDAP ist im Zusammenhang mit der Account-Prüfung auch aus folgendem Grund interessant:

The pam_ldap module provides the ability to specify a list of hosts a user is allowed to log into, in the "host" attribute in LDAP. The host attribute can be specified multiple times for each user. If any of the entries match the hostname (of the machine logging in to), login is succesful. Otherwise, login is denied.

This feature is enabled by specifying pam_check_host_attr yes in /etc/pam_ldap.conf. When it is enabled, the account facility of pam_ldap will perform the checks and return an error when no proper host attribute is present. 

Zitiert nach: https://wiki.debian.org/LDAP/PAM

Das “pam_ldap.so”-Modul kann also untersuchen, ob im LDAP-System eingetragene User bestimmten Hosts zugeordnet sind. Hierdurch kann der Zugriff auf bestimmte Hosts verhindert werden. Mit diesem sicherheitsrelevanten Thema werden wir uns im Beitrag “LDAP – V” genauer befassen.

Im Anschluss an PAM’s account- und Berechtigungs-Prüfungen kommen Bedingungen an Passwörter zu tragen, die dann von Bedeutung sind, wenn ein User im Login-Vorgang zur Änderung des Passworts gezwungen ist. Das genaue Studium und die Analyse der Bedingungen in “common-password” überlassen wir dem interessierten Leser.

/etc/pam.d/common-acount

password    requisite    pam_cracklib.so    minlen=8
password    optional    pam_gnome_keyring.so    use_authtok
password    sufficient    pam_unix2.so    use_authtok    nullok
password    required    pam_ldap.so    try_first_pass    use_authtok

Die “Session”-Bedingungen sorgen für eine ordnungsgemäße Sitzungsabwicklung. Hier ein Auszug

session    optional    pam_mkhomedir.so
session    required    pam_limits.so
session    required    pam_unix2.so
session    optional    pam_ldap.so
session    optional    pam_umask.so
session    optional    pam_systemd.so

Wir erkennen an den Namen der Module bereits Aufgaben der involvierten Module:

  • Falls erforderlich kümmert sich zunächst “pam_mkhomedir.so” beim Login eines neuen Users um die Erzeugung eines Home-Dirs (oder aber um die Umlenkung auf ein Ersatz-Verzeichnis).
  • Pam_unix2 protokolliert in den Logfiles nicht nur den Beginn einer Sitzung, sondern auch deren Ende.
  • Das Modul “limits.so” begrenzt Systemressourcen-Anforderungen, u.a. Hauptspeicherbedarf, CPU-Zeit, Prozesse und Dateien für einzelne Benutzer bzw. Benutzergruppen.
  • Danach werden LDAP-Einträge für Session-Bedingungen abgefragt. Diese Abfrage ist im Gegensatz zu anderen PAM-Bedingungen jedoch optional – das Ergebnis verhindert den Erfolg eines Einloggens in keinem Fall.
  • Es folgen die Prüfung von umask-Regeln und unter Opensuse neuerdings auch von systemd-Regeln.

Hinweis: User- oder gruppen-spezifische Limit-Einstellungen können in der Konfigurationsdatei “/etc/security/limits.conf” vorgenommen werden. Systemweite Limit-Konfigurationen erfolgen unter Opensuse unter “/etc/sysconfig/ulimit” (s. auch: https://build.opensuse.org/package/show?package=ulimit&project=openSUSE%3A12.1).

Ich denke, der Leser hat nun ein gewisses Gefühl dafür bekommen, dass und in welcher Form PAM und LDAP ineinander greifen. Bei Opensuse ist das Ganze (vernünftigerweise?) so organisiert, dass bestimmte erfolgreiche lokale Authentifizierungsprüfungen in der Regel hinreichend sind. Erst im negativen Fall wird auf die LDAP-Einträge zur Auth- und Account-Prüfung ausgewichen. Entsprechend Anfragen müssen dann aber auch zu einem positiven Ergebnis führen. Bzgl. der Login-Session-Handhabung sind LDAP-Einträge nur optional.

Zu beachten ist, dass es in der PAM-Konfiguration, die die YaST2-Module standardmäßig vornehmen, keine einzige “sufficient”-Bedingung im Zshg. mit LDAP-Anfragen gibt.

Nun kann man ja versucht sein, den Ergebnissen von LDAP-Abfragen ein höheres Gewicht zu geben als lokalen Bedingungen. Dies führt typischerweise zu Experimenten, bei denen man die Reihenfolge der PAM-Bedingungen für LDAP-Abfragen und lokale Abfragen umstellt.

Warnung:

Hierbei muss man wirklich genau wissen, was man tut. Im besonderen sind dann auch Kriterien wie “use_first_pass” und “use_authtok” nicht mehr unbedingt in der Zeile zum LDAP-Modul sondern bei den nachfolgenden PAM-Bedingungen
anzugeben. Generell gilt, dass ein unvorsichtiges Vorgehen bei der PAM-Konfiguration zu erheblichen Schwierigkeiten bzgl. des Systemzugangs führen kann. Also seid bitte vorsichtig und experimentiert bzgl. PAM nicht an Produktivsystemen herum!

Ich persönlich finde übrigens an der Politik von Opensuse, lokalen Kriterien den Vorrang zu geben, nicht viel auszusetzen.

Wer LDAP-Abfragen dennoch den Vorrang geben will, sollte sich unbedingt die von PADL vorgeschlagenen Standard-Konfigurationen für PAM ansehen

http://oss.sgi.com/LDP/HOWTO/LDAP-Implementation-HOWTO/pamnss.html ,

gründlich analysieren und sich fragen, ob und wie das zum eigenen System passt.

Weniger gefährlich sind entsprechende Tests für die Einstellungen zu SSH in der Datei “/etc/pam.d/sshd”. Siehe hierzu:

(http://quark.humbug.org.au/publications/ldap/system_auth/sage-au/system_auth.html

oder

http://www.linuxlaboratory.org/articles/linux-ldap-client/

Wir haben uns durch die obigen Betrachtungen folgendes Verständnis der User-Authentifzierung während eines Login-Vorgangs auf einem Linux-Host erarbeitet, der mit einem LDAP-Srrver zusammenarbeitet:

  • Auf dem Host überwacht PAM auf Basis der vorgegebenen PAM-Konfiguration User-Login-Vorgänge und autorisiert diese gemäß lokaler Authentifizierungskriterien oder aber über LDAP-Einträge.
  • Zur Abfrage des LDAP-Servers setzt PAM u.a. das Modul “pam_ldap.so” ein.
  • Auf dem LDAP-Server wird bei entsprechenden Anfragen ein Bind-Versuch mit den User-Credentials (UID, Password) vorgenommen.
  • Der Erfolg des LDAP-Binds entscheidet über den Erfolg des Logins auf dem anfragenden Host (soweit nicht noch weitere Kriterien abgefragt werden).

Der letzte Satz ist wiederum einer weitergehenden Überlegung wert: Ohne den Zusatz in Klammern würde er nämlich im Kern nichts anderes bedeuten, als dass die Authentifizierung durch einen LDAP-Bind der Autorisierung eines Zugangs zu jedem Host im Netzwerk gleichkäme, wenn dieser Host für eine PAM-basierte LDAP-Authentifizierung konfiguriert wäre.

Zusammenfassung und offene Punkte

Wir haben in diesem Beitrag gesehen, wie wir ein anderes System (hier einen Host “vms1”) an den zentralen LDAP-Server eines Netzwerkes anbinden können. Wir haben die Verbindung ferner mit TLS abgesichert. Ferner haben wir uns damit befasst, in welcher Form Opensuse auf dem LDAP-Server templateartige Vorgaben zur Anlage von Usern und Gruppen hinterlegt und wie man diese Vorgaben verändert.

Ergänzend haben wir uns über die entsprechenden Konfigurationsdateien auf dem Testsystem ein paar Hinweise dazu geholt, wie das Zusammenwirken von NSS, PAM mit LDAP durch die von YaST2 automatisch vorgenommenen Einstellungen konfiguriert wird. Der Zugriff auf relevanten Konfigurationsdateien ermöglicht uns künftig eine direkte Einstellung von wichtigen Parametern – auch ohne YaST2.

Im Ergebnis können wir nun mehrere Clientsysteme mit dem LDAP-Server TLS-gesichert verbinden und von jedem Client aus (per YaST2) neue User für die Benutzung des jeweiligen Clients anlegen. Ein User, der sich danach auf einem System des Netzwerks einloggen will, kann über das zentrale LDAP-System und PAM-gesteuerte Bind-Versuche zum LDAP-Verzeichnis authentifiziert werden. Die entsprechende Kommunikation läuft ebenfalls TLS-gesichert ab. Damit haben wir einen wichtigen Schritt in Richtung auf eine zentrale Authentifizierungs-Infrastruktur in einem Opensuse-Netzwerk hinter uns gebracht.

Leider haben wir dabei aber immer noch nicht alle Grundlagen für eine wirklich tragfähige zentrale, LDAP-basierte Authentifizierungs- und Autorisierungs-Struktur für ein Netzwerk geschaffen. Folgende sicherheitskritische Fragen sind bislang nämlich offen geblieben und sollten von einem verantwortungsbewußten Admin untersucht werden:

  • Wie kann ich unter Opensuse auf dem LDAP-Server eine zentrale Passwort-Politik hinterlegen, die für alle LDAP-User gleichermaßen gelten soll?
  • Können sich eigentlich User, die man von bestimmten Clientsystemen aus auf dem LDAP-Server (hier “vms2”) angelegt hat, auch auf dem Server “vms2” selbst einloggen? Oder auf anderen Host-Systemen, die an den LDAP-Server angebunden sind? Per grafischer Oberfläche oder am Login-Prompt oder per ssh ? Ist ein Login möglich, selbst wenn auf dem System kein Home-Verzeichnis angelegt wurde?
  • Wie schütze ich ggf. den LDAP-Server oder auch andere Host-Systeme gegen den Zugriff von x-beliebigen Usern, die wir im LDAP-Verzeichnis per YaST2 von irgendeinem bestimmten Client-System aus angelegt haben ? Wie begrenze ich den Zugriff eines im LDAP erfassten Users oder einer Gruppe auf bestimmte Hosts? Wie realisiere ich mit LDAP eine user- und host-spezifische Zugangs-Autorisierung?

Auf diese Fragen bieten die nächsten beiden Beiträge LDAP IV und LDAP V aus der LDAP-Reihe dieses Blogs eine Antwort. Und dabei werden wir auch die Grenzen der Bordmittel von YaST2 zur Konfiguration des LDAP-Servers und zur Verwaltung der User und Hosts erkennen.