Skip to content

Commit e8dd6c9

Browse files
committed
docs: add adr-0012-glob-support-for-role-assignments
1 parent 16a6bbb commit e8dd6c9

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
0012: Glob Support For Role Assignments
2+
#######################################
3+
4+
Status
5+
******
6+
7+
**Draft** - *2026-03-18*
8+
9+
Context
10+
*******
11+
12+
The current authorization system is based on Casbin and models:
13+
14+
- **Permissions per role** (``p`` policies), where the ``scope`` field may already use patterns (for example, ``lib^*``) through matcher functions in the model.
15+
- **Role assignments** (``g`` policies), which link a subject to a role within a scope.
16+
17+
The current Casbin model treats the ``scope`` field in ``g`` policies as an **exact match**. This is sufficient when roles are granted for a single, concrete scope value, but it is limiting when operators need to:
18+
19+
- Assign roles that are valid for a **set of resources** that share a common prefix (for example, all courses or all content libraries belonging to a given organization).
20+
- Avoid enumerating a large or evolving set of resources one by one, which increases operational overhead and risk of drift.
21+
22+
This ADR proposes enabling glob-like matching for role assignments, so that a single ``g`` policy can represent a multi-scope assignment such as:
23+
24+
.. code:: text
25+
26+
g, user^contributor, role^course_staff, course-v1^course-v1:OpenedX+*
27+
28+
In that example, checking a permission such as:
29+
30+
.. code:: text
31+
32+
authz_api.is_user_allowed("contributor", "courses.manage_advanced_settings", "course-v1:OpenedX+Some+Course")
33+
34+
should be allowed if the user's role assignment matches the ``course-v1:OpenedX+*`` pattern.
35+
36+
At the same time, we must preserve the guarantees of the authorization model:
37+
38+
- **Safety**: Glob patterns must not accidentally grant permissions outside of the intended boundary.
39+
- **Clarity**: Patterns must be easy to understand and reason about for operators and auditors.
40+
- **Extensibility**: The mechanism should be general enough to support future use cases without requiring a redesign of the model.
41+
42+
Decision
43+
********
44+
45+
We will introduce support for glob-like matching on the ``scope`` field of **role assignments** (``g`` policies), combined with explicit validation in the public APIs that manage those assignments.
46+
47+
The decision is intentionally **general**: the core change is to allow glob matching for scopes in ``g`` policies, and to guard its usage with well-defined, namespace-specific validation rules. This creates a foundation that can be extended later without changing the Casbin model again.
48+
49+
1. Enable glob matching on ``g`` scopes in the enforcer
50+
=======================================================
51+
52+
We will configure the ``AuthzEnforcer`` to use a domain/scope matching function for ``g`` policies that supports glob-like suffixes. Concretely:
53+
54+
- The enforcer will register a domain matching function for the ``g`` (grouping) function (for example, using ``key_match_func``).
55+
- This matching function will treat ``*`` as a wildcard at the **end** of the string. That is, patterns such as ``course-v1:OpenedX+*`` will match ``course-v1:OpenedX+SOME+COURSE``, but the model will not rely on complex patterns or regular expressions.
56+
- Existing ``g`` policies that use exact scopes remain valid and continue to behave identically.
57+
58+
This change allows the Casbin engine to evaluate role assignments that apply to a family of scopes instead of a single exact value, without modifying the underlying storage schema (``CasbinRule``) or the overall request format (``r = sub, act, scope``).
59+
60+
2. Validate glob scopes at the API boundary
61+
===========================================
62+
63+
All APIs that create, update, or delete role assignments (i.e., policies of type ``g``) must validate any scope that includes a glob pattern. The goals of validation are:
64+
65+
- **Constrain** what forms of glob are permitted for each namespace.
66+
- **Reject** malformed or overly broad patterns that would be difficult to reason about or audit.
67+
68+
The following rules apply initially:
69+
70+
- The glob character (``*``) is only supported as a **suffix wildcard**. It cannot appear in the middle of a scope identifier.
71+
- A glob pattern represents a **bounded prefix match** for the external key portion of a scope within its namespace. The API validation ensures the prefix is meaningful (i.e., it corresponds to a valid identifier boundary for that namespace), so the glob cannot be used to accidentally broaden access.
72+
- For any glob patterns (courses, libraries, or future namespaces), malformed inputs (such as mid-string wildcards or prefixes that do not match the expected key format/boundaries) are **rejected**.
73+
- Additional namespaces must define their own, explicit validation rules before accepting glob scopes.
74+
- As needs evolve, more glob types can be added safely by introducing namespace-specific semantics and validations (for example, additional prefix boundaries such as program/tenant prefixes, or narrower matching strategies if required).
75+
76+
These validation rules are implemented in the Open edX layer (API / data layer), not in the Casbin matcher itself. The enforcer remains general-purpose. The domain-specific semantics of what constitutes an acceptable glob pattern are enforced at the boundary where user/operator input is turned into policies.
77+
78+
3. Keep the model general and extensible
79+
========================================
80+
81+
By introducing glob support in role assignments in a constrained way, we unlock a set of future extensions without redesigning the model:
82+
83+
- **Other scope types**
84+
85+
- Scope types with hierarchical or prefix-based identifiers (for example, libraries or other content groupings) can adopt glob support by:
86+
87+
- Defining their own namespace-specific rules for valid suffix globs.
88+
- Reusing the same enforcer-level domain matching capability.
89+
90+
- **Future matching strategies**
91+
92+
- If, in the future, there is a strong need for more expressive matching (for example, segment-based matching or multiple wildcards), these can be introduced as **new, explicitly-scoped features** with their own validation rules and migration story.
93+
- For now, we deliberately keep glob support simple and limited (single trailing ``*``) to minimize complexity and security risk.
94+
95+
Consequences
96+
************
97+
98+
Positive consequences
99+
=====================
100+
101+
- **Increased expressiveness**: Operators can express multi-scope role assignments (for example, "course staff for all courses in organization OpenedX") without enumerating each course in individual ``g`` policies.
102+
- **Reduced operational overhead**: New resources that fall under an existing glob pattern automatically inherit the appropriate role assignments, reducing the need for ongoing manual updates.
103+
- **Better alignment with real-world use cases**: Many organizational setups naturally require "all resources under this prefix" semantics. Glob support maps directly to those needs.
104+
- **Clear extension path**: The mechanism is generic enough to be reused for other namespaces (such as organization or library scopes), as long as each namespace defines and enforces its own validation rules.
105+
106+
Negative consequences / risks
107+
=============================
108+
109+
- **Security and safety**: If validation is misconfigured or bypassed, glob patterns could unintentionally grant access beyond the intended boundary. This risk is mitigated by:
110+
111+
- Enforcing validation in the Open edX API layer.
112+
- Restricting globs to trailing ``*`` patterns.
113+
- Defining precise, namespace-specific rules.
114+
115+
- **Complexity in mental model**: Operators and developers must understand that some role assignments apply to families of scopes instead of a single scope. This can be addressed by:
116+
117+
- Providing clear documentation and examples for glob-based assignments.
118+
- Exposing introspection tooling that explains which policies matched a given decision.
119+
120+
- **Performance considerations**: Glob matching adds some overhead to Casbin evaluations. However:
121+
122+
- The cost of simple suffix matching is low.
123+
- The policy store still uses the same schema and indexing strategy.
124+
- The feature should be used primarily for coarse-grained groupings (e.g., by organization), not for highly fragmented patterns.
125+
126+
Rejected Alternatives
127+
**********************
128+
129+
- **Keep exact matching only for 'g' scopes**
130+
131+
- Pros:
132+
133+
- Simpler to reason about.
134+
- No changes to matcher configuration.
135+
- Cons:
136+
137+
- Does not scale for environments with many resources per organization.
138+
- Forces operators to maintain large numbers of nearly-identical assignments.
139+
140+
- **Introduce full regular-expression support on scopes**
141+
142+
- Pros:
143+
144+
- Maximum flexibility for expressing patterns.
145+
- Cons:
146+
147+
- Harder to reason about and audit.
148+
- Higher risk of misconfiguration and security overshoot.
149+
- Potentially worse performance.
150+
151+
References
152+
**********
153+
154+
- `Casbin function documentation (matching functions) <https://casbin.org/docs/function/>`_

0 commit comments

Comments
 (0)