mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-04 02:57:27 +09:00
The `OIDCUser` typedef in `packages/extra/monitoring/values.yaml`
declared only `@field {string} email`; `cozyvalues-gen` regenerated
`values.schema.json`, `README.md`, and the mirrored `openAPISchema`
on the `Monitoring` ApplicationDefinition WITHOUT a `role` field.
Consequences:
- The `@enum OIDCRole` declaration was orphan — referenced from
nowhere, so the schema's items object had `required: ["email"]`
and one property.
- A dashboard-driven CR would offer a form without any role picker;
a schema-conformant `{email}` submission would render into the
users-Job with `role: null`, `jq --raw-output` yields the string
`"null"`, the `POST /api/orgs/1/users` body carries
`"role":"null"`, Grafana returns HTTP 400, and the post-install
hook exhausts `backoffLimit: 6` — HelmRelease never becomes Ready.
- Unit + e2e tests all hardcoded `role: Admin` / `role: Viewer`, so
the contract mismatch never surfaced in CI.
Fix:
- Add `@field {OIDCRole} role - ...` to the `OIDCUser` typedef in
`packages/extra/monitoring/values.yaml` so cozyvalues-gen materialises
the field with enum + required.
- Regenerate `values.schema.json`, `README.md`, and mirrored
`openAPISchema` via `make generate`.
- Add `monitoring.oidc.assertUsersRoleShape` template-level guard
(same shape as `assertUsersEmailShape`) so a stale-schema CR or a
direct-helm invocation fails at render time with a legible error
instead of at hook execution with a Grafana 400.
- Consolidate all `spec.oidc.users` guards into a single
`monitoring.oidc.assertUsersPrologue` include and call it once from
`oidc-users-job.yaml`, ordering the incompat check
(`assertCustomSecretRefUsersEmpty`) before the per-entry role /
email regexes so operators see the more actionable message first.
Drop the duplicate include from `grafana.yaml` (Job template renders
in every mode anyway).
- Two new helm-unittest cases lock the regression:
`oidc.users entry missing role fails the render` and
`oidc.users entry with unknown role fails the render`.
- Point the previous `secretRef + users` incompat unit test at the
users-Job template since that's where the prologue now fires.
- `docs/oidc-grafana.md`: correct the failed-hook post-mortem window
claim — with `ttlSecondsAfterFinished: 3600` the Kubernetes TTL
controller reaps the Job + Pod 1h after the terminal condition,
not "until the next helm-upgrade".
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
227 lines
9.3 KiB
YAML
227 lines
9.3 KiB
YAML
## @section Common parameters
|
|
##
|
|
|
|
## @param {string} host - The hostname used to access Grafana externally (defaults to 'grafana' subdomain for the tenant host).
|
|
host: ""
|
|
|
|
##
|
|
## @section Metrics storage configuration
|
|
##
|
|
|
|
## @typedef {struct} Request - Minimum guaranteed resources.
|
|
## @field {quantity} [cpu] - CPU request.
|
|
## @field {quantity} [memory] - Memory request.
|
|
|
|
## @typedef {struct} Limit - Maximum allowed resources.
|
|
## @field {quantity} [cpu] - CPU limit.
|
|
## @field {quantity} [memory] - Memory limit.
|
|
|
|
## @typedef {struct} VMComponent - VictoriaMetrics component configuration.
|
|
## @field {Request} [minAllowed] - Minimum guaranteed resources.
|
|
## @field {Limit} [maxAllowed] - Maximum allowed resources.
|
|
|
|
## @typedef {struct} Resources - Combined resource configuration.
|
|
## @field {Request} [requests] - Resource requests.
|
|
## @field {Limit} [limits] - Resource limits.
|
|
|
|
## @typedef {struct} MetricsStorage - Configuration of metrics storage instance.
|
|
## @field {string} name - Name of the storage instance.
|
|
## @field {string} retentionPeriod - Retention period for metrics.
|
|
## @field {string} deduplicationInterval - Deduplication interval for metrics.
|
|
## @field {string} storage="10Gi" - Persistent volume size.
|
|
## @field {string} [storageClassName] - StorageClass used for the data.
|
|
## @field {VMComponent} [vminsert] - Configuration for vminsert.
|
|
## @field {VMComponent} [vmselect] - Configuration for vmselect.
|
|
## @field {VMComponent} [vmstorage] - Configuration for vmstorage.
|
|
|
|
## @param {[]MetricsStorage} metricsStorages - Configuration of metrics storage instances.
|
|
metricsStorages:
|
|
## Example:
|
|
## metricsStorages:
|
|
## - name: shortterm
|
|
## retentionPeriod: "3d"
|
|
## deduplicationInterval: "15s"
|
|
## storage: 10Gi
|
|
## storageClassName: ""
|
|
## vminsert:
|
|
## minAllowed:
|
|
## cpu: 200m
|
|
## memory: 512Mi
|
|
## maxAllowed:
|
|
## cpu: 1500m
|
|
## memory: 3Gi
|
|
## vmselect:
|
|
## minAllowed:
|
|
## cpu: 300m
|
|
## memory: 1Gi
|
|
## maxAllowed:
|
|
## cpu: 3500m
|
|
## memory: 6Gi
|
|
## vmstorage:
|
|
## minAllowed:
|
|
## cpu: 500m
|
|
## memory: 2Gi
|
|
## maxAllowed:
|
|
## cpu: 4000m
|
|
## memory: 8Gi
|
|
- name: shortterm
|
|
retentionPeriod: "3d"
|
|
deduplicationInterval: "15s"
|
|
storage: 10Gi
|
|
storageClassName: ""
|
|
- name: longterm
|
|
retentionPeriod: "14d"
|
|
deduplicationInterval: "5m"
|
|
storage: 10Gi
|
|
storageClassName: ""
|
|
|
|
##
|
|
## @section Logs storage configuration
|
|
##
|
|
|
|
## @typedef {struct} LogsStorage - Configuration of logs storage instance.
|
|
## @field {string} name - Name of the storage instance.
|
|
## @field {string} retentionPeriod="1" - Retention period for logs.
|
|
## @field {string} storage="10Gi" - Persistent volume size.
|
|
## @field {string} storageClassName="replicated" - StorageClass used to store the data.
|
|
|
|
## @param {[]LogsStorage} logsStorages - Configuration of logs storage instances.
|
|
logsStorages:
|
|
- name: generic
|
|
retentionPeriod: "1"
|
|
storage: 10Gi
|
|
storageClassName: replicated
|
|
|
|
##
|
|
## @section Alerta configuration
|
|
##
|
|
|
|
## @typedef {struct} TelegramAlerts - Telegram alert configuration.
|
|
## @field {string} token - Telegram bot token.
|
|
## @field {string} chatID - Telegram chat ID(s), separated by commas.
|
|
## @field {[]string} [disabledSeverity] - List of severities without alerts (e.g. ["informational","warning"]).
|
|
|
|
## @typedef {struct} SlackAlerts - Slack alert configuration.
|
|
## @field {string} url - Configuration uri for Slack alerts.
|
|
## @field {[]string} [disabledSeverity] - List of severities without alerts (e.g. ["informational","warning"]).
|
|
|
|
## @typedef {struct} Alerts - Alert routing configuration.
|
|
## @field {TelegramAlerts} [telegram] - Configuration for Telegram alerts.
|
|
## @field {SlackAlerts} [slack] - Configuration for Slack alerts.
|
|
|
|
## @typedef {struct} Alerta - Configuration for the Alerta service.
|
|
## @field {string} [storage] - Persistent volume size for the database.
|
|
## @field {string} [storageClassName] - StorageClass used for the database.
|
|
## @field {Resources} [resources] - Resource configuration.
|
|
## @field {Alerts} [alerts] - Alert routing configuration.
|
|
|
|
## @param {Alerta} alerta - Configuration for the Alerta service.
|
|
alerta:
|
|
storage: 10Gi
|
|
storageClassName: ""
|
|
resources:
|
|
limits:
|
|
cpu: "1"
|
|
memory: 1Gi
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
alerts:
|
|
telegram:
|
|
token: ""
|
|
chatID: ""
|
|
disabledSeverity: []
|
|
slack:
|
|
url: ""
|
|
disabledSeverity: []
|
|
##
|
|
## @section Grafana configuration
|
|
##
|
|
|
|
## @typedef {struct} GrafanaDB - Grafana database configuration.
|
|
## @field {string} [size] - Persistent volume size for the database.
|
|
|
|
## @typedef {struct} Grafana - Grafana service configuration.
|
|
## @field {GrafanaDB} [db] - Database configuration.
|
|
## @field {Resources} [resources] - Resource configuration.
|
|
|
|
## @param {Grafana} grafana - Configuration for Grafana.
|
|
grafana:
|
|
db:
|
|
size: 10Gi
|
|
resources:
|
|
limits:
|
|
cpu: "1"
|
|
memory: 1Gi
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
##
|
|
## @section Vmagent configuration
|
|
##
|
|
|
|
## @typedef {struct} VmagentRemoteWrite - Remote write configuration.
|
|
## @typedef {stringSlice} VmagentRemoteWriteURLs - List of remoteWrite endpoint URLs.
|
|
|
|
## @typedef {struct} VmagentExternalLabels - External labels for metrics.
|
|
## @field {string} [<key>] - Label value for the given key.
|
|
|
|
## @typedef {struct} Vmagent - VictoriaMetrics Agent configuration.
|
|
## @field {VmagentExternalLabels} [externalLabels] - External labels applied to all metrics.
|
|
## @field {VmagentRemoteWrite} [remoteWrite] - Remote write configuration.
|
|
|
|
## @param {Vmagent} vmagent - Configuration for VictoriaMetrics Agent.
|
|
vmagent:
|
|
externalLabels:
|
|
cluster: cozystack
|
|
remoteWrite:
|
|
urls:
|
|
- http://vminsert-shortterm:8480/insert/0/prometheus
|
|
- http://vminsert-longterm:8480/insert/0/prometheus
|
|
## inlineScrapeConfig: |
|
|
## - job_name: "custom"
|
|
## static_configs:
|
|
## - targets: ["my-service:9090"]
|
|
|
|
##
|
|
## @section OIDC authentication
|
|
##
|
|
|
|
## @enum {string} OIDCMode - Identity mode for the Grafana instance.
|
|
## @value None
|
|
## @value System
|
|
## @value CustomConfig
|
|
|
|
## @typedef {struct} OIDCSecretRef - Reference to a Secret carrying an `[auth.generic_oauth]` ini fragment.
|
|
## @field {string} [name] - Name of an existing Secret in the release namespace whose `auth.ini` key holds a ready-made `[auth.generic_oauth]` block. Mutually exclusive with `customConfig.config`.
|
|
|
|
## @typedef {struct} OIDCCustomConfigInline - Inline map of grafana.ini `[auth.generic_oauth]` keys.
|
|
## @field {string} [<key>] - Value for the generic_oauth key (e.g. `client_id`, `client_secret`, `auth_url`, `token_url`, `api_url`, `scopes`, `role_attribute_path`).
|
|
|
|
## @typedef {struct} OIDCCustomConfig - Tenant-supplied AuthN payload; consumed only when `mode: CustomConfig`. Exactly one of `config` or `secretRef.name` must be set.
|
|
## @field {OIDCCustomConfigInline} [config] - Inline map of `[auth.generic_oauth]` keys. Written verbatim into the Grafana CR `spec.config`. Mutually exclusive with `secretRef.name`.
|
|
## @field {OIDCSecretRef} [secretRef] - Reference to a Secret holding an `auth.ini` fragment; mounted under `/etc/grafana/oidc` and loaded via `GF_PATHS_CUSTOM_INI`.
|
|
|
|
## @enum {string} OIDCRole - Grafana org role bound to a listed user.
|
|
## @value Admin
|
|
## @value Editor
|
|
## @value Viewer
|
|
|
|
## @typedef {struct} OIDCUser - Grafana user reconciled into the release's org.
|
|
## @field {string} email - Email address matched against the `email` claim from the issuer. The chart pre-provisions a Grafana account with this email so the users-Job can set the org role before the operator's first login (`oauth_allow_insecure_email_lookup = true` glues the two together). Must match a conservative pattern: local part is `[A-Za-z0-9._%+-]+`, domain is `[A-Za-z0-9.-]+\.[A-Za-z]{2,}`. Whitespace, quoted literals, and unusual URL-reserved characters are rejected on schema level so the reconcile-Job's shell handling never has to defend against malformed input.
|
|
## @field {OIDCRole} role - Grafana org role to bind: `Admin`, `Editor`, or `Viewer`. Applied to the release's Grafana org (`Main Org.`); server-level `GrafanaAdmin` promotion is out of scope for Phase 1. Required — the users-Job POSTs `{loginOrEmail, role}` to `/api/orgs/1/users` and PATCHes `{role}` to converge across re-runs; omitting the field would render `role: "null"` into the body and fail with HTTP 400.
|
|
|
|
## @typedef {struct} OIDC - OIDC selector for the Grafana instance (Phase 1 — per-instance audience binding; no per-tenant Keycloak realm).
|
|
## @field {OIDCMode} mode - Identity mode. `None`: no OIDC, only the `grafana-admin-password` Secret works. `System`: trust the platform `cozy` realm via a per-instance confidential client and audience binding; zero-config default. `CustomConfig`: trust a tenant-supplied issuer directly (BYO); `cozy` is not in the path.
|
|
## @field {OIDCCustomConfig} [customConfig] - Tenant-supplied `[auth.generic_oauth]` payload; consumed only when `mode: CustomConfig`.
|
|
## @field {[]OIDCUser} [users] - Users granted access to this Grafana instance's org. Each entry is reconciled into Grafana org membership + role by a chart-owned post-install/post-upgrade Job. Works for both `System` and `CustomConfig` modes; ignored when `mode: None`. Users not listed here get nothing (no default org role from group mapping).
|
|
|
|
## @param {OIDC} oidc - OIDC authentication for the Grafana instance. See docs/oidc-grafana.md for the operator guide.
|
|
oidc:
|
|
mode: "None"
|
|
customConfig:
|
|
config: {}
|
|
secretRef:
|
|
name: ""
|
|
users: []
|