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.
Di mana RBAC jebol pada aplikasi multi-tenant
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.
- Ledakan peran. Untuk menyatakan nuansa per-resource Anda menciptakan peran seperti project-42-editor atau region-eu-viewer, dan tabel peran tumbuh lebih cepat daripada fiturnya sampai tak ada yang bisa mengaudit siapa punya apa.
- Resource bersarang dan hierarkis. User yang bisa mengedit sebuah folder biasanya seharusnya bisa mengedit dokumen di dalamnya, tetapi peran datar tak punya konsep induk, sehingga pewarisan harus dihitung ulang di kode aplikasi pada setiap request.
- Sharing lintas-tenant. Begitu satu tenant berbagi record dengan tamu dari tenant lain, asumsi rapi satu-peran-per-tenant runtuh dan Anda akhirnya menempelkan pengecualian pada pengecekan peran.
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: modelkan akses sebagai relasi
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
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.
Relationship tuple dan Check API
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 per tenant versus satu store bersama
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 ReBAC versus Cerbos ABAC berbasis policy
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.
Dari mana memulai
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.

