ADR-007: Chiến lược RBAC phân tầng¶
Bối cảnh¶
Hệ thống dx-vas phục vụ nhiều trường thành viên (multi-tenant), mỗi trường có người dùng, vai trò và quyền riêng biệt. Một người dùng có thể hoạt động ở nhiều tenant khác nhau với vai trò khác nhau.
Hệ thống cần một chiến lược RBAC động, linh hoạt, mở rộng được và: - Phân quyền đúng trong từng tenant - Cho phép kế thừa hoặc tuỳ biến quyền theo từng trường - Hỗ trợ caching để tăng hiệu năng - Dễ audit, rollback, và quản trị
Quyết định¶
1. Phân tầng RBAC: Master vs Sub¶
| Thành phần | Vai trò |
|---|---|
| User Service Master | Quản lý định danh toàn cục (users_global), danh sách tenant, và template role/permission dùng chung |
| Sub User Service (per tenant) | Quản lý người dùng trong tenant, role/permission nội bộ, mapping user ↔ role ↔ permission |
Mỗi tenant có stack riêng. RBAC được đánh giá tại API Gateway trong ngữ cảnh tenant_id.
2. JWT và Phân quyền¶
- JWT luôn chứa:
user_id(global)tenant_idroles: danh sách mã vai trò (role_code)- JWT không chứa
permissions - Việc đánh giá quyền chi tiết (bao gồm cả
condition) sẽ được thực hiện tại API Gateway -
Gateway tra cứu từ Redis cache theo key:
-
Nếu cache miss → Gateway gọi Sub User Service thông qua API Gateway để lấy
permissionstheo role
3. Cấu trúc dữ liệu RBAC¶
Tại Master:
CREATE TABLE global_permissions_templates (
template_id UUID PRIMARY KEY,
permission_code TEXT UNIQUE NOT NULL,
action TEXT NOT NULL,
resource TEXT NOT NULL,
default_condition JSONB,
description TEXT
);
permission_codegiúp mapping và clone xuống Sub User Service dễ dàng- Cấu trúc tương tự
permissions_in_tenant, giúp tenant kế thừa hoặc override khi cần
Tại Sub User Service (per tenant):
CREATE TABLE permissions_in_tenant (
permission_id UUID PRIMARY KEY,
permission_code TEXT UNIQUE NOT NULL,
action TEXT NOT NULL,
resource TEXT NOT NULL,
condition JSONB
);
- Trường
action,resourceđều cóNOT NULLđể đảm bảo permission luôn đủ thông tin để đánh giá
4. Điều kiện phân quyền (condition JSONB)¶
Permissions có thể chứa điều kiện động:
Gateway sẽ đánh giá điều kiện này dựa trên context user và request. Điều kiện được lưu và tra cứu từ Redis hoặc gọi API nếu cần.
5. Cache tại Gateway¶
- Key:
rbac:{user_id}:{tenant_id} - TTL mặc định: 5–15 phút
-
Invalidation:
-
Khi user bị gán quyền mới
- Khi user bị vô hiệu hóa
- Qua sự kiện Pub/Sub:
rbac_updated,user_status_changed
6. Đồng bộ template¶
-
Các tenant có thể:
-
Kế thừa template vai trò từ Master (tự động đồng bộ)
- Clone để tuỳ chỉnh (độc lập về sau)
- Sự kiện
rbac_template_updatedđược phát từ Master → Sub nhận và xử lý
7. Báo cáo và quyền truy cập báo cáo¶
- Mỗi Report Template sẽ có một trường
required_permission, ví dụ"report.view_login_by_tenant". - Người dùng chỉ có thể truy cập template hoặc sinh báo cáo khi có đủ quyền tương ứng trong RBAC, được đánh giá tại API Gateway.
required_permissionđược tra cứu từ Redis cache tương tự như các API business khác.- Nếu template có
scope: global, thì permission phải là của tenant "superadmin"; nếu làscope: tenant, thì permission được kiểm tra trong contexttenant_idhiện tại.
8. Liên kết với hệ thống quản lý báo cáo¶
-
Bảng
permissions_in_tenantcó thể lưu các quyền đặc thù cho từng loại báo cáo, bao gồm: -
"report.view_*"– quyền xem từng nhóm báo cáo "report.manage_templates"– quyền quản lý định nghĩa báo cáo"report.export"– quyền export kết quả- Các quyền này cũng có thể được đồng bộ từ
global_permissions_templatesnếu báo cáo là toàn cục.
Hệ quả¶
✅ Ưu điểm:
- Phân tách rõ ràng giữa định danh toàn cục và phân quyền nội bộ
- Dễ mở rộng khi có tenant mới hoặc role mới
- Tối ưu hiệu năng qua Redis cache và Pub/Sub
- Quản trị tập trung, nhưng cho phép mỗi tenant tùy biến độc lập
- Hỗ trợ condition động, RBAC đa ngữ cảnh
⚠️ Lưu ý:
- Cần xây dựng giao diện quản lý role/permission rõ ràng cho từng tenant
- Cần cơ chế trace + audit phân quyền theo
tenant_id