ข้ามไปยังเนื้อหาหลัก

การอนุญาตใน APISIX โดยใช้ Casbin

· อ่าน 1 นาที
Rushikesh Tote

บทนำ

APISIX เป็น API gateway ที่มีประสิทธิภาพสูงและสามารถขยายได้ตามความต้องการ พัฒนาบนพื้นฐานของ Nginx และ etcd เป็นโปรเจกต์โอเพนซอร์สโดยมูลนิธิซอฟต์แวร์ Apache นอกจากนี้สิ่งที่ทำให้ APISIX ดีเยี่ยมคือการสนับสนุนปลั๊กอินที่มีประสิทธิภาพมากมายที่สามารถใช้ในการดำเนินการฟีเจอร์ต่างๆ เช่น การตรวจสอบสิทธิ์, การตรวจสอบการทำงาน, การกำหนดเส้นทาง ฯลฯ และความจริงที่ว่าปลั๊กอินใน APISIX สามารถรีโหลดได้ทันที (ไม่ต้องรีสตาร์ท) ทำให้มันมีความยืดหยุ่นสูง

แต่ขณะใช้งาน APISIX อาจมีสถานการณ์ที่คุณต้องการเพิ่มตรรกะการอนุญาตที่ซับซ้อนในแอปพลิเคชันของคุณ นี่คือที่ที่ authz-casbin อาจช่วยคุณได้, authz-casbin เป็นปลั๊กอินของ APISIX ที่พัฒนาบน Lua Casbin ที่ช่วยให้สามารถอนุญาตได้อย่างมีประสิทธิภาพตามโมเดลการควบคุมการเข้าถึงต่างๆ Casbin เป็นไลบรารีการอนุญาตที่รองรับโมเดลการควบคุมการเข้าถึงเช่น ACL, RBAC, ABAC เขียนขึ้นเดิมในภาษา Go และได้ถูกพอร์ตไปยังภาษาอื่นๆ และ Lua Casbin เป็นการนำไปใช้ของ Casbin ในภาษา Lua การพัฒนา authz-casbin เริ่มต้นเมื่อเราเสนอปลั๊กอินใหม่สำหรับการอนุญาตในที่เก็บข้อมูล APISIX (#4674) ซึ่งสมาชิกหลักตกลง และหลังจากการทบทวนที่มีประโยชน์ซึ่งนำไปสู่การเปลี่ยนแปลงและการปรับปรุงที่สำคัญ คำขอ PR (#4710) ก็ถูกผสานเข้าไปในที่สุด

ในบล็อกนี้ เราจะใช้ปลั๊กอิน authz-casbin เพื่อแสดงวิธีการที่คุณสามารถนำไปใช้โมเดลการอนุญาตตาม Role Based Access Control (RBAC) ใน APISIX

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

การสร้างโมเดล

ปลั๊กอินใช้สามพารามิเตอร์ในการอนุญาตคำขอใดๆ - หัวข้อ, วัตถุ และการกระทำ ที่นี่ หัวข้อคือค่าของหัวข้อ username ซึ่งอาจเป็นอะไรก็ได้เช่น [username: alice] จากนั้น วัตถุคือเส้นทาง URL ที่กำลังถูกเข้าถึง และการกระทำคือวิธีการขอที่กำลังถูกใช้

สมมติว่าเราต้องการสร้างโมเดลที่มีทรัพยากรสามอย่างที่เส้นทาง - /, /res1 และ /res2 และเราต้องการมีโมเดลเช่นนี้:

รูปภาพ

นี่จะหมายความว่าผู้ใช้ทุกคน (*) เช่น jack สามารถเข้าถึงหน้าแรก (/) และผู้ใช้ที่มีสิทธิ์ admin เช่น alice และ bob สามารถเข้าถึงทุกหน้าและทรัพยากร (เช่น res1 และ res2) นอกจากนี้ มาจำกัดผู้ใช้ที่ไม่มีสิทธิ์ admin ให้ใช้เฉพาะวิธีการขอ GET สำหรับสถานการณ์นี้ เราสามารถกำหนดโมเดลได้เป็น:

[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)

การสร้างนโยบาย

จากสถานการณ์ข้างต้น นโยบายจะเป็น:

p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin

ตัวจับคู่จากโมเดลหมายถึง:

  1. (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)): หัวข้อของคำขอมีบทบาทเหมือนกับหัวข้อของนโยบาย หรือหัวข้อของคำขอตรงกับหัวข้อของนโยบายใน keyMatch keyMatch เป็นฟังก์ชันที่มีอยู่ใน Lua Casbin คุณสามารถดูคำอธิบายของฟังก์ชันและฟังก์ชันอื่นๆ ที่อาจมีประโยชน์ ที่นี่
  2. keyMatch(r.obj, p.obj): วัตถุของคำขอตรงกับวัตถุของนโยบาย (เส้นทาง URL ที่นี่)
  3. keyMatch(r.act, p.act): การกระทำของคำขอตรงกับการกระทำของนโยบาย (วิธีการขอ HTTP ที่นี่)

การเปิดใช้งานปลั๊กอินบนเส้นทาง

เมื่อคุณได้สร้างโมเดลและนโยบายแล้ว คุณสามารถเปิดใช้งานได้บนเส้นทางโดยใช้ APISIX Admin API เพื่อเปิดใช้งานโดยใช้เส้นทางไฟล์โมเดลและนโยบาย:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model_path": "/path/to/model.conf",
"policy_path": "/path/to/policy.csv",
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'

ที่นี่ ฟิลด์ username เป็นชื่อหัวข้อที่คุณจะใช้ในการส่งหัวข้อ ตัวอย่างเช่น ถ้าคุณจะส่งหัวข้อ username เป็น user: alice คุณจะใช้ "username": "user"

สำหรับการใช้ข้อความโมเดล/นโยบายแทนไฟล์ คุณสามารถใช้ฟิลด์ model และ policy แทน:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model": "[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",

"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin",

"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'

การเปิดใช้งานปลั๊กอินโดยใช้โมเดล/นโยบายสากล

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

curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/authz-casbin -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -i -X PUT -d '
{
"model": "[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",

"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin"
}'

และจากนั้นเพื่อเปิดใช้งานการกำหนดค่าเดียวกันบนเส้นทางใดๆ ส่งคำขอโดยใช้ Admin API:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/route1/*"
}'

นี่จะเพิ่มการกำหนดค่าข้อมูลเมตาของปลั๊กอินไปยังเส้นทาง คุณยังสามารถอัปเดตการกำหนดค่าข้อมูลเมตาของปลั๊กอินได้อย่างง่ายดายโดยการส่งคำขอใหม่ไปยังข้อมูลเมตาของปลั๊กอินด้วยการกำหนดค่าโมเดลและนโยบายที่อัปเดต ปลั๊กอินจะอัปเดตเส้นทางทั้งหมดที่ใช้การกำหนดค่าข้อมูลเมตาโดยอัตโนมัติ

กรณีการใช้งาน

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