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

· 5 хв читання

2024 was the year AI agents went from demos to production. With the Model Context Protocol (MCP) gaining adoption from Google, OpenAI, Microsoft, and countless others, we're seeing a fundamental shift in how applications interact with external services. And with that shift comes a whole new set of authorization challenges that we at Casbin have been thinking about.

· 7 хв читання

In this post, I will explain the design and implementation of RBAC using the Casbin library. For a SaaS platform dealing with multiple resource hierarchies and roles that inherit permissions from higher levels, Casbin provides a performant alternative to consider.

Introduction to RBAC

RBAC is a method of restricting access to resources based on the roles that individuals hold. To better understand how hierarchical RBAC works, let's take a look at Azure's RBAC system in the next section and then attempt to implement a similar system.

Understanding Azure's Hierarchical RBAC

Azure Hierarchy

There is a role called Owner for all resources in Azure. Suppose if I have the Owner role assigned to me at the subscription level, that means I am the Owner of all the resource groups and resources under that subscription. If I have Owner at the resource group level, then I am the Owner of all the resources under that resource group.

This image shows that I have Owner access at the subscription level. Subscription Owner

When I check the IAM of a Resource Group under this Subscription, you can see that I have inherited Owner access from the subscription. RG Owner

So, this is how Azure's RBAC is hierarchical. Most enterprise software uses hierarchical RBAC because of the hierarchical nature of the resource levels. In this tutorial, we'll try to implement a similar system using Casbin.

How Does Casbin Work?

Before diving into the implementation, it is important to understand what Casbin is and how it functions at a high level. This understanding is necessary because each Role-Based Access Control (RBAC) system may vary based on specific requirements. By grasping the workings of Casbin, we can effectively fine-tune the model.

What is ACL?

ACL stands for Access Control List. It is a method in which users are mapped to actions and actions to resources.

The model definition

Let's consider a simple example of an ACL model.

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

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

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  1. The request_definition is the query template of the system. For example, a request alice, write, data1 can be interpreted as "Can subject Alice perform the action 'write' on object 'data1'?".

  2. The policy_definition is the assignment template of the system. For example, by creating a policy alice, write, data1, you are assigning permission to subject Alice to perform the action 'write' on object 'data1'.

  3. The policy_effect defines the effect of the policy.

  4. In the matchers section, the request is matched with the policy using the conditions r.sub == p.sub && r.obj == p.obj && r.act == p.act.

Now let's test the model on the Casbin editor

Open the editor and paste the above model in the Model editor.

Paste the following in the Policy editor:

p, alice, read, data1
p, bob, write, data2

and the following in the Request editor:

alice, read, data1

The result will be:

true

Visual representation of the ACL model, policy, and request matching

acl

What is RBAC?

RBAC stands for Role-Based Access Control. In RBAC, a user is assigned a role for a resource, and a role can contain arbitrary actions. The request then checks if the user has the permission to perform the action on the resource.

The model definition

Let's consider a simple example RBAC model:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

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

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj
  1. The role_definition is a graph relation builder that uses a Graph to compare the request object with the policy object.

Now let's test the model on Casbin editor

Open the editor and paste the above model in the Model editor.

Paste the following in the Policy editor:

p, alice, reader, data1
p, bob, owner, data2

g, reader, read
g, owner, read
g, owner, write

and the following in the Request editor:

alice, read, data1
alice, write, data1
bob, write, data2
bob, read, data2
bob, write, data1

The result will be:

true
false
true
true
false

Visual representation of the RBAC model, policy, and request matching

rbac

The g - Role to action mapping table has a Graph mapping the role to action. This Graph can be coded as a list of edges, as shown in the policy which is a common way of representing a Graph:

g, reader, read
g, owner, read
g, owner, write
інформація

p indicates a normal policy that can be compared using the == operator. g is a Graph-based comparison function. You can define multiple Graph comparators by adding a numerical suffix like g, g2, g3, ... and so on.

What is Hierarchical RBAC?

In Hierarchical RBAC, there are more than one type of resources and there is an inheritance relationship between the resource types. For example, "subscription" is one type and "resourceGroup" is another type. A sub1 of type Subscription can contain multiple resourceGroups (rg1, rg2) of type ResourceGroup.

Similar to the resource hierarchy, there will be two types of roles and actions: Subscription roles and actions, and ResourceGroup roles and actions. There is an arbitrary relationship between the Subscription role and ResourceGroup role. For example, consider a Subscription Role sub-owner. This role is inherited by a ResourceGroup Role rg-owner, which means that if I am assigned the sub-owner role on Subscription sub1, then I automatically also get the rg-owner role on rg1 and rg2.

The model definition

Let's take a simple example of the Hierarchical RBAC model:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

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

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && g2(p.obj, r.obj)
  1. The role_definition is a graph relation builder which uses a Graph to compare the request object with the policy object.

Now let's test the model on the Casbin editor

Open the editor and paste the above model in the Model editor.

Paste the following in the Policy editor:

p, alice, sub-reader, sub1
p, bob, rg-owner, rg2

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

And paste the following in the Request editor:

alice, rg-read, rg1

The result will be:

true

Visual representation of the RBAC model, policy, and request matching

hrbac

The g - Role to (Action, Role) Mapping table has a graph mapping the role to the action, role mapping. This graph can be coded as a list of edges, as shown in the policy, which is a common way of representing a graph:

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

The g2 - Sub to RG Mapping table has a graph mapping subscription to resourceGroup:

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

Subject Matching Visual representation

hrbac-sub-match

Action Matching Visual representation

hrbac-act-match

Object Matching Visual representation

hrbac-obj-match

інформація

When a request is submitted to Casbin, this matching happens for all the policies. If at least one policy matches, then the result of the request is true. If no policy matches the request, then the result is false.

Conclusion

In this tutorial, we learned about how different authorization models work and how they can be modeled using Casbin. In the second part of this tutorial, we will implement this in a demo Spring Boot Application and secure the APIs using 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 мають різні набори дозволів користувачів. Ви також можете використовувати це, коли маєте справу з більшими політиками, оскільки це прискорить авторизацію, коли вона фільтрується на кілька маршрутів.

· Читання за одну хвилину
Casbin

Сьогодні ми раді оголосити, що засновник Casbin, Ян Луо отримав нагороду "Переможці Google Open Source Peer Bonus" за свою роботу над Casbin, Npcap та Nmap у 2019 Q3.

ospb

Оригінальний лист з нагородою можна переглянути тут.

Програма Google Open Source Peer Bonus описана так:

Так само, як Google Peer Bonus використовується для визнання колеги з Google, який зробив більше ніж очікувалося, Open Source Peer Bonus визнає зовнішніх людей, які зробили винятковий внесок у відкрите програмне забезпечення.

Оголошення переможців за 2019 рік доступне за посиланням: announcement for the 2019 winners

https://opensource.googleblog.com/2020/01/announcing-2019-second-cycle-google.html

Ян та Casbin згадані серед розробників відкритого коду та проектів, які мають значний вплив, таких як Git, TensorFlow, V8, CPython, LLVM, проекти Apache, Angular або Jenkins.

Ми раді бачити, що Casbin визнаний таким чином за його внесок у відкрите програмне забезпечення та безпеку хмарних обчислень!

Дякуємо, що літаєте з Casbin!

· Читання за одну хвилину
Yang Luo

Сьогодні ми перенесли документацію Casbin з GitHub Wiki на Docs цього веб-сайту, який працює на Docusaurus. Docusaurus надає багато чудових функцій, таких як кращі стилі Markdown, повнотекстовий пошук, версіонування, переклад.

Документація ще не ідеальна і потребує допрацювання. Вихідний код розміщено на GitHub: https://github.com/casbin/casbin-website-v2 .

Будь-який внесок або пропозиція вітається!

· Читання за одну хвилину
Zixuan Liu

Сьогодні ми успішно портували Casbin на Node.js, який називається: node-Casbin.

node-Casbin має схожий спосіб використання та API з іншими реалізаціями Casbin. Проміжне програмне забезпечення для Express, Koa2 та Egg.js готове до використання. Також підготовлено адаптер зберігання для Sequelize.

Сподіваємося, що воно добре задовольнить ваші потреби :)

GitHub: https://github.com/casbin/node-casbin

· Читання за одну хвилину
Helong Zhang

Деякі наші клієнти запитують, чи можна використовувати Casbin як сервіс замість бібліотеки. Відповідь - ТАК. Сьогодні ми запустили проект Casbin Server як конкретне рішення для Контролю Доступу як Сервісу.

Casbin Server активно розробляється нашою основною командою. Він має кілька особливостей:

  • Розроблений виключно на Golang.
  • Може управляти тисячами інстанцій Casbin, тому ви можете перенести логіку контролю політик з кількох сервісів в один Casbin Server.
  • gRPC використовується для зв'язку з Casbin Server. Ми також розглядаємо можливість додати підтримку RESTful у найближчому майбутньому.
  • Дружній веб-портал адміністратора надається для адміністраторів, які не є розробниками, для управління всіма деталями, такими як інстанції Casbin, моделі, зберігання політик та балансування навантаження.

Вихідний код розміщено на GitHub: https://github.com/casbin/casbin-server

Будь-які проблеми чи запити на злиття вітаються :)