RBAC مع API Gateway و Open Policy Agent (OPA)

مع توفر نماذج تحكم وصول مختلفة وطرق تنفيذ متعددة، لا يزال بناء نظام تفويض لواجهات برمجة التطبيقات (APIs) للخدمات الخلفية يمثل تحديًا. ومع ذلك، فإن الهدف النهائي هو ضمان أن الشخص الصحيح لديه الوصول المناسب إلى المورد ذي الصلة. في هذه المقالة، سنناقش كيفية تمكين نموذج التحكم في الوصول القائم على الأدوار (RBAC) لواجهة برمجة التطبيقات الخاصة بك باستخدام بوابة API مفتوحة المصدر Apache APISIX وOpen Policy Agent (OPA).

أهداف التعلم

ستتعلم خلال المقالة ما يلي:

  • ما هو RBAC وكيف يعمل؟
  • ما هو OPA وكيف يعمل؟
  • كيفية تنفيذ RBAC باستخدام OPA و Apache APISIX؟
  • كيفية تعريف وتسجيل السياسة في OPA.
  • كيفية إنشاء upstream و route وتمكين مكون OPA plugin.
  • كيفية تحليل دور المستخدم والإذن من حمولة رمز JWT أو بيانات المستهلك.

ما هو RBAC؟

التحكم في الوصول القائم على الأدوار (RBAC) والتحكم في الوصول القائم على السمات (ABAC) هما نموذجان شائعان للتحكم في الوصول يستخدمان لإدارة الأذونات والتحكم في الوصول إلى الموارد في أنظمة الكمبيوتر. يعين RBAC الأذونات للمستخدمين بناءً على دورهم داخل المنظمة. في RBAC، يتم تعريف الأدوار بناءً على وظائف أو مسؤوليات المستخدمين، ويتم تعيين الأذونات لتلك الأدوار. ثم يتم تعيين المستخدمين لواحد أو أكثر من الأدوار، ويرثون الأذونات المرتبطة بتلك الأدوار. في سياق API، على سبيل المثال، قد يكون لدور المطور إذن لإنشاء وتحديث موارد API، بينما قد يكون لدور المستخدم النهائي إذن فقط لقراءة أو تنفيذ موارد API.

بشكل أساسي، يعين RBAC الأذونات بناءً على أدوار المستخدمين، بينما يعين ABAC الأذونات بناءً على السمات المرتبطة بالمستخدمين والموارد.

في RBAC، يتم تعريف السياسة من خلال مجموعة من الدور المعين للمستخدم، والإجراءات التي يُصرح لهم بتنفيذها، والموارد التي يمكنهم تنفيذ تلك الإجراءات عليها.

ما هو OPA؟

OPA (Open Policy Agent) هو محرك سياسات ومجموعة من الأدوات التي توفر نهجًا موحدًا لفرض السياسات عبر نظام موزع بالكامل. يسمح لك بتعريف وإدارة وفرض السياسات بشكل مركزي من نقطة واحدة. من خلال تعريف السياسات ككود، يتيح OPA مراجعة وتحرير واستعادة السياسات بسهولة، مما يسهل إدارة السياسات بكفاءة.

صورة مثال Open Policy Agent

يوفر OPA لغة تعريفية تسمى Rego، والتي تتيح لك إنشاء وفرض السياسات عبر نظامك. عندما تطلب قرارًا سياسيًا من OPA، يستخدم القواعد والبيانات التي قدمتها في ملف .rego لتقييم الاستعلام وإنتاج استجابة. يتم إرسال نتيجة الاستعلام إليك كقرار سياسي. يقوم OPA بتخزين جميع السياسات والبيانات التي يحتاجها في ذاكرة التخزين المؤقت الخاصة به. نتيجة لذلك، يعيد OPA النتائج بسرعة. إليك مثال على ملف Rego بسيط لـ OPA:

package example

default allow = false

allow {
    input.method == "GET"
    input.path =="/api/resource"
    input.user.role == "admin"
}

في هذا المثال، لدينا حزمة تسمى "example" تعرف قاعدة تسمى "allow". تحدد قاعدة "allow" أن الطلب مسموح به إذا كانت طريقة الإدخال هي "GET"، وكان المسار المطلوب هو /api/resource، وكان دور المستخدم هو "admin". إذا تم استيفاء هذه الشروط، فإن قاعدة "allow" ستقيّم على أنها "true"، مما يسمح للطلب بالمتابعة.

لماذا نستخدم OPA وبوابة API لـ RBAC؟

توفر بوابة API موقعًا مركزيًا لتكوين وإدارة API والمستهلكين. يمكن استخدامها كبوابة مصادقة مركزية من خلال تجنب تنفيذ كل خدمة فردية لمنطق المصادقة داخل الخدمة نفسها. من ناحية أخرى، يضيف OPA طبقة تفويض ويفصل السياسة عن الكود من خلال إنشاء فائدة متميزة للتفويض. مع هذا المزيج، يمكنك إضافة أذونات لمورد API لدور. قد يكون المستخدمون مرتبطين بواحد أو أكثر من أدوار المستخدمين. يحدد كل دور مستخدم مجموعة من الأذونات (GET, PUT, DELETE) على موارد RBAC (المحددة بواسطة مسارات URI). في القسم التالي، دعنا نتعلم كيفية تحقيق RBAC باستخدام هذين.

Open Policy Agent مع بوابة Apache APISIX API

كيفية تنفيذ RBAC باستخدام OPA و Apache APISIX

في Apache APISIX، يمكنك تكوين routes وplugins لتحديد سلوك API الخاص بك. يمكنك استخدام مكون opa plugin في APISIX لفرض سياسات RBAC عن طريق توجيه الطلبات إلى OPA لاتخاذ القرار. ثم يتخذ OPA قرار التفويض بناءً على أدوار المستخدمين وأذوناتهم في الوقت الفعلي.

لنفترض أن لدينا Conference API حيث يمكنك استرداد/تحرير جلسات الأحداث والموضوعات ومعلومات المتحدثين. يمكن للمتحدث فقط قراءة جلساتهم وموضوعاتهم بينما يمكن للمسؤول إضافة/تحرير المزيد من الجلسات والموضوعات. أو يمكن للحضور ترك تعليقاتهم حول جلسة المتحدث عبر طلب POST إلى /speaker/speakerId/session/feedback ويمكن للمتحدث فقط رؤيتها عن طريق طلب طريقة GET لنفس URI. يوضح الرسم البياني أدناه السيناريو بأكمله:

Open Policy Agent مع Apache APISIX

  1. يطلب مستهلك API مسارًا على بوابة API باستخدام بيانات الاعتماد الخاصة به مثل رمز JWT في رأس التفويض.
  2. ترسل بوابة API بيانات المستهلك مع رأس JWT إلى محرك OPA.
  3. يقوم OPA بتقييم ما إذا كان المستهلك لديه الحق في الوصول إلى المورد باستخدام السياسات (الأدوار والأذونات) التي نحددها في ملف .rego.
  4. إذا كان قرار OPA مسموحًا به، فسيتم توجيه الطلب إلى خدمة Conference الخلفية.

بعد ذلك، نقوم بتثبيت وتكوين APISIX، وتحديد السياسات في OPA.

المتطلبات الأساسية

  • Docker يستخدم لتثبيت etcd و APISIX المعبأة في حاويات.
  • curl يستخدم لإرسال الطلبات إلى واجهة برمجة التطبيقات الإدارية لـ APISIX. يمكنك أيضًا استخدام أدوات مثل Postman للتفاعل مع API.

الخطوة 1: تثبيت Apache APISIX

يمكن تثبيت APISIX وبدء تشغيله بسهولة باستخدام البرنامج النصي التالي للبدء السريع:

curl -sL https://run.api7.ai/apisix/quickstart | sh

الخطوة 2: تكوين خدمة الخلفية (upstream)

لتوجيه الطلبات إلى خدمة الخلفية لـ Conference API، ستحتاج إلى تكوينها عن طريق إضافة خادم upstream في Apache APISIX عبر واجهة برمجة التطبيقات الإدارية.

curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -X PUT -d '
{
   "name":"Conferences API upstream",
   "desc":"Register Conferences API as the upstream",
   "type":"roundrobin",
   "scheme":"https",
   "nodes":{
      "conferenceapi.azurewebsites.net:443":1
   }
}'

الخطوة 3: إنشاء مستهلك API

بعد ذلك، نقوم بإنشاء مستهلك (متحدث جديد) باسم المستخدم jack في Apache APISIX. يتم إعداد مكون jwt-auth للمستهلك باستخدام المفتاح والسر المحددين. سيسمح ذلك للمستهلك بالمصادقة باستخدام رمز ويب JSON (JWT).

curl http://127.0.0.1:9180/apisix/admin/consumers -X PUT -d '
{
    "username": "jack",
    "plugins": {
        "jwt-auth": {
            "key": "user-key",
            "secret": "my-secret-key"
        }
    }
}'

الخطوة 4: إنشاء نقطة نهاية عامة لإنشاء رمز JWT

تحتاج أيضًا إلى إعداد Route جديد يقوم بإنشاء وتوقيع الرمز باستخدام مكون public-api. في هذا السيناريو، تعمل بوابة API كخادم موفر هوية لإنشاء والتحقق من الرمز باستخدام مفتاح المستهلك jack. يمكن أن يكون موفر الهوية أيضًا أي خدمات طرف ثالث أخرى مثل Google، Okta، Keycloak، وOry Hydra.

curl http://127.0.0.1:9180/apisix/admin/routes/jas -X PUT -d '
{
    "uri": "/apisix/plugin/jwt/sign",
    "plugins": {
        "public-api": {}
    }
}'

الخطوة 5: المطالبة برمز JWT جديد لمستهلك API

الآن يمكننا الحصول على رمز جديد لمتحدثنا Jack من بوابة API باستخدام نقطة النهاية العامة التي أنشأناها. يقوم الأمر التالي بإنشاء رمز جديد باستخدام بيانات اعتماد Jack وتعيين الدور والإذن في الحمولة.

curl -G --data-urlencode 'payload={"role":"speaker","permission":"read"}' http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key -i

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

الخطوة 6: إنشاء تكوين مكون جديد

تتضمن هذه الخطوة تكوين 3 مكونات في APISIX، وهي proxy-rewrite، jwt-auth وopa.

curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PUT -d '
{
   "plugins":{
      "jwt-auth":{
      },
      "proxy-rewrite":{
         "host":"conferenceapi.azurewebsites.net"
      }
   }
}'
  • تم تكوين مكون proxy-rewrite لتوجيه الطلبات إلى المضيف conferenceapi.azurewebsites.net.
  • تم تكوين مكون OPA للمصادقة لاستخدام محرك السياسات OPA الذي يعمل على http://localhost:8181/v1/data/rbacExample. أيضًا، يرسل APISIX جميع المعلومات المتعلقة بالمستهلك إلى OPA. سنضيف ملف السياسة .rego هذا في قسم تكوين Opa.

الخطوة 7: إنشاء Route لجلسات Conference

الخطوة الأخيرة هي إنشاء Route جديد لجلسات متحدثي Conference API:

curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
{
    "name":"Conferences API speaker sessions route",
    "desc":"Create a new route in APISIX for the Conferences API speaker sessions",
    "methods": ["GET", "POST"],
    "uris": ["/speaker/*/topics","/speaker/*/sessions"],
    "upstream_id":"1",
    "plugin_config_id":1
}'

تحتوي الحمولة على معلومات حول Route، مثل اسمه ووصفه وطرقه وURIs ومعرف upstream ومعرف تكوين المكون. في هذه الحالة، تم تكوين Route للتعامل مع طلبات GET وPOST لـ URIين مختلفين، /speaker/topics و /speaker/sessions. يحدد حقل "upstream_id" معرف خدمة upstream التي ستتعامل مع الطلبات الواردة لهذا Route، بينما يحدد حقل "plugin_config_id" معرف تكوين المكون الذي سيتم استخدامه لهذا Route.

الخطوة 8: اختبار الإعداد بدون OPA

حتى الآن، قمنا بإعداد جميع التكوينات اللازمة لـ APISIX لتوجيه الطلبات الواردة إلى نقاط نهاية Conference API، مع السماح فقط للمستهلكين المصرح لهم. الآن، في كل مرة يريد مستهلك API الوصول إلى نقطة نهاية، يجب عليه تقديم رمز JWT لاسترداد البيانات من خدمة Conference الخلفية. يمكنك التحقق من ذلك عن طريق الوصول إلى نقطة النهاية وعنوان النطاق الذي نطلبه الآن هو بوابة API المخصصة لدينا وليس خدمة Conference الفعلية:

curl -i http://127.0.0.1:9080/speaker/1/topics -H 'Authorization: {API_CONSUMER_TOKEN}'

الخطوة 9: تشغيل خدمة OPA

الخطوتان الأخريان هما تشغيل خدمة OPA باستخدام Docker وتحميل تعريف السياسة باستخدام واجهة برمجة التطبيقات الخاصة بها والتي يمكن استخدامها لتقييم سياسات التفويض للطلبات الواردة.

docker run -d --network=apisix-quickstart-net --name opa -p 8181:8181 openpolicyagent/opa:latest run -s

يقوم هذا الأمر بتشغيل حاوية من صورة OPA بأحدث إصدار. يقوم بإنشاء حاوية جديدة على شبكة APISIX الحالية apisix-quickstart-net باسم opa ويعرض المنفذ 8181. لذلك، يمكن لـ APISIX إرسال طلبات التحقق من السياسات إلى OPA مباشرة باستخدام العنوان [http://opa:8181](http://opa:8181) لاحظ أن OPA و APISIX يجب أن يعملان في نفس شبكة Docker.

الخطوة 10: تعريف وتسجيل السياسة

الخطوة الثانية على جانب OPA هي أنك تحتاج إلى تعريف السياسات التي سيتم استخدامها للتحكم في الوصول إلى موارد API. يجب أن تحدد هذه السياسات السمات المطلوبة للوصول (أي المستخدمين لديهم أي أدوار) والإذن (أي الأدوار لديها أي أذونات) المسموح بها أو المرفوضة بناءً على تلك السمات. على سبيل المثال، في التكوين أدناه، نقول لـ OPA أن يتحقق من جدول user_roles ما هو الدور لـ jack. يتم إرسال هذه المعلومات بواسطة APISIX داخل input.consumer.username. أيضًا، نقوم بالتحقق من إذن المستهلك عن طريق قراءة حمولة JWT واستخراج token.payload.permission من هناك. توضح التعليقات الخطوات بوضوح.

curl -X PUT '127.0.0.1:8181/v1/policies/rbacExample' \
    -H 'Content-Type: text/plain' \
    -d 'package rbacExample

# تعيين أدوار المستخدمين

user_roles := {
    "jack": ["speaker"],
    "bobur":["admin"]
}

# تعيين أذونات الأدوار
role_permissions := {
    "speaker": [{"permission": "read"}],
    "admin":   [{"permission": "read"}, {"permission": "write"}]
}

# وظائف مساعدة لـ JWT
bearer_token := t {
 t := input.request.headers.authorization
}

# فك تشفير رمز التفويض للحصول على دور وإذن
token = {"payload": payload} {
 [_, payload, _] := io.jwt.decode(bearer_token)
}

# المنطق الذي ينفذ RBAC
default allow = false

allow {
    # البحث عن قائمة الأدوار للمستخدم
    roles := user_roles[input.consumer.username]

    # لكل دور في تلك القائمة
    r := roles[_]

    # البحث عن قائمة الأذونات للدور r
    permissions := role_permissions[r]

    # لكل إذن
    p := permissions[_]

    # التحقق مما إذا كان الإذن الممنوح لـ r يتطابق مع طلب المستخدم
    p == {"permission": token.payload.permission}
}'

الخطوة 11: تحديث تكوين المكون الحالي بمكون OPA

بمجرد تعريف السياسات في خدمة OPA، نحتاج إلى تحديث تكوين المكون الحالي للـ Route لاستخدام مكون OPA. نحدد في سمة policy لمكون OPA.

curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PATCH -d '
{
   "plugins":{
      "opa":{
         "host":"http://opa:8181",
         "policy":"rbacExample",
         "with_consumer":true
      }
   }
}'

الخطوة 12: اختبار الإعداد مع OPA

الآن يمكننا اختبار جميع الإعدادات التي قمنا بها مع سياسات OPA. إذا حاولت تشغيل نفس الأمر curl للوصول إلى نقطة نهاية بوابة API، فإنه يتحقق أولاً من رمز JWT كعملية مصادقة ويرسل بيانات المستهلك ورمز JWT إلى OPA للتحقق من الدور والإذن كعملية تفويض. سيتم رفض أي طلب بدون رمز JWT أو أدوار مسموح بها.

curl -i http://127.0.0.1:9080/speaker/1/topics -H 'Authorization: {API_CONSUMER_TOKEN}'

الخلاصة

في هذه المقالة، تعلمنا كيفية تنفيذ RBAC باستخدام OPA و Apache APISIX. قمنا بتعريف منطق سياسة مخصص بسيط للسماح/رفض الوصول إلى موارد API بناءً على دور المستهلك وأذوناته. كما أظهر هذا البرنامج التعليمي كيف يمكننا استخراج المعلومات المتعلقة بمستهلك API في ملف السياسة من حمولة رمز JWT أو كائن المستهلك المرسل بواسطة APISIX.

الموارد ذات الصلة

المحتوى الموصى به

Share article link