التخطي إلى المحتوى الرئيسي

التفويض في APISIX باستخدام Casbin

· قراءة لمدة 5 دقيقة
Rushikesh Tote

مقدمة

APISIX هو بوابة API سحابية عالية الأداء وقابلة للتوسعة تعتمد على Nginx و etcd. إنه مشروع مفتوح المصدر من قبل مؤسسة Apache للبرمجيات. بالإضافة إلى ذلك، ما يجعل APISIX جيدًا جدًا هو دعم العديد من الإضافات الرائعة المدمجة التي يمكن استخدامها لتنفيذ ميزات مثل المصادقة، والمراقبة، والتوجيه، وما إلى ذلك. وحقيقة أن الإضافات في APISIX يتم إعادة تحميلها بشكل ساخن (دون إعادة التشغيل) تجعلها ديناميكية للغاية.

ولكن أثناء استخدام APISIX، قد تكون هناك سيناريوهات ترغب فيها بإضافة منطق تفويض معقد في تطبيقك. هنا يمكن أن يساعدك authz-casbin، authz-casbin هو إضافة APISIX تعتمد على Lua Casbin والتي تمكن التفويض القوي بناءً على نماذج مختلفة للتحكم في الوصول. Casbin هو مكتبة تفويض تدعم نماذج التحكم في الوصول مثل ACL، RBAC، ABAC. كتبت أصلاً بلغة Go، وتم نقلها إلى العديد من اللغات و Lua Casbin هي تنفيذ Lua لـ Casbin. بدأ تطوير authz-casbin عندما اقترحنا إضافة جديدة للتفويض في مستودع APISIX (#4674) وافق عليها الأعضاء الأساسيون. وبعد المراجعات المفيدة التي أدت إلى بعض التغييرات الكبيرة والتحسينات، تم دمج الطلب (#4710) أخيرًا.

في هذه المدونة، سنستخدم إضافة authz-casbin لإظهار كيف يمكنك تنفيذ نموذج تفويض يعتمد على نموذج التحكم في الوصول بناءً على الأدوار (RBAC) في APISIX.

ملاحظة: ستحتاج إلى استخدام إضافة أخرى أو سير عمل مخصص لمصادقة المستخدم لأن Casbin سيقوم فقط بالتفويض وليس المصادقة.

إنشاء نموذج

تستخدم الإضافة ثلاث معاملات لتفويض أي طلب - الفاعل، والموضوع، والفعل. هنا، الفاعل هو قيمة رأس الاسم المستخدم، والتي يمكن أن تكون شيئًا مثل [username: alice]. ثم، الموضوع هو مسار URL الذي يتم الوصول إليه والفعل هو طريقة الطلب المستخدمة.

لنقل نريد إنشاء نموذج بثلاث موارد على المسارات - /، /res1 و /res2. ونريد أن يكون لدينا نموذج مثل هذا:

صورة

هذا يعني أن جميع المستخدمين (*) مثل jack يمكنهم الوصول إلى الصفحة الرئيسية (/). والمستخدمون الذين لديهم صلاحيات admin مثل alice و bob يمكنهم الوصول إلى جميع الصفحات والموارد (مثل res1 و res2). أيضًا، دعونا نقيد المستخدمين بدون أي صلاحيات إدارية على استخدام طريقة الطلب GET فقط. لهذا السيناريو، يمكننا تعريف النموذج على النحو التالي:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)

إنشاء سياسة

من السيناريو أعلاه، ستكون السياسة:

p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin

المطابقة من النموذج تعني:

  1. (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)): إما أن يكون لفاعل الطلب دور كفاعل السياسة أو يطابق فاعل الطلب فاعل السياسة في keyMatch. keyMatch هي وظيفة مدمجة في Lua Casbin، يمكنك الاطلاع على وصف الوظيفة والمزيد من الوظائف المفيدة هنا.
  2. keyMatch(r.obj, p.obj): يطابق موضوع الطلب موضوع السياسة (مسار URL هنا).
  3. keyMatch(r.act, p.act): يطابق فعل الطلب فعل السياسة (طريقة الطلب HTTP هنا).

تمكين الإضافة على المسار

بمجرد إنشاء النموذج والسياسة، يمكنك تمكينها على مسار باستخدام واجهة برمجة تطبيقات APISIX الإدارية. لتمكينها باستخدام مسارات ملفات النموذج والسياسة:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model_path": "/path/to/model.conf",
"policy_path": "/path/to/policy.csv",
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'

هنا، حقل الاسم المستخدم هو اسم الرأس الذي ستستخدمه لتمرير الفاعل. على سبيل المثال، إذا كنت ستمرر رأس الاسم المستخدم كـ user: alice، فستستخدم "username": "user".

للاستخدام نص النموذج/السياسة بدلاً من الملفات، يمكنك استخدام حقول model و policy بدلاً من ذلك:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model": "[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",

"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin",

"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'

تمكين الإضافة باستخدام نموذج/سياسة عالمية

قد تكون هناك حالات ترغب فيها باستخدام نموذج وسياسة تكوين واحدة عبر مسارات متعددة. يمكنك القيام بذلك أولاً بإرسال طلب PUT لإضافة تكوين النموذج والسياسة إلى بيانات الإضافة الوصفية بواسطة:

curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/authz-casbin -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -i -X PUT -d '
{
"model": "[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",

"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin"
}'

ثم لتمكين نفس التكوين على بعض المسار، أرسل طلبًا باستخدام واجهة برمجة التطبيقات الإدارية:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/route1/*"
}'

سيضيف هذا تكوين بيانات الإضافة الوصفية إلى المسار. يمكنك أيضًا تحديث تكوين بيانات الإضافة الوصفية بسهولة عن طريق إعادة إرسال الطلب إلى بيانات الإضافة الوصفية مع تحديث تكوين النموذج والسياسة، وستقوم الإضافة تلقائيًا بتحديث جميع المسارات التي تستخدم تكوين بيانات الإضافة الوصفية.

حالات الاستخدام

  • الحالة الأساسية لاستخدام هذه الإضافة ستكون في تنفيذ التفويض في واجهات برمجة التطبيقات الخاصة بك. يمكنك بسهولة إضافة هذه الإضافة على أي مسار واجهة برمجة تطبيقات تستخدمه مع نموذج التفويض وتكوين السياسة الخاص بك.
  • إذا كنت ترغب في امتلاك نموذج تفويض واحد لجميع واجهات برمجة التطبيقات الخاصة بك، يمكنك استخدام طريقة النموذج/السياسة العالمية. هذا يجعل تحديث السياسة سهلًا لجميع المسارات، حيث أنك تحتاج فقط إلى تحديث البيانات الوصفية في etcd.
  • بينما إذا كنت ترغب في استخدام نموذج مختلف لكل مسار مختلف، يمكنك استخدام طريقة المسار. هذا مفيد عندما تحتوي مسارات واجهة برمجة التطبيقات المختلفة على مجموعات مختلفة من أذونات المستخدم. يمكنك أيضًا استخدام هذا عند التعامل مع سياسات أكبر، حيث سيجعل عملية التفويض أسرع عند تصفيتها إلى مسارات متعددة.