Skip to content

Casbin

ที่เก็บข้อมูลอย่างเป็นทางการ: casbin/casbin: An authorization library that supports access control models like ACL, RBAC, ABAC in Golang (github.com)

เอกสารอย่างเป็นทางการ: ภาพรวม | Casbin

TIP

บทความนี้เป็นเพียงบทความเบื้องต้นเกี่ยวกับ Casbin หากต้องการเรียนรู้เพิ่มเติมอย่างละเอียดโปรดไปที่เว็บไซต์ทางการ

บทนำ

ในระบบ โปรแกรมเมอร์ Backend ต้องรับผิดชอบการจัดการสิทธิ์ของ API ซึ่งต้องใช้การทำงานจำนวนมาก หากแต่ละโปรเจกต์ต้องเขียนระบบควบคุมสิทธิ์เองจะเสียเวลาเป็นอย่างมาก บริษัทใหญ่ที่มีทรัพยากรมากกว่ามักจะ傾向ที่จะพัฒนาระบบควบคุมสิทธิ์ของตัวเอง แต่บริษัทขนาดเล็กและกลางส่วนใหญ่ไม่สามารถรับต้นทุนการพัฒนาได้ ดังนั้นเฟรมเวิร์กควบคุมสิทธิ์แบบ Open Source ในตลาดจึงเป็นตัวเลือกแรกของพวกเขา Casbin เป็นไลบรารีควบคุมการเข้าถึงแบบ Open Source ที่มีประสิทธิภาพสูง พัฒนาด้วยภาษา Go และรองรับภาษาหลักอื่นๆ ด้วย

ควรทราบว่า Casbin เป็นเพียงเฟรมเวิร์กควบคุมการเข้าถึงเท่านั้น รับผิดชอบเฉพาะการควบคุมการเข้าถึง ไม่รับผิดชอบตรรกะการตรวจสอบสิทธิ์การเข้าถึง เก็บเฉพาะความสัมพันธ์การแมประหว่างผู้ใช้และบทบาท รองรับแบบจำลองการควบคุมการเข้าถึงต่อไปนี้:

  1. ACL (Access Control List, รายการควบคุมการเข้าถึง)
  2. ACL ที่มี Superuser
  3. ACL ที่ไม่มีผู้ใช้: มีประโยชน์เป็นพิเศษสำหรับระบบที่ไม่มีการตรวจสอบสิทธิ์หรือการเข้าสู่ระบบของผู้ใช้
  4. ACL ที่ไม่มีทรัพยากร: บางสถานการณ์อาจมุ่งเน้นเฉพาะประเภทของทรัพยากร ไม่ใช่ทรัพยากรเดี่ยว เช่น สิทธิ์ write-article, read-log เป็นต้น ไม่ควบคุมการเข้าถึงบทความหรือบันทึกเฉพาะ
  5. RBAC (Role-Based Access Control, การควบคุมการเข้าถึงตามบทบาท)
  6. RBAC ที่รองรับบทบาททรัพยากร: ผู้ใช้และทรัพยากรสามารถมีบทบาท (หรือกลุ่ม) ได้พร้อมกัน
  7. RBAC ที่รองรับโดเมน/ผู้เช่า: ผู้ใช้สามารถตั้งค่าชุดบทบาทที่แตกต่างกันสำหรับโดเมน/ผู้เช่าที่แตกต่างกัน
  8. ABAC (Attribute-Based Access Control, การควบคุมการเข้าถึงตามคุณลักษณะ): รองรับการใช้ syntax sugar เช่น resource.Owner เพื่อดึงคุณลักษณะขององค์ประกอบ
  9. RESTful: รองรับพาธ เช่น /res/*, /res/:id และวิธีการ HTTP เช่น GET, POST, PUT, DELETE
  10. ปฏิเสธก่อน: รองรับอนุญาตและปฏิเสธการอนุญาต การปฏิเสธมีความสำคัญเหนือการอนุญาต
  11. ลำดับความสำคัญ: กฎนโยบายจัดลำดับความสำคัญตามลำดับก่อนหลัง คล้ายกับกฎไฟร์วอลล์

หลักการทำงาน

ใน Casbin แบบจำลองการควบคุมการเข้าถึงถูกแยกออกเป็นไฟล์การกำหนดค่าที่ใช้ PERM PERM หมายถึง Policy (นโยบาย), Effect (ผลลัพธ์), Request (คำขอ), Matcher (การจับคู่) เมื่อต้องการแก้ไขกลไกการอนุญาตในโปรเจกต์ เพียงแก้ไขไฟล์การกำหนดค่าอย่างง่าย เนื้อหาของไฟล์ Model ปกติมีดังนี้:

bash
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

นี่เป็นแบบจำลองการควบคุมการเข้าถึง ACL ที่ง่ายที่สุด

นโยบาย

ในไฟล์การกำหนดค่า ส่วนการกำหนดค่านโยบายคือ

[policy_definition]
p = sub, obj, act

p หมายถึง policy ไม่สามารถใช้ตัวอักษรอื่นแทนได้ sub หมายถึง subject เป็นหลักของนโยบาย obj คือ object เป็นวัตถุของนโยบาย act คือ action หมายถึงการกระทำ

p = sub, obj, act

หรือสามารถมีฟิลด์ที่สี่ eft ได้ หากละไว้ eft จะเป็น allow โดยค่าเริ่มต้น

p=sub, obj, act, eft

บรรทัดนี้เพียงอธิบายว่าจะเขียน policy อย่างไร ไม่ใช่การกำหนดนโยบายที่แท้จริง ด้านล่างนี้เป็นตัวอย่าง policy ที่เฉพาะเจาะจง

p, jojo, cake, eat

p แสดงว่านี่คือนิยามกฎนโยบาย jojo คือหลักของนโยบาย cake คือวัตถุของนโยบาย eat คือการกระทำ ความหมายเต็มคือหลัก jojo สามารถดำเนินการ eat กับวัตถุ cake ได้ กฎนโยบายที่เฉพาะเจาะจงจะไม่ปรากฏในไฟล์โมเดล แต่จะมีไฟล์ policy หรือฐานข้อมูลเฉพาะสำหรับเก็บนโยบาย

คำขอ

ในไฟล์การกำหนดค่า ส่วนการกำหนดคำขอคือ

[request_definition]
r = sub, obj, act

r หมายถึง request ไม่สามารถใช้ตัวอักษรอื่นแทนได้ sub คือ subject หมายถึงหลักของคำขอ obj คือ object หมายถึงวัตถุของคำขอ act คือ action หมายถึงการกระทำของคำขอ โดยทั่วไปการกำหนดคำขอและการกำหนดนโยบายมีชื่อฟิลด์เหมือนกัน ส่วนคำขอไม่รับผิดชอบโดย Casbin แต่เป็นสิ่งที่ผู้พัฒนากำหนดเองว่าอะไรคือหลักของคำขอ อะไรคือวัตถุของคำขอ Casbin เพียงรับผิดชอบควบคุมการเข้าถึงตามฟิลด์ที่ส่งเข้ามา

การจับคู่

ในไฟล์การกำหนดค่า ส่วนการกำหนดการจับคู่คือ

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

m หมายถึง matcher ไม่สามารถใช้ตัวอักษรอื่นแทนได้ หลังจากนั้นคือกฎการจับคู่ที่สอดคล้องกัน ด้านบนนี้เป็นนิพจน์บูลีนอย่างง่าย หมายความว่าหากฟิลด์ทั้งหมดของคำขอที่ส่งเข้ามาตรงกับฟิลด์ของกฎนโยบายก็จะจับคู่ได้ แน่นอนว่ามันอาจเป็น wildcard หรือนิพจน์ปกติที่มีพลังการแสดงออกมากกว่า

นอกจากนี้ matcher ยังรองรับ syntax in เช่น

[matchers]
m = r.sub in ("root","admin")

หรือ

[matchers]
m = r.sub.Name in (r.obj.Admins)
go
e.Enforce(Sub{Name: "alice"}, Obj{Name: "a book", Admins: []interface{}{"alice", "bob"}})

เมื่อทำการจับคู่ Casbin จะไม่ตรวจสอบประเภท แต่จะใช้ interface เพื่อตรวจสอบ == ว่าเท่ากันหรือไม่

ผลลัพธ์

ส่วนการกำหนดผลลัพธ์ทำการตัดสินเชิงตรรกะกับผลการจับคู่อีกครั้ง ในไฟล์การกำหนดค่า ส่วนการกำหนดผลลัพธ์คือ

[policy_effect]
e = some(where (p.eft == allow))

e หมายถึง effect ไม่สามารถใช้ตัวอักษรอื่นแทนได้ some เป็นตัวบ่งปริมาณว่ามีนโยบายที่ตรงตามตัวจับคู่หรือไม่ any เป็นตัวบ่งปริมาณว่านโยบายทั้งหมดตรงตามตัวจับคู่หรือไม่

some(where (p.eft == allow))

กฎนี้หมายความว่าหากมีผลลัพธ์ allow ในการจับคู่ ผลลัพธ์สุดท้ายจะเป็น allow

e = !some(where (p.eft == deny))

กฎนี้หมายความว่าหากไม่มีผลลัพธ์ deny ในการจับคู่ ผลลัพธ์สุดท้ายจะเป็น allow

e = some(where (p.eft == allow)) && !some(where (p.eft == deny))

กฎนี้หมายความว่าในการจับคู่ หากมี allow หนึ่งรายการและไม่มีผลลัพธ์ deny ผลลัพธ์สุดท้ายจะเป็น allow

แม้ว่า Casbin จะออกแบบ syntax สำหรับผลลัพธ์นโยบายดังกล่าว แต่การดำเนินการในปัจจุบันใช้ผลลัพธ์นโยบายที่ hardcode ไว้ พวกเขาไม่คิดว่าความยืดหยุ่นนี้จำเป็นมากนัก จนถึงขณะนี้คุณต้องใช้ผลลัพธ์นโยบายที่มีอยู่ในตัว ไม่สามารถกำหนดเองได้ ผลลัพธ์นโยบายที่รองรับมีดังนี้

นิยาม Policy effectความหมายตัวอย่าง
some(where (p.eft == allow))allow-overrideACL, RBAC, ฯลฯ
!some(where (p.eft == deny))deny-overrideการปฏิเสธ改写
some(where (p.eft == allow)) && !some(where (p.eft == deny))allow-and-denyอนุญาตและปฏิเสธ
priority(p.eft) || denypriorityลำดับความสำคัญ
subjectPriority(p.eft)ลำดับความสำคัญตามบทบาทลำดับความสำคัญของหัวข้อ

TIP

  1. นิยามทั้งสี่ข้างต้นสามารถกำหนดได้หลายรายการ syntax คือ type+number เช่น r2,p2,e2,m2

  2. ไฟล์โมเดลสามารถมีคำอธิบายประกอบได้ โดยใช้สัญลักษณ์ # เป็นคำอธิบายประกอบ

ตัวอย่าง

ด้านล่างนี้เป็นตัวอย่างที่สาธิตกระบวนการทำงานของไฟล์โมเดล ก่อนอื่นกำหนดไฟล์โมเดล ACL อย่างง่ายดังนี้

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

ไฟล์ Policy ดังนี้

p, alice, data1, read
p, bob, data2, write

กระบวนการแยกหลัก วัตถุ การกระทำถูกกำหนดโดยตรรกะทางธุรกิจ ซึ่งไม่สำคัญที่นี่จึงละไว้ ด้านล่างนี้แสดงคำขอที่ส่งเข้ามาอย่างง่ายที่สุด ดังนี้

alice, data1, read
bob, data1, read
alice, data2, write
bob, data2, write

ไฟล์ policy กำหนดว่า alice มีสิทธิ์อ่าน data1, bob มีสิทธิ์เขียน data2 ดังนั้นในคำขอที่ส่งเข้ามา

alice, data1, read

หมายความว่า alice ต้องการดำเนินการอ่านกับ data1

bob, data1, read

หมายความว่า bob ต้องการดำเนินการอ่านกับ data1 ส่วนที่เหลือก็เช่นกัน ดังนั้นผลลัพธ์สุดท้ายคือ

true
false
false
true

นี่เป็นตัวอย่าง ACL ที่ง่ายที่สุด เว็บไซต์ทางการของ Casbin สามารถแก้ไขและทดสอบตัวอย่างออนไลน์ได้ ไปที่ Casbin editor เพื่อทดสอบ

RBAC

RBAC (Role-Based-Access-Controll) การควบคุมการเข้าถึงตามบทบาท เมื่อเทียบกับโมเดล ACL จะมี [role_definition] เพิ่มเติม ด้านล่างนี้เป็นโมเดล RBAC อย่างง่าย

[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) && r.obj == p.obj && r.act == p.act

การกำหนดบทบาทคือ

[role_definition]
g = _, _

g หมายถึง group ไม่สามารถใช้ตัวอักษรอื่นแทนได้ รองรับวิธีการ type+number เพื่อสร้างหลายรายการ _ เป็นตัวยึด แสดงว่ามีพารามิเตอร์เข้ากี่ตัว โดยทั่วไปใน Policy, g มักเป็นรูปแบบดังนี้

g, alice, data2_admin
g, mike, data1_admin
g, data1_admin data2_admin

alice หมายถึงหลัก data2_admin หมายถึงบทบาท โดยเคร่งครัดแล้ว Casbin จะมองว่าเป็นสตริงทั้งหมด การตีความความหมายและการใช้งานขึ้นอยู่กับผู้พัฒนา

g, alice, data2_admin

หมายความว่า alice มีบทบาท data2_admin

g, mike, data1_admin

หมายความว่า mike มีบทบาท data1_admin

g, data1_admin data2_admin

หมายความว่าบทบาท data1_admin มีบทบาท data2_admin นี่คือความสัมพันธ์การสืบทอดระหว่างบทบาท

โมเดลบทบาททรัพยากร

โมเดลบทบาททรัพยากรเพิ่ม g2 เป็นนิยามบทบาทของทรัพยากร นิยามโมเดลดังนี้

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && r.act == p.act

ตัวอย่าง Policy ดังนี้

p, alice, data1, read
p, bob, data2, write
p, data_group_admin, data_group, write

g, alice, data_group_admin
g2, data1, data_group
g2, data2, data_group

g2 นิยามกลุ่มบทบาททรัพยากร มอบทรัพยากรให้กับบทบาทต่างๆ และกำหนดความสัมพันธ์ระหว่างบทบาทผู้ใช้กับบทบาททรัพยากร

p, data_group_admin, data_group, write

นโยบายนี้กำหนดว่าผู้ใช้ที่มีบทบาท data_group_admin สามารถดำเนินการเขียนกับทรัพยากรที่มีบทบาท data_group

โมเดลโดเมนหลายผู้เช่า

[request_definition]
r = sub, dom, obj, act

[policy_definition]
p = sub, dom, obj, act

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act

โมเดลโดเมนหลายผู้เช่ามีฟิลด์ dom เพิ่มเติมเมื่อเทียบกับโมเดล RBAC แบบดั้งเดิม ใช้แสดงโดเมนที่หลักสังกัด ตัวอย่าง Policy ดังนี้

p, admin, domain1, data1, read
p, admin, domain1, data1, write
p, admin, domain2, data2, read
p, admin, domain2, data2, write

g, alice, admin, domain1
g, bob, admin, domain2

เช่น

p, admin, domain1, data1, read

กำหนดว่าหลัก admin ที่สังกัดโดเมน domain1 มีสิทธิ์อ่าน data1

g, alice, admin, domain1

กำหนดว่า alice สังกัด domain1 มีบทบาท admin

ABAC

Golang by www.golangdev.cn edit