Skip to content

Commit f51ddca

Browse files
docs: use glossary to explain concepts
1 parent ee4f224 commit f51ddca

5 files changed

Lines changed: 197 additions & 32 deletions

File tree

docs/decisions/0002-authorization-model-foundation.rst

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -189,20 +189,6 @@ References
189189
Glossary
190190
********
191191

192-
* **Action**: The operation attempted on a resource (e.g., view, edit, delete).
193-
* **Attribute**: Property of a user or resource used in ABAC (e.g., user.profile.department == course.org).
194-
* **Authorization check**: The explicit way a service asks whether an operation is allowed, always expressed in S-A-O-C form.
195-
* **Authorization models**: Frameworks or approaches that define how to express who can do what, on which resource, and under which conditions. Common models include RBAC, ABAC, and ReBAC.
196-
197-
* **RBAC (Role-Based Access Control)**: Authorization model where access is granted based on roles assigned to users.
198-
* **Scoped RBAC**: A variant of RBAC where roles apply within a specific scope (e.g., organization, course, library).
199-
* **ABAC (Attribute-Based Access Control)**: Authorization model where access is granted based on attributes of the subject, object, and context (e.g., user's organization, resource type, time of day).
200-
* **ReBAC (Relationship-Based Access Control)**: Authorization model where access decisions are based on explicit relationships between subjects and objects, often modeled as a graph.
201-
202-
* **Permission**: Atomic unit of access (e.g., ``CREATE_COURSE``, ``EDIT_ROLE``).
203-
* **Policy**: A declarative rule that defines which subjects can perform which actions on which objects under which context. Policies are stored outside of code, versioned, and auditable.
204-
* **Relationship**: Link between entities granting access in ReBAC (e.g., user:alice#editor@course:math101).
205-
* **Resource**: The object being accessed (e.g., Course).
206-
* **Role**: A collection of permissions assigned to a user (e.g., Instructor).
207-
* **S-A-O-C (Subject-Action-Object-Context)**: The canonical shape of any authorization check: *is Subject allowed to perform Action on Object under Context?*
208-
* **Scope**: The boundary where a role applies (e.g., Instructor in Course A, Admin in Org B).
192+
See the :doc:`central glossary </references/glossary>` for definitions of all terms used across
193+
these ADRs, including :term:`Action`, :term:`Policy`, :term:`Role`, :term:`Scope`,
194+
:term:`S-A-O-C`, :term:`RBAC`, :term:`ABAC`, and :term:`ReBAC`.

docs/decisions/0005-architecture-and-data-modeling.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The architecture consists of several key components:
3232
- **Policy Store**: The database (via Django ORM) where all authorization policies are persisted. The policy store holds two categories of policies:
3333

3434
1. **Static policies**: Default role-permission definitions (e.g., the built-in permissions for ``library_admin`` or ``course_staff``) and action groupings. These are defined in the ``authz.policy`` file shipped with the package, and loaded into the policy store via the ``load_policies`` management command at deployment time. They are not meant to be edited by operators. A parallel Python representation exists in ``openedx_authz.constants`` (``roles.py``, ``permissions.py``) for use in code (e.g., migration scripts, API views).
35-
2. **Dynamic policies**: Created at runtime through the Policy Management API or Django Admin. These include role assignments (granting a user a role in a scope) and any operator-defined policy additions.
35+
2. **Dynamic policies**: Created at runtime through the Role Management API or Django Admin. These include role assignments (granting a user a role in a scope) and any operator-defined policy additions.
3636

3737
Both categories are stored in the same ``CasbinRule`` table and are loaded into the engine uniformly. The distinction is organizational, not structural.
3838

@@ -73,7 +73,7 @@ A Dedicated Open edX Layer for Authorization
7373
---------------------------------------------
7474
- Implement an Open edX-specific layer that encapsulates all authorization logic by interacting with the Authorization Engine, ensuring that services interact with a consistent interface.
7575
- The Open edX Layer provides a stable Enforcement API that abstracts Casbin internals, allowing services to request authorization decisions without needing to understand Casbin specifics.
76-
- Implement a Policy Management API within the Open edX Layer to allow administrators to manage and update authorization policies centrally.
76+
- Implement a Role Management API within the Open edX Layer to allow administrators to manage and update authorization policies centrally.
7777
- The Open edX Layer is implemented as a Django app (``openedx_authz``) installable as a pip dependency. It registers as both an LMS and CMS plugin via ``entry_points`` for automatic discovery. It may also serve as a shared library for other services.
7878
- All modifications to the Authorization Engine configuration (model, adapters, etc.) are done through the Open edX Layer, so no forks of Casbin are needed.
7979

@@ -236,7 +236,7 @@ Consequences
236236
#. **New Components in the Open edX Ecosystem**: There are several new components introduced as part of this architecture:
237237
- Policy Store: The database tables (``CasbinRule``, ``ExtendedCasbinRule``, ``PolicyCacheControl``, ``Scope`` subclasses, ``Subject`` subclasses) managed through the Django ORM.
238238
- Enforcement API: The Public Python API and REST API for enforcing authorization policies and making authorization decisions.
239-
- Policy Management API: Functions for creating, updating, and deleting dynamic policies in the Policy Store.
239+
- Role Management API: Functions for creating, updating, and deleting dynamic policies in the Policy Store.
240240
- Open edX Layer: The ``openedx_authz`` Django app that abstracts access to the Policy Store and provides a unified interface for authorization.
241241
- Authorization Engine: The Casbin-based ``AuthzEnforcer`` singleton that evaluates authorization requests based on defined policies.
242242

@@ -271,6 +271,7 @@ Consequences
271271
References
272272
**********
273273

274+
- :doc:`/references/glossary` — definitions of :term:`Authorization Engine`, :term:`Policy Store`, :term:`Enforcement API`, :term:`Open edX Layer`, :term:`Static Policy`, :term:`Dynamic Policy`, :term:`Scope`, :term:`Subject`, and other terms used in this ADR.
274275
- `Authorization Model Foundations ADR`_
275276
- `Technology Selection ADR`_
276277
- `ADR 0007`_

docs/decisions/0006-policy-store-and-enforcement-model.rst

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Status
88
Context
99
*******
1010

11-
This ADR details how authorization policies are stored, versioned, and configured across the platform. It defines the Policy Store as the single source of truth, describes the relational database schema and metadata, and establishes naming conventions for subjects, actions, objects, and contexts. It also specifies the Casbin ``model.conf`` configuration, including the default matcher, allow/deny effects, static vs. dynamic policies, versioning rules, and how services ship and manage their ``authz.policy`` files.
11+
This ADR details how authorization policies are stored, versioned, and configured across the platform. It defines the :term:`Policy Store` as the single source of truth, describes the relational database schema and metadata, and establishes naming conventions for :term:`subjects<Subject>`, :term:`actions<Action>`, objects, and contexts. It also specifies the Casbin :term:`model configuration<Model Configuration>` (``model.conf``), including the default :term:`matcher<Matcher>`, allow/deny effects, :term:`static<Static Policy>` vs. :term:`dynamic policies<Dynamic Policy>`, versioning rules, and how services ship and manage their ``authz.policy`` files.
12+
13+
.. seealso:: :doc:`/references/glossary` for definitions of all terms used in this ADR.
1214

1315
Decision
1416
********
@@ -49,43 +51,43 @@ Use ``authz.policy`` Files for Default Policies
4951
#. Policy Management and Versioning
5052
====================================
5153

52-
Store Dynamic Policies Directly in the Policy Store
53-
---------------------------------------------------
54-
- Consider two types of policies: static policies (shipped with services in ``authz.policy`` files) and dynamic policies (created and managed via the Policy Management API and persisted in the policy store).
55-
- Dynamic policies created via the Policy Management API will be stored directly in the policy store (MySQL database) using a Casbin adapter.
54+
Store Dynamic Policies Directly in the Policy Store (Django ORM Adapter)
55+
------------------------------------------------------------------------
56+
- Consider two types of policies: static policies (shipped with services in ``authz.policy`` files) and dynamic policies (created and managed via the Role Management API and persisted in the policy store).
57+
- Dynamic policies created via the Role Management API will be stored directly in the policy store (MySQL database) using a Casbin adapter.
5658

5759
Differentiate Between Static and Dynamic Policies
5860
-------------------------------------------------
5961
- Static policies (default) should be differentiated from dynamic policies in the policy store using a metadata field (e.g., ``is_static`` boolean field) and should be immutable after being loaded from the ``authz.policy`` file.
60-
- Dynamic policies can be created, updated, and deleted via the Policy Management API, allowing administrators to adapt policies to changing requirements without modifying service code.
62+
- Dynamic policies can be created, updated, and deleted via the Role Management API, allowing administrators to adapt policies to changing requirements without modifying service code.
6163
- Using dynamic policies allows for greater flexibility and adaptability, as policies can be modified in response to evolving business needs or security requirements. However, they might also introduce complexity and potential performance overhead if not defined and managed carefully.
6264

6365
Version Static Policies and Make Dynamic Policies Immutable
6466
-----------------------------------------------------------
65-
- Version the ``authz.policy`` files with the service version to ensure that changes to static policies are tracked and can be rolled back if needed.
66-
- Dynamic policies created via the Policy Management API should be immutable once created. To change a dynamic policy, it should be deleted and recreated with the desired changes. This approach ensures that policy changes are auditable and traceable.
67+
- Version the ``authz.policy`` files with the along with the framework version to ensure that changes to static policies are tracked and can be rolled back if needed.
68+
- Dynamic policies created via the Role Management API should be immutable once created. To change a dynamic policy, it should be deleted and recreated with the desired changes. This approach ensures that policy changes are auditable and traceable.
6769
- Implement auditing and logging for all policy changes, including who made the change, when it was made, and what the change was. This is crucial for maintaining security and compliance.
6870

6971
#. Authorization Source of Truth
7072
=================================
7173

7274
Make the Policy Store the Single Source of Truth
7375
------------------------------------------------
74-
- The ``model.conf`` with the Casbin model configuration (``model.conf``) and the policy store (via MySQL adapter) together form the single source of truth for authorization in Open edX.
76+
- The ``model.conf`` with the Casbin model configuration (``model.conf``) and the policy store (via Django ORM adapter) together form the single source of truth for authorization in Open edX.
7577
- The policy store contains all dynamic policies and the static policies loaded from the ``authz.policy`` files at service initialization.
7678
- The policy store is the single source of truth for authorization rules. By default, services share the same store to ensure consistency and avoid conflicts.
7779

7880
Allow Shared or Separate Policy Stores as Needed
7981
------------------------------------------------
80-
- By default, all services share the same policy store to ensure consistency and avoid conflicts.
82+
- By default, all services share the same policy store (LMS) to ensure consistency and avoid conflicts.
8183
- If isolation between services is required, this can be achieved in two ways: (1) by using a namespace or domain field in the shared table, or (2) by creating a separate policy store for a specific service.
8284

8385
#. Authorization Ownership
8486
===========================
8587

8688
Delegate Policy Ownership to Services
8789
-------------------------------------
88-
- Services are responsible for defining their own policies in the ``authz.policy`` files and managing their own dynamic policies via the Policy Management API.
90+
- Services are responsible for defining their own policies in the ``authz.policy`` files and managing their own dynamic policies via the Role Management API.
8991
- These policies are managed by each service according to its domain. For example, the LMS manages courseware access policies, while the CMS manages content creation policies.
9092
- Authorization decisions must always be answered by the service that owns the relevant data and policies (policy owner). For instance, the LMS decides whether a user can access a course because it owns enrollments and courseware data. The CMS decides whether a user can edit content because it owns the content data.
9193
- The policy store is by default shared across services, but each service is responsible for its own policies and authorization decisions.
@@ -122,7 +124,7 @@ Consequences
122124

123125
#. **Static Policies will be Immutable**: Policies defined in the ``authz.policy`` files will be immutable after being loaded into the policy store. For a policy to be removed, should go through a deprecation cycle where it is first marked as deprecated and then removed in a future version.
124126

125-
#. **Each Service Should Define Its Own Policies (``authz.policy``)**: Each service is responsible for defining its own policies in the ``authz.policy`` files and managing its own dynamic policies via the Policy Management API. This ensures that services can tailor their authorization rules to their specific needs while maintaining a clear boundary of responsibility. If no defaults are defined, the service will start with an empty policy set.
127+
#. **Each Service Should Define Its Own Policies (``authz.policy``)**: Each service is responsible for defining its own policies in the ``authz.policy`` files and managing its own dynamic policies via the Role Management API. This ensures that services can tailor their authorization rules to their specific needs while maintaining a clear boundary of responsibility. If no defaults are defined, the service will start with an empty policy set.
126128

127129
#. **Clients Share the Same Policy Store**: By default, all services share the same policy store to ensure consistency and avoid conflicts. This means that policies defined by one service can affect authorization decisions in another service.
128130

0 commit comments

Comments
 (0)