swarm UI: an alerts page, read by the controller with a Viewer Grafana token from bao
swarm-bao-grafana-controller-token, on the host that runs Grafana, logs in to Grafana's API over its socket as the built-in admin (the password swarm-bao-grafana-admin minted, #5138) and keeps a `swarm-controller` service account that is an enabled Viewer. It mints a token for that account and writes it to bao at swarm/controller/swarm-controller/grafana/token under Grafana's leaf. A ten-minute timer runs it again. The unit keeps a stored token Grafana accepts. If Grafana refuses the stored token with 401, or bao holds none, the unit deletes every token of the account and mints a new one. Grafana's grant gains create/read/update on that leaf, and the controller's gains read. swarm-controller serves GET /api/alerts from Grafana's /api/prometheus/grafana/api/v1/alerts. It reads the token from bao, keeps it in memory, and re-reads bao once on a 401. The HTTP client has 5s connect and 15s request timeouts. Any failure is a 503 that names its cause. swarm-ui gets an /alerts page listing them, built the same way as the hives page. This is option (c) on #5129, the operator's choice.
This commit is contained in:
parent
8cb6273782
commit
7d09776742
23 changed files with 888 additions and 37 deletions
|
|
@ -249,6 +249,33 @@ let
|
|||
&& lib.hasInfix "admin reset-admin-password --password-from-stdin < /var/lib/grafana-admin/password" service.preStart
|
||||
&& lib.hasInfix "-config ${resetConfig}" service.script;
|
||||
}
|
||||
{
|
||||
# swarm-controller reads alerts with this token, so the account it
|
||||
# belongs to is created and kept a Viewer, the token lands at the path
|
||||
# the controller's grant reads, and an attempt against a Grafana or a
|
||||
# store that never answers ends and retries. The timer re-runs it, so
|
||||
# the unit must not stay active.
|
||||
name = "the controller's Grafana token is a Viewer account's, stored under Grafana's leaf, and each attempt is bounded";
|
||||
ok =
|
||||
let
|
||||
unit = grafanaRemoteAuthelia.systemd.services.swarm-bao-grafana-controller-token;
|
||||
s = unit.script;
|
||||
in
|
||||
!(lib.elem (toString (unit.serviceConfig.TimeoutStartSec or "infinity")) [
|
||||
"infinity"
|
||||
"0"
|
||||
])
|
||||
&& lib.hasInfix "curl --silent --show-error --connect-timeout 5 --max-time 15" s
|
||||
&& lib.hasInfix "--data '{\"name\":\"swarm-controller\",\"role\":\"Viewer\",\"isDisabled\":false}'" s
|
||||
&& lib.hasInfix "--data '{\"role\":\"Viewer\",\"isDisabled\":false}'" s
|
||||
&& lib.hasInfix "bao kv put secret/swarm/controller/swarm-controller/grafana/token value=-" s
|
||||
&& lib.hasInfix "--unix-socket /run/swarm-grafana/grafana.sock" s
|
||||
&& unit.environment.BAO_CLIENT_CERT == "/etc/pki/bao-grafana-oidc.pem"
|
||||
&& unit.serviceConfig.Restart == "on-failure"
|
||||
&& !(unit.serviceConfig.RemainAfterExit or false)
|
||||
&& lib.elem "swarm-bao-grafana-admin.service" unit.after
|
||||
&& grafanaRemoteAuthelia.systemd.timers ? swarm-bao-grafana-controller-token;
|
||||
}
|
||||
{
|
||||
# Same 403-not-a-miss reason as the matrix and queue arms below: the
|
||||
# reader's grant covers the `services` prefix, so a path outside it is
|
||||
|
|
|
|||
Loading…
Reference in a new issue