Contoh 2: Kontrol akses multi-penyewa dan RBAC yang ditentukan pengguna dengan OPA dan Rego - AWS Bimbingan Preskriptif

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Contoh 2: Kontrol akses multi-penyewa dan RBAC yang ditentukan pengguna dengan OPA dan Rego

Contoh ini menggunakan OPA dan Rego untuk mendemonstrasikan bagaimana kontrol akses dapat diimplementasikan pada API untuk aplikasi multi-penyewa dengan peran khusus yang ditentukan oleh pengguna penyewa. Ini juga menunjukkan bagaimana akses dapat dibatasi berdasarkan penyewa. Model ini menunjukkan bagaimana OPA dapat membuat keputusan izin terperinci berdasarkan informasi yang diberikan dalam peran tingkat tinggi.

RBAC yang ditentukan pengguna dengan OPA dan Rego

Peran untuk penyewa disimpan dalam data eksternal (data RBAC) yang digunakan untuk membuat keputusan akses untuk OPA:

{ "roles": { "tenant_a": { "all_access_role": ["viewData", "updateData"] }, "tenant_b": { "update_data_role": ["updateData"], "view_data_role": ["viewData"] } } }

Peran ini, ketika didefinisikan oleh pengguna penyewa, harus disimpan dalam sumber data eksternal atau penyedia identitas (idP) yang dapat bertindak sebagai sumber kebenaran saat memetakan peran yang ditentukan penyewa ke izin dan penyewa itu sendiri. 

Contoh ini menggunakan dua kebijakan dalam OPA untuk membuat keputusan otorisasi dan untuk memeriksa bagaimana kebijakan ini menegakkan isolasi penyewa. Kebijakan ini menggunakan data RBAC yang ditentukan sebelumnya.

default allowViewData = false allowViewData = true { input.method == "GET" input.path = ["viewData", tenant_id] input.tenant_id == tenant_id role_permissions := data.roles[input.tenant_id][input.role][_] contains(role_permissions, "viewData") }

Untuk menunjukkan bagaimana aturan ini akan berfungsi, pertimbangkan kueri OPA yang memiliki masukan berikut:

{ "tenant_id": "tenant_a", "role": "all_access_role", "path": ["viewData", "tenant_a"], "method": "GET" }

Keputusan otorisasi untuk panggilan API ini dibuat sebagai berikut, dengan menggabungkan data RBAC, kebijakan OPA, dan input kueri OPA:

  1. Seorang pengguna dari Tenant A membuat panggilan API ke/viewData/tenant_a.

  2. Layanan mikro Data menerima panggilan dan menanyakan allowViewData aturan, meneruskan input yang ditunjukkan dalam contoh input kueri OPA.

  3. OPA menggunakan aturan yang ditanyakan dalam kebijakan OPA untuk mengevaluasi masukan yang diberikan. OPA juga menggunakan data dari data RBAC untuk mengevaluasi input. OPA melakukan hal berikut:

    1. Memverifikasi bahwa metode yang digunakan untuk melakukan panggilan API adalahGET.

    2. Memverifikasi bahwa jalur yang diminta adalahviewData.

    3. Memeriksa bahwa tenant_id di jalur sama dengan yang input.tenant_id terkait dengan pengguna. Ini memastikan bahwa isolasi penyewa dipertahankan. Penyewa lain, bahkan dengan peran yang identik, tidak dapat diotorisasi dalam melakukan panggilan API ini.

    4. Menarik daftar izin peran dari data eksternal peran dan menetapkannya ke variabel. role_permissions Daftar ini diambil dengan menggunakan peran yang ditentukan penyewa yang dikaitkan dengan pengguna di input.role.

    5. Memeriksa role_permissions untuk melihat apakah itu berisi izin viewData.

  4. OPA mengembalikan keputusan berikut ke layanan mikro Data:

{ "allowViewData": true }

Proses ini menunjukkan bagaimana RBAC dan kesadaran penyewa dapat berkontribusi untuk membuat keputusan otorisasi dengan OPA. Untuk mengilustrasikan poin ini lebih lanjut, pertimbangkan panggilan API /viewData/tenant_b dengan input kueri berikut:

{ "tenant_id": "tenant_b", "role": "view_data_role", "path": ["viewData", "tenant_b"], "method": "GET" }

Aturan ini akan mengembalikan output yang sama dengan input kueri OPA meskipun untuk penyewa berbeda yang memiliki peran berbeda. Ini karena panggilan ini untuk /tenant_b dan data view_data_role dalam RBAC masih memiliki viewData izin yang terkait dengannya. Untuk menerapkan jenis kontrol akses yang sama/updateData, Anda dapat menggunakan aturan OPA yang serupa:

default allowUpdateData = false allowUpdateData = true { input.method == "POST" input.path = ["updateData", tenant_id] input.tenant_id == tenant_id role_permissions := data.roles[input.tenant_id][input.role][_] contains(role_permissions, "updateData") }

Aturan ini secara fungsional sama dengan allowViewData aturan, tetapi memverifikasi jalur dan metode input yang berbeda. Aturan masih memastikan isolasi penyewa dan memeriksa apakah peran yang ditentukan penyewa memberikan izin pemanggil API. Untuk melihat bagaimana hal ini dapat diterapkan, periksa input kueri berikut untuk panggilan API ke/updateData/tenant_b:

{ "tenant_id": "tenant_b", "role": "view_data_role", "path": ["updateData", "tenant_b"], "method": "POST" }

Input kueri ini, ketika dievaluasi dengan allowUpdateData aturan, mengembalikan keputusan otorisasi berikut:

{ "allowUpdateData": false }

Panggilan ini tidak akan diizinkan. Meskipun pemanggil API dikaitkan dengan yang benar tenant_id dan memanggil API dengan menggunakan metode yang disetujui, pemanggil input.role adalah yang ditentukan oleh penyewaview_data_role. view_data_roleTidak memiliki updateData izin; oleh karena itu, panggilan ke /updateData tidak sah. Panggilan ini akan berhasil bagi tenant_b pengguna yang memilikiupdate_data_role.