Authentifizierung von Anwendungsbenutzern mit LDAP mithilfe von NGINX Plus und NGINX

NGINX | 22. Juni 2015

Kunden fragen uns häufig, wie sie mit NGINX Plus und NGINX geschützte Ressourcen oder Anwendungen absichern können, indem sie die Benutzer authentifizieren, die darauf zugreifen möchten. Heute stellen wir eine Referenzimplementierung eines solchen Authentifizierungssystems vor und machen sie im Repository von NGINX, Inc. auf GitHub verfügbar. In diesem Beitrag beschreiben wir, wie die Implementierung funktioniert, wie sie installiert wird und wie Sie sie als Vorlage für Ihr eigenes Authentifizierungssystem verwenden können.

Die Lösung nutzt das ngx_http_auth_request_module-Modul in NGINX Plus und NGINX, das Authentifizierungsanfragen an einen externen Dienst weiterleitet. In der Referenzimplementierung ist dieser Dienst ein Daemon namens ldap‑auth. Er ist in Python geschrieben und kommuniziert mit einem Authentifizierungsserver, der das Lightweight Directory Access Protocol (LDAP) verwendet – standardmäßig OpenLDAP. Wir haben den ldap‑auth-Daemon jedoch auch mit den Standardkonfigurationen von Microsoft® Windows® Server Active Directory getestet (sowohl mit der Version 2003 als auch mit der Version 2012).

Der ldap‑auth-Daemon dient als Vorlage für Ihre eigene „Connector“-App, die Sie in anderen Sprachen entwickeln, mit anderen Authentifizierungssystemen bereitstellen oder beides tun können. Das NGINX-Team Professional Services unterstützt Sie gerne bei solchen Anpassungen.

Hinweise:

  • Die Referenzimplementierung ist nicht für den produktiven Einsatz vorgesehen, sondern dient lediglich als Vorlage für Ihre eigenen Implementierungen.
  • Zur besseren Lesbarkeit wird im weiteren Verlauf dieses Artikels auf NGINX Plus Bezug genommen, die Referenzimplementierung funktioniert jedoch auch mit NGINX Open Source. Das erforderliche Modul http_auth_request ist sowohl in NGINX Plus-Paketen als auch in vorkompilierten NGINX-Binärdateien enthalten.

So funktioniert die Authentifizierung in der Referenzimplementierung

Zur Authentifizierung sendet das Modul http_auth_request eine HTTP-Unteranfrage an den ldap‑auth-Daemon, der als Vermittler fungiert und die Unteranfrage für den LDAP-Server interpretiert. Dabei verwendet er HTTP für die Kommunikation mit NGINX Plus und die entsprechende API für die Kommunikation mit dem LDAP-Server.

Wir gehen davon aus, dass Sie bereits über eine Anwendung oder andere Ressourcen verfügen, die Sie durch eine erforderliche Authentifizierung schützen möchten, wenn Sie sich für die Referenzimplementierung interessieren. Um das Testen der Referenzimplementierung zu erleichtern, stellen wir jedoch einen ebenfalls in Python geschriebenen Beispiel-Backend-Daemon bereit, der Port 9000 überwacht. Er kann beim Testen als Ersatz für eine tatsächliche HTTP-Anwendung dienen, indem er zur Eingabe von Benutzeranmeldedaten auffordert und auf deren Grundlage ein Cookie erstellt.

Die NGINX Plus-Referenzimplementierung für die LDAP-Authentifizierung umfasst den ldap-auth-Daemon und einen Beispiel-Backend-Daemon

Im Folgenden wird der Authentifizierungsprozess in der Referenzimplementierung Schritt für Schritt beschrieben. Die Einzelheiten werden durch die Einstellungen in der Konfigurationsdatei nginx-ldap-auth.conf bestimmt; siehe unten „Konfigurieren der Referenzimplementierung“. Das Flussdiagramm unterhalb der Schritte fasst den Prozess zusammen.

  1. Ein Client sendet eine HTTP-Anfrage für eine geschützte Ressource, die auf einem Server gehostet wird, für den NGINX Plus als Reverse-Proxy fungiert.
  2. NGINX Plus (genauer gesagt das Modul http_auth_request) leitet die Anfrage an den ldap‑auth-Daemon weiter, der mit dem HTTP-Code 401 antwortet, da keine Anmeldedaten angegeben wurden.
  3. NGINX Plus leitet die Anfrage an http://backend/login weiter, was dem Backend-Daemon entspricht. Dabei wird der ursprüngliche Anfrage-URI in den X-Target-Header der weitergeleiteten Anfrage geschrieben.
  4. Der Backend-Daemon sendet dem Client ein Anmeldeformular (das Formular ist im Python-Code für den Daemon definiert). Wie durch die error_page-Direktive konfiguriert, setzt NGINX den HTTP-Code des Anmeldeformulars auf 200.
  5. Der Benutzer füllt die Felder „Benutzername“ und „Passwort“ im Formular aus und klickt auf die Schaltfläche „Anmelden“. Gemäß dem Code im Formular generiert der Client eine HTTP-POST-Anfrage an /login, die NGINX Plus an den Backend-Daemon weiterleitet.
  6. Der Backend-Daemon erstellt eine Zeichenfolge im Format username:password, codiert sie mit Base64, erzeugt ein Cookie namens nginxauth, dessen Wert auf die codierte Zeichenfolge gesetzt wird, und sendet das Cookie an den Client. Er setzt das httponly-Flag, um zu verhindern, dass das Cookie mit JavaScript gelesen oder manipuliert wird (zum Schutz vor der Schwachstelle Cross-Site-Scripting [XSS]).
  7. Der Client sendet seine ursprüngliche Anfrage (aus Schritt 1) erneut und fügt dieses Mal das Cookie in das Feld Cookie des HTTP-Headers ein. NGINX Plus leitet die Anfrage an den ldap-auth-Daemon weiter (wie in Schritt 2).
  8. Der ldap‑auth-Daemon decodiert das Cookie und sendet den Benutzernamen und das Passwort in einer Authentifizierungsanfrage an den LDAP-Server.
  9. Die nächste Aktion hängt davon ab, ob der LDAP-Server den Benutzer erfolgreich authentifiziert:
    • Wenn die Authentifizierung erfolgreich ist, sendet der ldap‑auth-Daemon den HTTP-Code 200 an NGINX Plus. NGINX Plus fordert die Ressource vom Backend-Daemon an. In der Referenzimplementierung gibt der Backend-Daemon den folgenden Text zurück:
   Hello, world! Requested URL: URL
  • Die Datei „nginx-ldap-auth.conf“ enthält Direktiven zum Zwischenspeichern der Ergebnisse des Authentifizierungsversuchs. Informationen zum Deaktivieren der Zwischenspeicherung finden Sie weiter unten unter „Zwischenspeicherung“.
  • Wenn die Authentifizierung fehlschlägt, sendet der ldap‑auth-Daemon den HTTP-Code 401 an NGINX Plus. NGINX Plus leitet die Anfrage erneut an den Backend-Daemon weiter (wie in Schritt 3), und der Vorgang wiederholt sich.

In der NGINX Plus-Referenzimplementierung für die LDAP-Authentifizierung fungiert der ldap-auth-Daemon als Vermittler zwischen NGINX Plus und dem LDAP-Server

Installieren der Komponenten

Die mit der Referenzimplementierung bereitgestellte NGINX Plus-Konfigurationsdatei nginx-ldap-auth.conf konfiguriert alle Komponenten außer dem LDAP-Server (also NGINX Plus, den Client, den ldap‑auth-Daemon und den Backend-Daemon) so, dass sie auf demselben Host ausgeführt werden, was für Testzwecke ausreichend ist. Während der Tests kann auch der LDAP-Server auf diesem Host ausgeführt werden.

In einer tatsächlichen Bereitstellung werden die Backend-Anwendung und der Authentifizierungsserver in der Regel jeweils auf einem separaten Host ausgeführt, während NGINX Plus auf einem dritten Host läuft. Der ldap-auth-Daemon benötigt in den meisten Fällen nur wenige Ressourcen und kann daher auf dem NGINX Plus-Host oder einem anderen Host Ihrer Wahl ausgeführt werden.

  1. Klonen Sie das GitHub-Repository.
  2. Falls NGINX Plus noch nicht ausgeführt wird, installieren Sie es gemäß den Anweisungen für Ihr Betriebssystem.
  3. Wenn noch kein LDAP-Server ausgeführt wird, installieren und konfigurieren Sie einen. Standardmäßig kommuniziert der ldap‑auth-Daemon mit OpenLDAP, aber Microsoft Windows Active Directory 2003 und 2012 werden ebenfalls unterstützt. Wenn Sie den LDAP-Server nur zum Testen der Referenzimplementierung verwenden, können Sie das auf GitHub verfügbare Docker-Image für den OpenLDAP-Server verwenden oder einen Server anhand einer Anleitung wie Installieren und Konfigurieren von OpenLDAP und phpLDAPadmin unter Ubuntu 16.04 einrichten. Notieren Sie sich die Werte, die Sie für Base DN, Bind DN und das Bind-Kennwort festlegen. Sie tragen diese in der NGINX-Konfigurationsdatei unter Konfigurieren der Referenzimplementierung ein.
  4. Installieren Sie auf dem Host, auf dem der ldap‑auth-Daemon ausgeführt werden soll, die folgende zusätzliche Software. Wir empfehlen, die mit dem Betriebssystem bereitgestellten Versionen zu verwenden, anstatt die Software aus einem Open-Source-Repository herunterzuladen.
    • Python Version 2. Version 3 wird nicht unterstützt.
    • Das Python-LDAP-Modul python‑ldap (entwickelt vom Open-Source-Projekt python-ldap.org).
  5. Kopieren Sie die folgenden Dateien aus Ihrem Repository-Klon auf die angegebenen Hosts:
    • nginx-ldap-auth.conf – NGINX Plus-Konfigurationsdatei, die den Mindestsatz an Direktiven zum Testen der Referenzimplementierung enthält. Installieren Sie sie auf dem NGINX Plus-Host (im Verzeichnis /etc/nginx/conf.d, wenn Sie das herkömmliche Konfigurationsschema verwenden). Um Konfigurationskonflikte zu vermeiden, denken Sie daran, alle mit NGINX Plus installierten Standardkonfigurationsdateien zu verschieben oder umzubenennen.
    • nginx-ldap-auth-daemon.py – Python-Code für den ldap‑auth-Daemon. Installieren Sie ihn auf einem Host Ihrer Wahl.
    • nginx-ldap-auth-daemon-ctl.sh – Beispiel-Shell-Skript zum Starten und Stoppen des Daemons. Installieren Sie es auf demselben Host wie den ldap‑auth-Daemon.
    • backend-sample-app.py – Python-Code für den Daemon, der bei Tests als Ersatz für einen Backend-Anwendungsserver dient. Installieren Sie ihn auf einem Host Ihrer Wahl.
  6. Ändern Sie die NGINX Plus-Konfigurationsdatei wie unter „Konfigurieren der Referenzimplementierung“ beschrieben. Führen Sie nach Ihren Änderungen den Befehl „nginx -t“ aus, um zu überprüfen, ob die Datei syntaktisch korrekt ist.
root# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  1. Starten Sie NGINX Plus. Wenn NGINX Plus bereits ausgeführt wird, führen Sie den folgenden Befehl aus, um die Konfigurationsdatei neu zu laden:
root# nginx -s reload
  1. Führen Sie die folgenden Befehle auf den entsprechenden Hosts aus, um den ldap‑auth-Daemon und den Backend-Daemon zu starten.
root# nginx-ldap-auth-daemon-ctl.sh start
root# python backend-sample-app.py
  1. Rufen Sie in einem Webbrowser http://nginx-server-address:8081 auf. Vergewissern Sie sich, dass im Browser das Authentifizierungsformular angezeigt wird. Nachdem Sie das Formular ausgefüllt und abgesendet haben, überprüfen Sie, ob der Server bei gültigen Anmeldedaten die erwartete Antwort zurückgibt. Wie oben erwähnt, gibt der Backend-Daemon den folgenden Text zurück:
   Hello, world! Requested URL: URL

Konfigurieren der Referenzimplementierung

Nehmen Sie die folgenden Änderungen in der Datei „nginx-ldap-auth.conf“ vor. Einige sind erforderlich, andere optional, wie jeweils angegeben.

LDAP-Servereinstellungen

Wie in nginx-ldap-auth-daemon.py implementiert, kommuniziert der ldap‑auth-Daemon mit einem OpenLDAP-Server und übergibt Parameter, die angeben, welches Benutzerkonto authentifiziert werden soll. Damit der Python-Code nicht geändert werden muss, enthält die Datei nginx-ldap-auth.conf proxy_set_header-Direktiven, die Werte im HTTP-Header festlegen, anhand derer anschließend die Parameter gesetzt werden. Die folgende Tabelle zeigt die Zuordnung zwischen Parametern und Headern.

LDAP-Parameter HTTP-Headerbasedn X-Ldap-BaseDNbinddn X-Ldap-BindDNbindpasswd X-Ldap-BindPasscookiename X-CookieNamerealm X-Ldap-Realmtemplate X-Ldap-Templateurl X-Ldap-URL

  • (Erforderlich) Ersetzen Sie in den folgenden Direktiven die fett gedruckten Werte durch die korrekten Werte für Ihre LDAP-Serverbereitstellung. Beachten Sie insbesondere, dass die Datei nginx-ldap-auth.conf den bekannten Port 636 für LDAPS verwendet. Wenn Sie den Port auf 389 (den bekannten Port für LDAP) oder einen anderen LDAP-Port ändern, denken Sie daran, auch den Protokollnamen von ldaps in ldap zu ändern.
# URL and port for connecting to the LDAP server
proxy_set_header X-Ldap-URL "ldaps://example.com:636";
 
# Base DN
proxy_set_header X-Ldap-BaseDN "cn=Users,dc=test,dc=local";
 
# Bind DN
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
 
# Bind password
proxy_set_header X-Ldap-BindPass "secret";
  • (Erforderlich, wenn Active Directory anstelle von OpenLDAP verwendet wird) Entfernen Sie wie gezeigt das Kommentarzeichen vor der folgenden Direktive:
proxy_set_header X-Ldap-Template "(SAMAccountName=%(username)s)";
  • (Optional) Die Referenzimplementierung verwendet eine Cookie-basierte Authentifizierung. Wenn Sie stattdessen die HTTP-Basisauthentifizierung verwenden, kommentieren Sie die folgenden Direktiven wie gezeigt aus:
#proxy_set_header X-CookieName "nginxauth";
#proxy_set_header Cookie nginxauth=$cookie_nginxauth;
  • (Optional) Wenn Sie den Wert für den Parameter „template“ ändern möchten, den der ldap-auth-Daemon standardmäßig an den OpenLDAP-Server übergibt, entfernen Sie wie gezeigt das Kommentarzeichen vor der folgenden Direktive und ändern Sie den Wert:
proxy_set_header X-Ldap-Template "(cn=%(username)s)";
  • (Optional) Wenn Sie den Namen des Realms vom Standardwert (Restricted) ändern möchten, entfernen Sie bei der folgenden Direktive die Auskommentierung und passen Sie sie an:
proxy_set_header X-Ldap-Realm "Restricted";

IP-Adresse für den Backend-Daemon

Wenn der Backend-Daemon nicht auf demselben Host wie NGINX Plus ausgeführt wird, ändern Sie seine IP-Adresse im Konfigurationsblock upstream:

upstream backend {    server 127.0.0.1:9000;
 }

IP-Adresse für den ldap‑auth-Daemon

Wenn der ldap‑auth-Daemon nicht auf demselben Host wie NGINX Plus ausgeführt wird, ändern Sie die IP-Adresse in dieser proxy_pass-Direktive:

location = /auth-proxy {    proxy_pass http://127.0.0.1:8888;
    # ...
}

IP-Adresse und Port, auf denen NGINX lauscht

Wenn der Client nicht auf demselben Host wie NGINX Plus ausgeführt wird, ändern Sie die IP-Adresse in dieser listen-Direktive (oder entfernen Sie die Adresse vollständig, um Datenverkehr von beliebigen Clients zuzulassen). Sie können bei Bedarf auch den Port 8081 ändern, auf dem NGINX lauscht:

server {    listen 127.0.0.1:8081;
    # ...
 }

Caching

Die Datei nginx-ldap-auth.conf ermöglicht das Zwischenspeichern von Daten und Anmeldedaten. Optional können Sie die folgenden Einstellungen ändern:

  • Die proxy_cache_path-Direktive im http-Konfigurationsblock erstellt ein lokales Verzeichnis namens cache auf dem Datenträger und weist einer Zone namens auth_cache, in der Metadaten gespeichert werden, 10 MB im gemeinsam genutzten Speicher zu.
proxy_cache_path cache/ keys_zone=auth_cache:10m;
  • Wenn Sie den Namen der gemeinsam genutzten Speicherzone ändern, müssen Sie ihn auch in der proxy_cache-Direktive ändern (im location-Block, der den Datenverkehr an den ldap‑auth-Daemon weiterleitet).
location = /auth-proxy {
    proxy_cache auth_cache;
    # ...
}
  • Die proxy_cache_valid-Direktive (im selben location-Block wie proxy_cache) legt fest, dass zwischengespeicherte Antworten mit dem HTTP-Code 200 oder 403 10 Minuten lang gültig sind.
location = /auth-proxy {    proxy_cache_valid 200 403 10m;
    # ...
}

Um das Caching zu deaktivieren, kommentieren Sie diese drei Direktiven sowie die Direktive proxy_cache_key aus.

Anpassen des Authentifizierungssystems

Wie oben erwähnt, können Sie den ldap‑auth-Daemon als Vorlage für Ihre eigene Anwendung verwenden, die Anfragen vom Modul http_auth_request entgegennimmt. Wenn Sie eine Python-App schreiben, die mit einem anderen Authentifizierungsservertyp (ohne LDAP) kommuniziert, erstellen Sie eine neue Klasse für den Authentifizierungs-Handler, die LDAPAuthHandler im Skript nginx-ldap-auth-daemon.py ersetzt.

Ein Hinweis zur Sicherheit

Der Backend-Daemon codiert den Benutzernamen und das Passwort im Cookie mit Base64. Base64 ist eine sehr schwache Form der Verschleierung, wodurch die Anmeldedaten leicht ausgelesen und missbraucht werden können. Damit die Authentifizierung einen echten Zweck erfüllt, müssen Sie in Ihrer Backend-Anwendung eine sicherere Verschlüsselung verwenden.


Teilen

Über den Autor

Owen Garrett
Owen GarrettSenior Director, Produktmanagement

Weitere Blogbeiträge von Owen Garrett

Ähnliche Blogbeiträge

Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
NGINX | 23.08.2022

Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln

Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
NGINX | 08.09.2021

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen

Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.

Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
NGINX | 16.08.2021

Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet

Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
NGINX | 12.12.2018

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77

Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.

Ankündigung von NGINX Plus R16
NGINX | 05.09.2018

Ankündigung von NGINX Plus R16

NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.

5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
NGINX | 13.10.2016

5 Gründe für den Umstieg auf softwarebasiertes Load Balancing

Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.