posit-dev / posit-dev/team-operator
Keycloak DB provisioning fails when main-database-url has an explicit port (Hostname/Host compare asymmetry)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 10
- Forks
- 1
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 4
Description
Found standing up a Keycloak-enabled Site on team-operator v1.30.2 (workshop rebuild, rstudio/rstudio-ide-automation#5619).
Symptom: the Site's <site>-keycloak PostgresDatabase never reconciles — postgres database mismatched db host — so the keycloak role/database are never created and the Keycloak StatefulSet crashloops on FATAL: password authentication failed for user "keycloak".
Cause: an asymmetry in how the keycloak path builds its PostgresDatabase versus how the reconciler compares hosts:
internal/controller/core/site_controller_keycloak.gobuilds the config withHost: dbUrl.Hostname()— port stripped.internal/controller/core/postgresdatabase_controller.go(~L448) comparesspecDbUrl.Host != mainDBURL.Host—url.Hostincludes the port.
So whenever the workload secret's main-database-url carries an explicit :5432, the keycloak compare fails unconditionally (spec side is portless), while connect/pm/workbench pass because their spec URLs retain the port. Deployments with portless URLs (the PTD convention) never hit it, which is presumably why it went unnoticed.
Repro: Site with keycloak.enabled: true and a workload secret main-database-url of postgresql://host:5432/db?sslmode=require.
Workaround: write main-database-url without the explicit port (postgres defaults to 5432).
Suggested fix: compare hostnames consistently — either specDbUrl.Hostname() != mainDBURL.Hostname() in the reconciler, or keep the port in the keycloak path (Host: dbUrl.Host).
Addendum — second asymmetry in the same path (username): the reconciler provisions the role from the PostgresDatabase URL username (<site>_keycloak, e.g. workshop_site_keycloak), but the Keycloak CR wires usernameSecret to the site secret's keycloak-db-user key, which nothing forces to match. A deployment supplying keycloak there gets a Keycloak that can never authenticate (FATAL: password authentication failed for user "keycloak") while the actual role sits unused. Suggested fix: derive both from one source — either provision the role from usernameSecret, or render usernameSecret from the URL username.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with internal/controller/core/site_controller_keycloak.go and the host comparison around line 448 of internal/controller/core/postgresdatabase_controller.go. Reproduce with keycloak enabled and main-database-url set to postgresql://host:5432/db?sslmode=require, then trace the usernameSecret path as well. Done means explicit ports no longer trigger a host mismatch and the provisioned database role matches the username used by Keycloak.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes, postgresql
- Domain
- backend, database, devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100