FDE PulseViệc làm FDE đang mở 316Mới đăng 7 ngày qua 10Chủ đề nổi bật: Đào tạo kỹ năng FDE tại Đông Nam Á

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

RBAC, ABAC, ReBAC hay PBAC: đưa mô hình phân quyền của khách vào ứng dụng AI

Chatbot nội bộ lộ dữ liệu thường không phải vì model nói bậy, mà vì bước retrieval chưa biết người đang hỏi là ai.

Đồ hoạPre-filter và post-filter trong RAG có phân quyền
Post-filterPre-filter
Thứ tự xử lýTìm vector top-k trước, rồi kiểm tra quyền từng kết quảLấy danh sách tài liệu được xem trước, dùng ID làm bộ lọc
Top 8 đều là tài liệu mậtNgười hỏi nhận 0 chunk dù hạng thứ 9 là tài liệu hợp lệChỉ tìm trong tài liệu được phép nên vẫn đủ 8 chunk hợp lệ
Rủi ro cần đoCâu trả lời rỗng với người ít quyềnDanh sách ID rất dài với người xem được nhiều thứ

Lọc quyền trước khi tìm vector giúp người ít quyền không nhận về kết quả rỗng.

Đồ hoạ: FDE Times

Tóm tắt nhanh

  • Với RAG, quyền phải được áp ở bước retrieval để pipeline chỉ trả về tài liệu người hỏi được phép xem.
  • RBAC dễ audit nhưng dễ phình số vai trò; ABAC cần ít policy hơn vì khớp theo thuộc tính; PBAC gom luật vào một policy engine để dễ version và audit.
  • Khi tài liệu nằm ở Drive, Confluence hay SharePoint, phải đồng bộ cả nội dung lẫn quyền, và giữ cả hai khớp với hệ thống nguồn.
Chia sẻLinkedInFacebookX

Thử hình dung tuần thứ hai ở site khách. Demo chatbot nội bộ chạy mượt, cho đến khi một nhân viên kinh doanh hỏi về chính sách thưởng năm nay và bot trích nguyên một đoạn từ bảng lương của ban giám đốc.

Model không sai. Nó trả lời đúng câu hỏi, dựa trên đúng tài liệu mà bước retrieval đưa cho nó. Lỗi nằm ở chỗ pipeline không hề biết người đang hỏi là ai, và người đó được xem những gì.

Đây là việc FDE nào làm RAG hay agent cho doanh nghiệp cũng sẽ gặp. Khách đã có sẵn một mô hình phân quyền, đôi khi rõ ràng, thường là ngầm định trong SharePoint hay Confluence. Việc của bạn là chuyển mô hình đó vào ứng dụng AI mà không làm rơi một quy tắc nào.

Vì sao lỗ hổng nằm ở retrieval?

Tài liệu của OpenFGA nói thẳng yêu cầu: quyền ở cấp tài liệu phải được áp vào pipeline để RAG chỉ trả về nội dung người dùng được phép xem. Nghĩa là quyết định phân quyền phải xảy ra trước khi văn bản lọt vào context của model.

Một khi đoạn văn bản đã nằm trong prompt, mọi chỉ dẫn kiểu “đừng tiết lộ thông tin mật” chỉ còn là lời nhờ vả. Vì thế câu hỏi kỹ thuật thật sự là: bạn mô phỏng quyền của khách bằng mô hình nào, và lọc ở đâu.

Một quy tắc, bốn cách mô tả

Giữ nguyên công ty trong ví dụ trên, và thử viết quy tắc “chỉ ban giám đốc được xem bảng lương” bằng từng mô hình. Bạn sẽ thấy mỗi mô hình đặt một câu hỏi khác nhau về cùng một quyền.

Cách quen thuộc nhất là RBAC: gán quyền theo vai trò trong tổ chức, mỗi vai trò là một tập quyền áp lên người dùng, như cách Auth0 định nghĩa. Với bảng lương, bạn tạo vai trò “Ban giám đốc” là xong, và việc audit cũng đơn giản.

Rắc rối đến khi quy tắc bắt đầu có ngữ cảnh. Giả sử khách có 5 phòng ban, 4 cấp bậc, 3 vùng địa lý; nếu mỗi tổ hợp cần một vai trò riêng, bạn đã có 60 vai trò trước khi tính đến dự án.

Đó chính là “role explosion” mà Ping Identity cảnh báo, và AWS chỉ ra thêm một nhược điểm: mỗi khi có tài nguyên mới, bạn phải cập nhật policy để cho phép truy cập nó.

Nếu tài liệu của khách đã được gắn nhãn phòng ban và mức mật, ABAC gọn hơn nhiều. Một luật kiểu “phòng ban của người hỏi trùng với phòng ban của tài liệu, và cấp bậc đủ cao so với mức mật” thay cho cả 60 vai trò, vì quyết định dựa trên thuộc tính của người, tài nguyên và môi trường.

AWS cho biết cách này cần ít policy hơn và tự mở rộng theo tài nguyên mới; cái giá là nhãn phải sạch, vì một file bảng lương bị quên gắn nhãn là lọt.

Nhưng nhiều khách chẳng gắn nhãn gì. Quyền của họ nằm ở chỗ thư mục “Lương” được share cho ai, tức là một quan hệ. ReBAC mô phỏng đúng điều đó: quyền xuất phát từ quan hệ giữa user, group và tài liệu, và bạn phải mô tả cả đồ thị quan hệ ấy; Zanzibar của Google thường được nhắc tới như hình mẫu.

PBAC trả lời một câu hỏi khác hẳn: luật nằm ở đâu và ai quản. Mọi quyết định được gom vào một policy engine với luật viết bằng ngôn ngữ khai báo, để đội bảo mật viết, version và audit, và đổi quyền nhanh mà không phải rà lại vai trò trên toàn tổ chức.

Mô hình Câu hỏi nó trả lời Hợp với khách khi Cái giá phải trả
RBAC Người này giữ vai trò gì? Tổ chức ít vai trò, cần audit đơn giản Số vai trò phình to, tài nguyên mới phải sửa policy
ABAC Thuộc tính của người, tài liệu, bối cảnh có khớp không? Tài liệu đã được gắn tag phòng ban, mức mật Thuộc tính phải sạch và được cập nhật
ReBAC Người này có quan hệ gì với tài liệu? Quyền đi theo thư mục, nhóm, người chia sẻ Phải mô tả và đồng bộ cả đồ thị quan hệ
PBAC Luật trung tâm nói gì? Đội bảo mật muốn quản luật như code Cần một policy engine và người duy trì luật

Bài học thực tế: khách nói “chúng tôi dùng vai trò” không có nghĩa họ dùng RBAC. Nếu quyền của họ nằm ở “ai được share thư mục này”, đó là quan hệ, và bạn nên mô phỏng bằng ReBAC.

Ví dụ: tài liệu kế thừa quyền từ thư mục

OpenFGA đưa ra một ví dụ rất gần với site khách: tài liệu thuộc về một thư mục và kế thừa người xem của thư mục đó, ai xem được thư mục thì xem được mọi tài liệu bên trong. Viết bằng ngôn ngữ mô hình của OpenFGA, quy tắc này chỉ cần vài dòng:

model
  schema 1.1

type user

type folder
  relations
    define viewer: [user]

type document
  relations
    define parent: [folder]
    define viewer: [user] or viewer from parent

Dòng cuối là toàn bộ logic kế thừa. Thư mục “Lương” chỉ có ban giám đốc là viewer, nên file bảng lương bên trong tự động chỉ hiện với họ, không cần một vai trò mới nào.

Bước tiếp theo là quyết định lọc ở đâu. OpenFGA mô tả hai cách: post-filter, tức truy vấn vector trước rồi kiểm tra quyền từng kết quả; và pre-filter, tức lấy danh sách tài liệu người dùng được xem trước, rồi truyền các ID đó làm bộ lọc cho vector search. Phác thảo pre-filter:

def retrieve(user_id, question, k=8):
    allowed = fga.list_objects(
        user=f"user:{user_id}",
        relation="viewer",
        type="document",
    )
    return vector_db.search(
        query=question,
        top_k=k,
        filter={"doc_id": {"$in": allowed}},
    )

Lý do nên ưu tiên pre-filter là một bài toán đếm đơn giản. Với post-filter, nếu bạn lấy top 8 và cả 8 chunk đều thuộc tài liệu mật, người dùng nhận về 0 chunk dù có tài liệu hợp lệ ở hạng thứ 9.

Pre-filter thì có rủi ro ngược lại: danh sách ID có thể rất dài với người xem được nhiều thứ, nên bạn phải đo trên dữ liệu thật của khách.

Làm từ đầu ở site khách thế nào?

Bắt đầu bằng discovery, không phải bằng code. Mang theo vài câu hỏi ngắn:

  • Tài liệu đang nằm ở những hệ thống nào?
  • Ai là người quyết định quyền?
  • Quyền gắn theo vai trò, theo tag hay theo thư mục được chia sẻ?
  • Khi một người nghỉ việc, quyền bị thu hồi ở hệ thống nào?

Câu trả lời cho câu cuối thường chỉ ra nguồn sự thật mà bạn phải bám vào.

Sau đó chọn mô hình theo cách quyền đang thật sự vận hành, không theo cái tên khách dùng. Quyền theo thư mục và chia sẻ thì nghiêng về ReBAC. Tài liệu đã có nhãn phòng ban, mức mật thì ABAC hợp hơn. Đội bảo mật muốn review luật như code thì cân nhắc PBAC.

Khi tài liệu nằm ở Drive, Confluence hay SharePoint, OpenFGA khuyên đồng bộ nội dung vào vector database và quyền vào OpenFGA, giữ cả hai khớp với hệ thống nguồn. Đây là hai pipeline, không phải một. Cả hai cần lịch chạy, cảnh báo khi lệch và cách xử lý khi xoá.

Cuối cùng, viết test bằng người dùng thật. Lấy ba tài khoản ở ba phòng ban, hỏi cùng một câu, và kiểm tra rằng tập tài liệu được trích dẫn khác nhau đúng như kỳ vọng.

Trong CV, đừng viết chung chung “làm RAG”; hãy viết bạn đã mô phỏng phân quyền cấp tài liệu và đồng bộ quyền từ hệ thống nguồn. Khi phỏng vấn cho một vị trí làm RAG cho doanh nghiệp, hãy chủ động hỏi họ xử lý quyền cấp tài liệu thế nào.

Câu hỏi đó vừa cho bạn biết độ chín của sản phẩm, vừa cho họ thấy bạn hiểu chỗ dự án hay vỡ.

Những cái bẫy hay gặp

Bẫy đầu tiên là đồng bộ quyền một lần lúc demo rồi quên. Nội dung có thể cũ vài ngày mà không ai để ý, nhưng quyền cũ vài ngày nghĩa là người vừa bị rút quyền vẫn hỏi được bot.

Bẫy thứ hai là để agent đọc tài liệu bằng một service account quyền rộng rồi trông chờ prompt tự kiềm chế. Bẫy thứ ba là xử lý mọi trường hợp lạ bằng cách tạo thêm vai trò, con đường ngắn nhất dẫn tới role explosion.

Bẫy cuối cùng là chỉ dùng post-filter với top-k cố định, khiến người ít quyền nhận câu trả lời rỗng và kết luận rằng bot “kém”. Lúc đó bạn sẽ mất niềm tin của đúng nhóm người dùng đông nhất.

Một ứng dụng AI ở doanh nghiệp được tin hay không không nằm ở việc nó trả lời hay đến đâu. Nó nằm ở việc nó im lặng đúng lúc, với đúng người.

7 nguồn
Đọc tiếp trên lộ trình · Chặng 5: Triển khaiThiết kế phản hồi lỗi theo RFC 9457 để đội vận hành của khách tự xử lý sự cốNếu API chỉ trả về một mã 500 kèm câu "Something went wrong", sự cố nào bên khách cũng sẽ thành ticket gửi về bạn. Vài trường JSON đặt đúng chỗ có thể thay đổi điều đó.