Bỏ qua đến nội dung chính

Ủy quyền trong APISIX sử dụng Casbin

· Đọc trong 1 phút
Rushikesh Tote

Giới thiệu

APISIX là một cổng API đáng tin cậy, hiệu suất cao và có khả năng mở rộng dựa trên Nginx và etcd. Nó là một dự án nguồn mở của Quỹ Phần mềm Apache. Ngoài ra, điều làm cho APISIX trở nên tuyệt vời là sự hỗ trợ của nhiều plugin tích hợp đỉnh cao có thể được sử dụng để triển khai các tính năng như xác thực, giám sát, định tuyến, v.v. Và thực tế là các plugin trong APISIX được tải lại nóng (không cần khởi động lại) làm cho nó rất linh hoạt.

Tuy nhiên, khi sử dụng APISIX, có thể có những tình huống mà bạn muốn thêm logic ủy quyền phức tạp vào ứng dụng của mình. Đây là nơi mà authz-casbin có thể giúp bạn, authz-casbin là một plugin của APISIX dựa trên Lua Casbin cho phép ủy quyền mạnh mẽ dựa trên nhiều mô hình kiểm soát truy cập khác nhau. Casbin là một thư viện ủy quyền hỗ trợ các mô hình kiểm soát truy cập như ACL, RBAC, ABAC. Ban đầu được viết bằng Go, nó đã được chuyển sang nhiều ngôn ngữ khác và Lua Casbin là việc triển khai Lua của Casbin. Sự phát triển của authz-casbin bắt đầu khi chúng tôi đề xuất một plugin mới cho ủy quyền trong kho lưu trữ APISIX (#4674) mà các thành viên chính đã đồng ý. Và sau những đánh giá hữu ích dẫn đến một số thay đổi và cải tiến lớn, PR (#4710) cuối cùng đã được hợp nhất.

Trong bài blog này, chúng tôi sẽ sử dụng plugin authz-casbin để chỉ ra cách bạn có thể triển khai một mô hình ủy quyền dựa trên Kiểm soát Truy cập Dựa trên Vai trò (RBAC) trong APISIX.

LƯU Ý: Bạn sẽ cần sử dụng một số plugin khác hoặc quy trình làm việc tùy chỉnh để xác thực người dùng vì Casbin chỉ thực hiện ủy quyền, không phải xác thực.

Tạo một mô hình

Plugin sử dụng ba tham số để ủy quyền bất kỳ yêu cầu nào - chủ thể, đối tượng và hành động. Ở đây, chủ thể là giá trị của tiêu đề tên người dùng, có thể là một cái gì đó như [username: alice]. Sau đó, đối tượng là đường dẫn URL đang được truy cập và hành động là phương thức yêu cầu đang được sử dụng.

Giả sử chúng ta muốn tạo một mô hình với ba tài nguyên tại các đường dẫn - /`\`, /res1\ và `/res2`. Và chúng ta muốn có một mô hình như thế này:

hình ảnh

Điều này có nghĩa là tất cả người dùng (*`\`) ví dụ như jack\ có thể truy cập trang chủ (/`\`). Và người dùng có quyền admin\ như alice`\` và bob\ có thể truy cập tất cả các trang và tài nguyên (như res1`\` và res2\). Ngoài ra, hãy giới hạn người dùng không có bất kỳ quyền admin nào chỉ sử dụng phương thức yêu cầu `GET`. Đối với kịch bản này, chúng ta có thể định nghĩa mô hình như sau:

[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)

Tạo một chính sách

Từ tình huống trên, chính sách sẽ là:

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

Bộ so khớp từ mô hình có nghĩa là:

  1. (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)): Hoặc là chủ thể của yêu cầu có một vai trò như chủ thể của chính sách hoặc chủ thể của yêu cầu khớp với chủ thể của chính sách trong keyMatch. keyMatch là hàm tích hợp sẵn trong Lua Casbin, bạn có thể xem mô tả của hàm và nhiều hàm khác có thể hữu ích tại đây.
  2. keyMatch(r.obj, p.obj): Đối tượng của yêu cầu khớp với đối tượng của chính sách (đường dẫn URL ở đây).
  3. keyMatch(r.act, p.act): Hành động của yêu cầu khớp với hành động của chính sách (phương thức yêu cầu HTTP ở đây).

Kích hoạt plugin trên tuyến đường

Sau khi bạn đã tạo mô hình và chính sách, bạn có thể kích hoạt nó trên một tuyến đường bằng cách sử dụng APISIX Admin API. Để kích hoạt nó sử dụng đường dẫn tệp mô hình và chính sách:

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": "/*"
}'

Ở đây, trường username là tên tiêu đề mà bạn sẽ sử dụng để truyền vào chủ thể. Ví dụ, nếu bạn sẽ truyền tiêu đề usernameuser: alice`\`, bạn sẽ sử dụng "username": "user"\.

Để sử dụng văn bản mô hình/chính sách thay vì tệp, bạn có thể sử dụng các trường modelpolicy thay thế:

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": "/*"
}'

Kích hoạt plugin sử dụng mô hình/chính sách toàn cục

Có thể có những tình huống mà bạn muốn sử dụng một cấu hình mô hình và chính sách duy nhất trên nhiều tuyến. Bạn có thể làm điều đó bằng cách gửi một yêu cầu PUT để thêm cấu hình mô hình và chính sách vào siêu dữ liệu của plugin bằng:

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"
}'

Và sau đó để kích hoạt cấu hình giống nhau trên một tuyến đường, gửi một yêu cầu sử dụng 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/*"
}'

Điều này sẽ thêm cấu hình siêu dữ liệu plugin vào tuyến đường. Bạn cũng có thể dễ dàng cập nhật cấu hình siêu dữ liệu plugin bằng cách gửi lại yêu cầu đến siêu dữ liệu của plugin với cấu hình mô hình và chính sách đã cập nhật, plugin sẽ tự động cập nhật tất cả các tuyến đường sử dụng siêu dữ liệu plugin.

Trường hợp sử dụng

  • Trường hợp sử dụng chính của plugin này sẽ là trong việc thực hiện ủy quyền trong các API của bạn. Bạn có thể dễ dàng thêm plugin này vào bất kỳ tuyến đường API nào mà bạn đang sử dụng với mô hình ủy quyền và cấu hình chính sách của mình.
  • Nếu bạn muốn có một mô hình ủy quyền duy nhất cho tất cả các API của mình, bạn có thể sử dụng phương pháp mô hình/chính sách toàn cầu. Điều này giúp cập nhật chính sách dễ dàng cho tất cả các tuyến đường, vì bạn chỉ cần cập nhật siêu dữ liệu trong etcd.
  • Trong khi đó, nếu bạn muốn sử dụng một mô hình khác nhau cho mỗi tuyến đường khác nhau, bạn có thể sử dụng phương pháp tuyến đường. Điều này rất hữu ích khi các tuyến API khác nhau có các tập hợp quyền người dùng khác nhau. Bạn cũng có thể sử dụng điều này khi bạn đang xử lý các chính sách lớn hơn, vì nó sẽ làm cho việc ủy quyền nhanh hơn khi được lọc vào nhiều tuyến.