IlmHamroh
JavaScript Full-stack/28-qism. Autentifikatsiya va backend xavfsizligi21/31-dars18 daqiqa
Mundarija (29)

ABAC, ReBAC va policy engine'lar: atribut, munosabat va CASL

Qisqacha: RBAC "rol nima qila oladi" degan savolga javob beradi. Lekin "faqat ish vaqtida", "bajarilgan vazifani hech kim o'zgartirmaydi", "menga ulashilgan vazifani o'qiyman" kabi qoidalar rolga sig'maydi. ABAC qarorni atributlar (foydalanuvchi, resurs, muhit) bo'yicha, ReBAC esa munosabatlar ("azo", "ulashilgan", "ota papka") bo'yicha qiladi. Qoidalar ko'paysa, ularni bitta joyga — siyosat (policy) qatlamiga yig'ishadi. Kanon bir xil to'rtta qoidani oddiy funksiya va CASL bilan yozdi: natijalar 9 holatda bir xil, lekin funksiya tezroq va CASL qobiliyatini har so'rovda qurish qimmat.

Bu darsda

  • RBAC qayerda yetmasligini va "rollar portlashi" ni tushuntira olasiz.
  • ABAC qoidasini (foydalanuvchi, resurs, muhit atributlari) funksiya sifatida yozasiz.
  • ReBAC va Zanzibar g'oyasini munosabatlar ro'yxati bilan ko'rsatasiz.
  • CASL kabi policy engine nima berishini va nima turishini (tezlik, murakkablik) baholaysiz.
  • Bu tajriba nega vazifalar-api ga kirmaganini tushunasiz.

Oldin bilishingiz kerak: RBAC va resurs egaligi, Row Level Security, Intl.DateTimeFormat.

Oldingi darsda ikkita rol va "o'z vazifasi" qoidasi bilan vazifalar-api ni himoyaladik. Bir kishilik vazifalar ro'yxati uchun bu yetarli. Endi tasavvur qiling: «Bahor» oshxonasida Jasur aka vazifalarni oshpazlar bilan ulashmoqchi, admin Bekzod esa tunda hisoblarni bloklay olmasin. Rollar bilan bu qoidalarni qanday yozasiz?

1. Nega bu kerak?

1.1 Rollar portlashi

Yangi qoidalarni rol bilan yozib ko'ramiz:

  • "admin hisoblarni bloklay oladi, lekin faqat 09:00–18:00" → admin_kunduzgi roli?
  • "Dilnoza Azizning 10-vazifasini o'qiy oladi" → vazifa10_oquvchi roli?
  • "bajarilgan vazifani hech kim tahrirlamaydi" → bu umuman rol emas, vazifaning holati.

Har yangi shart rollar sonini ko'paytiradi. Bu hodisa rollar portlashi (role explosion) deyiladi. Tez orada sizda 200 ta rol bo'ladi va hech kim kimda nima borligini bilmaydi.

Muammo shundaki, bu qoidalar kimga emas, vaziyatga bog'liq: soatga, vazifa holatiga, ikki odam orasidagi munosabatga. Ular uchun boshqa modellar bor.

1.2 Uch model

Model Qaror nimaga qarab Misol
RBAC foydalanuvchi roli "admin bloklaydi"
ABAC atributlar "admin, 09–18 da, adminni emas"
ReBAC munosabatlar "ulashilgan vazifani o'qiydi"

Ular bir-birini inkor qilmaydi. Amalda RBAC asos bo'ladi, ABAC va ReBAC esa uning ustiga qo'shiladi.

2. ABAC: atributlarga asoslangan ruxsat

2.1 To'rt xil atribut

ABAC (Attribute-Based Access Control) qarorni to'rt manbadagi atributlardan chiqaradi:

  • subyekt (subject) — kim: id, rol, bo'lim, malaka;
  • resurs (resource) — nima: egasi, holati (bajarildi), maxfiylik darajasi;
  • amal (action) — nima qilmoqchi: oqish, yangilash, bloklash;
  • muhit (environment) — qachon va qayerdan: soat, IP, qurilma.

Qoida — shu atributlar ustidagi mantiqiy ifoda. Oldingi darsdagi egalik ham aslida ABAC: resurs.egasiId === subyekt.id.

2.2 To'rt qoida bitta funksiyada

Kanon tajribasi uchun to'rtta qoida tanlandi — ular kelajakdagi jamoaviy loyihaga ko'prik:

  1. Egasi o'z vazifasini o'qiydi va yangilaydi (RBAC + egalik).
  2. Vazifa ulashilgan foydalanuvchi uni faqat o'qiydi (ReBAC — munosabat).
  3. Admin hisoblarni bloklay oladi, lekin faqat ish vaqtida, 09:00–18:00 Toshkent vaqti bilan, va adminni emas (ABAC — muhit atributi).
  4. Bajarilgan vazifani hech kim yangilamaydi (ABAC — resurs atributi).

Kanon tajribasidagi funksiya (telefon uchun bo'lingan) va o'sha 9 ta holat:

js
const toshkentSoati = (d) => Number(new Intl.DateTimeFormat("en-GB", {
  timeZone: "Asia/Tashkent", hour: "2-digit", hour12: false,
}).format(d));

function mumkinmi(f, amal, resurs, muhit) {
  if (resurs.tur === "Vazifa") {
    const v = resurs.v;
    if (amal === "yangilash" && v.bajarildi) return false;
    if (v.egasiId === f.id) return true;
    return amal === "oqish" && v.ulashilgan.includes(f.id);
  }
  if (resurs.tur === "Hisob" && amal === "bloklash") {
    const s = toshkentSoati(muhit.vaqt);
    return f.rol === "admin" && s >= 9 && s < 18 &&
      resurs.h.rol !== "admin";
  }
  return false;
}

const aziz = { id: 1, rol: "foydalanuvchi" };
const dilnoza = { id: 2, rol: "foydalanuvchi" };
const bekzod = { id: 3, rol: "admin" };
const v1 = { id: 10, egasiId: 1, bajarildi: false, ulashilgan: [2] };
const v2 = { id: 11, egasiId: 1, bajarildi: true, ulashilgan: [] };
const kun = { vaqt: new Date("2026-10-28T06:00:00Z") }; // 11:00
const tun = { vaqt: new Date("2026-10-28T20:00:00Z") }; // 01:00
const V = (v) => ({ tur: "Vazifa", v });
const H = (id, rol) => ({ tur: "Hisob", h: { id, rol } });

const HOLATLAR = [
  ["Aziz o'z vazifasini yangilaydi", aziz, "yangilash", V(v1), kun],
  ["Aziz bajarilganni yangilaydi", aziz, "yangilash", V(v2), kun],
  ["Dilnoza ulashilganni o'qiydi", dilnoza, "oqish", V(v1), kun],
  ["Dilnoza ulashilganni yangilaydi", dilnoza, "yangilash", V(v1),
    kun],
  ["Dilnoza ulashilmaganni o'qiydi", dilnoza, "oqish", V(v2), kun],
  ["Bekzod Azizni bloklaydi, 11:00", bekzod, "bloklash",
    H(1, "foydalanuvchi"), kun],
  ["Bekzod Azizni bloklaydi, 01:00", bekzod, "bloklash",
    H(1, "foydalanuvchi"), tun],
  ["Bekzod adminni bloklaydi", bekzod, "bloklash", H(4, "admin"),
    kun],
  ["Aziz bloklaydi", aziz, "bloklash", H(2, "foydalanuvchi"), kun],
];
for (const [nom, f, amal, r, m] of HOLATLAR) {
  console.log(nom.padEnd(34), mumkinmi(f, amal, r, m));
}

Konsolda:

text
Aziz o'z vazifasini yangilaydi     true
Aziz bajarilganni yangilaydi       false
Dilnoza ulashilganni o'qiydi       true
Dilnoza ulashilganni yangilaydi    false
Dilnoza ulashilmaganni o'qiydi     false
Bekzod Azizni bloklaydi, 11:00     true
Bekzod Azizni bloklaydi, 01:00     false
Bekzod adminni bloklaydi           false
Aziz bloklaydi                     false

Uchta narsaga e'tibor bering:

  • Sukut — rad. Funksiya oxirida return false. Qoidada ko'rsatilmagan har narsa taqiqlangan ("deny by default"). Teskarisi — "hamma narsa mumkin, faqat ... dan tashqari" — xavfli: yangi amal qo'shilsa, u avtomatik ochiq bo'ladi.
  • Taqiq birinchi. "Bajarilgan vazifa" sharti egalikdan oldin tekshiriladi. Aks holda egasi uchun true qaytib, taqiq ishlamay qolardi.
  • Vaqt server soatidan. muhit.vaqt — serverning new Date(). Uni mijozdan (sarlavha, so'rov tanasi) olsangiz, hujumchi o'z soatini "11:00" deb yuboradi.

Toshkent soati Intl.DateTimeFormat bilan olinadi (Intl.DateTimeFormat), serverning o'z vaqt mintaqasiga bog'liq emas. 06:00Z — Toshkentda 11:00, 20:00Z — ertasi kuni 01:00.

Tekshirib ko'ring: if (amal === "yangilash" && v.bajarildi) return false; qatorini egalik tekshiruvidan keyinga ko'chirsak, qaysi holat natijasi o'zgaradi?

Javob

"Aziz bajarilganni yangilaydi" — true bo'lib qoladi: Aziz egasi, funksiya taqiqqa yetmasdan qaytadi. Siyosatda taqiqlar ("hech kim") ruxsatlardan oldin turishi kerak — yoki, CASL kabi kutubxonalardagidek, cannot qoidasi can dan ustun bo'lishi kerak.

3. ReBAC: munosabatlar

3.1 Zanzibar g'oyasi

"Dilnoza ulashilgan vazifani o'qiydi" — bu Dilnozaning xususiyati ham emas, vazifaning xususiyati ham emas. Bu ikkalasi orasidagi munosabat. Google Drive'ni eslang: papka jamoaga ulashilgan, jamoada siz borsiz, papka ichidagi hujjat — demak siz uni ko'rasiz. Bu zanjir.

ReBAC (Relationship-Based Access Control) ruxsatni munosabatlar grafi orqali beradi. Eng mashhur tizim — Google'ning Zanzibari (2019-yilda USENIX ATC konferensiyasida maqola bo'lib chiqqan). Google Drive, YouTube, Calendar kabi xizmatlar ruxsatlarini shu tizim saqlaydi. G'oyasi: hamma ruxsat ko'rinishdagi munosabat yozuvlari (relation tuple):

text
obyekt#munosabat@subyekt
vazifa:10#oquvchi@foydalanuvchi:dilnoza

Subyekt boshqa guruh ham bo'la oladi (jamoa:bahor#azo — "bahor jamoasining hamma a'zosi"). Tekshiruv — grafda yo'l bormi degan savol.

3.2 O'zimizning kichik ReBAC

js
const MUNOSABATLAR = [
  "jamoa:bahor#azo@foydalanuvchi:aziz",
  "jamoa:bahor#azo@foydalanuvchi:dilnoza",
  "loyiha:menyu#oquvchi@jamoa:bahor#azo",
  "loyiha:menyu#muharrir@foydalanuvchi:aziz",
  "vazifa:10#ota@loyiha:menyu",
];

function bormi(obyekt, munosabat, subyekt, chuqurlik = 0) {
  if (chuqurlik > 5) return false;
  for (const qator of MUNOSABATLAR) {
    const [chap, kim] = qator.split("@");
    const [obj, rel] = chap.split("#");
    if (obj !== obyekt) continue;
    if (rel === munosabat && kim === subyekt) return true;
    if (rel === munosabat && kim.includes("#")) {
      const [guruh, gRel] = kim.split("#");
      if (bormi(guruh, gRel, subyekt, chuqurlik + 1)) return true;
    }
    if (rel === "ota") {
      if (bormi(kim, munosabat, subyekt, chuqurlik + 1)) return true;
    }
  }
  return false;
}

const oqiydimi = (v, kim) =>
  bormi(v, "oquvchi", kim) || bormi(v, "muharrir", kim);

for (const kim of ["aziz", "dilnoza", "sardor"]) {
  const s = `foydalanuvchi:${kim}`;
  console.log(kim, oqiydimi("vazifa:10", s),
    bormi("vazifa:10", "muharrir", s));
}

Konsolda:

text
aziz true true
dilnoza true false
sardor false false

Shu besh yozuv graf sifatida:

flowchart LR
  V["vazifa:10"] -->|ota| L["loyiha:menyu"]
  L -->|oquvchi| J["jamoa:bahor (azo)"]
  L -->|muharrir| A["foydalanuvchi:aziz"]
  J -->|azo| A
  J -->|azo| D["foydalanuvchi:dilnoza"]

Zanjirni kuzating. 10-vazifaning o'zida hech kim yozilmagan. Lekin uning otasi — loyiha:menyu. Loyihani bahor jamoasining a'zolari o'qiydi, Dilnoza — a'zo. Demak Dilnoza vazifani o'qiydi, lekin tahrirlay olmaydi. Aziz loyihaning muharriri — tahrirlaydi. Sardor jamoada yo'q — hech narsa.

Bitta qator qo'shsangiz (jamoa:bahor#azo@foydalanuvchi:sardor), Sardor menyu loyihasidagi hamma vazifani o'qiy boshlaydi. Kodda hech narsa o'zgarmaydi — faqat ma'lumot. ReBAC'ning kuchi shunda.

chuqurlik > 5 — himoya: munosabatlarda aylana bo'lsa (A guruh B ning a'zosi, B esa A ning), rekursiya cheksiz bo'lmaydi. Haqiqiy tizimlarda bu chegara ham, kesh ham, "yangi yozuv qachon ko'rinadi" degan izchillik savoli ham bor — Zanzibar maqolasining katta qismi aynan shular haqida.

3.3 Tayyor ReBAC xizmatlari

Bunday tizimni o'zingiz to'liq yozmaysiz. Zanzibar g'oyasidagi ochiq loyihalar:

  • OpenFGA — Auth0/Okta boshlagan, CNCF loyihasi; sxema DSL'da yoziladi, alohida server sifatida ishlaydi;
  • SpiceDB (AuthZed) — Zanzibar'ning yana bir ochiq talqini;
  • Permit.io, Oso — boshqariladigan xizmat va kutubxonalar (RBAC, ABAC, ReBAC).

Bularning hech biri kursda sinalmagan — faqat hujjat bo'yicha, tanishuv uchun (2026-10-28). Ularning umumiy narxi — yana bitta xizmat: ruxsatlar endi asosiy bazangizda emas, alohida tizimda. Munosabatlarni ikki joyda sinxron tutish kerak bo'ladi.

4. Policy engine: qoidalar alohida qatlamda

4.1 PDP va PEP

Qoidalar ko'payganda ular har yo'lga sochilib ketadi. Yechim — ularni bitta joyga yig'ish. Atamalar XACML standartidan qolgan:

  • PEP (policy enforcement point) — qarorni bajaradigan joy: middleware, yo'l, ombor;
  • PDP (policy decision point) — qarorni chiqaradigan joy: siyosat funksiyasi yoki engine.
flowchart LR
  S[So'rov] --> PEP[PEP: middleware yoki yo'l]
  PEP -->|kim, amal, resurs, muhit| PDP[PDP: siyosat]
  PDP -->|ruxsat yoki rad| PEP
  PEP -->|ruxsat| H[Ishlovchi]
  PEP -->|rad| X[403 yoki 404]
  PDP -.-> Q[(Qoidalar: kod, JSON yoki DSL)]

Oldingi darsdagi rolKerak — eng sodda PEP+PDP bitta funksiyada. Policy engine — PDP'ni alohida kutubxona yoki xizmatga chiqarish.

4.2 CASL: qoidalar ma'lumot sifatida

CASL — JavaScript uchun kutubxona: qoidalar can va cannot chaqiruvlari bilan yoziladi, shartlar esa MongoDB so'rovi uslubida. Kanon xuddi shu to'rt qoidani CASL 7 da yozdi (@casl/ability 7.0.2, kanon tajriba kodi, telefon uchun bo'lingan):

js
import { AbilityBuilder, createMongoAbility, subject }
  from "@casl/ability";

function caslQobiliyat(f, muhit) {
  const { can, cannot, build } =
    new AbilityBuilder(createMongoAbility);
  can(["oqish", "yangilash"], "Vazifa", { egasiId: f.id });
  // Mongo sintaksisi: massivda bor
  can("oqish", "Vazifa", { ulashilgan: f.id });
  cannot("yangilash", "Vazifa", { bajarildi: true });
  const s = toshkentSoati(muhit.vaqt);
  if (f.rol === "admin" && s >= 9 && s < 18) {
    can("bloklash", "Hisob", { rol: { $ne: "admin" } });
  }
  return build();
}

// tekshirish: obyektga tur nomi beriladi
caslQobiliyat(dilnoza, kun).can("oqish", subject("Vazifa", v1));

Kanon 9 ta holatni ikkala usulda ishga tushirdi. Chiqishda "funksiya" va "CASL" ustunlarini qatorma-qator solishtiring:

text
holat                                           funksiya  CASL
  Aziz o'z vazifasini yangilaydi                 true      true
  Aziz bajarilgan vazifani yangilaydi            false     false
  Dilnoza ulashilganni o'qiydi                   true      true
  Dilnoza ulashilganni yangilaydi                false     false
  Dilnoza ulashilmaganni o'qiydi                 false     false
  Bekzod (admin) Azizni bloklaydi, 11:00         true      true
  Bekzod (admin) Azizni bloklaydi, 01:00         false     false
  Bekzod boshqa adminni bloklaydi                false     false
  Aziz (foydalanuvchi) bloklaydi                 false     false
farqlar: 0

Farq nol — ikkala usul ham to'g'ri. CASL'da taqiq tartibi o'zi hal bo'ladi: keyin yozilgan cannot oldingi can dan ustun.

4.3 Qoidalar JSON — frontend bilan ulashish

CASL'ning asosiy afzalligi — qoidalar ma'lumot. Dilnozaning qobiliyati JSON'ga aylanadi (kanon chiqishi):

text
CASL qoidalari JSON (frontend'ga yuborish mumkin): [{"action":["oqish","yangilash"],"subject":"Vazifa","conditions":{"egasiId":2}},{"action":"oqish","subject":"Vazifa","conditions":{"ulashilgan":2}},{"action":"yangilash","inverted":true,"subject":"Vazifa","conditions":{"bajarildi":true}}]

Server bu ro'yxatni /men javobida yuborsa, frontend xuddi shu kutubxona bilan "Tahrirlash" tugmasini ko'rsatish yoki yashirishni hal qiladi (@casl/react dagi <Can> komponenti). Qoidalar ikki joyda takrorlanmaydi. Bu imkoniyat kanonda sinalmagan — CASL hujjati bo'yicha.

Lekin oldingi darsdagi qoida o'z kuchida: frontend'dagi tekshiruv — faqat UX. Server qarorini baribir serverdagi qobiliyat chiqaradi.

inverted: true — bu cannot. Uchinchi qoida JSON'da ham taqiq bo'lib qoldi.

4.4 Narxi: o'lchov

Kanon har usulni 10 000 marta, 21 marta takrorlab o'lchadi (mediana, bitta tekshiruv uchun):

Bitta ruxsat tekshiruvi: mediana
  • oddiy funksiya18,8 ns
  • CASL, qobiliyat bir marta434,3 ns
  • CASL, har so'rovda qurish~111 µs111 210,2 ns

Manba: kanon o'lchovi (IlmHamroh, 2026-10): @casl/ability 7.0.2, Node 24.21.0, i5-12500H, Windows 11, 2026-10-28

Raqamlarni o'qiymiz:

  • Oddiy funksiya — 18.8 ns. Amalda bepul.
  • CASL, qobiliyat oldindan qurilgan — 434 ns, funksiyadan ~23 marta sekin. Lekin bu ham bitta so'rov uchun sezilmaydi: ma'lumotlar bazasiga bitta so'rov millisekundlarda o'lchanadi.
  • CASL, har so'rovda createMongoAbility qurish + tekshirish — ~111 µs. Bu bitta tekshiruvdan ~250 marta qimmat.

Ustunlar bir xil shkalada: uchinchisi qolgan ikkitasini ko'rinmas qilib qo'ydi. Xulosa: qobiliyatni har tekshiruvda qayta qurmang. Uni so'rov boshida bir marta quring va so'rov davomida ishlating. Yoki — qoidalar rolga bog'liq bo'lsa — rol bo'yicha oldindan qurib, keshlang.

4.5 Boshqa engine'lar

Engine Qoidalar qayerda Izoh
CASL JS kod / JSON kutubxona, frontend bilan ulashadi
Casbin model fayli + siyosat jadvali ko'p tilli, ACL/RBAC/ABAC
OPA (Rego) alohida til, alohida xizmat infratuzilmada ko'p (Kubernetes)
Cedar alohida til AWS ochiq manbali qilgan

Casbin, OPA va Cedar kursda sinalmagan (hujjat bo'yicha). Ularning umumiy g'oyasi bir: siyosat — koddan alohida, versiyalanadi va o'z testlari bor.

4.6 Ma'lumotlar bazasi bilan bog'lash

Siyosat bitta obyekt uchun "mumkinmi?" deb javob beradi. Lekin ro'yxat-chi? "Dilnoza o'qiy oladigan hamma vazifalar" — 10 000 ta vazifani bazadan olib, har birini filtrlash mumkin emas. Qoida SQL WHERE ga aylanishi kerak.

vazifalar-api da bu muammo yo'q: egalik — oddiy WHERE egasi_id va RLS. CASL uchun @casl/prisma paketi qoidalardan Prisma where shartini yasaydi; ReBAC xizmatlari esa "bu foydalanuvchi uchun obyektlar ro'yxati" so'rovini beradi. Ikkalasi ham kursda sinalmagan. Shuni bilib qo'ying: policy engine tanlaganda "ro'yxatni qanday filtrlaydi?" degan savol birinchi o'rinda.

4.7 Siyosatni test qilish

Siyosat — xavfsizlikning yuragi, shuning uchun u kodning eng yaxshi sinalgan qismi bo'lishi kerak. Kanon tajribasi buning yaxshi shaklini ko'rsatdi: jadvalga asoslangan test (table-driven test). Har qator — "kim, nima, qaysi resurs, qachon, kutilgan javob". Yangi qoida qo'shsangiz, jadvalga yangi qator qo'shasiz.

Uch qoida bunday testni kuchli qiladi:

  • har qoida uchun kamida bitta "ha" va bitta "yo'q" holati bo'lsin (masalan, 11:00 va 01:00);
  • chegaralar alohida: 08:59, 09:00, 17:59, 18:00 — "≥ 9" va "< 18" xatolari aynan shu yerda;
  • engine almashtirilsa (funksiyadan CASL'ga yoki aksincha), o'sha jadval ikkala usulda yurgizilib, farq nol bo'lishi kerak — kanon aynan shunday qildi.

Bunday test siyosatni o'zgartirishdan qo'rqmaslikka yordam beradi: biror qator qizarsa, qaysi qoida buzilgani darhol ko'rinadi.

5. Hujumchi nigohi

Har qatorda: hujum, himoya va siyosat jadvalidagi test qatori.

Hujum Himoya Test (jadval qatori)
soatni mijozdan yuborish vaqt — serverdan 11:00 → ha, 01:00 → yo'q
qoidada yo'q amalni chaqirish sukut — rad "Aziz bloklaydi" → yo'q
taqiqni egalik bilan aylanib o'tish taqiq oldin / cannot ustun "Aziz bajarilganni yangilaydi" → yo'q
frontend qoidalarini o'zgartirish qaror serverda, JSON — faqat UX server testi, frontend emas
rol olinganidan keyin eski qobiliyat so'rov boshida qurish, kesh kaliti — rol adminlikdan olingach — 403
ro'yxatda begona obyekt qoida WHERE ga aylanadi ro'yxatda begona yo'q

6. Ko'p uchraydigan xatolar

Xato Nega xavfli To'g'risi
har shart uchun yangi rol rollar portlashi atribut yoki munosabat
qoidalar har yo'lda sochilgan biri unutiladi bitta siyosat moduli (PDP)
"sukut — ruxsat" yangi amal ochiq "sukut — rad"
CASL qobiliyatini har tekshiruvda qurish ~111 µs so'rovda bir marta
ReBAC'da chuqurlik chegarasisiz aylana — cheksiz rekursiya chegara, kesh
kichik loyihaga policy engine ortiqcha murakkablik oddiy funksiya, testlar bilan

7. Mashqlar

Mashqlar kurs/mashqlar/28/21-abac/ da.

1-mashq (oson): qaysi model?

Har qoidani RBAC, ABAC yoki ReBAC ga ajrating:

  1. "Faqat adminlar foydalanuvchilar ro'yxatini ko'radi."
  2. "Hujjatni faqat uning bo'limidagi xodimlar o'qiydi."
  3. "Papkaga ulashilgan har kim uning ichidagi fayllarni ko'radi."
  4. "To'lovni faqat Toshkent IP manzillaridan tasdiqlash mumkin."
  5. "Menejer o'z jamoasi a'zolarining ta'tilini tasdiqlaydi."
Yechim
  1. RBAC — faqat rol.
  2. ABAC — subyekt atributi (bo'lim) va resurs atributi (bo'lim) teng.
  3. ReBAC — munosabat zanjiri: fayl → papka → ulashilgan.
  4. ABAC — muhit atributi (IP).
  5. ReBAC — "menejeri" munosabati (atribut bilan ham yozsa bo'ladi: xodim.menejerId === f.id; chegara aniq emas, bu normal).

2-mashq (o'rta): bo'lim va maxfiylik

«Bahor» hujjatlari uchun siyosat yozing. Hujjatda bolim va maxfiy (true/false), xodimda bolim va daraja (1–3). Qoidalar: xodim faqat o'z bo'limi hujjatini o'qiydi; maxfiy hujjatni faqat daraja >= 3 o'qiydi; rol: "auditor" hamma bo'limni o'qiydi, lekin maxfiy hujjatga daraja qoidasi unga ham amal qiladi. Sukut — rad. To'rt holatni sinang.

Yechim
js
function oqiyOladimi(xodim, hujjat) {
  if (hujjat.maxfiy && xodim.daraja < 3) return false;
  if (xodim.rol === "auditor") return true;
  return xodim.bolim === hujjat.bolim;
}

const oshxona = { bolim: "oshxona", daraja: 1, rol: "xodim" };
const auditor = { bolim: "moliya", daraja: 2, rol: "auditor" };
const menyu = { bolim: "oshxona", maxfiy: false };
const retsept = { bolim: "oshxona", maxfiy: true };

console.log(oqiyOladimi(oshxona, menyu));
console.log(oqiyOladimi(oshxona, retsept));
console.log(oqiyOladimi(auditor, menyu));
console.log(oqiyOladimi(auditor, retsept));

Konsolda:

text
true
false
true
false

Taqiq (maxfiylik) birinchi turibdi — shuning uchun auditor ham maxfiy retseptni ko'rmaydi. Agar auditor tekshiruvini birinchi qo'ysangiz, to'rtinchi qator true bo'lardi — aynan darsdagi "taqiq birinchi" tuzog'i.

3-mashq (qiyin): kesh bilan qobiliyat

CASL o'lchovidagi saboqni oddiy JS'da takrorlang. qobiliyatQur(rol) funksiyasi qimmat bo'lsin: ichida 200 000 qadamli bo'sh sikl va natija — ruxsatlar Set i. keshli(rol) esa Map da saqlab, har rol uchun faqat bir marta qursin. 1000 ta tekshiruvda nechta qurish bo'lganini sanang: keshsiz va keshli. Rollar: ["admin", "foydalanuvchi"] navbatma-navbat.

Yechim
js
let qurishlar = 0;
function qobiliyatQur(rol) {
  qurishlar++;
  let x = 0;
  for (let i = 0; i < 200_000; i++) x += i;
  return rol === "admin"
    ? new Set(["oqish", "yozish", "bloklash"])
    : new Set(["oqish", "yozish"]);
}

const kesh = new Map();
function keshli(rol) {
  if (!kesh.has(rol)) kesh.set(rol, qobiliyatQur(rol));
  return kesh.get(rol);
}

const ROLLAR = ["admin", "foydalanuvchi"];
let ruxsat = 0;
for (let i = 0; i < 1000; i++) {
  if (qobiliyatQur(ROLLAR[i % 2]).has("bloklash")) ruxsat++;
}
console.log("keshsiz:", qurishlar, ruxsat);

qurishlar = 0;
ruxsat = 0;
for (let i = 0; i < 1000; i++) {
  if (keshli(ROLLAR[i % 2]).has("bloklash")) ruxsat++;
}
console.log("keshli:", qurishlar, ruxsat);

Konsolda:

text
keshsiz: 1000 500
keshli: 2 500

Natija bir xil (500 ta ruxsat), qurish esa 1000 dan 2 ga tushdi. Vaqtni chiqarmadik — u har mashinada boshqa. Lekin bitta tuzoq bor: rol o'zgarsa, kesh eskiradi. Oldingi darsda rol har so'rovda bazadan olinardi va adminlikdan olingan odam darhol 403 olardi. Kesh kaliti rol bo'lsa, bu xavfsiz: yangi rol — boshqa kalit. Kesh kaliti foydalanuvchi id bo'lsa, eskirgan qobiliyat qolishi mumkin.

8. Loyiha qadami: nega kanonga kirmadi

ABAC va CASL tajribasi vazifalar-api ga qo'shilmadi. Sabablar:

  • vazifalar-api — bir kishilik ro'yxat. Ulashish yo'q, demak ReBAC qoidasiga ehtiyoj ham yo'q. Ulashish va jamoalar — kursning keyingi qismlaridagi jamoaviy loyihada.
  • Muhit sharti (ish vaqti) yo'q: admin istalgan payt bloklay oladi. Bu ataylab — xavfsizlik hodisasi tunda ham bo'ladi.
  • Mavjud ikki qoida — rol (rolKerak) va egalik (SQL WHERE + RLS) — bitta funksiya va bitta siyosatdan iborat. Engine qo'shish — yana bitta bog'liqlik va qoidalarni ikki joyda (CASL va RLS) saqlash.

Halol xulosa: kichik loyihada oddiy funksiya + testlar policy engine'dan yaxshiroq. Engine qoidalar ko'p, o'zgaruvchan va frontend bilan ulashilishi kerak bo'lganda o'zini oqlaydi.

9. Real ishda

  • GitHub tashkilot, jamoa, repozitoriy va filial himoyasi bo'yicha ruxsatlarni aralashtiradi — bu RBAC + ReBAC.
  • Google Drive, Notion, Figma — "ulashish" bor joyda ReBAC bor.
  • Bank va davlat tizimlari ABAC'ni ko'p ishlatadi: lavozim, bo'lim, ish vaqti, IP, maxfiylik darajasi.
  • Kubernetes va bulut infratuzilmasida siyosatlar ko'pincha OPA (Rego) bilan yoziladi.
  • Intervyuda: "RBAC, ABAC, ReBAC farqi?", "Rollar portlashi nima?", "Policy engine qachon kerak?", "Ruxsatlarni frontend bilan qanday ulashasiz?".

Xulosa

  • RBAC — rol; ABAC — atributlar (subyekt, resurs, amal, muhit); ReBAC — munosabatlar grafi.
  • Vaziyatga bog'liq qoidalarni rol bilan yozish — rollar portlashi.
  • Siyosat: sukut — rad; taqiq birinchi; muhit atributlari (vaqt, IP) — faqat serverdan.
  • ReBAC (Zanzibar g'oyasi): obyekt#munosabat@subyekt yozuvlari; ruxsat — grafda yo'l.
  • CASL qoidalari JSON — frontend bilan ulashiladi; qobiliyatni har tekshiruvda qurish ~111 µs, bir marta qurib ishlating.
  • Kichik loyihada oddiy funksiya va testlar yetarli; engine — qoidalar ko'p va o'zgaruvchan bo'lganda.

Keyingi dars: API kalitlar va servislararo autentifikatsiya — foydalanuvchi emas, dastur so'rov yuborganda uni qanday tanish va unga qanday cheklangan ruxsat berish.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
ABAC, ReBAC va policy engine'lar: atribut, munosabat va CASL — IlmHamroh