Autorisation utilisateur dans Django via GSSAPI et délégation de droits utilisateur au serveur

Récemment, mes collègues et moi avons dû implémenter une autorisation transparente (SSO) dans notre projet. Maintenant, il y a pas mal d'informations sur le sujet, surtout en russe. Pour cette raison, il a été décidé de partager avec les descendants la mise en œuvre d'une telle fonctionnalité.

La tâche était donc la suivante: il fallait configurer une autorisation transparente via GSSAPI de l'utilisateur vers le serveur, puis pouvoir accéder à la base de données au nom de cet utilisateur.

Nous avions:

  • serveur Kerberos + LDAP configuré
  • Serveur PostgreSQL configuré pour l'autorisation exclusivement par GSSAPI
  • Serveur d'applications Django + UWSGI + nginx avec Kerberos configuré

Initialement, l'idée était de déléguer l'autorisation utilisateur dans l'application au serveur Web, en configurant l'autorisation GSSAPI dessus, et Django pour indiquer que nous travaillerions avec RemoteUser. Dans le cadre de cette description, je ne parlerai pas de la façon de configurer nginx pour qu'il fonctionne sur GSSAPI et Django pour déléguer l'autorisation à un serveur Web, ceci est une partie bien documentée et il y a beaucoup d'articles à ce sujet. Après réglage et tests, nous avons réalisé que ce n'était absolument pas ce dont nous avions besoin. Oui, nous pouvons autoriser et obtenir le nom d'utilisateur principal, mais nous n'avons pas le droit de faire quoi que ce soit au nom de cet utilisateur.

Ensuite, nous avons tenté de trouver quelque chose d'intéressant sur Internet. Ils ont relativement bien réussi et les packages suivants pour Django ont été trouvés: django-kerberos , django-auth-spnego , django-auth-kerbero . En fait, tous ces packages ont fait la même chose, certains n'ont pas été mis à jour depuis longtemps et ont dû "danser avec un tambourin" pendant longtemps, de sorte qu'au moins quelque chose a fonctionné. Ils ont fourni les mêmes fonctionnalités que le bundle nginx (GSSAPI) + Django (RemouteUser). Tous ont aidé à résoudre le problème avec leur code source.

Ensuite, les packages suivants ont été trouvés pour travailler avec GSSAPI en Python: ccs-pykerberos et python-gssapi , en fait ils importent l'implémentation des standards RFC2744 et RFC4559 en Python. En utilisant le paquet ccs-pykerberos, nous avons juste réussi à implémenter la fonctionnalité prévue, puis je vais montrer un petit code où la communication avec LDAP et l'utilisateur est implémentée, ainsi qu'une requête vers la base de données en son nom.

from django.shortcuts import render from django.template.response import TemplateResponse import kerberos import psycopg2 def index(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) 

Tout d'abord, nous devons vérifier si l'en-tête d'autorisation nous a été donné, sinon, nous devons envoyer l'en-tête avec Negotiate en réponse, et attendre à nouveau le jeton de l'utilisateur Negotiate. Ce jeton ressemble à un grand footcloth encodé en base64. Après avoir reçu le jeton, nous initialisons (autorisons) le serveur de notre application dans le service LDAP à l'aide de la fonction authGSSServerInit (). Ensuite, nous autoriserons dans le service LDAP au nom de l'utilisateur, en utilisant la fonction authGSSServerStep () uniquement pour le jeton reçu de l'en-tête. Ensuite, nous obtenons le principal de l'utilisateur, que nous utiliserons en tant qu'utilisateur, lors de l'exécution de la requête dans la base de données. Et aussi, nous devons créer un cache de bitels Kerberos, qui sera utilisé automatiquement afin de nous autoriser dans PostgreSQL, la fonction authGSSServerStoreDelegate (). Cette fonction n'est disponible que dans la dernière version de ce paquet, vous devez donc cloner vos sources avec git et build.

Le navigateur doit être configuré pour renvoyer Négocier, par défaut cette option est désactivée. Tous les tests ont été effectués sur Firefox dans CentOS7, et CentOS7 a été installé sur tous les serveurs.

De plus, nous pouvons avoir un problème dans lequel le cache de tickets généré par notre fonction ne sera pas visible pour notre processus et, par conséquent, nous obtiendrons que l'utilisateur n'était pas autorisé dans GSSAPI. Il est résolu en définissant la mise en cache des tickets dans krb5.conf. Juste au cas où, je vais donner un exemple de notre configuration:

/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 


Ce morceau de code a été créé afin de comprendre comment se déroulent l'autorisation et la délégation des droits, puis avec cette connaissance, vous pouvez créer des décorateurs d'autorisation et des liens de communication avec la base de données. Le paquet ccs-pykerberos a été développé par Apple pour ses besoins internes, respectivement, je fournirai un lien vers leur code, où ils l'utiliseront. Il nous a beaucoup aidés à comprendre qu'ils ont développé ccs-calendarserver / twistedcaldav / authkerb.py

Liens utiles


Source: https://habr.com/ru/post/fr427839/


All Articles