ADORSYS-GIS / ADORSYS-GIS/ai-helm

[Ticket]: Read-only Grafana Postgres datasource over the governance database

Abierto
#879 0 comentarios 0 reacciones 0 asignados Ver en GitHub
governance grafana ticket
Lenguaje dominante
Go Template
Estrellas
3
Forks
1
Merge medio
19 h 24 min
PR fusionados (30 d)
80

Descripción

### Type

Operational task

### Summary

We need a **read-only Grafana Postgres datasource over the `governance` database**, because the governance dashboards — which are **the product** — read tenant, application, repo and team as *columns* rather than as metric labels.

Expected result:
> A `GrafanaDatasource` pointing at a least-privilege read-only role on the governance database, with the Cilium egress that makes it reachable, so dashboards can be built against it.

### Intent

This is what lets both connectors drop most of their metric-publishing and all of their low-cardinality label constraints. Usernames, repos, teams and applications become columns. The "keep cardinality low, avoid `username` labels" constraint that shapes the source specs simply evaporates for the business dashboards — Mimir keeps only the ~10 operational metrics.

It is not a new idea here: ADR-0063 already runs exactly this pattern for the Keycloak user directory (`uid: keycloak`).

### Source of truth (links)

- Epic: ADORSYS-GIS/lightbridge-governance#4
- Enables the dashboards in ADORSYS-GIS/lightbridge-governance#5
- Roadmap: ADORSYS-GIS/ai-helm#872 §2 ("The Grafana-reads-Postgres pattern")
- **Precedent: ADR-0063** and `docs/patterns/per-user-observability.md`
- Depends on: the `governance` role + database ticket

### Current Behavior

No governance database exists yet, so no datasource. The precedent (`uid: keycloak`) is live and working, including its least-privilege role and its Cilium egress.

### Expected Behavior

- A `GrafanaDatasource` (`uid: governance`) over the governance database, **read-only**.
- A dedicated least-privilege role — **not** the application's own role.
- Cilium egress from Grafana to Postgres.
- Dashboards can query tenant/application/repo/team as columns.

### Acceptance Criteria

- [ ] Given the datasource, when Grafana queries it, then it succeeds and returns governance data.
- [ ] Given the role it connects as, when its grants are inspected, then it has **SELECT only**, on **only** the tables the dashboards need. ⚠️ Least-privilege is not a formality here — ADR-0063's `grafana_ro` was deliberately never granted the Keycloak `credential` or federated-token tables. Apply the same discipline: grant the minimum, enumerate it, and write down why anything excluded is excluded.
- [ ] Given the role, when a write is attempted, then it fails.
- [ ] Given Cilium's default-deny egress, when Grafana connects, then an explicit `CiliumNetworkPolicy` allows it — shipped in the same change.
- [ ] Given the datasource definition, when it is stored, then credentials come from an ExternalSecret, never a literal.
- [ ] ⚠️ **Secret-first**, or the ExternalSecret sits in `SecretSyncedError` and the datasource silently fails to authenticate.

### Out of Scope

- The dashboards themselves — separate ticket under the Copilot epic.
- Any write path from Grafana.
- Changing the existing `keycloak` datasource.

### Technical Context

- Datasource + egress + secret-copy belong in **`ai-helm-values`**; the dashboard sources live in `ai-helm` (`tools/dashboards/`).
- ⚠️ **Values-repo-first.** The file must exist on `ai-helm-values` `main` before the chart change merges, or `ignoreMissingValueFiles` silently falls back to chart defaults.
- ⚠️ The GRANT itself should be idempotent and owned where the cluster is owned — the `grafana_ro` precedent uses an idempotent GRANT Job in the repo that owns the database.
- After editing dashboard sources: `uv run dashboards build` and commit the regenerated JSON, or `dashboards-drift` CI fails.

### Risks

| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| **Over-granted role exposes more than the dashboards need** | Medium | **High** | Enumerate grants explicitly; SELECT-only; review the grant list as part of this ticket, not later |
| Cilium blocks the connection, looks like a datasource bug | **High** | Low | Ship the CNP in the same change; this has bitten every Postgres datasource here |
| Secret not synced → silent auth failure | Medium | Medium | Secret-first; verify `SecretSynced=True` |
| Values-repo ordering wrong → chart defaults silently used | Medium | Medium | Values-repo-first, always |

### Test Plan

1. Confirm the remote secret key exists.
2. Apply the read-only role and its grants; verify with `\dp` (or equivalent) that only the intended tables are readable.
3. Attempt a write as that role; confirm it fails.
4. Apply the datasource + CNP; use Grafana's "Test" button.
5. Run a representative query from a panel.

### Verification evidence

*To be completed on delivery.*

Required:
- The enumerated grants for the read-only role.
- Evidence a write attempt fails.
- Grafana datasource test passing.
- `SecretSynced=True`.
- Confirmation the values-repo file landed before the chart change.

### Human accountable owner

@stephane-segning

### AI Usage Declaration

Drafting the ticket

### Human verification completed

- [x] I understood the intent
- [x] I checked the source of truth
- [x] I documented remaining risks
- [x] I am the accountable owner and accept responsibility for this ticket.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.