RBAC / AuthZ – Milestone 0 (M0)
1. Overview
Milestone 0 introduces the foundational integration between the Open edX platform and the new AuthZ authorization framework, focusing on Course Authoring. The goal of this milestone is to establish the foundation required to migrate from the legacy role management system used in Course Authoring to a policy-based authorization system powered by Casbin, while maintaining compatibility with the existing system.
This milestone focuses on:
Establishing the migration path between legacy roles and AuthZ policies
Providing safe rollback capabilities
Adding initial frontend support for managing roles
Ensuring operational safety during the transition period
Introduce feature flags to safely enable and test the new functionality.
The changes implemented in this milestone allow the new AuthZ system to coexist with the legacy authorization model, enabling incremental adoption.
2. Release Notes
New Features
1. Migration tooling between legacy roles and AuthZ
Introduced migration scripts to convert legacy
CourseAccessRoleassignments into AuthZ roles.Added reverse migration capability to restore legacy roles from AuthZ policies.
Key PRs:
2. AuthZ integration in the platform
Introduced initial integration points between openedx-platform and the AuthZ service.
Role assignments can now be propagated through the new authorization API layer.
3. Frontend integration
Added frontend changes to support the new role management flows in the authoring interface.
Key PR:
4. Authorization service improvements
Improvements to role assignment APIs
Additional tooling for role migration
Enhancements to the internal AuthZ data model
Related issue:
openedx-authz#180
3. Feature Flag (Waffle Flag)
To safely introduce the new authorization functionality, Milestone 0 includes a Waffle feature flag that controls whether the AuthZ-based role management is enabled.
Feature flags in Open edX allow developers and operators to gradually roll out functionality and safely test new features in production environments without impacting all users.
The feature flag introduced in this milestone enables the platform to:
Toggle the use of the AuthZ authorization layer.
Allow testing and validation in controlled environments.
Provide a rollback mechanism if issues arise.
When the flag is disabled, the platform continues to rely entirely on the legacy authorization system.
When enabled, role assignments and authorization checks can be routed through the new AuthZ framework while still maintaining compatibility with the legacy role storage.
This incremental rollout strategy ensures that the migration to the new authorization system can be performed safely and progressively.
Testing instructions
How to use
# Import the flag
from openedx.core.toggles import AUTHZ_COURSE_AUTHORING_FLAG
# Check if it's enabled, passing the course_key
is_enabled = AUTHZ_COURSE_AUTHORING_FLAG.is_enabled(course_key=course_key)To enable it globally:
In the Django Admin, go to Home > django-waffle > Flags (/admin/waffle/flag/)
Click on ADD FLAG
Set the Name to "authz.enable_course_authoring"
Set Everyone: "Yes"
Click "Save"
To enable for a specific course (or override if it was previously enabled globally):
In the Django Admin, go to Home > Waffle_Utils > Waffle flag course overrides (/admin/waffle_utils/waffleflagcourseoverridemodel/)
Click on "ADD WAFFLE FLAG COURSE OVERRIDE"
Set Waffle flag to "authz.enable_course_authoring"
Set Course id to the desired course key
Set Override choice to the desired effect
Check the "Enabled" box
Click "Save"
To enable for an org (or override if it was previously enabled globally):
In the Django Admin, go to Home > Waffle_Utils > Add Waffle flag org override (/admin/waffle_utils/waffleflagorgoverridemodel/)
Click on "ADD WAFFLE FLAG ORG OVERRIDE"
Set Waffle flag to "authz.enable_course_authoring"
Set Course id to the desired Org name
Set Override choice to the desired effect
Check the "Enabled" box
Click "Save"
How will the flag behave:
Course level flags take precedence over Org level flags.
Both override the global Flag.
Course and Org level flags need to be "Enabled" for the override to apply
Caveats:
Waffle Flags allow configuring the flag to be enabled to specific users or groups of users. This won't be supported by the openedx-authz implementation because it would cause validation inconsistencies. A Waffle Switch would have been a better fit, but there are no existing ways to override Waffle Switchs for specific courses or orgs.
4. Migration Strategy
The migration process converts legacy course authoring roles stored in CourseAccessRole into AuthZ role assignments.
Each legacy role entry is translated into an equivalent role assignment using the AuthZ role assignment API.
Migration is executed using a Django management command.
Migration Command
./manage.py authz_migrate_course_authoringRequired Filters
To prevent accidental full migrations, the command requires a filter.
You must specify either:
--course-id-list--org-id
Example:
./manage.py authz_migrate_course_authoring \
--course-id-list course-v1:edX+DemoX+Demo_CourseExample using organization ID:
./manage.py authz_migrate_course_authoring \
--org-id edXBoth options cannot be used together.
Optional Flag: Delete Legacy Roles
Legacy roles can be removed after successful migration using the --delete flag.
Example:
./manage.py authz_migrate_course_authoring \
--org-id edX \
--deleteIf this flag is used, the command prompts for confirmation before deleting legacy roles.
Only successfully migrated roles are deleted.
Operational Behavior
In the final system behavior, migrations are expected to be executed with the equivalent of the --delete option enabled (this is currently not implemented and is expected to be available in the next milestone).
The compatibility layer assumes that once a course is migrated to the AuthZ system, the legacy CourseAccessRole entries should no longer exist for that course. Maintaining role assignments in both systems simultaneously may lead to inconsistent authorization behavior.
For this reason, production migrations should remove legacy roles after a successful migration.
Automation via Feature Flags
The current CLI-based migration command is primarily intended for development, testing, and operational debugging.
In the final rollout process, migrations will be automatically triggered when enabling or disabling the relevant AuthZ feature flags. This ensures that role assignments remain consistent with the active authorization system without requiring manual intervention.
Migration Safety
The migration command includes several safety mechanisms:
Requires explicit filtering (
--course-id-listor--org-id)Prevents using both filters simultaneously
Requires confirmation before deletion
Runs inside a database transaction
Only deletes roles that were successfully migrated
If the migration fails due to an unexpected error, the transaction is rolled back.
5. Rollback Strategy
If issues occur after enabling the AuthZ system, administrators can restore legacy role assignments.
The rollback process reads role assignments from the AuthZ system and recreates equivalent entries in the CourseAccessRole model.
Rollback Command
./manage.py authz_rollback_course_authoringRequired Filters
Rollback requires specifying either:
--course-id-list--org-id
Example:
./manage.py authz_rollback_course_authoring \
--course-id-list course-v1:edX+DemoX+Demo_CourseExample using organization ID:
./manage.py authz_rollback_course_authoring \
--org-id edXOptional Flag: Remove AuthZ Assignments
To remove AuthZ assignments after restoring legacy roles:
--deleteExample:
./manage.py authz_rollback_course_authoring \
--org-id edX \
--deleteWhen enabled, the command prompts for confirmation before removing the AuthZ assignments.
6. Known Limitations
The M0 implementation introduces several temporary limitations.
1. Partial system coverage
AuthZ currently supports only a limited subset of role scopes and use cases.
Some services still rely exclusively on legacy authorization.
2. Dual authorization systems
Both legacy and AuthZ systems coexist during the transition.
This may cause temporary complexity in debugging authorization decisions.
3. Limited UI coverage
The UI only exposes a subset of the new authorization capabilities.
Advanced policy management remains backend-only.
4. Role parity assumptions
The migration assumes that legacy roles have direct equivalents in the AuthZ model.
Custom or non-standard roles may require manual validation.
7. Operational Playbook
This section provides guidance for running the migration and handling issues during the transition.
Running the Migration
Example migration:
./manage.py authz_migrate_course_authoring \
--org-id edX --deleteExample migrating specific courses:
./manage.py authz_migrate_course_authoring \
--course-id-list course-v1:edX+DemoX+Demo_Course --deleteVerifying Migration
Administrators can verify migration results by checking both systems.
Check legacy roles
SELECT * FROM student_courseaccessrole
WHERE course_id = '<COURSE_ID>';If --delete was used, successfully migrated entries will not appear.
Check AuthZ policies
AuthZ role assignments are stored in the Casbin rule table.
Example query:
SELECT * FROM openedx_authz_extendedcasbinrule;Administrators should verify that the expected role assignments exist.
Debugging Migration Failures
Migration errors may occur if:
a role mapping does not exist
a role assignment fails
a database error occurs
Typical log messages include:
Unknown access levelor
Failed to migrate permission for UserWhen failures occur:
review application logs
identify affected users or courses
correct the issue
re-run the migration for the affected scope
Re-running Migration
The migration command can be safely re-run.
Existing role assignments will not create duplicate assignments in the AuthZ system.
Performing a Rollback
If problems occur, administrators can restore legacy roles.
Example rollback:
./manage.py authz_rollback_course_authoring \
--org-id edXExample for a specific course:
./manage.py authz_rollback_course_authoring \
--course-id-list course-v1:edX+DemoX+Demo_CourseRemoving AuthZ Assignments After Rollback
To remove AuthZ assignments after restoring legacy roles:
./manage.py authz_rollback_course_authoring \
--org-id edX \
--deleteRecovery Procedure
If issues occur after migration:
run the rollback command
verify legacy roles were restored
investigate migration errors
correct any data or mapping issues
re-run the migration
Because migration and rollback run inside database transactions, unexpected failures will automatically roll back database changes.