LDAP-Anmeldung
Zielgruppe: Technische Administration
Überblick
Neben lokalen Konten kann oPBWeb Benutzer gegen ein LDAP-Verzeichnis oder Active Directory anmelden. Die Rolle in oPBWeb ergibt sich dann aus den Gruppenmitgliedschaften im Verzeichnis. Du konfigurierst die Anbindung über LDAP_*-Variablen in der .env und das Passwort des Dienstkontos in secrets/ldap_bind_password.txt. In der Oberfläche gibt es dafür keine Einstellungen.
So läuft die Anmeldung ab
- Gibt es in oPBWeb ein lokales Konto mit dem eingegebenen Benutzernamen, meldet oPBWeb ausschließlich lokal an. Das Verzeichnis wird nicht gefragt, auch wenn das Passwort falsch ist.
- Sonst, bei
LDAP_ENABLED=true, verbindet sich oPBWeb mit dem Dienstkonto (LDAP_BIND_DN) oder anonym, wenn kein Bind-DN gesetzt ist. - oPBWeb sucht mit
LDAP_USER_FILTERunterhalb vonLDAP_USER_SEARCH_BASE(leer:LDAP_BASE_DN). Die Suche muss genau einen Eintrag liefern. - Mit dem gefundenen DN und dem eingegebenen Passwort meldet sich oPBWeb als Benutzer an und prüft so das Passwort.
- Aus dem Attribut
memberOfbestimmt oPBWeb die Rolle (siehe unten). Ohne passende Gruppe gibt es keinen Zugang. - Beim ersten erfolgreichen Login legt oPBWeb das Konto mit der Herkunft „Verzeichnis (LDAP)“ an. Anzeigename (
displayName), E-Mail (mail) und Rolle werden bei jeder Anmeldung neu aus dem Verzeichnis übernommen.
Lokale Konten bleiben also immer lokal, auch das erste Administrator-Konto. So kommst du auch bei einem Ausfall des Verzeichnisses noch an oPBWeb heran.
Variablen
| Variable | Standard | Bedeutung |
|---|---|---|
LDAP_ENABLED | false | LDAP-Anmeldung einschalten |
LDAP_HOST | – | Hostname des Domänencontrollers bzw. LDAP-Servers |
LDAP_PORT | 636 | Port |
LDAP_USE_SSL | true | LDAPS (TLS ab Verbindungsaufbau); StartTLS wird nicht unterstützt |
LDAP_TLS_VERIFY | true | Serverzertifikat prüfen |
LDAP_CA_CERTS_FILE | – | CA-Datei im Container, z. B. /run/certs/ldap/ca.pem |
LDAP_BASE_DN | – | Basis-DN des Verzeichnisses |
LDAP_USER_SEARCH_BASE | – | Suchbasis für Benutzer; leer = LDAP_BASE_DN |
LDAP_USER_FILTER | (&(objectClass=user)(sAMAccountName={username})) | Suchfilter; {username} wird durch den eingegebenen Namen ersetzt (maskiert) |
LDAP_BIND_DN | – | DN des Dienstkontos für die Suche; leer = anonyme Suche |
LDAP_ADMIN_GROUPS | – | Gruppen-DNs für die Rolle Administrator |
LDAP_RELEASER_GROUPS | – | Gruppen-DNs für die Rolle Releaser |
LDAP_PACKAGER_GROUPS | – | Gruppen-DNs für die Rolle Packager |
LDAP_VIEWER_GROUPS | – | Gruppen-DNs für die Rolle Leser |
Das Passwort des Dienstkontos steht nicht in der .env, sondern in secrets/ldap_bind_password.txt (von init-secrets.sh leer angelegt). Die Verbindung hat ein Zeitlimit von 10 Sekunden für den Aufbau und 15 Sekunden für Antworten.
Mit LDAP_USE_SSL=false gehen Benutzerpasswörter unverschlüsselt über das Netz. Verwende im Betrieb LDAPS. LDAP_TLS_VERIFY=false schaltet die Zertifikatsprüfung ab und ist nur für einen kurzen Test gedacht.
Beispiel Active Directory
Ein Beispiel für eine Domäne example.local. Ersetze alle Namen durch deine Werte:
LDAP_ENABLED=true
LDAP_HOST=dc01.example.local
LDAP_PORT=636
LDAP_USE_SSL=true
LDAP_TLS_VERIFY=true
LDAP_CA_CERTS_FILE=/run/certs/ldap/ca.pem
LDAP_BASE_DN=dc=example,dc=local
LDAP_USER_SEARCH_BASE=ou=Benutzer,dc=example,dc=local
LDAP_USER_FILTER=(&(objectClass=user)(sAMAccountName={username}))
LDAP_BIND_DN=cn=svc-opbweb,ou=Dienstkonten,dc=example,dc=local
LDAP_ADMIN_GROUPS=cn=opbweb-admins,ou=Gruppen,dc=example,dc=local
LDAP_RELEASER_GROUPS=cn=opbweb-releaser,ou=Gruppen,dc=example,dc=local
LDAP_PACKAGER_GROUPS=cn=opbweb-packager,ou=Gruppen,dc=example,dc=local;cn=client-team,ou=Gruppen,dc=example,dc=local
LDAP_VIEWER_GROUPS=cn=opbweb-leser,ou=Gruppen,dc=example,dc=local
Weitere Filter, an dein Verzeichnis anzupassen:
| Zweck | Filter |
|---|---|
| Anmeldung mit UPN statt Kontoname | (&(objectClass=user)(userPrincipalName={username})) |
| deaktivierte AD-Konten ausschließen | (&(objectClass=user)(sAMAccountName={username})(!(userAccountControl:1.2.840.113556.1.4.803:=2))) |
OpenLDAP mit uid | (&(objectClass=inetOrgPerson)(uid={username})) – setzt das memberOf-Overlay voraus |
Einrichten
Trage die Variablen wie oben in die
.envein.Schreibe das Passwort des Dienstkontos in
secrets/ldap_bind_password.txt(ohne Zeilenumbruch am Ende ist am sichersten; führende und abschließende Leerzeichen entfernt oPBWeb).Lege bei einer eigenen Unternehmens-CA das CA-Zertifikat im PEM-Format vor dem Setup als
ldap-ca.pemnebensetup-opbweb.sh(das Setup verschiebt es nachcerts/ldap/ldap-ca.pemund schlägt es als CA-Datei vor) oder direkt untercerts/ldap/ab. Das Verzeichniscerts/ldap/ist im Container als/run/certs/ldap/schreibgeschützt eingebunden;LDAP_CA_CERTS_FILEgibt den Pfad im Container an. Ohne CA-Datei prüft oPBWeb gegen die Standard-CAs des Containers.Starte den Stack neu, damit die API die neuen Werte und das Secret liest:
./stop.sh ./start.shMelde dich mit einem Verzeichniskonto an. Unter Benutzer und Rollen erscheint das Konto mit der Herkunft „Verzeichnis (LDAP)“ und der zugeordneten Rolle.
Gruppen und Rollen
- In jeder
LDAP_*_GROUPS-Variablen stehen ein oder mehrere vollständige Gruppen-DNs, getrennt durch;. - oPBWeb vergleicht die DNs ohne Rücksicht auf Groß- und Kleinschreibung, aber sonst exakt mit den Werten aus
memberOf. - Die höchste Rolle gewinnt: Administrator vor Releaser vor Packager vor Leser.
- Keine passende Gruppe, kein Zugang: Die Anmeldung scheitert mit „Keine Berechtigung für oPBWeb (keine passende Gruppe).“ Ist keine der vier Variablen gesetzt, kann sich niemand über LDAP anmelden.
- Verschachtelte Gruppen löst oPBWeb nicht auf; maßgeblich ist nur, was
memberOfdirekt liefert. Die primäre Gruppe eines AD-Kontos (meist „Domänen-Benutzer“) steht nicht inmemberOf.
Was die Rollen im Einzelnen dürfen, beschreibt Benutzer und Rollen .
Verhalten von Verzeichniskonten
| Thema | Verhalten |
|---|---|
| Rolle | kommt aus den Gruppen und wird bei jeder Anmeldung neu gesetzt; in der Oberfläche nicht änderbar |
| Rollenänderung im Verzeichnis | wirkt erst bei der nächsten Anmeldung mit Passwort; eine laufende Sitzung erneuert sich bis zu 7 Tage lang ohne Rückfrage beim Verzeichnis |
| Passwort | wird im Verzeichnis geändert; Passwort ändern und Passwort setzen gibt es für diese Konten nicht |
| Sperre nach Fehlversuchen | die Kontosperre gilt nur für lokale Konten; für Verzeichniskonten greift die Sperrrichtlinie des Verzeichnisses. Die Grenze für Fehlversuche pro Adresse gilt auch für LDAP-Anmeldungen. |
| Deaktivieren in oPBWeb | möglich; das Konto kann sich dann trotz gültigem Verzeichnis-Passwort nicht mehr anmelden |
| Zugang sofort entziehen | Konto unter Benutzer und Rollen deaktivieren; das beendet auch laufende Sitzungen |
Gleichnamige Konten: Existiert ein lokales Konto mit demselben Namen wie ein Verzeichniskonto, gilt immer das lokale Konto.
Fehlersuche
| Meldung beim Anmelden | Ursache | Abhilfe |
|---|---|---|
| „Verzeichnisdienst nicht erreichbar.“ | Verbindung, TLS oder Suche mit dem Dienstkonto fehlgeschlagen | Log der API prüfen (siehe unten): Host, Port, CA-Datei, Bind-DN und Passwort |
| „Benutzername oder Passwort falsch.“ | falsches Passwort, Benutzer nicht gefunden oder Filter liefert mehr als einen Eintrag | Filter und Suchbasis prüfen; Anmeldung mit demselben Konto direkt am Verzeichnis testen |
| „Keine Berechtigung für oPBWeb (keine passende Gruppe).“ | Anmeldung gelungen, aber keine Gruppe passt | Gruppen-DNs exakt mit memberOf des Benutzers vergleichen; direkte Mitgliedschaft prüfen |
| „Konto ist deaktiviert.“ | Konto in oPBWeb deaktiviert | unter Benutzer und Rollen wieder aktivieren |
Fehler bei Verbindung und Suche schreibt die API ins Log:
docker logs opbweb-api 2>&1 | grep -i "LDAP search failed"
Typische Ursachen sind ein Hostname, der nicht zum Zertifikat passt, eine fehlende oder falsche CA-Datei (Pfad im Container, nicht auf dem Host), ein leeres secrets/ldap_bind_password.txt oder ein Domänencontroller, der vom Docker-Host aus nicht erreichbar ist.
Zum Gegenprüfen der Suche eignet sich ldapsearch auf einem Rechner mit den OpenLDAP-Werkzeugen. Beispiel, an deine Werte anzupassen:
ldapsearch -H ldaps://dc01.example.local:636 \
-D "cn=svc-opbweb,ou=Dienstkonten,dc=example,dc=local" -W \
-b "ou=Benutzer,dc=example,dc=local" \
"(&(objectClass=user)(sAMAccountName=mmuster))" memberOf displayName mail
Die ausgegebenen memberOf-Werte kannst du direkt in die LDAP_*_GROUPS-Variablen übernehmen.