Skip to content

docs(monitoring): add OIDC authentication guide for Grafana#597

Open
IvanHunters wants to merge 4 commits into
mainfrom
docs/monitoring-oidc-authentication
Open

docs(monitoring): add OIDC authentication guide for Grafana#597
IvanHunters wants to merge 4 commits into
mainfrom
docs/monitoring-oidc-authentication

Conversation

@IvanHunters

@IvanHunters IvanHunters commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new guide under content/en/docs/next/operations/services/monitoring/: OIDC authentication for Grafana.

Documents how to enable per-user OIDC authentication on the Grafana instance shipped by every Monitoring release, using the new spec.oidc selector. Ships alongside cozystack/cozystack#3176, the code PR that adds the selector to the chart. The identity model is per-instance audience isolation on the flat cozy realm — same shape as the tenant kube-apiserver's Phase 1 (cozystack/cozystack#3044); architectural rationale in cozystack/community#24.

What

  • New page content/en/docs/next/operations/services/monitoring/oidc-authentication.md (weight: 5, positioned between setup.md (2) and dashboards.md (10)).
  • Covers all three modes (None, System, CustomConfig), the three role-mapping KeycloakRealmGroups the chart owns, how a user is added via KeycloakRealmUser, browser login flow, and gotchas: emailVerified prescriptive requirement, self-signed CA under CustomConfig.secretRef, admin_user break-glass posture.
  • Explicit "out of scope" section (per-tenant realms, backend-logout-url, CEL claimValidationRules) so readers know where the boundary sits.
  • Only adds to docs/next/; version-specific pages (v1.5, ...) get the guide when the code PR lands in a release.

Why

  • The spec.oidc selector on the Monitoring CR is a new user-facing surface — needs a user-facing guide before v1.6.
  • Uses the same tone and section shape as the tenant Kubernetes OIDC page (content/en/docs/next/kubernetes/oidc-authentication.md, docs(kubernetes): add OIDC authentication guide #596), so operators land on a familiar layout.
  • Site builds cleanly in dev mode (Hugo, 1686+ pages, zero warnings); the page is reachable at /docs/next/operations/services/monitoring/oidc-authentication/.

Summary by CodeRabbit

  • Documentation
    • Added detailed guidance for enabling OIDC authentication for Monitoring Grafana, including per-instance audience behavior that prevents token reuse across instances.
    • Documented supported OIDC modes (None, System, CustomConfig), required prerequisites, and the expected sign-in and role-mapping behavior.
    • Clarified group-based access control, admin opt-in behavior, and required Grafana OIDC settings (including version-specific considerations).
    • Expanded operational notes, gotchas, and limitations/out-of-scope items (e.g., break-glass admin password, CA handling, and effects of switching modes).

@netlify

netlify Bot commented Jul 1, 2026

Copy link
Copy Markdown

Deploy Preview for cozystack ready!

Name Link
🔨 Latest commit 23e94ad
🔍 Latest deploy log https://app.netlify.com/projects/cozystack/deploys/6a59d832b1a6f20008b5fa8e
😎 Deploy Preview https://deploy-preview-597--cozystack.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@IvanHunters, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 33f2862b-1dc8-4925-b69b-40bb41924810

📥 Commits

Reviewing files that changed from the base of the PR and between 9b34d67 and 23e94ad.

📒 Files selected for processing (1)
  • content/en/docs/next/operations/services/monitoring/oidc-authentication.md
📝 Walkthrough

Walkthrough

This PR adds a documentation page covering OIDC authentication for Cozystack Monitoring Grafana instances, including authentication modes, per-instance audience isolation, role and group handling, prerequisites, reconciliation, break-glass access, and operational limitations.

Changes

OIDC Authentication Documentation

Layer / File(s) Summary
OIDC authentication documentation
content/en/docs/next/operations/services/monitoring/oidc-authentication.md
Documents the None, System, and CustomConfig modes, per-instance audiences, Keycloak artifacts, Grafana configuration, user reconciliation, role mapping, group authorization, break-glass access, prerequisites, gotchas, and out-of-scope behavior.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested reviewers: kvaps

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the new Grafana OIDC authentication guide added under monitoring docs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/monitoring-oidc-authentication

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces documentation for configuring OIDC authentication for Grafana in Cozystack, detailing the available modes (System and CustomConfig), role assignment, and prerequisites. The review feedback suggests minor formatting improvements, such as replacing Unicode ellipsis characters with standard ASCII characters. Additionally, it corrects a technical inaccuracy by clarifying that Grafana does not support Kubernetes-style CEL claimValidationRules and that any such validation must be handled via JMESPath in role_attribute_path.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

role_attribute_path: "contains(groups[*], 'grafana-admins') && 'Admin' || 'Viewer'"
```

…or via a pre-existing Secret in the tenant namespace holding a ready-made `[auth.generic_oauth]` ini fragment in the `auth.ini` key:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using standard ASCII characters (like starting the sentence directly with Or) is preferred over the Unicode ellipsis character to ensure consistent rendering and avoid copy-paste issues.

Suggested change
…or via a pre-existing Secret in the tenant namespace holding a ready-made `[auth.generic_oauth]` ini fragment in the `auth.ini` key:
Or via a pre-existing Secret in the tenant namespace holding a ready-made `[auth.generic_oauth]` ini fragment in the `auth.ini` key:

username: alice@acme.example
email: alice@acme.example
emailVerified: true
password: "…"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use standard three dots ... instead of the Unicode ellipsis inside the code block.

Suggested change
password: ""
password: "..."


## Prerequisites and gotchas

- **`emailVerified: true` on Keycloak users.** Phase 1 does not add a `claimValidationRules` entry — so `email_verified` is not chart-enforced. Set `emailVerified: true` on the `KeycloakRealmUser` (or complete the email-verify flow through the Keycloak UI) so the identity holding a given email is guaranteed authentic. The `cozy` realm's default `duplicateEmails: false` prevents a second account from claiming an already-registered address. CEL `claimValidationRules` to make this a hard gate is a follow-up hardening path.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The mention of CEL claimValidationRules seems to be a copy-paste leftover from the Kubernetes OIDC guide. Grafana's generic OAuth does not support Kubernetes-style CEL (Common Expression Language) or claimValidationRules. Instead, claim validation or enforcement of email_verified in Grafana is typically achieved using JMESPath expressions within role_attribute_path (potentially combined with role_attribute_strict: true). Let's update this to refer to JMESPath-based enforcement instead of CEL claimValidationRules.

Suggested change
- **`emailVerified: true` on Keycloak users.** Phase 1 does not add a `claimValidationRules` entry — so `email_verified` is not chart-enforced. Set `emailVerified: true` on the `KeycloakRealmUser` (or complete the email-verify flow through the Keycloak UI) so the identity holding a given email is guaranteed authentic. The `cozy` realm's default `duplicateEmails: false` prevents a second account from claiming an already-registered address. CEL `claimValidationRules` to make this a hard gate is a follow-up hardening path.
- **`emailVerified: true` on Keycloak users.** The default configuration does not enforce `email_verified` in the role mapping. Set `emailVerified: true` on the `KeycloakRealmUser` (or complete the email-verify flow through the Keycloak UI) so the identity holding a given email is guaranteed authentic. The `cozy` realm's default `duplicateEmails: false` prevents a second account from claiming an already-registered address. Enforcing this in Grafana's `role_attribute_path` via JMESPath is a follow-up hardening path.

- **Per-tenant Keycloak realms.** Managed multi-tenant identity is a separate proposal, evaluated against Keycloak Organizations. Track it in the [community proposal](https://github.com/cozystack/community/pull/24).
- **Federating an external IdP into the platform `cozy` realm.** BYO-for-Cozystack-itself is a distinct problem — this feature is BYO-for-a-managed-service.
- **Full-logout through Keycloak's end-session endpoint.** Native `auth.generic_oauth` covers the OAuth part; `backend-logout-url` wiring is a follow-up.
- **CEL `claimValidationRules` for `email_verified`.** Explicit-gate hardening; not required for Phase 1 given the layered guarantees above.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since Grafana does not support CEL or claimValidationRules, we should clarify that this is a limitation of Grafana's OAuth capabilities rather than an out-of-scope feature that could be added later using CEL.

Suggested change
- **CEL `claimValidationRules` for `email_verified`.** Explicit-gate hardening; not required for Phase 1 given the layered guarantees above.
- **CEL `claimValidationRules` for `email_verified`.** Grafana does not support Kubernetes-style CEL validation rules; any such validation must be done via JMESPath in `role_attribute_path`.

@IvanHunters
IvanHunters marked this pull request as ready for review July 1, 2026 21:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@content/en/docs/next/operations/services/monitoring/oidc-authentication.md`:
- Line 53: Update both fenced configuration blocks in the OIDC authentication
documentation to include an appropriate language identifier, such as ini, on
each opening fence while leaving their configuration content unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 45d325e9-d03d-4247-9dbd-612f36f426c1

📥 Commits

Reviewing files that changed from the base of the PR and between 3aa9c29 and 710a840.

📒 Files selected for processing (1)
  • content/en/docs/next/operations/services/monitoring/oidc-authentication.md

Comment thread content/en/docs/next/operations/services/monitoring/oidc-authentication.md Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOT LGTM — the page is well-structured and the tone matches the tenant Kubernetes OIDC guide, but three of its claims contradict the code PR it ships alongside (cozystack/cozystack#3176). I checked each against that PR's templates, values and unit tests rather than against its prose.

Business context: a user-facing guide for the new spec.oidc selector on the Monitoring CR, landing in docs/next/ ahead of v1.6.

Blockers

B1: spec.oidc.grafanaAdmin does not exist, and the behaviour it describes is explicitly out of scope

Line 70: "Server-level GrafanaAdmin promotion is opt-in via spec.oidc.grafanaAdmin: true — the chart then sets allow_assign_grafana_admin: true … The platform bundle flips this on for the platform Grafana release."

The oidc struct in packages/extra/monitoring/values.yaml (as added by #3176) has exactly three fields: mode, customConfig, users. There is no grafanaAdmin. The string grafanaAdmin does not appear anywhere in #3176's diff. That PR's own operator guide states the opposite outright: "Server-level GrafanaAdmin promotion (allow_assign_grafana_admin) is out of scope for Phase 1. All Grafana instances — platform and tenant — cap at org-level Admin." And packages/system/monitoring/tests/oidc_test.yaml pins the absence with notExists: spec.config["auth.generic_oauth"].allow_assign_grafana_admin.

An operator following this paragraph would add a field the CR schema rejects. Remove the paragraph, and instead list server-level GrafanaAdmin under "What's out of scope".

B2: the example clientId is wrong

Line 47: "clientId set to <namespace>-<release> (for the CR above: tenant-acme-monitoring-system)."

The rule is right, the worked example is not. monitoring.oidc.clientId is printf "%s-%s" .Release.Namespace .Release.Name, and the Monitoring ApplicationDefinition sets release.prefix: "", so the CR shown just above (name: monitoring, namespace: tenant-acme) produces the release monitoring and therefore the clientId tenant-acme-monitoring. monitoring-system is the platform release name — the one living in cozy-monitoring, which the page itself names correctly two paragraphs earlier. As written, a reader hunting for their KeycloakClient looks for an object that does not exist.

B3: the "mode toggle prunes accounts" gotcha inverts the code

Line 150: "Flipping spec.oidc.mode from System to None prunes every user the users-Job provisioned … Flipping back re-provisions them empty."

oidc-users-job.yaml renders only when spec.oidc.users is non-empty, and its header comment says this is deliberate, naming mode=None as one of three empty-users states it guards: "a prune pass with an empty desired list would silently delete every non-admin Main-Org member on every helm upgrade … Removing the last users: entry therefore no longer prunes it."

So flipping SystemNone runs no Job and prunes nothing; the local Grafana accounts survive. The page tells operators to treat the toggle "like an admin-Secret rotation" — the opposite of the actual, deliberately-safe behaviour. Worth also re-checking the neighbouring claim under "Assigning roles" that removing a user from the list "deletes the account": the Job's documented action is pruning non-admin Main-Org members, which is an org-membership change, not necessarily account deletion.

Non-blocking follow-ups

  1. Two operator guides for one feature. #3176 also ships docs/oidc-grafana.md (410 lines) inside the monorepo, covering the same ground. Two authoritative guides will drift — this PR is already the proof, since all three blockers above are places where this page and that one disagree. Worth deciding which is canonical and having the other link to it.
  2. Docs are ahead of the code. #3176 is still open and unmerged, so nothing yet pins these claims. Sequencing the guide before the code it documents is precisely how the three errors above got in. Re-verify every claim against the merged code once #3176 lands.
  3. The branch is BEHIND its base; rebase before merge.


`skip_org_role_sync=true` keeps a login from overwriting the users-Job's role assignments; `oauth_allow_insecure_email_lookup=true` lets Grafana attach the OIDC identity to the pre-provisioned local account by email; `allow_sign_up=false` is the isolation lever — without it, Grafana's default `allow_sign_up=true` combined with `skip_org_role_sync=true` would mint a Viewer account for every `cozy`-realm identity that hits the login flow.

Server-level `GrafanaAdmin` promotion is opt-in via `spec.oidc.grafanaAdmin: true` — the chart then sets `allow_assign_grafana_admin: true` on the rendered `[auth.generic_oauth]` block. The platform bundle flips this on for the platform Grafana release (`monitoring-system` in `cozy-monitoring`); tenant Grafana releases inherit the chart default `false` and stay at org-level Admin.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spec.oidc.grafanaAdmin does not exist in the code PR this page ships alongside. The oidc struct in packages/extra/monitoring/values.yaml has exactly three fields — mode, customConfig, users — and the string grafanaAdmin appears nowhere in cozystack/cozystack#3176.

That PR states the opposite explicitly in its own guide: "Server-level GrafanaAdmin promotion (allow_assign_grafana_admin) is out of scope for Phase 1. All Grafana instances — platform and tenant — cap at org-level Admin." Its unit suite pins the absence: notExists: spec.config["auth.generic_oauth"].allow_assign_grafana_admin.

An operator following this paragraph would set a field the CR schema rejects. Please drop it and move server-level GrafanaAdmin into the "What's out of scope" section instead.


Cozystack provisions:

- A per-instance **`KeycloakClient`** in the `cozy` realm with `clientId` set to `<namespace>-<release>` (for the CR above: `tenant-acme-monitoring-system`). Confidential (`clientAuthenticatorType: client-secret`), `secret` sourced from a chart-owned Kubernetes Secret. `redirectUris` locked to `https://grafana.<host>/login/generic_oauth`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule (<namespace>-<release>) is right but the worked example is not. monitoring.oidc.clientId is printf "%s-%s" .Release.Namespace .Release.Name, and the Monitoring ApplicationDefinition sets release.prefix: "" — so the CR shown directly above (name: monitoring in tenant-acme) yields the release monitoring and the clientId tenant-acme-monitoring.

monitoring-system is the platform release name, in cozy-monitoring — which this page names correctly two paragraphs earlier. As written, a reader goes looking for a KeycloakClient that does not exist.

- **`groups_attribute_path` is not optional on Grafana v11.x+.** The chart wires it automatically for `System` mode; in `CustomConfig` inline the operator must add it explicitly (`groups_attribute_path: groups`) if their IdP emits a top-level `groups` array. Otherwise `allowed_groups` becomes a silent no-op and every login fails.
- **BYO issuer with a self-signed CA.** In `CustomConfig` mode the `secretRef` path is the way to ship a CA bundle alongside the `[auth.generic_oauth]` block — you package `auth.ini` and any `ca-cert` files into the Secret and mount both under `/etc/grafana/oidc`.
- **`admin_user` stays a break-glass path.** Even under `mode: System` the login form and the `grafana-admin-password` Secret remain wired. Locking the form off is a follow-up hardening.
- **Mode toggle drops the users-Job's local accounts.** Flipping `spec.oidc.mode` from `System` to `None` prunes every user the users-Job provisioned (the accounts are ephemeral shadows of `spec.oidc.users[]`). Any dashboards those users starred / owned move to their original creators; the local passwords / API keys go away. Flipping back re-provisions them empty. Treat mode toggle like an admin-Secret rotation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This inverts the code. oidc-users-job.yaml renders only when spec.oidc.users is non-empty, and its header comment says so deliberately, naming mode=None as one of three empty-users states it guards against: "a prune pass with an empty desired list would silently delete every non-admin Main-Org member on every helm upgrade … Removing the last users: entry therefore no longer prunes it."

So SystemNone runs no Job and prunes nothing — the local Grafana accounts survive. Telling operators to treat the toggle "like an admin-Secret rotation" is the opposite of the actual, deliberately-safe behaviour.

While you are here, please re-check the related claim under "Assigning roles" that removing a user from the list "deletes the account" — the Job's documented action is pruning non-admin Main-Org members, which is an org-membership change, not necessarily account deletion.

@IvanHunters

Copy link
Copy Markdown
Contributor Author

Aleksei Sviridkin (@lexfrei) thanks for the careful cross-check against #3176. I re-verified all three against the now-merged code. B1 and B3 were correct — both fixed in the latest commit. On B2 I have to push back: the worked example tenant-acme-monitoring-system is actually correct.

The key detail: the OIDC objects are rendered by the inner HelmRelease, not the outer Monitoring release.

packages/extra/monitoring/templates/helmrelease.yaml names the inner release with a -system suffix:

kind: HelmRelease
metadata:
  name: {{ .Release.Name }}-system

The clientId helper lives in packages/system/monitoring (the inner chart), so .Release.Name there is monitoring-system, not monitoring:

{{- define "monitoring.oidc.clientId" -}}
{{- printf "%s-%s" .Release.Namespace .Release.Name -}}
{{- end -}}

The merged e2e test pins exactly this — for a CR named monitoring in tenant-test:

CR_NAME="monitoring"
INNER_REL="${CR_NAME}-system"
CID="tenant-test-${INNER_REL}"   # tenant-test-monitoring-system
...
[ "${client_id}" = "${CID}" ]

(hack/e2e-apps/monitoring-oidc-system.bats, plus its header comment: "every OIDC identifier derived by the helpers (clientId, audience scope, client-secret Secret) is built off that inner name".)

So for the CR in the guide (name: monitoring, namespace: tenant-acme) the clientId is tenant-acme-monitoring-system. The -system is the inner-release suffix, not the platform release name. Since the <namespace>-<release> shorthand was genuinely confusing (it reads as if <release> = the CR name), I've added an explicit note that <release> resolves to the inner <CR-name>-system release.

B1, B3 and the org-membership-vs-account-deletion wording are all fixed in the same commit. On the non-blocking follow-ups: canonical-doc cross-linking and the rebase are noted.

Guide covers spec.oidc modes (None/System/CustomConfig) on the
Monitoring CR, how System mode provisions a per-instance Keycloak
client + audience scope + three role-mapping groups in the cozy
realm, and how a user logs in through the Grafana browser flow.
Placed under docs/next/operations/services/monitoring/ (weight 5,
between setup and dashboards); ships alongside the code PR that adds
the spec.oidc selector to the Monitoring chart.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
… loss note

Two doc updates paired with the cozystack chart fix:

- Server-level GrafanaAdmin promotion is now driven by an explicit
  spec.oidc.grafanaAdmin: true field (was: chart-side .Release.Name
  detection). Document the new field and where the platform bundle
  flips it on.
- Mode toggle (System → CustomConfig/None) deletes the three
  chart-owned <clientId>-{admin,editor,viewer} KeycloakRealmGroups
  and every user's membership goes with them. Not a bug, but a one-
  way UX cost on the toggle — document it under Prerequisites and
  gotchas so operators know before flipping.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…ob architecture

The website doc was written against the initial PR#3176 shape
(three chart-owned KeycloakRealmGroups + role_attribute_path mapping
groups to Admin/Editor/Viewer). Later commits on the code PR dropped
that architecture entirely — chart-owned groups gone (commit
3b36966e2), role_attribute_path replaced with skip_org_role_sync +
app-side users-map reconciled by a Job (commit sequence 2b3751edc /
7e2ac3cb8 / 4e8c5f4ed / e47308961 / b370998fc / efc27b33c). The
website guide had drifted six revisions behind the code.

Rewrite covers the actual current surface:

- spec.oidc.users[] with Grafana org-role (Admin/Editor/Viewer) is
  the assignment mechanism; users-Job reconciles it on every helm
  action.
- Login authorization is separate: allowed_groups gate on the
  tenant-scoped <ns>-{view,use,admin,super-admin} groups from the
  platform-managed cozy realm.
- groups_attribute_path=groups is REQUIRED on Grafana v11.x+
  alongside allowed_groups (matches the code fix committed on the
  cozystack side).
- CustomConfig inline vs secretRef with the users[] compatibility
  contract (secretRef requires users: []).
- Mode-toggle gotcha now describes the users-Job's ephemeral-account
  cleanup, not the deleted KeycloakRealmGroups.

Also drops the stale role_attribute_path example that used a
grafana-admins group name that this chart never provisioned.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Reconcile the guide with cozystack/cozystack#3176 as merged:

- Drop the spec.oidc.grafanaAdmin paragraph: the field does not exist
  (oidc struct is mode/customConfig/users only) and server-level
  GrafanaAdmin promotion is out of scope for Phase 1; list it under
  What's out of scope instead.
- Fix the mode-toggle note: the users-Job renders only when mode is not
  None and users[] is non-empty, so flipping to None prunes nothing and
  the provisioned accounts survive.
- Clarify that removing a user is an org-membership removal, not deletion
  of the Grafana account.
- Clarify that OIDC identifiers derive from the inner <CR-name>-system
  HelmRelease, so the example clientId tenant-acme-monitoring-system is
  correct.
- Add ini language to the two config fenced blocks and replace Unicode
  ellipsis with ASCII.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
@IvanHunters
IvanHunters force-pushed the docs/monitoring-oidc-authentication branch from 9b34d67 to 23e94ad Compare July 17, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants