Skip to content

feat: add multiple SSO tenants during devstack provisioning - #2662

Merged
pwnage101 merged 1 commit into
masterfrom
pwnage101/ENT-11568-multi-tenant-devstack
Jul 28, 2026
Merged

feat: add multiple SSO tenants during devstack provisioning#2662
pwnage101 merged 1 commit into
masterfrom
pwnage101/ENT-11568-multi-tenant-devstack

Conversation

@pwnage101

@pwnage101 pwnage101 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

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:

ENT-11568


Smoke Test

  1. Add 127.0.0.1 edx.devstack.keycloak to /etc/hosts.
  2. Start relevant devstack services:
    make dev.up.lms+frontend-app-authn+frontend-app-learner-portal-enterprise
    
  3. From the edx-enterprise directory, provision keycloak and run this script:
    make dev.provision.keycloak
    ./scripts/provision-integration-test-ENT-11568.sh
    
  4. Disable the AuthN MFE in py_configuration_files/lms.py:
    • set ENABLE_AUTHN_MICROFRONTEND = False
    • make lms-stop && make lms-up
  5. Open a fresh incognito tab and go to this URL: http://localhost:18000/login?tpa_hint=saml-gryffindor
    • Expect to see a Gryffindor logo.
    • email: gryffindor_learner@example.com
    • password: edx
  6. Open a fresh incognito tab and go to this URL: http://localhost:18000/auth/login/tpa-saml/?idp=gryffindor
    • Expect to get redirected to a keycloak login page titled "GRYFFINDOR".
    • username: gryffindor_learner
    • password: testpass
  7. Repeat steps 3-5 with the AuthN MFE enabled.

@pwnage101
pwnage101 force-pushed the pwnage101/ENT-11568-multi-tenant-devstack branch 3 times, most recently from 1cf425c to 3d81e45 Compare July 24, 2026 00:39
@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.29060% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.97%. Comparing base (4b78a36) to head (151ced5).

Files with missing lines Patch % Lines
enterprise/devstack_api.py 97.91% 0 Missing and 1 partial ⚠️
...nagement/commands/seed_enterprise_devstack_data.py 94.11% 0 Missing and 1 partial ⚠️
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     
Flag Coverage Δ
unittests 86.97% <98.29%> (+0.23%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment on lines +1 to +3
"""
Management command for assigning a system-wide enterprise role to an existing user.
"""

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See also edx/devstack#227

@pwnage101
pwnage101 force-pushed the pwnage101/ENT-11568-multi-tenant-devstack branch from 505cd6d to 1f80582 Compare July 25, 2026 01:19
Comment thread provision-tpa.py
Comment on lines -121 to +207
call_command('saml', pull=True)
with mock.patch('common.djangoapps.third_party_auth.tasks.validate_saml_metadata_url'):
call_command('saml', pull=True)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@pwnage101
pwnage101 marked this pull request as ready for review July 25, 2026 01:27
@pwnage101
pwnage101 force-pushed the pwnage101/ENT-11568-multi-tenant-devstack branch from 1f80582 to 415805f Compare July 25, 2026 01:46
Comment on lines -71 to -102
# 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,
),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py currently calls optional imports (UserProfile, SAMLProviderConfig) unconditionally and has a non-idempotent/unsafe create_system_wide_role_assignment lookup. 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.

Comment thread enterprise/devstack_api.py
Comment thread enterprise/devstack_api.py
Comment thread enterprise/devstack_api.py Outdated
Comment thread scripts/provision-integration-test-ENT-11568.sh Outdated

@kiram15 kiram15 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but wasn't able to get the redirect to the keycloak login locally in testing

Comment thread CHANGELOG.rst
Comment thread provision-tpa.py
Comment thread enterprise/devstack_api.py
@pwnage101
pwnage101 force-pushed the pwnage101/ENT-11568-multi-tenant-devstack branch from 415805f to dfca956 Compare July 28, 2026 01:00
@pwnage101
pwnage101 requested a review from Copilot July 28, 2026 01:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 22 changed files in this pull request and generated 2 comments.

Comment thread keycloak-devstack.properties Outdated
Comment thread enterprise/devstack_api.py
@pwnage101
pwnage101 force-pushed the pwnage101/ENT-11568-multi-tenant-devstack branch from dfca956 to fc3b325 Compare July 28, 2026 01:18
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
@pwnage101
pwnage101 force-pushed the pwnage101/ENT-11568-multi-tenant-devstack branch from fc3b325 to 151ced5 Compare July 28, 2026 01:23
@pwnage101
pwnage101 merged commit 5779fab into master Jul 28, 2026
11 checks passed
@pwnage101
pwnage101 deleted the pwnage101/ENT-11568-multi-tenant-devstack branch July 28, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants