Files
cozystack/hack
myasnikovdaniil 6c9edf5038 fix(platform): route OIDC backend calls through the in-cluster Keycloak by default (#3289)
## What this PR does

Defaults `authentication.oidc.keycloakInternalUrl` to
`http://keycloak-http.cozy-keycloak.svc:8080/realms/cozy` instead of an
empty string.

With the empty default, oauth2-proxy performed OIDC discovery against
the external Keycloak hostname. That request resolves through public DNS
and lands on the root ingress controller, which does not serve yet on a
fresh install: the root tenant's IngressClass only exists once
`tenant-root` is ready, and `tenant-root` is still reconciling while the
dashboard starts. Discovery has nothing to talk to, the gatekeeper
fails, and the dashboard never comes up — with no obvious diagnosis for
a first-time installer.

The bundled Keycloak is the only supported provider (the external
hostname is templated as `keycloak.<host>` and the realm is fixed), so
backend-to-backend calls have no reason to leave the cluster. The new
default is the same Service address `keycloak-configure` already uses
for its own backend calls. The dashboard and linstor-gui gatekeepers
then run with `--skip-oidc-discovery` and send token, jwks, userinfo and
logout requests straight to the Service, while browser-facing redirects
stay on the external host.

Both gatekeeper templates already branch on the value being non-empty,
so neither needed a change. The value stays overridable for a Keycloak
that does not live at the standard in-cluster address, and setting it
back to `""` restores the previous external-discovery behaviour.

Token validation is unaffected: Keycloak pins `KC_HOSTNAME` to the
external URL, so tokens redeemed over the internal Service still carry
the external `iss` and match the unchanged `--oidc-issuer-url`.

### Upgrade behaviour

Existing OIDC clusters that never set `keycloakInternalUrl` pick up the
new default on upgrade: their gatekeepers roll once and move to the
internal path. Clusters that set the value explicitly — including to
`""` — keep exactly what they configured.

### Security posture

The backend leg (token redemption, which carries the gatekeeper's
Keycloak client secret, plus jwks/userinfo/logout) now travels as
plaintext HTTP between pods rather than HTTPS to the ingress. This is
stated in the `values.yaml` comment rather than left implicit. The
`keycloak-http` Service has no TLS listener, so in-cluster HTTPS is not
an available alternative, and `keycloak-configure` already sends
Keycloak *admin* credentials over that identical address — anyone
positioned to read this traffic can already reach a strictly more
powerful secret. The externally reachable front door (browser to
oauth2-proxy) is unchanged.

### Testing

helm-unittest coverage across all three affected charts: the default
landing on the `_cluster` channel, both gatekeepers rendering the
in-cluster backend URLs while keeping browser URLs external, an explicit
override winning, the empty-string escape hatch still rendering the
external-discovery shape, and OIDC-disabled clusters (now the common
case of "OIDC off, internal URL set") ignoring the value entirely.

The E2E OIDC case previously applied this exact URL as a manual
workaround. It now sets only `oidc.enabled` and asserts the consequence:
it waits for the `auth-proxy` container to appear in the gatekeeper
Deployment, then gates on `kubectl rollout status`. Readiness alone
would prove nothing there — the HelmRelease is still `Ready` from the
token-proxy install, and with `replicas: 1` and `maxUnavailable: 25%`
(which rounds down to 0) the Deployment keeps the old ReplicaSet
`Available` while a new pod crashloops. Only the rollout catches a
regression back to external discovery.

Follow-up: the OIDC documentation in the website repo still frames
`keycloakInternalUrl` as an optional tweak "for self-signed certificates
or restricted external access". It is now the default path and needs a
separate docs PR.

Closes #3288

### Screenshots

No UI changes.

### Release note

```release-note
fix(platform): `authentication.oidc.keycloakInternalUrl` now defaults to the in-cluster Keycloak Service (`http://keycloak-http.cozy-keycloak.svc:8080/realms/cozy`). OIDC backend calls from the dashboard and linstor-gui gatekeepers no longer leave the cluster, so enabling OIDC on a fresh install no longer leaves the dashboard down while the root ingress is not yet serving. Existing clusters that never set the value pick up the new default and roll their gatekeepers once. Set the value explicitly to point at a non-standard Keycloak placement, or to an empty string to restore external OIDC discovery.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- OIDC-enabled applications now use the internal Keycloak service for
backend authentication by default, improving reliability and avoiding
unnecessary external discovery.
- Browser redirects and login flows continue using the external Keycloak
address.
- Operators can provide a custom internal Keycloak URL or set it to an
empty value to restore external OIDC discovery.

- **Bug Fixes**
- Dashboard and Linstor GUI authentication now correctly apply internal
Keycloak settings only when OIDC is enabled.
- Dashboard upgrades now wait for authentication components to become
ready before completing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 13:08:56 +05:00
..
2026-02-17 22:54:12 +01:00