Link unlinked organizations to their Keycloak org by alias - #3993
Open
blarghmatey wants to merge 2 commits into
Open
blarghmatey wants to merge 2 commits into
blarghmatey wants to merge 2 commits into
Conversation
In production 45 of 71 organizations have no sso_organization_id. The reconciler only matches a Keycloak org to a page by UUID, so for a page that predates provisioning and shares its org_key with a realm alias it builds a second page, fails on the unique org_key, logs the error, and leaves the page unlinked on every run. This makes the reconciler link such a page to the Keycloak org whose alias is its org_key (ignoring case). More than one candidate page raises a ValidationError rather than guessing. A page already linked to a different Keycloak org is left alone. It also adds backfill_keycloak_orgs, which reports what the link would do and writes nothing without --apply. Pages with no Keycloak org are only reported unless --create-missing is passed, since some are demo or test orgs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WZoM2TYuY8g9C15R2dJNKy
OpenAPI ChangesShow/hide changesUnexpected changes? Ensure your branch is up-to-date with |
The rest of backfill_keycloak_organizations compares org_keys ignoring case, but the --org-key filter used an exact match. `--org-key utk` against a page keyed `UTK` matched nothing and reported nothing, which reads as success. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WZoM2TYuY8g9C15R2dJNKy
Comment on lines
+865
to
+866
| _link_organization(organization, keycloak_org.id) | ||
| claimed_ids.add(keycloak_org.id) |
Contributor
There was a problem hiding this comment.
Bug: The backfill_keycloak_organizations function does not handle cases where keycloak_org.id is None, leading to a silent failure to link the organization.
Severity: MEDIUM
Suggested Fix
Add a check in backfill_keycloak_organizations to validate that keycloak_org.id is not None before attempting to use it. If the ID is None, the iteration should be skipped or an error should be logged to prevent silent failures and potential data corruption.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: b2b/provisioning.py#L865-L866
Potential issue: In the `backfill_keycloak_organizations` function, the
`keycloak_org.id` can be `None` as per its type definition `str | None`. However, there
is no validation to handle this case. If `keycloak_org.id` is `None`, the code will
proceed to call `_link_organization(organization, None)`, which will silently fail to
link the organization by setting its `sso_organization_id` to `None`. The function would
then incorrectly report that the operation was applied successfully, leading to data
inconsistencies where an organization is believed to be linked in Keycloak but is not.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What are the relevant tickets?
Part of https://github.com/mitodl/hq/discussions/12784. Follows #3928 to #3932.
Description (What does it do?)
sso_organization_idto the Keycloak org whose alias equals itsorg_key(ignoring case), instead of building a duplicate page that fails on the uniqueorg_key.backfill_keycloak_orgscommand reports what linking would do. It writes nothing without--apply.--create-missingcreates Keycloak orgs for pages with no match, and--org-keylimits the run.As of 2026-09-18, production has 71 organizations and 45 have no
sso_organization_id. I have not checked how many of the 45 have a Keycloak org, so the dry run in prod is the first step after merge.Implementation details
reconcile_single_keycloak_orgused to match on UUID only.test_reconcile_bad_keycloak_orgshows the old behavior: theorg_keycollision surfaces as aValidationErrorfromsave(), whichreconcile_keycloak_orgslogs and skips.find_unlinked_page_for_aliasraisesValidationErrorwhen more than one unlinked page matches (e.g.UTKandutk). A page already linked to a different Keycloak org is not a candidate. Aliases longer thanORG_KEY_MAX_LENGTH(30) and missing aliases match nothing, so a long alias cannot match a page by its first 30 characters.save(), to skipfull_cleanand a Wagtail revision. It also creates theOrganizationOnboardingrecord.conflictfor a Keycloak org whose UUID is already on another page, and for pages that differ only in case (neither is linked).--create-missingwrites the Keycloak org first and the UUID second, with no compensating delete. If the second step fails, the reconciler links the org by alias on its next run. The Keycloak create body is now shared withcreate_organization(_create_keycloak_organization).How can this be tested?
Ran
pytest b2b/provisioning_test.py b2b/api_test.py b2b/commands_test.pyin the dev image against a throwaway Postgres and Redis: 266 passed, 1 skipped. The Keycloak side is mocked. Nothing has run against a real realm.After merge, run
manage.py backfill_keycloak_orgs(dry run) in QA, then in production, and check the link/create/no_keycloak_org split before using--apply.Additional Context
KEYCLOAK_ORG_SYNC_FREQUENCY, default 86400 s) will start linking matching pages on its next run after deploy. I did not check the production override for that setting.🤖 Generated with Claude Code
https://claude.ai/code/session_01WZoM2TYuY8g9C15R2dJNKy