For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/others/permissions-101.md.

Beginner guide to AEM permissions, group inheritance, and ACL evaluation.

Nội dung

  1. Giải thích nguyên nhân user bị thiếu quyền khi thao tác trên AEM (mở trang, sửa content, upload asset, replicate/publish, ...).
  2. Hiểu rõ ý nghĩa của wildcard và restriction ("", *, /*, */jcr:content*, ...) trong rep:glob.
  3. Cung cấp quy trình từng bước để troubleshooting lỗi phân quyền nhanh chóng.

1. Cơ chế phân quyền JCR & Oak

Trên AEM Author, dữ liệu như Page, Asset, Component, Configuration và User được lưu trữ dưới dạng Node/Property trong JCR Repository, được quản lý bởi Apache Jackrabbit Oak.

Cơ chế kiểm soát truy cập của JCR/Oak dựa trên Access Control List (ACL). Mỗi node có thể có node con rep:policy (type rep:ACL, orderable) chứa các Access Control Entry (ACE) (node type rep:GrantACE / rep:DenyACE). Mỗi ACE gồm rep:principalName, rep:privileges và optional node con rep:restrictions (chứa các restriction như rep:glob, rep:ntNames, ...). ACL restriction

Có thể hình dung quá trình authorization như sau: Authorization flow

Các thuật ngữ cốt lõi

Principal

Principal là identity được Oak sử dụng để đánh giá quyền truy cập, thường là User hoặc Group.

Ví dụ:

content-authors
dam-users
administrators
user123

Một user có thể là member của nhiều group. Khi Oak đánh giá quyền, các ACE áp dụng cho user và các group mà user thuộc về đều có thể tham gia vào quá trình authorization evaluation.

Privilege

Privilege mô tả một hoặc một nhóm thao tác mà Principal có thể thực hiện trên một JCR item.

Ví dụ:

jcr:read
jcr:modifyProperties
jcr:addChildNodes
jcr:removeNode
jcr:removeChildNodes
jcr:write
crx:replicate

Privilege có thể là:

  • Aggregate privilege: bao gồm nhiều privilege khác.
  • Non-aggregate privilege: privilege nguyên thủy.

Ví dụ:

jcr:write
├── jcr:modifyProperties
├── jcr:addChildNodes
├── jcr:removeNode
└── jcr:removeChildNodes

Do đó, jcr:write không phải là một thao tác cụ thể mà là một aggregate privilege bao gồm nhiều quyền thao tác khác. Lưu ý: jcr:write KHÔNG bao gồm jcr:nodeTypeManagement — muốn tạo node với node type mới (vd tạo page/component mới) phải cấp thêm privilege này.

ACE — Access Control Entry

ACE là một entry trong ACL, xác định một Principal được Allow hoặc Deny một hoặc nhiều Privilege tại một JCR path, có thể kèm theo Restriction.

Có thể biểu diễn một ACE như:

ACE
├── Principal
├── Privilege(s)
├── Allow / Deny
└── Restriction(s)

Ví dụ:

Principal   = content-authors
Path        = /content/my-site
Privilege   = jcr:read
Effect      = ALLOW
Restriction = rep:glob = "public/*"

Có thể hiểu:

content-authors được phép đọc các item phù hợp với restriction public/* trong phạm vi của ACE này.


Restriction

Restriction là một điều kiện giới hạn phạm vi áp dụng của ACE.

Restriction không phải là một Privilege và cũng không phải là Allow/Deny. Nó bổ sung điều kiện để xác định ACE áp dụng cho những item nào hoặc trong điều kiện nào.

Một restriction thường gặp trong AEM là:

rep:glob

Ví dụ:

rep:glob = "*/jcr:content*"

Có thể hiểu ở mức khái niệm:

ACE chỉ áp dụng cho các item/path phù hợp với pattern được chỉ định bởi rep:glob.

Restriction được lưu dưới dạng property trong node con rep:restrictions của ACE. Ngoài rep:glob, Oak còn hỗ trợ rep:ntNames, rep:prefixes, rep:itemNames, rep:globs (multi-value, Oak 1.44+), rep:subtrees (Oak 1.44+).


Allow / Deny

Allow / Deny xác định ACE đang cho phép hoặc từ chối các Privilege được khai báo.

Ví dụ:

ALLOW
  Principal: content-authors
  Privilege: jcr:read

DENY
  Principal: content-authors
  Privilege: jcr:modifyProperties

Allow/Deny là effect của ACE, không phải Action.

Permission

Permission nên được hiểu là quyết định authorization cuối cùng của Oak Security: một Principal có được phép thực hiện một thao tác tương ứng với required privilege trên một JCR item/path hay không.

Ví dụ:

Principal:
    content-authors

Target:
    /content/my-site/page/jcr:content

Required privilege:
    jcr:modifyProperties

             │
             ▼

     Oak Security Evaluation
             │
             ▼

       Permission Decision
             │
        ┌────┴────┐
        ▼         ▼
     GRANTED    DENIED

Do đó, có thể ghi nhớ:

Principal
    +
JCR Path / Item
    +
Required Privilege
    +
Applicable ACEs
       ├── Allow / Deny
       └── Restrictions
    ↓
Oak Security Evaluation
    ↓
Permission Decision
NOTE

Permission không phải là một thành phần đơn lẻ của ACE. ACE chứa thông tin về Principal, Privilege, Allow/Deny và Restriction. Permission là kết quả của quá trình Oak Security đánh giá các ACE áp dụng cho một Principal và một JCR item/path để quyết định thao tác có được phép hay không.

Tóm tắt

Khái niệmTrả lời câu hỏi
PrincipalAi?
JCR Path / ItemỞ đâu / trên resource nào?
PrivilegeĐược phép làm gì?
Allow / DenyCho phép hay từ chối?
RestrictionTrong điều kiện/phạm vi nào?
ACEMột rule authorization cụ thể
ACLTập hợp các ACE
PermissionQuyết định cuối cùng: được phép hay bị từ chối

Có thể nhớ ngắn gọn:

ACE là rule, ACL là tập hợp các rule, còn Permission là kết quả sau khi Oak đánh giá các rule đó.

Quy tắc đánh giá ACL (Oak Access Control Evaluation)

Khi user thao tác trên một JCR item, Oak thu thập các ACE khớp principal set (user + tất cả group của user) dọc theo cây từ target đi lên, sắp xếp chúng theo thứ tự ưu tiên, rồi lấy ACE khớp đầu tiên trong thứ tự đó làm kết quả:

Thứ tự ưu tiên (theo tài liệu chính thức Oak — Default Permission Evaluation):

  1. Mặc định DENY: Nếu không có ACE nào khớp trên toàn bộ đường đi từ target lên tới root → từ chối. (AEM docs: "If no permissions are defined for a page, then all actions are denied.")
  2. ACE cụ thể hơn thắng (Most specific path wins): Oak đánh giá từ node đang bị tác động, đi ngược lên các node cha cho tới khi gặp ACE khớp đầu tiên — ACE ở node gần target nhất được xét trước ACE kế thừa từ node cha. Hệ quả quan trọng: Deny ở node cha KHÔNG chặn được Allow ở node con cụ thể hơn. Ví dụ: deny jcr:read tại /content + allow jcr:read tại /content/public → subtree /content/public vẫn đọc được.
  3. ACE của User thắng ACE của Group: ACE gán trực tiếp cho user luôn được đánh giá trước ACE của các group mà user thuộc về, bất kể thứ tự trong danh sách hay độ sâu của node ("user principals always take precedence over group principals"). Ví dụ: user có allow tại /home/user-a trong khi group everyone có deny tại chính path đó → user vẫn có quyền.
  4. Trong cùng principal type + cùng path: ACE ghi SAU thắng (entry order): Các ACE trong một ACL được đánh giá theo thứ tự ngược với thứ tự được ghi vào danh sách — ACE ghi sau cùng có độ ưu tiên cao nhất, và ACE khớp đầu tiên trong thứ tự đánh giá quyết định kết quả. KHÔNG có quy tắc "Deny thắng Allow" trong Oak: một Deny chỉ thắng khi nó được ghi sau Allow cạnh tranh (hoặc là ACE của user).
  5. Restriction là một phần của điều kiện "khớp" ACE (rep:glob, rep:ntNames, ...) — nếu restriction không khớp item đang xét, ACE đó bị bỏ qua và Oak tiếp tục tìm ACE khác; restriction không phải một bước đánh giá riêng sau khi đã quyết định allow/deny.
  6. Administrators không bị ràng buộc bởi ACL: các principal admin (vd admin) luôn có toàn quyền trên toàn bộ repository, kể cả khi tồn tại ACE deny-everyone trên node.
WARNING

Yếu tố quyết định là thứ tự đánh giá ACE, không phải Allow hay Deny. Quan niệm "Deny luôn thắng Allow" là quy tắc của Jackrabbit 2.x / CRX 2 — Oak đã bỏ quy tắc này. Khi troubleshooting, hãy xem thứ tự thực tế của các ACE trong rep:policy (CRXDE → tab Access Control) hoặc trong file cấu hình Repoinit / Netcentric ACL Tool, đừng chỉ nhìn "có allow hay có deny".


2. Wildcard & Restriction Patterns (rep:glob)

rep:glob là restriction dùng để giới hạn phạm vi tác dụng của ACE xuống một tập item con bên dưới path được gán mà không cần tạo thêm ACE thủ công tại từng node con. Các ví dụ dưới đây lấy ACE gán tại /content/mysite:

Ký hiệuÝ nghĩa
TrốngKhông có quyền(Deny) - user/group không có quyền này trên path đó
✅Allow

3. Tại sao User bị thiếu quyền? (Root Causes & Hidden Dependencies)

Dev và Support Engineer rất hay gặp tình trạng: User được gán Allow trên path trang nhưng vẫn bị lỗi 403, không sửa được trang, hoặc bấm Replicate/Publish không có tác dụng.

Dưới đây là các nguyên nhân cốt lõi về Dependency của AEM Architecture:

Nguyên nhân 1: Thiếu Read permission trên Path cha (Hierarchy Scope)

Để mở được path /content/mysite/en/page-a, Oak yêu cầu user phải có jcr:read trên node đó và trên các node tổ tiên (để traverse cây JCR). Nếu user bị deny jcr:read ở /content hoặc /content/mysite (và không có allow cụ thể hơn ở dưới), user sẽ không thể đi xuyên cây để tới trang con. (Nhớ quy tắc most-specific-wins: một allow jcr:read tại node con cụ thể hơn sẽ khôi phục quyền đọc ở chính node con đó.)

Nguyên nhân 2: Thiếu Read trên các Path phụ thuộc (Hidden Dependencies)

Trang AEM không đứng một mình. Để render và chỉnh sửa 1 trang trên Author Instance, User bắt buộc phải có jcr:read trên:

  1. /conf/...: Nơi chứa Editable Templates, Content Policies, Page Component Configurations. Nếu thiếu -> Trang báo lỗi "Error loading page" hoặc trắng trang.
  2. /apps/... & /libs/...: Nơi chứa Client Libraries (JS/CSS), Component Dialogs, Granite UI icons. Nếu thiếu -> Dialog không mở được, UI bị hỏng.
  3. /content/dam/...: Nơi chứa Hình ảnh, Video, Content Fragments được nhúng vào trang. Nếu thiếu -> Không thấy asset trong Asset Finder hoặc không chọn được Image.
  4. /content/cq:tags/...: Nơi chứa taxonomy tags. Thiếu quyền -> Không chọn được Tag trong Page Properties.

Nguyên nhân 3: Nhầm lẫn giữa Node Privileges (Modify vs Add/Remove Child)

  • Edit Property (VD: Sửa Title, Description): Cần Privilege jcr:modifyProperties.
  • Thêm Component mới vào Layout Container: Cần jcr:addChildNodes + jcr:nodeTypeManagement (để tạo node component mới bên dưới jcr:content/root/... với node type riêng — jcr:write không bao gồm jcr:nodeTypeManagement).
  • Xóa / Di chuyển Component: Cần jcr:removeChildNodes (trên node cha) hoặc jcr:removeNode (trên chính node bị xóa); di chuyển thêm jcr:addChildNodes + jcr:nodeTypeManagement ở đích.

Nguyên nhân 4: Tại sao không Replicate / Publish được?

Để một Author bấm nút Quick Publish hoặc Manage Publication thành công:

  1. User cần privilege crx:replicate trên path trang /content/mysite/....
  2. User cần crx:replicate trên cả Assets phụ thuộc /content/dam/... nếu chọn "Publish with referenced assets".
  3. Việc ghi vào queue /var/replication/... do replication agent (chạy bằng service user / credentials riêng) đảm nhiệm — user tác giả KHÔNG cần quyền trên /var.
  4. Nếu site dùng workflow publish (Manage Publication với tùy chọn "Request for Publish"), user cần thuộc nhóm được phép khởi tạo workflow (vd workflow-users) để bắt đầu workflow.

4. Ma trận Thao tác Authoring vs JCR Path & Privilege

Bảng tra cứu nhanh dành cho Support Engineers & Developers khi cấp quyền cho Group:

Thao tác trên AEM Author UIJCR Path liên quanPrivileges tối thiểu cần gán
Mở Sites Console & Xem danh sách trang/content/mysitejcr:read
Xem / Mở trang trong Page Editor/content/mysite
/conf/mysite
/apps, /libs, /etc.clientlibs
jcr:read
Sửa Page Properties (Title, Meta, ...)/content/mysitejcr:read, jcr:modifyProperties
Thêm / Xóa Component vào trang/content/mysitejcr:read, jcr:modifyProperties, jcr:addChildNodes, jcr:removeChildNodes, jcr:nodeTypeManagement
Tạo trang mới (Create Page)/content/mysitejcr:read, jcr:addChildNodes, jcr:modifyProperties, jcr:nodeTypeManagement
Xóa trang (Delete Page)/content/mysitejcr:removeChildNodes, jcr:removeNode
Replicate / Publish trang/content/mysite
/content/dam/mysite (nếu publish kèm Asset)
crx:replicate
Upload & Quản lý Assets / DAM/content/dam/mysitejcr:read, rep:write (= jcr:write + jcr:nodeTypeManagement)
Publish Asset trong DAM/content/dam/mysitecrx:replicate
Sửa Editable Templates/conf/mysite/settings/wcm/templatesjcr:read, rep:write
Gán Tags trong Page Properties/content/cq:tagsjcr:read

5. Quy trình Troubleshooting dành cho Support Engineer & Dev

Khi nhận được Ticket báo lỗi "User X không thể làm Y (mở trang/sửa trang/publish)", hãy thực hiện 5 bước sau:

Bước 1: Kiểm tra User thuộc những Group nào?

  • Vào User Admin (/libs/granite/security/content/admin.html hoặc /security/users.html).
  • Tra cứu User, xem danh sách Groups mà User tham gia. Lưu ý các Group kế thừa (Group lồng Group).

Bước 2: Kiểm tra Phân quyền tại Path chính

  • Kiểm tra xem Group của User có được cấp jcr:read từ root /content xuống target path hay chưa (nhớ quy tắc most-specific-wins: deny ở cha có thể bị allow ở con cụ thể hơn ghi đè).
  • Thao tác Create/Edit/Publish đã có đúng Privilege tương ứng (xem Ma trận ở Section 4) chưa?

Bước 3: Soi các ACE xung đột (Deny vs Allow, thứ tự, rep:glob)

  • Liệt kê toàn bộ ACE áp dụng cho user và các group của user trên path đang lỗi (CRXDE → tab Access Control, hoặc đọc trực tiếp node rep:policy).
  • Nhớ 3 quy tắc đánh giá: (1) ACE của user thắng ACE của group; (2) ACE cụ thể hơn (node gần target) thắng ACE kế thừa từ cha; (3) cùng principal + cùng path thì ACE ghi sau thắng — không có quy tắc "Deny thắng Allow". Một Deny "có vẻ" không có tác dụng thường do bị Allow ghi sau (hoặc Allow của user) thắng.
  • Kiểm tra rep:glob: glob được nối vào path của node chứa ACE. Ví dụ rep:glob = "" chỉ ảnh hưởng đúng node đó (không phải con cháu); rep:glob = "*/jcr:content*" chỉ phủ các node jcr:content ở mọi cấp — nếu Allow chỉ phủ pattern này thì user sửa được nội dung trong trang nhưng không tạo/đổi tên/xóa được cq:Page (đúng thiết kế, không phải lỗi phân quyền).

Bước 4: Kiểm tra Path phụ thuộc (Dependencies)

  • Nếu User mở trang bị lỗi 403 / 500 hoặc không thấy Template: Kiểm tra quyền jcr:read trên /conf/<site-name>.
  • Nếu không thấy Asset: Kiểm tra quyền jcr:read trên /content/dam/<site-name>.

Bước 5: Verify bằng công cụ

  1. User Impersonation: Trong AEM Author, admin có thể Impersonate thành User đó để tái hiện lỗi trên giao diện UI.
  2. CRXDE Lite Access Control Tab: Chọn node -> Tab Access Control ở góc dưới phải để xem danh sách ACE thực tế đang có hiệu lực (kể cả thứ tự ACE).
  3. Repository initialiser (Repoinit) / Netcentric ACL Tool: Đảm bảo file cấu hình ACL trong codebase (Repoinit / YAML) khớp với môi trường đang chạy. Lưu ý thứ tự câu lệnh allow/deny trong file quyết định thứ tự ghi ACE — do đó quyết định ACE nào thắng khi xung đột.

Tài liệu tham khảo thêm