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