feat: add multiple SSO tenants during devstack provisioning - #2662
Conversation
1cf425c to
3d81e45
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2662 +/- ##
==========================================
+ Coverage 86.73% 86.97% +0.23%
==========================================
Files 260 261 +1
Lines 17064 17143 +79
Branches 1687 1693 +6
==========================================
+ Hits 14801 14910 +109
+ Misses 1927 1896 -31
- Partials 336 337 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
999a8ad to
505cd6d
Compare
| """ | ||
| Management command for assigning a system-wide enterprise role to an existing user. | ||
| """ |
505cd6d to
1f80582
Compare
| call_command('saml', pull=True) | ||
| with mock.patch('common.djangoapps.third_party_auth.tasks.validate_saml_metadata_url'): | ||
| call_command('saml', pull=True) |
There was a problem hiding this comment.
This patch is needed to bypass recently-added validation in openedx-platform which forces all SAML providers to use HTTPS. This is a non-starter for devstack and using keycloak locally.
1f80582 to
415805f
Compare
| # Super admin with the admin role on all enterprises. | ||
| get_or_create_enterprise_user( | ||
| username=ENTERPRISE_ADMIN_ROLE, | ||
| role=ENTERPRISE_ADMIN_ROLE, | ||
| applies_to_all_contexts=True, | ||
| ), | ||
| get_or_create_enterprise_user( | ||
| username=ENTERPRISE_OPERATOR_ROLE, | ||
| role=ENTERPRISE_OPERATOR_ROLE, | ||
| applies_to_all_contexts=True, | ||
| ), | ||
| # Service workers as operators for all enterprises. | ||
| get_or_create_enterprise_user( | ||
| username='license-manager_worker', | ||
| role=ENTERPRISE_OPERATOR_ROLE, | ||
| applies_to_all_contexts=True, | ||
| ), | ||
| get_or_create_enterprise_user( | ||
| username='enterprise-catalog_worker', | ||
| role=ENTERPRISE_OPERATOR_ROLE, | ||
| applies_to_all_contexts=True, | ||
| ), | ||
| get_or_create_enterprise_user( | ||
| username='enterprise_worker', | ||
| role=ENTERPRISE_OPERATOR_ROLE, | ||
| applies_to_all_contexts=True, | ||
| ), | ||
| get_or_create_enterprise_user( | ||
| username='ecommerce_worker', | ||
| role=ENTERPRISE_OPERATOR_ROLE, | ||
| applies_to_all_contexts=True, | ||
| ), |
There was a problem hiding this comment.
For one reason or another, these were all useless cruft. Devstack itself is responsible for provisioning worker users, and it does a better job at that.
There was a problem hiding this comment.
Pull request overview
This PR expands the devstack SAML/Keycloak provisioning setup to support multiple SSO “tenants” (Gryffindor, Slytherin) to enable integration testing of enterprise logistration flows across different SSO configurations.
Changes:
- Extend
provision-tpa.py+ Keycloak realm inputs to provision multiple tenant realms/IdPs and enterprise branding in a single workflow. - Add devstack provisioning helpers (SAML provider creation, branding upload, user cleanup, system-wide role assignment) and a new CLI command to assign system-wide enterprise roles.
- Add an ENT-11568 provisioning script and expand unit tests around the new devstack helper/command behavior.
Critical issues:
enterprise/devstack_api.pycurrently calls optional imports (UserProfile,SAMLProviderConfig) unconditionally and has a non-idempotent/unsafecreate_system_wide_role_assignmentlookup. These can break provisioning or role assignment behavior in certain environments.
Reviewed changes
Copilot reviewed 17 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_enterprise/test_devstack_api.py | Adds/updates unit tests for new devstack helper functions (branding, SAML provider provisioning, role assignment, user cleanup). |
| tests/test_enterprise/management/test_seed_enterprise_devstack_data.py | Adds tests for seed_enterprise_devstack_data, including --no-create-users. |
| tests/test_enterprise/management/test_assign_system_wide_enterprise_role.py | Adds tests for the new assign_system_wide_enterprise_role command (scoping/idempotency/errors). |
| scripts/provision-integration-test-ENT-11568.sh | Introduces a devstack provisioning script for ENT-11568 integration test fixtures. |
| provision-tpa.py | Refactors provisioning to support multiple tenants; seeds operator, per-tenant enterprise/IdP/branding/users, and pulls SAML metadata. |
| keycloak-realms/slytherin.json | Updates Slytherin realm to use tenant-specific env vars and adds a second “newcomer” user. |
| keycloak-realms/gryffindor.json | Adds a new Gryffindor realm definition with learner + newcomer users. |
| keycloak-devstack.properties | Switches Keycloak import to load all realm JSONs from /config directory. |
| keycloak-devstack.env | Splits shared vs per-tenant configuration and defines Gryffindor/Slytherin realm/user variables. |
| enterprise/management/commands/seed_enterprise_devstack_data.py | Adds --no-create-users, removes redundant global users, seeds a single global operator, and scopes tenant user creation/linking. |
| enterprise/management/commands/create_enterprise_linked_learner.py | Minor adjustment to call get_or_create_user with explicit keyword args. |
| enterprise/management/commands/assign_system_wide_enterprise_role.py | Adds new command to assign system-wide enterprise roles with all-contexts or customer-scoped options. |
| enterprise/devstack_api.py | Adds helpers for branding upload, SAML provider provisioning, system-wide role assignment, global operator seeding, and user cleanup; adjusts user creation behavior. |
| enterprise/init.py | Bumps package version to 8.7.2. |
| docs/saml_testing.rst | Updates documentation to describe multi-tenant provisioning and new Gryffindor/Slytherin testing flows. |
| docker-compose.yml | Updates Keycloak config-cli container to mount keycloak-realms/ directory rather than a single realm JSON. |
| CHANGELOG.rst | Adds 8.7.2 release notes for multi-tenant SSO provisioning changes. |
kiram15
left a comment
There was a problem hiding this comment.
Looks good, but wasn't able to get the redirect to the keycloak login locally in testing
415805f to
dfca956
Compare
dfca956 to
fc3b325
Compare
The goal is ultimately to support integration testing logistration flows which depend on many different enterprise SSO configurations, including multi-tenant configurations. Changes directly in service of that goal: - Update provision-tpa.py to provision multiple SSO tenants (gryffindor, slytherin). - Add devstack_api.py helpers for SAML providers, enterprise branding, etc. - Add ENT-11568 integration-test script. Cleanup work along the way: - Eliminated legacy code that provisioned several redundant worker and admin users (devstack already provisions them). - Add `assign_system_wide_enterprise_role` management command to finally fix this: https://github.com/edx/devstack/blob/4e42eeda/provision-enterprise-access.sh#L25 - [Performance] Add --no-create-users flag to seed_enterprise_devstack_data command ENT-11568
fc3b325 to
151ced5
Compare
The goal is ultimately to support integration testing logistration flows which depend on many different enterprise SSO configurations, including multi-tenant configurations.
Changes directly in service of that goal:
Cleanup work along the way:
assign_system_wide_enterprise_rolemanagement command to finally fix this: https://github.com/edx/devstack/blob/4e42eeda/provision-enterprise-access.sh#L25ENT-11568
Smoke Test
127.0.0.1 edx.devstack.keycloakto /etc/hosts.py_configuration_files/lms.py:ENABLE_AUTHN_MICROFRONTEND = Falsemake lms-stop && make lms-upgryffindor_learner@example.comedxgryffindor_learnertestpass