Status: verifiziert gegen den echten
concordia-openldap-Container (sieheinfra/docker-compose.yml).Hinweis: die hier gezeigte Konfiguration lief ursprünglich über Klartext-LDAP (Port 1389).
04-ldaps-tls.mdstellt auf LDAPS (verschlüsselt, Port 1636) um — inkl. zweier echter Stolpersteine (abgelaufene Standard-CA des Images, Hostname-Verifikation) und ist der aktuell verwendete Stand (port="1636",sslEnabled="true"inserver.xml).
ldapType="Custom"Liberty kennt vordefinierte ldapType-Profile für verbreitete Verzeichnisse (z. B.
IBM Tivoli Directory Server, Microsoft Active Directory). Für generisches OpenLDAP mit
selbst gewähltem Schema (inetOrgPerson für Nutzer, groupOfNames für Gruppen, siehe
infra/openldap/bootstrap/01-concordia-bank.ldif)
ist Custom mit expliziten <customFilters> der korrekte, weil eindeutige Weg — ein
vordefiniertes Profil hätte implizite Annahmen über Attributnamen getroffen, die nicht zu unserem
Bootstrap-Schema passen.
<ldapRegistry id="concordiaLdap"
realm="ConcordiaBankLDAP"
host="localhost"
port="1389"
ignoreCase="true"
baseDN="dc=concordia-bank,dc=local"
bindDN="cn=admin,dc=concordia-bank,dc=local"
bindPassword="${env.CONCORDIA_LDAP_BIND_PASSWORD}"
ldapType="Custom">
<customFilters
userFilter="(&(uid=%v)(objectclass=inetOrgPerson))"
groupFilter="(&(cn=%v)(objectclass=groupOfNames))"
userIdMap="*:uid"
groupIdMap="*:cn"
groupMemberIdMap="groupOfNames:member"/>
</ldapRegistry>
Nicht fachlich, sondern eine echte Betriebsrandbedingung dieser Lernumgebung: Podman läuft hier
rootless, und rootless Container dürfen keine privilegierten Ports (< 1024) auf dem Host
binden. infra/docker-compose.yml mappt deshalb 1389:389 (Container lauscht weiterhin intern
auf 389, nur der Host-seitige Port ist verschoben) — server.xml verwendet folgerichtig 1389. In
einer echten Produktionsumgebung mit klassischem (nicht-rootless) Betrieb wäre das nicht nötig;
genau die Art von Detail, die man beim Übertragen einer Lern-/Dev-Konfiguration auf einen echten
Server anpassen muss.
bindPassword als ${env.…} statt KlartextLiberty löst ${env.VARNAME} beim Start direkt aus einer Umgebungsvariablen auf — kein
zusätzliches Bootstrap-Mapping nötig (dasselbe Muster wie im Novaris-Referenzprojekt für
Datenbank-Zugangsdaten). Gestartet wurde hier mit:
CONCORDIA_LDAP_BIND_PASSWORD="ConcordiaAdmin123!" mvn liberty:run
Wichtiger Hinweis: das Demo-Passwort steht bewusst offen im
infra/docker-compose.yml (Umgebungsvariable
LDAP_ADMIN_PASSWORD für den Container selbst) — für ein reines Lernprojekt mit Wegwerf-Daten
akzeptabel, in echten Umgebungen gehören Bind-Passwörter in ein Secret-Management-System
(Vault, CyberArk o. ä.), nie in eine Compose-Datei.
Um sicherzustellen, dass ein Auth-Fehlschlag später tatsächlich an Liberty/Rollen-Mapping liegt und nicht am LDAP-Server selbst, wurde der Container isoliert getestet:
$ podman exec concordia-openldap ldapwhoami -x -H ldap://localhost \
-D "uid=m.bauer,ou=people,dc=concordia-bank,dc=local" -w "AdminDemo123!"
dn:uid=m.bauer,ou=people,dc=concordia-bank,dc=local
$ podman exec concordia-openldap ldapwhoami -x -H ldap://localhost \
-D "uid=m.bauer,ou=people,dc=concordia-bank,dc=local" -w "falsch123"
ldap_bind: Invalid credentials (49)
Erst danach wurde die End-to-End-Kette über Liberty verifiziert (siehe
01-rollen-und-rechte.md) — bewusste Reihenfolge: erst die einzelne
Komponente isoliert prüfen, dann die Integration. Genau dieses Vorgehen ist im echten
Troubleshooting Gold wert (siehe docs/30-troubleshooting-runbooks/):
bei einem 401 zuerst klären, ob LDAP selbst das Problem ist oder die Liberty-Konfiguration
darüber.