Files
computer-playbook/plugins/lookup/sso_oidc_plugin.py
kevinveenbirkenbachandClaude Opus 5 9a68f0eaaf fix(sso): read the OIDC gate's flags through the rendering config lookup
meta/addons/oidc_login.yml gates on lookup('sso_oidc_plugin'), which the applications render evaluates while it is still in flight. Under that re-entry guard the merged view hands out service flags as their own Jinja text, and bool("{{ ... }}") is True. The lookup read services.sso.enabled and services.ldap.enabled as enabled on a deployment with neither Keycloak nor OpenLDAP and announced oidc_login, so Nextcloud advertised a login hand-off to a provider that is not there.

lookup('config', ...) renders the value it returns, which is why the roughly ninety '| bool' sites in meta/ do not have this problem. 238bc285c7 established reaching the merged config through the lookup loader; this one had not been converted. utils.roles.applications.config.get is the raw accessor and does not render.

Measured against the real render: with only web-app-nextcloud deployed the addon set is now empty; adding Keycloak yields sociallogin; adding OpenLDAP as well yields oidc_login. That is the resolution order the lookup's own docstring documents. All 14 nextcloud variants pin both flags as literal booleans, so no CI-deployed variant changes.

The stub next to the plugin answered every lookup with the applications payload; it now mirrors lookup('config', app, path, default). A stub resolves a path but does not render it, so it cannot see this defect at all: the regression test renders for real.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 11:52:15 +02:00

55 lines
2.0 KiB
Python

from __future__ import annotations
from typing import Any
from ansible.errors import AnsibleError
from ansible.plugins.loader import lookup_loader
from ansible.plugins.lookup import LookupBase
_APPLICATION_ID = "web-app-nextcloud"
class LookupModule(LookupBase):
"""
lookup('sso_oidc_plugin')
Resolves the effective OIDC plugin flavor for the Nextcloud role.
Resolution order:
1. "" if services.sso.enabled is falsy (no OIDC plugin should be
active when the OIDC service itself is disabled — otherwise
Nextcloud would still hand off to Keycloak using a redirect_uri
that the client no longer whitelists).
2. An explicit string value at applications['web-app-nextcloud']
.services.sso.oidc.plugin (inventory override).
3. "oidc_login" if services.ldap.enabled is truthy
(pulsejet/nextcloud-oidc-login, proxy-LDAP capable).
4. "sociallogin" otherwise (nextcloud/sociallogin).
Mirrors the former `_applications_nextcloud_oidc_flavor` group_vars helper
that was removed in commit 77a0e16ea.
"""
def run(self, terms, variables: dict[str, Any] | None = None, **kwargs):
if terms:
raise AnsibleError("lookup('sso_oidc_plugin') takes no positional terms.")
templar = getattr(self, "_templar", None)
variables = variables or getattr(self._templar, "available_variables", {}) or {}
config = lookup_loader.get("config", loader=self._loader, templar=templar)
def _setting(path: str, default: Any) -> Any:
return config.run([_APPLICATION_ID, path, default], variables=variables)[0]
if not bool(_setting("services.sso.enabled", False)):
return [""]
explicit = _setting("services.sso.oidc.plugin", None)
if isinstance(explicit, str) and explicit.strip():
return [explicit.strip()]
ldap_enabled = bool(_setting("services.ldap.enabled", False))
return ["oidc_login" if ldap_enabled else "sociallogin"]