Lewati ke konten utama

Otorisasi dalam APISIX menggunakan Casbin

· Satu menit baca
Rushikesh Tote

Pengantar

APISIX adalah gateway API berkinerja tinggi dan dapat diskalakan yang bersifat cloud native, berbasis Nginx dan etcd. Ini adalah proyek sumber terbuka oleh Yayasan Perangkat Lunak Apache. Selain itu, yang membuat APISIX begitu baik adalah dukungan untuk banyak plugin bawaan yang hebat yang dapat digunakan untuk mengimplementasikan fitur seperti autentikasi, pemantauan, perutean, dll. Dan fakta bahwa plugin di APISIX dimuat ulang secara dinamis (tanpa memulai ulang) membuatnya sangat dinamis.

Namun, saat menggunakan APISIX, mungkin ada skenario di mana Anda ingin menambahkan logika otorisasi yang kompleks dalam aplikasi Anda. Di sinilah authz-casbin mungkin dapat membantu Anda, authz-casbin adalah plugin APISIX yang didasarkan pada Lua Casbin yang memungkinkan otorisasi yang kuat berdasarkan berbagai model kontrol akses. Casbin adalah pustaka otorisasi yang mendukung model kontrol akses seperti ACL, RBAC, ABAC. Awalnya ditulis dalam Go, Casbin telah diadaptasi ke banyak bahasa dan Lua Casbin adalah implementasi Lua dari Casbin. Pengembangan authz-casbin dimulai ketika kami mengusulkan plugin baru untuk otorisasi di repositori APISIX (#4674) yang disetujui oleh anggota inti. Dan setelah tinjauan yang membantu yang menyebabkan beberapa perubahan dan peningkatan besar, PR (#4710) akhirnya digabungkan.

Dalam blog ini, kami akan menggunakan plugin authz-casbin untuk menunjukkan bagaimana Anda dapat mengimplementasikan model otorisasi berbasis Role Based Access Control (RBAC) di APISIX.

CATATAN: Anda perlu menggunakan plugin lain atau alur kerja kustom untuk mengautentikasi pengguna karena Casbin hanya akan melakukan otorisasi, bukan autentikasi.

Membuat model

Plugin ini menggunakan tiga parameter untuk mengotorisasi setiap permintaan - subjek, objek, dan aksi. Di sini, subjek adalah nilai dari header nama pengguna, yang bisa berupa sesuatu seperti [username: alice]. Kemudian, objeknya adalah jalur URL yang diakses dan tindakannya adalah metode permintaan yang digunakan.

Misalkan kita ingin membuat model dengan tiga sumber daya pada jalur - /`\`, /res1\ dan `/res2`. Dan kita ingin memiliki model seperti ini:

gambar

Ini berarti semua pengguna (*`\`) misalnya jack\ dapat mengakses halaman utama (/`\`). Dan pengguna dengan izin admin\ seperti alice`\` dan bob\ dapat mengakses semua halaman dan sumber daya (seperti res1`\` dan res2\). Juga, mari kita batasi pengguna tanpa izin admin hanya menggunakan metode permintaan `GET`. Untuk skenario ini, kita bisa mendefinisikan model sebagai:

[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)

Membuat kebijakan

Dari skenario di atas, kebijakan tersebut akan menjadi:

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

Pencocok dari model berarti:

  1. (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)): Baik subjek permintaan memiliki peran sebagai subjek kebijakan atau subjek permintaan cocok dengan subjek kebijakan dalam keyMatch. keyMatch adalah fungsi bawaan dalam Lua Casbin, Anda dapat melihat deskripsi fungsi dan lebih banyak fungsi serupa yang mungkin berguna di sini.
  2. keyMatch(r.obj, p.obj): Objek permintaan cocok dengan objek kebijakan (jalur URL di sini).
  3. keyMatch(r.act, p.act): Tindakan permintaan cocok dengan tindakan kebijakan (metode permintaan HTTP di sini).

Mengaktifkan plugin pada rute

Setelah Anda membuat model dan kebijakan, Anda dapat mengaktifkannya pada rute menggunakan APISIX Admin API. Untuk mengaktifkannya menggunakan jalur file model dan kebijakan:

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

Di sini, bidang username adalah nama header yang akan Anda gunakan untuk meneruskan subjek. Misalnya, jika Anda akan meneruskan header username sebagai user: alice, Anda akan menggunakan "username": "user".

Untuk menggunakan teks model/kebijakan alih-alih file, Anda dapat menggunakan bidang model dan policy sebagai gantinya:

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

Mengaktifkan plugin menggunakan model/kebijakan global

Mungkin ada situasi di mana Anda ingin menggunakan konfigurasi model dan kebijakan tunggal di beberapa rute. Anda dapat melakukannya dengan terlebih dahulu mengirim permintaan PUT untuk menambahkan konfigurasi model dan kebijakan ke metadata plugin dengan:

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

Kemudian untuk mengaktifkan konfigurasi yang sama pada beberapa rute, kirim permintaan menggunakan 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/*"
}'

Ini akan menambahkan konfigurasi metadata plugin ke rute tersebut. Anda juga dapat dengan mudah memperbarui konfigurasi metadata plugin dengan mengirim ulang permintaan ke metadata plugin dengan konfigurasi model dan kebijakan yang diperbarui, plugin akan secara otomatis memperbarui semua rute yang menggunakan metadata plugin tersebut.

Kasus Penggunaan

  • Kasus penggunaan utama dari plugin ini adalah dalam mengimplementasikan otorisasi pada API Anda. Anda dapat dengan mudah menambahkan plugin ini pada rute API apa pun yang Anda gunakan dengan konfigurasi model dan kebijakan otorisasi Anda.
  • Jika Anda ingin memiliki model otorisasi tunggal untuk semua API Anda, Anda dapat menggunakan metode model/kebijakan global. Hal ini memudahkan pembaruan kebijakan untuk semua rute, karena Anda hanya perlu memperbarui metadata di etcd.
  • Sedangkan jika Anda ingin menggunakan model yang berbeda untuk setiap rute yang berbeda, Anda dapat menggunakan metode rute. Ini berguna ketika rute API yang berbeda memiliki set izin pengguna yang berbeda. Anda juga dapat menggunakan ini ketika berhadapan dengan kebijakan yang lebih besar, karena akan mempercepat otorisasi ketika difilter ke beberapa rute.