feat: switch Keycloak admin API calls to cluster-internal URL #150
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/basketball-api!150
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "149-keycloak-internal-url"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Keycloak admin API calls (account creation, password reset, user lookup) now route through the cluster-internal service URL (
http://keycloak.keycloak.svc.cluster.local) instead of the external Tailscale funnel (https://keycloak.tail5b443a.ts.net). This eliminates the ~50% TLS failure rate observed for in-cluster requests through the funnel.OIDC token validation in
auth.pyis unchanged -- it must use the external URL to match the token issuer claim in Keycloak-issued JWTs.Changes
src/basketball_api/config.py: Addedkeycloak_admin_urlconfig field defaulting to the cluster-internal servicesrc/basketball_api/routes/password_reset.py: Switchedget_admin_token,get_existing_user, andreset_parent_passwordcalls to usekeycloak_admin_urlsrc/basketball_api/routes/register.py: Switched bothcreate_account_for_parentcall sites to usekeycloak_admin_urlsrc/basketball_api/routes/admin.py: Switchedget_admin_tokenandreset_parent_passwordin tryout announcement to usekeycloak_admin_urlsrc/basketball_api/routes/webhooks.py: Switchedcreate_account_for_parentin Stripe webhook to usekeycloak_admin_urlk8s/deployment.yaml: AddedBASKETBALL_KEYCLOAK_ADMIN_URLenv var pointing to internal servicetests/test_keycloak_integration.py: Updated mocks and assertions to usekeycloak_admin_urltests/test_password_reset.py: Updated mocks and assertions to usekeycloak_admin_urlTest Plan
ruff checkandruff format --checkclean on bothsrc/andtests/Review Checklist
Related
Review: LGTM
Diff reviewed: 8 files, +18/-15 lines. All changes are mechanical substitutions of
settings.keycloak_base_urltosettings.keycloak_admin_urlat admin API call sites.Correctness
routes/andwebhooks.pythat previously usedkeycloak_base_urlfor admin API calls now usekeycloak_admin_url. Verified via grep -- zero remaining references tokeycloak_base_urloutside ofconfig.py.auth.pyis correctly untouched -- OIDC token validation useskeycloak_realm_url, which is unrelated.keycloak_base_urlis retained inconfig.pyfor backwards compatibility (no breakage if anything else references it).k8s/deployment.yamlcorrectly addsBASKETBALL_KEYCLOAK_ADMIN_URLenv var matching the pydantic-settingsenv_prefix = "BASKETBALL_"convention.Tests
keycloak_admin_url.Discovered scope (not blocking)
scripts/create_keycloak_accounts.pyhardcodesKEYCLOAK_BASE_URL = "https://keycloak.tail5b443a.ts.net"(its own constant, not usingsettings). This batch script is run manually from outside the cluster, so the external URL is likely correct there. Worth a follow-up issue if it ever runs in-cluster.PR #150 Review
DOMAIN REVIEW
Tech stack: Python / FastAPI / Pydantic / SQLAlchemy / httpx / k8s manifests
Config layer (config.py):
keycloak_admin_urlfield added toSettingswith correct defaulthttp://keycloak.keycloak.svc.cluster.local. PydanticBaseSettingswithenv_prefix = "BASKETBALL_"means it maps toBASKETBALL_KEYCLOAK_ADMIN_URL-- correct.keycloak_base_urlretained as a dormant field (no remaining consumers in routes). Acceptable -- removing it would be a separate cleanup.keycloak_realm_urlunchanged. Correct.Route migration (all 4 route files):
routes/register.py: Bothcreate_account_for_parentcall sites (lines 995, 1323) switched fromkeycloak_base_urltokeycloak_admin_url. Confirmed via grep -- zero remainingkeycloak_base_urlreferences in routes.routes/admin.py:get_admin_token(line 530) andreset_parent_password(line 551) switched. Correct.routes/password_reset.py: All three call sites (get_admin_tokenline 163,get_existing_userline 169,reset_parent_passwordline 178) switched. Correct.routes/webhooks.py:create_account_for_parent(line 298) switched. Correct.auth.py (MUST NOT change):
settings.keycloak_realm_urlfor JWKS and issuer validation. Does not referencekeycloak_base_urlorkeycloak_admin_url. OIDC token validation correctly continues to use the external realm URL for issuer claim matching.services/keycloak.py:
get_admin_token,get_existing_user,create_keycloak_user,get_realm_role,assign_realm_role,reset_parent_password,create_account_for_parent) acceptbase_urlas a parameter -- the callers now pass the internal URL. Clean separation of concerns.k8s/deployment.yaml:
BASKETBALL_KEYCLOAK_ADMIN_URLadded with valuehttp://keycloak.keycloak.svc.cluster.local. Correctly uses HTTP (no TLS for cluster-internal traffic). Placement is logical, adjacent toBASKETBALL_KEYCLOAK_REALM_URL.Test updates:
test_keycloak_integration.py: Mock settings updated fromkeycloak_base_url = "https://keycloak.test"tokeycloak_admin_url = "http://keycloak.internal". Assertions onmock_get_tokenandmock_get_existingcall args updated to match. BothTestRegisterAutoKeycloakAccountandTestRegisterDuplicateKeycloakSkipupdated.test_password_reset.py: Same pattern --mock_settings.keycloak_admin_urland assertion onmock_reset_pwbase_url kwarg updated. Bothtest_successful_resetandtest_keycloak_failure_returns_errorupdated.BLOCKERS
None.
NITS
Dormant
keycloak_base_urlconfig field (config.py:15): Now has zero consumers in route code. Consider removing it in a follow-up to avoid confusion about which URL to use. Not blocking since it's just a config definition with a default.scripts/create_keycloak_accounts.pystill uses hardcoded external URL (line 52:KEYCLOAK_BASE_URL = "https://keycloak.tail5b443a.ts.net"). This batch script runs inside the pod viakubectl execand would benefit from using the internal URL too. This is discovered scope -- should become a Forgejo issue, not part of this PR.SOP COMPLIANCE
149-keycloak-internal-url-> issue #149)Closes forgejo_admin/basketball-api#149)PROCESS OBSERVATIONS
auth.pyOIDC path is correctly left untouched.scripts/create_keycloak_accounts.pyshould be updated to use the internal URL when run in-cluster. Track as a separate issue.VERDICT: APPROVED