Apache gegen mehrere Verzeichnisse authentifizieren

Ich verwalte einen Server der gegen zwei unterschiedliche Verzeichnisse autorisiert, einmal gegen Active Directory und einmal gegen einen lokalen LDAP-Server. Im lokalen LDAP-Server werden Accounts von Projektpartnern angelegt die nicht direkt ins AD sollen.

Dazu wurde bisher gegen Atlassian Crowd authentifiziert, da die Applikationen auf dem Server hauptsächlich von Atlassian sind und ebenfalls gegen Crowd authentifizieren.

Der Server ist nun etwas in die Jahre gekommen und muss dringend erneuert werden. Ein Problem dabei ist, dass der Crowd Connector für Apache seit 2014 End of Life ist, mit Apache 2.4 nicht mehr funktioniert, und mich die von der Community weiterentwickelten Projekte nicht ausreichend überzeugen dass ich sie auf einem wichtigen Produktivserver einsetzen möchte.

Auf meiner Suche nach Alternativen bin ich mehr oder weniger zufällig darüber gestolpert, dass man in der Apache Config Aliase für AuthProvider anlegen kann. Nach einem bisschen herumprobieren war ich dann mit der folgenden Konfiguration erfolgreich:

LDAPConnectionPoolTTL 0
<AuthnProviderAlias ldap ad>
AuthLDAPBindDN "user@example.com"
AuthLDAPBindPassword "secret"
AuthLDAPUrl ldaps://dc.example.com/dc=ad,dc=example,dc=com?sAMAccountName?sub?(&(objectclass=user)(!(objectclass=computer)))
LDAPReferrals Off
</AuthnProviderAlias>
<AuthnProviderAlias ldap local-ldap>
AuthLDAPBindDN cn=crowd,dc=server,dc=example,dc=com
AuthLDAPBindPassword secret
AuthLDAPURL ldap://server.example.com/dc=server,dc=example,dc=com?mail?sub?(objectclass=inetorgperson)
</AuthnProviderAlias>
<Location "/">
AuthName "Geschützter Bereich"
AuthType Basic
AuthBasicProvider ad local-ldap
<RequireAny>
Require valid-user
Require local
Require ip 1.2.3.4
</RequireAny>
</Location>

Hier definiere ich zwei AuthProvider, die ich dann hinterher im Location Block angeben kann. Beim AD ist die Direktive LDAPReferrals Off wichtig, über LDAPConnectionPoolTTL hatte ich bereits gebloggt.

Die Authentifizierung wird an die Atlassian-Applikationen durchgereicht, die direkte Kommunikation mit Crowd ist damit nicht mehr nötig.

Timeouts mit Apache/Windows/LDAP/Active Directory

Ich hatte eine ganze Zeit lang versucht ein Timeout-Problem bei einem Apache-Server zu analysieren. Das Muster sah folgendermaßen aus:

Bei jedem ersten Zugriff auf den Server fragte der Server sofort nach Benutzernamen und Passwort, danach wartete der Server exakt eine Minute bevor er die Antwort sendete.

Timeouts mit Apache/Windows/LDAP/Active Directory weiterlesen

Active Directory LDAP-Zugriffe mit mehreren Domain Controllern

Auch in einer Windows-Domänen Umgebung kommt man früher oder später darauf, dass es eine Anwendung gibt die nicht auf Windows und IIS, sondern auf einem Apache läuft, vielleicht mit PHP oder einer anderen Skriptsprache. Sowohl PHP als auch der Apache direkt bieten über LDAP die Möglichkeit einen Domain Controller abzufragen, Beispielsweise zur Authentifizierung.

Spätestens wenn ausgerechnet der Domain-Controller ausgefallen (oder wegen Wartungsarbeiten nicht erreichbar) ist, den die PHP-Scripte zur Authentifizierung benutzen, stellt sich die Frage wie man es einrichtet dass irgend ein verfügbarer Domain Controller genutzt wird. Glücklicherweise sind sowohl PHP als auch das Apache-Modul für diesen Fall vorbereitet, und nutzen sogar das gleiche Prinzip dafür. Man muss lediglich an der Stelle wo der Servername steht mehrere Adressen durch Leerzeichen getrennt eintragen.

PHP-Aufruf:

$conn = ldap_connect("dc01.domain.local dc02.domain.local");
ldap_bind($conn, $username, $password);

Eintrag in der Apache-Konfiguration:

AuthLDAPUrl "ldap://dc01.domain.local:3268 dc02.domain.local:3268/dc=domain,dc=local?sAMAccountName?sub?(objectClass=*)" STARTTLS

Hier muss man darauf achten dass der LDAP-String in Anführungszeichen steht (solange kein Leerzeichen vorkommt funktioniert es auch ohne).

Auf diese Art werden alle angegebenen Server durchprobiert bis einer gefunden wird der erreichbar ist.

Quellen: mod_auth_ldap Dokumentation, Kommentar in der PHP-Dokumentation zu ldap_connect()