إذن المستخدم في Django من خلال GSSAPI وتفويض حقوق المستخدم إلى الخادم

في الآونة الأخيرة ، احتجت أنا وزملائي إلى تنفيذ تفويض (SSO) شفاف في مشروعنا. الآن هناك القليل من المعلومات حول هذا الموضوع ، وخاصة باللغة الروسية. لهذا السبب ، تقرر مشاركة الأحفاد في تنفيذ هذه الوظيفة.

لذلك كانت المهمة على النحو التالي: كان من الضروري تكوين التفويض الشفاف من خلال GSSAPI من المستخدم إلى الخادم ، وكذلك القدرة على الانتقال إلى قاعدة البيانات بالنيابة عن هذا المستخدم.

كان لدينا:

  • تكوين Kerberos + خادم LDAP
  • تم تهيئة خادم PostgreSQL للتفويض حصريًا بواسطة GSSAPI
  • خادم تطبيقات Django + UWSGI + nginx مع تكوين Kerberos

في البداية ، كانت الفكرة تفويض تفويض المستخدم في التطبيق إلى خادم الويب ، وإعداد تفويض GSSAPI عليه ، و Django للإشارة إلى أننا سنعمل مع RemoteUser. كجزء من هذا الوصف ، لن أتحدث عن كيفية تكوين nginx للعمل على GSSAPI ، و Django لتفويض التفويض إلى خادم ويب ، وهذا جزء موثق جيدًا ، وهناك الكثير من المقالات حول هذا الموضوع. بعد الضبط والاختبارات ، أدركنا أن هذا ليس ما نحتاجه على الإطلاق. نعم ، يمكننا التفويض والحصول على الاسم الأساسي للمستخدم ، ولكن ليس لدينا الحق في القيام بأي شيء بالنيابة عن هذا المستخدم.

ثم قمنا بمحاولات للعثور على شيء ذي قيمة على الإنترنت. كانت ناجحة نسبيًا ، وتم العثور على الحزم التالية لـ Django: django-kerberos ، django-auth-spnego ، django-auth-kerbero . في الواقع ، كل هذه الحزم فعلت الشيء نفسه ، وبعضها لم يتم تحديثه لفترة طويلة واضطروا إلى "الرقص مع الدف" لفترة طويلة ، بحيث نجح شيء على الأقل. لقد قدموا نفس الوظائف مثل حزمة nginx (GSSAPI) + Django (RemouteUser). ساعدهم جميعًا في حل المشكلة باستخدام شفرة المصدر الخاصة بهم.

بعد ذلك ، تم العثور على الحزم التالية للعمل مع GSSAPI في Python: ccs-pykerberos و python-gssapi ، في الواقع أنها تستورد تنفيذ معيار RFC2744 و RFC4559 في Python. باستخدام حزمة ccs-pykerberos ، تمكنا للتو من تنفيذ الوظيفة المطلوبة ، ثم سأعرض رمزًا صغيرًا حيث يتم التواصل مع LDAP والمستخدم ، بالإضافة إلى استعلام لقاعدة البيانات نيابة عنه.

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) 

أولاً ، نحتاج إلى التحقق مما إذا تم منح رأس التفويض لنا ، وإذا لم يكن الأمر كذلك ، فيجب أن نرسل الرأس مع التفاوض في الرد ، وننتظر مرة أخرى الرمز المميز من مستخدم التفاوض. يبدو هذا الرمز المميز وكأنه وسادة قدم كبيرة مشفرة في base64. بعد تلقي الرمز المميز ، نقوم بتهيئة (تخويل) خادم تطبيقنا في خدمة LDAP باستخدام وظيفة authGSSServerInit (). بعد ذلك ، سنصرح في خدمة LDAP نيابة عن المستخدم ، باستخدام وظيفة authGSSServerStep () فقط للرمز المميز الذي تم تلقيه من الرأس. ثم نحصل على مدير المستخدم ، الذي سنستخدمه كمستخدم ، عند تنفيذ الاستعلام في قاعدة البيانات. ونحتاج أيضًا إلى إنشاء ذاكرة تخزين مؤقت بتريل Kerberos ، والتي سيتم استخدامها تلقائيًا لتفويضنا في PostgreSQL ، وظيفة authGSSServerStoreDelegate (). هذه الوظيفة متاحة فقط في أحدث إصدار من هذه الحزمة ، لذلك تحتاج إلى استنساخ مصادرك باستخدام git والبناء.

يجب تكوين المستعرض لإرجاع مفاوضة ، بشكل افتراضي يتم تعطيل هذا الخيار. تم إجراء جميع الاختبارات على Firefox في CentOS7 ، وتم تثبيت CentOS7 على جميع الخوادم.

بالإضافة إلى ذلك ، قد تكون لدينا مشكلة في أن ذاكرة التخزين المؤقت للتذاكر التي تم إنشاؤها بواسطة وظيفتنا لن تكون مرئية لعملياتنا ، وبالتالي ، سنحصل على أن المستخدم غير مصرح به في GSSAPI. يتم حلها عن طريق تعيين التخزين المؤقت للتذكرة في krb5.conf. فقط تحسبًا ، سأعطي مثالاً على التكوين لدينا:

/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 


تم إنشاء هذا الجزء من التعليمات البرمجية للمساعدة في فهم كيفية حدوث التفويض وتفويض الحقوق ، ومن ثم باستخدام هذه المعرفة يمكنك بناء مصممي التفويض والروابط الخلفية للاتصال بقاعدة البيانات. تم تطوير حزمة ccs-pykerberos من قبل شركة Apple لتلبية احتياجاتها الداخلية ، على التوالي ، سأقدم رابطًا إلى رمزهم ، حيث يستخدمونه. لقد ساعدنا كثيرًا في فهم أنهم طوروا ccs-calendarserver / twistedcaldav / authkerb.py

روابط مفيدة


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


All Articles