Repository navigation
OIDC group gate: extend to ancestor tenants + guard platform Monitoring release #3259
Description
Follow-up from #3176 (round-3 review comment from Timofei Larkin (@lllamnyp)).
Context
#3176 (Grafana OIDC in Monitoring) and merged #3044 (tenant kube-apiserver OIDC) both emit a chart-owned tenant-membership gate admitting only <namespace>-{view,use,admin,super-admin} groups:
- Monitoring/Grafana:
auth.generic_oauth.allowed_groups(unconditional in System mode). - Kubernetes/apiserver: CEL
claimValidationRuleson thegroupsclaim.
Both use release namespace as tenant prefix. Closes the cross-tenant hole where any cozy-realm user could sign into any tenant's Grafana or authenticate against any tenant's cluster.
Gap — ancestor tenants excluded
Everywhere else tenant subjects resolve via cozy-lib.rbac.allParentTenantsAndThis, which yields every ancestor tenant + tenant-root. That is what makes a parent-tenant admin a subject of the RoleBindings in a child's namespace.
Current gate rejects at login:
tenant-acme-adminontenant-acme-dev's Grafana / cluster (even thoughtenant-acmeis-dev's ancestor by the RBAC model)tenant-root-super-adminon any tenant (even though root is everyone's ancestor)
Root operators can arguably bootstrap themselves via Keycloak + break-glass admin passwords. For parent tenants the semantic mismatch is less defensible.
Direction to settle: should the gate span ancestors — building the allowed_groups / CEL in [...] list from cozy-lib.rbac.allParentTenantsAndThis in both charts?
Strict-today was picked deliberately: it can be relaxed later without breaking anyone, whereas contracting the surface later would.
Detail A — users-map accepts an email outside admitted groups
The users-Job (Monitoring) and bootstrap Job (Kubernetes) pre-provision org membership / ClusterRoleBinding for every users[].email. If the underlying Keycloak identity is not in one of the tenant's four groups, everything renders and provisions clean, but the login is refused at the gate. Renders + provisions clean, cannot authenticate. Worth a sentence in docs/oidc-grafana.md and docs/oidc-tenant.md.
Detail B — platform Monitoring footgun
allowed_groups (and by symmetry the CEL rule) is derived from .Release.Namespace. The platform Monitoring release lives in cozy-monitoring, not a tenant-* namespace, so the helper computes cozy-monitoring-{view,use,admin,super-admin} — groups that exist nowhere in the realm → every OIDC login locked out.
Inert today because the platform bundle passes no component values and the instance stays at mode: None, but a footgun for whoever wires that up. Also relevant to the direction above: cozy-lib.rbac.allParentTenantsAndThis hard-fails on a non-tenant- prefix, so adopting it needs a guard for this exact case.
Suggested scope
- Extend the group list in both
packages/system/monitoring/templates/_helpers.tpl(monitoring.oidc.allowedGroups) andpackages/apps/kubernetes/templates/_helpers.tpl(kubernetes.oidc.groupsClaimValidationExpr) to include ancestor tenants when the release lives in atenant-*namespace. - Add a namespace guard for non-
tenant-releases (platform Monitoring incozy-monitoring) — either fail-close the render with an explicit error, or fall back to a policy the operator can configure (e.g.spec.oidc.allowedRealmGroupson the CR). - Add a documentation sentence about
spec.oidc.usersentries outside the admitted groups.
Activity
docs(monitoring): correct the release name the OIDC comment, guide an…