grafana: mint the admin password into the store and apply it on every start
Grafana's built-in admin kept the nixpkgs default password `admin`, and Grafana's API takes basic auth whatever `auth.disable_login_form` says, so the public vhost gave server-admin to `admin:admin`. `swarm-bao-grafana-admin` creates a random password in the store under Grafana's existing leaf when none is stored (`create` without `update`, so the first one is kept), then copies it into the container. `security.admin_password` reads it for a new database, and a `grafana cli admin reset-admin-password` in `grafana.service`'s `preStart` applies it to an existing one on every start. Closes #5138
This commit is contained in:
parent
cf4c4cde87
commit
993f5fd99d
7 changed files with 251 additions and 48 deletions
|
|
@ -557,13 +557,28 @@ let
|
|||
# for this one is the OTHER service's: `services/*` would have granted
|
||||
# both, and the two are separate principals precisely because a
|
||||
# dashboard is not entitled to a collector's credential.
|
||||
name = "the Grafana OIDC reader's grant is Grafana's own client secret and nothing else";
|
||||
#
|
||||
# The admin password is the one leaf it may create, and without `update`:
|
||||
# a grant that could replace it would let a second run rotate the
|
||||
# password Grafana's database already holds.
|
||||
name = "the Grafana reader reads its own client secret and creates its admin password, and nothing else";
|
||||
ok =
|
||||
let
|
||||
s = baoGrantHere.systemd.services.swarm-bao-grafana-oidc-policy.script;
|
||||
in
|
||||
lib.hasInfix "path \"secret/data/swarm/services/swarm-grafana/oidc/client\" {" s
|
||||
&& lib.hasInfix "capabilities = [\"read\"]" s
|
||||
grantsIn s == [
|
||||
{
|
||||
path = "secret/data/swarm/services/swarm-grafana/oidc/client";
|
||||
caps = [ "read" ];
|
||||
}
|
||||
{
|
||||
path = "secret/data/swarm/services/swarm-grafana/admin/password";
|
||||
caps = [
|
||||
"create"
|
||||
"read"
|
||||
];
|
||||
}
|
||||
]
|
||||
&& !(lib.hasInfix "secret/data/swarm/agents" s)
|
||||
&& !(lib.hasInfix "secret/data/swarm/hives" s)
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/*" s)
|
||||
|
|
@ -827,6 +842,20 @@ let
|
|||
&& !(noReaders ? swarm-bao-matrix-oidc)
|
||||
&& !(noReaders ? swarm-bao-nats-callout-xkey);
|
||||
}
|
||||
{
|
||||
# The admin password is created under Grafana's leaf, so its unit waits
|
||||
# for the unit writing that leaf's role and policy; before it, the create
|
||||
# is refused. The second arm is the absence control.
|
||||
name = "grafana's admin password unit is ordered after grafana's policy unit";
|
||||
ok =
|
||||
let
|
||||
u = baoGrantWithConsumers.systemd.services.swarm-bao-grafana-admin;
|
||||
in
|
||||
lib.elem "swarm-bao-grafana-oidc-policy.service" u.after
|
||||
&& lib.elem "swarm-bao-grafana-oidc-policy.service" u.wants
|
||||
&& !(lib.elem "swarm-bao-grafana-oidc-policy.service" u.requires)
|
||||
&& !(baoGrantNoReaders.systemd.services ? swarm-bao-grafana-admin);
|
||||
}
|
||||
{
|
||||
# The ordering is set apart from each reader's own definition, so it can
|
||||
# define a reader by itself: `after` on a unit nothing else declares is a
|
||||
|
|
@ -959,6 +988,7 @@ let
|
|||
[
|
||||
"swarm-services-cert"
|
||||
"swarm-bao-forwarder-oidc"
|
||||
"swarm-bao-grafana-admin"
|
||||
]
|
||||
++ policyReaders
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue