OpenFGA ReBAC: Otorisasi Multi-Tenant Fine-Grained

Foto oleh Alina Grubnyak on Unsplash
OpenFGA adalah engine otorisasi open-source dari Cloud Native Computing Foundation untuk relationship-based access control (ReBAC). Ia terinspirasi sistem otorisasi Zanzibar milik Google, dan sintaks model JSON-nya mengikuti dekat paper Zanzibar asli. Anda menyimpan relasi sebagai tuple dan mengkuerinya lewat Check API.
RBAC memberi izin lewat peran statis seperti editor atau admin, yang jebol saat ada hierarki, sharing, dan multi-tenancy. ReBAC membuat akses bergantung pada relasi antara user dan objek, serta antar objek. OpenFGA menyebut ReBAC sebagai superset RBAC yang juga mencakup skenario berbasis atribut ketika atribut dinyatakan sebagai relasi.
Relationship tuple adalah unit data otorisasi: seorang user, sebuah relation, dan sebuah object, dengan condition opsional yang ditulis dalam bahasa CEL milik Google. Contohnya, user:anne adalah editor dari document:q3-roadmap. User bisa berupa subjek tertentu, objek lain, sebuah userset seperti member grup, atau wildcard publik.
Store mengorganisasi data otorisasi dan datanya tidak bisa dibagikan antar store. Kebanyakan aplikasi multi-tenant memakai satu store bersama dengan type tenant atau organization di model, sehingga sharing lintas-tenant tetap mungkin. Gunakan store per tenant hanya saat butuh isolasi data ketat, residensi per-tenant, atau penskalaan terpisah.
Pilih OpenFGA saat akses didominasi relasi yang harus ditelusuri, seperti folder, tim, dan dokumen yang dibagikan. Pilih Cerbos, sebuah policy decision point stateless yang mengevaluasi policy YAML atas atribut, saat keputusan bergantung pada atribut saat request seperti waktu, status resource, atau IP. Cerbos tidak menyimpan data relasi itu sendiri.

Foto oleh Alina Grubnyak on Unsplash
Ringkasan Utama
OpenFGA adalah engine open-source untuk relationship-based access control yang terinspirasi Google Zanzibar. Alih-alih memberi peran statis, Anda menyimpan relationship tuple seperti anne adalah editor dokumen q3-roadmap, mendefinisikan authorization model berisi type dan relation, lalu bertanya ke Check API apakah user punya relation pada satu objek tertentu.
Setiap produk multi-tenant yang pernah saya kerjakan dimulai dengan role-based access control karena sederhana: beri user peran editor, maka editor bisa mengedit. Model itu bertahan sampai seorang pelanggan minta berbagi satu dokumen dengan kolaborator luar, atau menyusun proyek di dalam folder di dalam workspace, atau memberi akses baca ke semua milik bawahan seorang manajer. Tiba-tiba satu peran datar per user tak bisa menyatakan siapa boleh menyentuh apa.
Pola yang menjawab pertanyaan itu adalah relationship-based access control, atau ReBAC, dan alat yang saya andalkan adalah OpenFGA, proyek Cloud Native Computing Foundation yang terinspirasi sistem otorisasi Zanzibar milik Google. Tulisan ini membahas di mana RBAC jebol, bagaimana ReBAC membingkai ulang masalah sebagai relasi, dan bagaimana OpenFGA mewujudkannya lewat authorization model, relationship tuple, dan Check API.
RBAC memberikan izin ke user berdasarkan peran seperti editor atau admin. Dokumentasi OpenFGA sendiri tegas soal batasnya: RBAC cocok untuk model akses datar dan single-tenant tetapi jebol saat ada hierarki, sharing, atau multi-tenancy. Tiga mode kegagalan muncul berulang begitu sebuah produk nyata membesar.
Masing-masing sebenarnya adalah pertanyaan tentang relasi antara user dan objek tertentu, atau antara dua objek. RBAC tak punya kosakata untuk relasi, jadi setiap relasi diratakan menjadi peran lain. Itulah jebakannya.
ReBAC membuat aturan akses bergantung pada relasi antara user dan objek, serta antar objek itu sendiri. Fine-grained authorization lalu berarti memutuskan akses di level tiap resource dan aksi: Alice bisa mengedit document-42, bukan sekadar Alice adalah editor. Pergeseran tunggal itulah yang membuat Anda bisa menjawab pertanyaan sharing, nesting, dan per-resource tanpa menciptakan peran baru.
OpenFGA menyebut ReBAC sebagai superset dari RBAC yang juga secara native mencakup skenario berbasis atribut ketika atribut dinyatakan sebagai relasi. Dalam praktik Anda jarang membuang peran; Anda menyatakan sebuah peran sebagai salah satu jenis relasi di antara banyak relasi, jadi relation admin dan relation shared-with hidup dalam model yang sama dan dievaluasi dengan cara yang sama.
Uji mental yang berguna: jika sebuah pertanyaan izin mengandung kata tertentu atau dibagikan dengan atau di dalam, itu pertanyaan relasi, bukan pertanyaan peran. Justru kasus-kasus itulah tempat ReBAC membayar dirinya sendiri dan tempat tabel peran biasanya membengkak.
Authorization model OpenFGA menggabungkan satu atau lebih type definition untuk mendeskripsikan model izin sebuah sistem. Anda bisa menulisnya sebagai JSON yang mengikuti dekat sintaks paper Zanzibar asli, atau dalam DSL yang lebih ramah. Berikut sebuah model kecil dalam DSL untuk penyimpanan dokumen dengan organisasi, folder, dan izin yang diwariskan.
model
schema 1.1
type user
type organization
relations
define member: [user]
type folder
relations
define owner: [user, organization#member]
define viewer: [user, organization#member]
type document
relations
define parent: [folder]
define owner: [user, organization#member]
define editor: [user, organization#member]
define viewer: [user, organization#member]
define can_view: viewer or editor or owner or viewer from parent
define can_edit: editor or owner
define can_share: owner or owner from parentBaca define can_view sebagai viewer or editor or owner or viewer from parent. Klausa viewer from parent adalah pewarisan yang tak bisa dinyatakan peran datar: siapa pun yang menjadi viewer folder induk dokumen otomatis bisa can_view dokumen itu, tanpa tuple tambahan per dokumen. Notasi organization#member memungkinkan sebuah relation diberikan ke setiap member organisasi sekaligus.
Model adalah skemanya; relationship tuple adalah datanya. Sebuah tuple berisi seorang user, sebuah relation, dan sebuah object, dengan condition opsional yang dinyatakan dalam bahasa CEL milik Google. User bisa berupa subjek tertentu, objek lain, sebuah userset seperti member sebuah grup, atau wildcard publik. Anda bertanya lewat Check API, yang menjawab apakah seorang user punya relation tertentu pada objek tertentu.
# 1. A relationship tuple: user -> relation -> object
{
"user": "user:anne",
"relation": "editor",
"object": "document:q3-roadmap"
}
# 2. A tuple linking a document to its parent folder
{
"user": "folder:planning",
"relation": "parent",
"object": "document:q3-roadmap"
}
# 3. A Check request: does anne have can_view on the doc?
POST /stores/{store_id}/check
{
"tuple_key": {
"user": "user:anne",
"relation": "can_view",
"object": "document:q3-roadmap"
}
}
# Response
{ "allowed": true }Check mengembalikan allowed true atau false biasa, dan ia mengevaluasi pewarisan untuk Anda: karena sebuah tuple parent menautkan dokumen ke folder planning, seorang viewer folder itu lolos pengecekan can_view tanpa tuple di level dokumen. Ketika Anda butuh pertanyaan sebaliknya, OpenFGA menyediakan ListObjects untuk menemukan setiap objek yang bisa diakses user, ListUsers, Expand, Read, dan BatchCheck.
Check menjawab apakah user X punya relation Y pada objek Z, dan sengaja tidak dibangun untuk menjawab siapa punya akses ke Z atau apa saja yang bisa diakses X. Memanggil Check dalam loop untuk menyusun daftar adalah kesalahan performa klasik; gunakan ListObjects atau ListUsers untuk itu, dan BatchCheck saat harus mengevaluasi banyak pasangan sekaligus.
Store adalah entitas OpenFGA yang mengorganisasi data otorisasi, memuat versi model dan tuple Anda. Aturan yang membentuk desain multi-tenant adalah data store tidak bisa dibagikan antar store, jadi data otorisasi yang saling terkait harus tinggal bersama dalam satu store. Fakta tunggal itu membingkai seluruh trade-off-nya.
Untuk kebanyakan SaaS multi-tenant, desain yang lebih sederhana dan lebih umum adalah satu store bersama dengan type tenant atau organization di dalam model, membatasi setiap objek ke tenant-nya. Ini menjaga sharing lintas-tenant tetap mungkin dan operasional tetap murah. Store per tenant adalah opsi lebih berat yang Anda pilih hanya saat butuh isolasi data ketat, retensi atau residensi per-tenant, atau penskalaan terpisah, dengan konsekuensi Anda tak bisa lagi menjawab satu Check lintas dua tenant.
OpenFGA bukan satu-satunya cara melakukan fine-grained authorization. Cerbos menempuh jalur berbasis policy dan berbasis atribut: sebuah policy decision point stateless yang mengevaluasi policy YAML yang memadukan peran dengan logika atribut bersyarat. Perbedaan arsitektur kuncinya adalah di mana datanya tinggal. OpenFGA menyimpan graph relasi Anda lalu menelusurinya; Cerbos tidak menyimpan data relasi itu sendiri dan malah mengevaluasi terhadap atribut yang Anda pasok saat request dari identity provider dan basis data Anda sendiri.
| Dimensi | OpenFGA (ReBAC) | Cerbos (ABAC berbasis policy) |
|---|---|---|
| Model inti | Graph relasi berisi tuple | Policy YAML atas atribut |
| Menyimpan data | Ya, tuple plus modelnya | Tidak, PDP stateless by design |
| Kekuatan alami | Nesting, sharing, pewarisan grup | Aturan kontekstual atas atribut request |
| Menjawab query siapa atau apa | Ya, lewat ListObjects dan ListUsers | Tidak, ia mengembalikan keputusan per-request |
| Silsilah | Terinspirasi Google Zanzibar | Decision point policy-as-code |
Tak ada yang mutlak lebih baik. Pilih OpenFGA saat akses didominasi relasi yang harus ditelusuri, seperti folder, tim, dan dokumen yang dibagikan. Pilih engine policy seperti Cerbos saat keputusan bergantung pada atribut saat request seperti waktu, status resource, atau IP, yang canggung dikodekan sebagai relasi tersimpan. Sistem nyata terkadang menjalankan keduanya.
Jika Anda kena ledakan peran, mulailah dengan menuliskan tiga atau empat pertanyaan yang terus gagal dijawab pengecekan peran Anda, lalu modelkan tepat itu sebagai relation dalam satu store OpenFGA. Buktikan satu izin warisan dari ujung ke ujung dengan sebuah Check, dan Anda akan punya skema yang tumbuh bersama sharing dan nesting alih-alih melawannya.