swarm-grafana: deliver the OIDC client secret through the secret store
Grafana's OIDC client secret only existed where authelia did. One `ssoLocal` gate — `grafana.enable && authelia.enable` — decided the client registration, the minted secret's delivery and the whole `auth.generic_oauth` block, so a swarm whose authelia runs on another host got Grafana with no SSO wiring at all. The local login form is disabled unconditionally, so that is no way in. Split the one gate into the two questions it was conflating: - `ssoConfigured` — does this SWARM have an identity provider (`swarm.authelia.url`, which is swarm-wide and whose own description makes null mean "no SSO configured"). With a delivery route present this is what emits Grafana's OIDC block. - `ssoLocal` — is authelia on THIS host, now spelled as the forge and matrix modules spell it. It decides only which unit delivers the secret. Where authelia is elsewhere, `swarm-bao-grafana-oidc.service` reads the secret from the swarm secret store, shaped after glue-queue-agent-credential.nix: cert login fails loudly because a retry fixes every state it fails on, the read degrades quietly because no retry turns "no value there" into a value, and nothing writes a stand-in. The producer is the publisher that already runs on authelia's host, which gains the swarm's service clients beside the per-hive ones at `swarm/services/<id>/oidc/client` — with the write grant in swarm-bao.nix and the hive read grant in `policy::render` to match. Registration moved to glue-grafana-oidc-client.nix. It has to be declared where authelia's config is rendered, and swarm-grafana.nix's config block hangs off this host running Grafana. Two judgement calls stated rather than buried: a hive's read policy now grants the whole `services` prefix, because a service's path names the service and nothing swarm-wide records which hive runs it (cost recorded in docs/trust-boundary/security.md); and the client is registered on any authelia host, because no swarm-wide "this swarm has a Grafana" fact exists to gate it on. Refs #4234 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
fbd9afa7fa
commit
4aa982cc2a
9 changed files with 577 additions and 85 deletions
|
|
@ -60,10 +60,22 @@ advertises a boundary it doesn't actually hold. A wide grant that says what it
|
|||
is beats a narrow one that only looks narrow.
|
||||
|
||||
What still holds: the grant is **read-only** (a hive can't write an agent's
|
||||
credential, so it can't hand itself an agent's identity), and it reaches two
|
||||
prefixes and nothing else in the store — every agent's credentials, and the
|
||||
reader's _own_ entry under the hive namespace, which names the hive asking and
|
||||
so widens nothing between them.
|
||||
credential, so it can't hand itself an agent's identity), and it reaches three
|
||||
prefixes and nothing else in the store — every agent's credentials, the reader's
|
||||
_own_ entry under the hive namespace, which names the hive asking and so widens
|
||||
nothing between them, and every **swarm service's** OIDC client secret.
|
||||
|
||||
That third prefix has the same shape of reason as the first, and the same honest
|
||||
cost. A swarm service (Grafana is the one there today) registers **one** client
|
||||
for the whole swarm, so its credential's path names the service and never the
|
||||
host — and which hive runs a given service is a `deploy.*` fact, per-host by
|
||||
definition, so nothing swarm-wide exists to scope the grant to. The host running
|
||||
such a service has no store identity of its own either; it reads with the
|
||||
certificate of the hive it is. So **any hive can read any swarm service's client
|
||||
secret**, which is worth what it buys: a swarm service whose identity provider
|
||||
lives on another machine can get its secret at all, instead of only working
|
||||
co-located. Giving such a service its own store identity is what would remove
|
||||
this rather than re-scope it.
|
||||
|
||||
**A tracked follow-up** narrows this, with the two candidate directions: scope
|
||||
the grant per hive (and pay for the re-emission), or give each agent container
|
||||
|
|
|
|||
Loading…
Reference in a new issue