Berechtigung von Benutzern in Django über GSSAPI und Delegierung von Benutzerrechten an den Server

Vor kurzem mussten meine Kollegen und ich eine transparente (SSO) Autorisierung in unserem Projekt implementieren. Nun gibt es ziemlich viele Informationen zu diesem Thema, insbesondere auf Russisch. Aus diesem Grund wurde beschlossen, die Implementierung dieser Funktionalität mit den Nachkommen zu teilen.

Die Aufgabe lautete also wie folgt: Es war notwendig, eine transparente Autorisierung über GSSAPI vom Benutzer zum Server zu konfigurieren und auch die Möglichkeit zu haben, für diesen Benutzer in die Datenbank zu gelangen.

Wir hatten:

  • konfigurierter Kerberos + LDAP-Server
  • PostgreSQL-Server, der so konfiguriert ist, dass er ausschließlich über GSSAPI autorisiert
  • Django + UWSGI + Nginx-Anwendungsserver mit konfiguriertem Kerberos

Ursprünglich bestand die Idee darin, die Benutzerautorisierung in einer Webserveranwendung zu delegieren, die GSSAPI-Autorisierung für sie einzurichten, und Django, um anzugeben, dass wir mit RemoteUser arbeiten werden. Als Teil dieser Beschreibung werde ich Ihnen nicht sagen, wie Nginx für die Arbeit mit GSSAPI konfiguriert wird, und Django, um die Autorisierung an einen Webserver zu delegieren. Dies ist ein gut dokumentierter Teil, und es gibt eine ganze Reihe von Artikeln dazu. Nach dem Einrichten und Durchführen von Tests haben wir festgestellt, dass dies absolut nicht das ist, was wir brauchen. Ja, wir können den Benutzernamen des Benutzers autorisieren und erhalten, aber wir haben keine Rechte, im Namen dieses Benutzers etwas zu tun.

Als Nächstes haben wir versucht, im Internet etwas Wertvolles zu finden. Sie waren mit relativem Erfolg gekrönt, die folgenden Pakete für Django wurden gefunden: django-kerberos ,django-auth-spnego , django-auth-kerbero . In der Tat haben alle diese Pakete dasselbe getan, einige wurden lange Zeit nicht aktualisiert und mussten lange Zeit mit einem Tamburin tanzen, so dass zumindest etwas funktionieren würde. Sie bieten die gleiche Funktionalität wie das Nginx-Bundle (GSSAPI) + Django (RemouteUser). Sie alle haben geholfen, das Problem mit ihrem Quellcode zu lösen.

Als Nächstes wurden die folgenden Pakete für die Arbeit mit GSSAPI in Python gefunden: ccs-pykerberos und python-gssapi . Tatsächlich importieren sie die Implementierung des Standards RFC2744 und RFC4559 in Python. Mit Hilfe des Pakets ccs-pykerberos ist es uns gerade erst gelungen, die geplante Funktionalität zu implementieren. Anschließend werde ich etwas Code zeigen, in dem die Kommunikation mit LDAP und dem Benutzer ausgeführt wird, sowie eine Datenbankabfrage.

from django.shortcuts import render
from django.template.response import TemplateResponse
import kerberos
import psycopg2
defindex(request):if'HTTP_AUTHORIZATION'in request.META:
        kind, initial_client_token = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
        if kind == 'Negotiate':
            service = 'HTTP@django-server-pricipal.che.ru'
            _ignore_result, krb_context = kerberos.authGSSServerInit(service)                        
            kerberos.authGSSServerStep(krb_context, initial_client_token)            
            principal = kerberos.authGSSServerUserName(krb_context)
            _ignore_result = kerberos.authGSSServerStoreDelegate(krb_context)            
            conn = psycopg2.connect(
                host='postgresql-server-host',
                user=principal,
                dbname='request-db',
            )
            cursor = conn.cursor()
            cursor.execute("SELECT version()")
            records = cursor.fetchall()
    else:
        unauthorized_template_name = 'gssapi_test/unauthorized.html'
        response = TemplateResponse(request, 'gssapi_test/index.html', status=401)
        response['WWW-Authenticate'] = 'Negotiate'return response    
    content = {'records': records}
    return render(request, 'gssapi_test/index.html', content)

Zuerst müssen wir prüfen, ob der Autorisierungsheader an uns übergeben wurde. Wenn nicht, sollten wir eine Antwort mit Negotiate senden und dann auf das Token des Negotiate-Benutzers warten. Dieses Token sieht aus wie ein großes, in base64 codiertes Fußtuch. Nach Erhalt des Tokens initialisieren (autorisieren) wir den Server unserer Anwendung im LDAP-Dienst mit der Funktion authGSSServerInit (). Als Nächstes melden wir uns beim LDAP-Dienst für den Benutzer an, und zwar nur mit dem Token, das vom Header empfangen wurde, der Funktion authGSSServerStep (). Dann erhalten wir das Prinzip des Benutzers, das wir als Benutzer verwenden, wenn Sie die Abfrage in der Datenbank ausführen. Außerdem müssen wir einen Kerberos-Bitel-Cache erstellen, der automatisch verwendet wird, um uns in PostgreSQL, der Funktion authGSSServerStoreDelegate (), zu autorisieren.

Der Browser muss so konfiguriert sein, dass er Negotiate zurückgibt. Diese Option ist standardmäßig deaktiviert. Alle Tests wurden unter Firefox in CentOS7 durchgeführt, CentOS7 wurde auch auf allen Servern installiert.

Darüber hinaus besteht möglicherweise ein Problem, dass der von unserer Funktion generierte Ticket-Cache für unseren Prozess nicht sichtbar ist und dementsprechend erhalten Sie, dass sich der Benutzer nicht bei der GSSAPI angemeldet hat. Sie können dieses Problem lösen, indem Sie das Ticket-Caching in krb5.conf festlegen. Nur für den Fall, dass ich ein Beispiel unserer Konfiguration geben werde:

/etc/krb5.conf
includedir /etc/krb5.conf.d/
includedir /var/lib/sss/pubconf/krb5.include.d/
[libdefaults]
  default_realm = DOMAIN.RU
  dns_lookup_realm = false
  dns_lookup_kdc = false
  rdns = false
  ticket_lifetime = 24h
  forwardable = true
  udp_preference_limit = 0# если раскомментировать опцию - работать не будет#default_ccache_name = KEYRING:persistent:%{uid}#Нужно для определения параметра KRB5_KTNAME в облатси видимости приложения
  default_keytab_name = FILE:/etc/httpd/http.keytab
[realms]
  DOMAIN.RU = {
    kdc = ldap-server-host.domain.ru:88
    master_kdc = ldap-server-host.domain.ru:88
    admin_server = ldap-server-host.domain.ru:749
    kpasswd_server = ldap-server-host.domain.ru:464 
    default_domain = domain.ru
    pkinit_anchors = FILE:/etc/domain/ca.crt
  }
[domain_realm]
  .domain.ru = DOMAIN.RU
  domain.ru = DOMAIN.RU
  .domain.ru = DOMAIN.RU


Dieser Code wurde erstellt, um zu verstehen, wie die Autorisierung erfolgt und welche Rechte delegiert werden. Mit diesem Wissen können Sie Autorisierungsdekoratoren und Backlinks erstellen, um mit der Datenbank zu kommunizieren. Das ccs-pykerberos-Paket wurde von Apple für interne Zwecke entwickelt bzw. ich werde einen Link zu ihrem Code geben, wo er es verwendet. Er hat uns sehr geholfen zu verstehen, dass sie ccs-calendarserver / twistedcaldav / authkerb.py entwickelt haben

Nützliche Links



Jetzt auch beliebt: