Перейти до основного контенту

Авторизація в APISIX за допомогою Casbin

· 5 хв читання
Rushikesh Tote

Вступ

APISIX - це високопродуктивний та масштабований хмарний нативний API шлюз на основі Nginx та etcd. Це відкритий проект Фонду Apache Software. Крім того, те, що робить APISIX таким хорошим, - це підтримка багатьох вбудованих плагінів, які можна використовувати для реалізації функцій, таких як аутентифікація, моніторинг, маршрутизація тощо. І той факт, що плагіни в APISIX можна гаряче перезавантажувати (без перезапусків), робить його дуже динамічним.

Але, використовуючи APISIX, можуть виникнути сценарії, коли вам може знадобитися додати складну логіку авторизації у ваш додаток. Саме тут може допомогти authz-casbin, authz-casbin - це плагін APISIX на основі Lua Casbin, який забезпечує потужну авторизацію на основі різних моделей контролю доступу. Casbin - це бібліотека авторизації, яка підтримує моделі контролю доступу, такі як ACL, RBAC, ABAC. Спочатку написаний на Go, він був портований на багато мов, і Lua Casbin - це реалізація Casbin на Lua. Розробка authz-casbin почалася, коли ми запропонували новий плагін для авторизації в репозиторії APISIX (#4674), з яким погодилися основні члени. І після корисних відгуків, які призвели до деяких важливих змін та поліпшень, PR (#4710) було нарешті злито.

У цьому блозі ми використаємо плагін authz-casbin, щоб показати, як ви можете реалізувати модель авторизації на основі контролю доступу на основі ролей (RBAC) в APISIX.

ПРИМІТКА: Вам потрібно буде використовувати якийсь інший плагін або власний робочий процес для аутентифікації користувача, оскільки Casbin здійснює лише авторизацію, а не аутентифікацію.

Створення моделі

Плагін використовує три параметри для авторизації будь-якого запиту - суб'єкт, об'єкт та дія. Тут суб'єкт - це значення заголовка username, яке може бути чимось на кшталт [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 Admin API. Щоб увімкнути їх, використовуючи шляхи до файлів моделі та політики:

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": "/*"
}'

Тут поле username - це назва заголовка, яку ви будете використовувати для передачі суб'єкта. Наприклад, якщо ви будете передавати заголовок username як 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"
}'

А потім, щоб увімкнути ту саму конфігурацію на деякому маршруті, надішліть запит за допомогою Admin API:

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/*"
}'

Це додасть конфігурацію метаданих плагіна до маршруту. Ви також можете легко оновити конфігурацію метаданих плагіна, повторно надіславши запит до метаданих плагіна з оновленою моделлю та конфігурацією політики, плагін автоматично оновить усі маршрути, які використовують метадані плагіна.

Сценарії використання

  • Основний сценарій використання цього плагіна - це реалізація авторизації у ваших API. Ви можете легко додати цей плагін на будь-який маршрут API, який ви використовуєте з вашою моделлю авторизації та конфігурацією політики.
  • Якщо ви хочете мати одну модель авторизації для всіх ваших API, ви можете використовувати метод глобальної моделі/політики. Це полегшує оновлення політики для всіх маршрутів, оскільки вам потрібно лише оновити метадані в etcd.
  • Тоді як, якщо ви хочете використовувати різну модель для кожного окремого маршруту, ви можете використовувати метод маршруту. Це корисно, коли різні маршрути API мають різні набори дозволів користувачів. Ви також можете використовувати це, коли маєте справу з більшими політиками, оскільки це прискорить авторизацію, коли вона фільтрується на кілька маршрутів.