From f892dc6a196cd77826cd592b31cfd5cf1d60b004 Mon Sep 17 00:00:00 2001 From: iris Date: Mon, 12 Oct 2026 00:45:16 +0200 Subject: [PATCH 1/2] nix: comments no longer say a hive's bao identity reads swarm/services/* The hive's bao policy grants read on swarm/agents/* and swarm/hives//* only. Five comments across four modules still listed swarm/services/* among its reads, or said a shared leaf would let a unit fetch another service's OIDC client secret, or that the hive's leaf reads every secret in the store. Comment and option-description text only. --- nix/host-modules/glue-queue-agent-credential.nix | 4 ++-- nix/host-modules/swarm-bao.nix | 13 +++++++------ nix/host-modules/swarm-grafana.nix | 4 ++-- nix/host-modules/swarm-otel.nix | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/nix/host-modules/glue-queue-agent-credential.nix b/nix/host-modules/glue-queue-agent-credential.nix index b38b5914..165ff565 100644 --- a/nix/host-modules/glue-queue-agent-credential.nix +++ b/nix/host-modules/glue-queue-agent-credential.nix @@ -45,8 +45,8 @@ let # 🩸 This principal's OWN leaf, not `clientCertFile` — the hive's. Bao # matches a cert-auth role on the CN, so one leaf shared by four readers # would be ONE principal holding the union of four grants: read on - # `swarm/agents/*` AND `swarm/hives//*` AND `swarm/services/*`, when - # this unit reads one queue credential and nothing else. Its own leaf carries + # `swarm/agents/*` AND `swarm/hives//*`, when this unit reads one + # queue credential and nothing else. Its own leaf carries # `-` and its role grants the single path # below — still this hive's own, so the narrowing costs no reach. haveClientIdentity = diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index 8b152347..b26780e0 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -802,12 +802,13 @@ let # 🩸 Each of these reads exactly ONE path in the store, and does it holding # its own leaf rather than `deploy.bao.clientCertFile` — the hive's own leaf, # whose policy (`swarm-secret-client`'s `policy::render`) grants read on - # `swarm/agents/*`, `swarm/hives//*` AND `swarm/services/*`. + # `swarm/agents/*` AND `swarm/hives//*`, and nothing under + # `swarm/services/`. # Principals presenting one certificate are ONE principal to bao, so sharing - # the hive's leaf would leave only the union of what they need expressible: - # the unit that fetches Grafana's OIDC client secret could fetch every agent - # credential in the swarm, and the unit that fetches this hive's queue - # credential could fetch Grafana's. + # the hive's leaf would give each of them everything that leaf reads: the + # unit that fetches this hive's queue credential could fetch every agent + # credential in the swarm, and a unit that fetches a service's OIDC client + # secret could not fetch it at all, as that path is not the hive's to read. # # Each gets its own leaf, its own cert-auth role and a policy holding the # one `secret/data/…` path that principal's script actually names — spelled @@ -1885,7 +1886,7 @@ in ⚠️ **Not** {option}`services.hyperhive.deploy.bao.clientCertFile`. Pointing this at the hive's own leaf would evaluate, deploy and log in — and hand a unit that reads one credential a certificate that reads every - secret in the store. + agent credential in the swarm and this hive's own secrets. No default here: ./glue-bao-tls.nix points it at the leaf it mints, wherever this host mints its own PKI. A deployment that reads a store on diff --git a/nix/host-modules/swarm-grafana.nix b/nix/host-modules/swarm-grafana.nix index c2a9ad30..15d03ace 100644 --- a/nix/host-modules/swarm-grafana.nix +++ b/nix/host-modules/swarm-grafana.nix @@ -218,8 +218,8 @@ let # 🩸 Grafana's OWN leaf, not `clientCertFile` — the hive's. Bao matches a # cert-auth role on the CN, so one leaf shared by four readers would be ONE # principal holding the union of four grants: this unit could read every - # agent credential in the swarm and every other service's OIDC client - # secret, when what it needs is the one path `storeSecretPath` names. + # agent credential in the swarm, when what it needs is the one path + # `storeSecretPath` names. haveClientIdentity = baoDeploy.grafanaOidcClientCertFile != null && baoDeploy.grafanaOidcClientKeyFile != null; diff --git a/nix/host-modules/swarm-otel.nix b/nix/host-modules/swarm-otel.nix index b19e69e6..f281668f 100644 --- a/nix/host-modules/swarm-otel.nix +++ b/nix/host-modules/swarm-otel.nix @@ -253,8 +253,8 @@ let # 🩸 The collector's OWN leaf, not `clientCertFile` — the hive's. Bao # matches a cert-auth role on the CN, so one leaf shared by four readers # would be ONE principal holding the union of four grants: this unit could - # read every agent credential in the swarm and Grafana's OIDC client - # secret, when what it needs is the one path `storeSecretPath` names. + # read every agent credential in the swarm, when what it needs is the one + # path `storeSecretPath` names. haveClientIdentity = baoDeploy.otelOidcClientCertFile != null && baoDeploy.otelOidcClientKeyFile != null; From d39ad6c465db7754fa71e9b32b4d1be9589907d1 Mon Sep 17 00:00:00 2001 From: iris Date: Mon, 12 Oct 2026 00:49:44 +0200 Subject: [PATCH 2/2] nix: the hive's leaf does not read every secret in the store Six more comments and option descriptions across five modules said the hive's leaf or grant reads every secret in the store. It reads swarm/agents/* and swarm/hives//* and nothing else, so they now say that, in the wording the clientCertFile option already used. Also the matrix-ctl check's label no longer calls the hive's leaf store-wide. --- nix/host-modules/glue-bao-tls.nix | 4 ++-- nix/host-modules/glue-queue-agent-credential.nix | 8 ++++---- nix/host-modules/hive-matrix.nix | 2 +- nix/host-modules/swarm-bao.nix | 8 +++++--- nix/host-modules/swarm-grafana.nix | 8 ++++---- nix/host-modules/swarm-otel.nix | 8 ++++---- nix/module-eval/bao-matrix-reader.nix | 4 ++-- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/nix/host-modules/glue-bao-tls.nix b/nix/host-modules/glue-bao-tls.nix index eba4071c..3c912967 100644 --- a/nix/host-modules/glue-bao-tls.nix +++ b/nix/host-modules/glue-bao-tls.nix @@ -193,8 +193,8 @@ in # local reads. # # Its own CN, not the reader's: the reader's leaf carries this hive's - # name and its policy reads the whole store, while this principal may - # only write one path — which is the entire point of giving the + # name and its policy reads every agent credential in the swarm, while this + # principal may only write one path — which is the entire point of giving the # container an identity instead of lending it the hive's. [ -s ${pkiDir}/matrix-ctl.pem ] || ${signLeaf} ${pkiDir} matrix-ctl \ ${lib.escapeShellArg deployCfg.bao.matrixCtlCommonName} "" clientAuth diff --git a/nix/host-modules/glue-queue-agent-credential.nix b/nix/host-modules/glue-queue-agent-credential.nix index 165ff565..d8450270 100644 --- a/nix/host-modules/glue-queue-agent-credential.nix +++ b/nix/host-modules/glue-queue-agent-credential.nix @@ -141,10 +141,10 @@ in a hive that reads the store at all is a hive that needs this pair. ⚠️ This reader's OWN leaf, not deploy.bao.clientCertFile. That one - is the hive's, and its grant reads every secret in the store; this - role reads the one queue-credential path. Pointing this option at - the hive's leaf would evaluate, deploy and log in — and undo the - split. + is the hive's, and its grant reads every agent credential in the + swarm and this hive's own secrets; this role reads the one + queue-credential path. Pointing this option at the hive's leaf + would evaluate, deploy and log in — and undo the split. On a hive that runs the store, glue-bao-tls.nix supplies both as defaults and there is nothing to do. Elsewhere the leaf is issued diff --git a/nix/host-modules/hive-matrix.nix b/nix/host-modules/hive-matrix.nix index e5a6e29f..65d63e16 100644 --- a/nix/host-modules/hive-matrix.nix +++ b/nix/host-modules/hive-matrix.nix @@ -412,7 +412,7 @@ in ⚠️ **Not the hive's own leaf**, and that is the whole deliverable of giving this container an identity: the hive's certificate reads every - secret in the store, while this one may write a single path. Pointing + agent credential in the swarm, while this one may write a single path. Pointing this at `deploy.bao.clientCertFile` would evaluate, deploy and work — and give away the separation in one line. diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index b26780e0..15c9e394 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -1583,8 +1583,9 @@ in the narrowest of the three: its grant is one path, that credential itself. The point of the whole arrangement is that the process holding the appservice token is not the hive, so handing it - the hive's own leaf — which reads every secret in the store — would - give the separation away in one line. + the hive's own leaf — which reads every agent credential in the swarm + and this hive's own secrets — would give the separation away in one + line. ⚠️ Same collision as its siblings, and the same answer: ./swarm.nix feeds this value into the guard on @@ -2282,7 +2283,8 @@ in normally gets both from ./glue-bao-tls.nix. ⚠️ Not deploy.bao.clientCertFile. That one is the hive's, and its - grant reads every secret in the store; this role reads one path. + grant reads every agent credential in the swarm and this hive's + own secrets; this role reads one path. ''; } { diff --git a/nix/host-modules/swarm-grafana.nix b/nix/host-modules/swarm-grafana.nix index 15d03ace..e9b880a1 100644 --- a/nix/host-modules/swarm-grafana.nix +++ b/nix/host-modules/swarm-grafana.nix @@ -432,10 +432,10 @@ in band, and every other secret comes from the store with it. ⚠️ Grafana's OWN leaf, not deploy.bao.clientCertFile. That one is the - hive's, and its grant reads every secret in the store; this role - reads the one path Grafana's client secret lives at. Pointing this - option at the hive's leaf would evaluate, deploy and log in — and - undo the split. + hive's, and its grant reads every agent credential in the swarm and + this hive's own secrets; this role reads the one path Grafana's + client secret lives at. Pointing this option at the hive's leaf would + evaluate, deploy and log in — and undo the split. On a hive that runs the store, glue-bao-tls.nix supplies both as defaults and there is nothing to do. Elsewhere the leaf is issued diff --git a/nix/host-modules/swarm-otel.nix b/nix/host-modules/swarm-otel.nix index f281668f..44b12646 100644 --- a/nix/host-modules/swarm-otel.nix +++ b/nix/host-modules/swarm-otel.nix @@ -576,10 +576,10 @@ in telemetry. That is not this host. ⚠️ The collector's OWN leaf, not deploy.bao.clientCertFile. That one - is the hive's, and its grant reads every secret in the store; this - role reads the one path this collector's client secret lives at. - Pointing this option at the hive's leaf would evaluate, deploy and - log in — and undo the split. + is the hive's, and its grant reads every agent credential in the + swarm and this hive's own secrets; this role reads the one path this + collector's client secret lives at. Pointing this option at the + hive's leaf would evaluate, deploy and log in — and undo the split. On a hive that runs the store, glue-bao-tls.nix supplies both as defaults and there is nothing to do. Elsewhere the leaf is issued diff --git a/nix/module-eval/bao-matrix-reader.nix b/nix/module-eval/bao-matrix-reader.nix index 08c049ab..051c775e 100644 --- a/nix/module-eval/bao-matrix-reader.nix +++ b/nix/module-eval/bao-matrix-reader.nix @@ -285,9 +285,9 @@ let # 🩸 The identity separation this whole arrangement buys, stated as the # one thing that would silently undo it. The container gets MATRIX-CTL's # leaf — whose grant is a single path — and not the hive's, which reads - # every secret in the store. Both files exist in the same directory and + # every agent credential in the swarm and this hive's own secrets. Both files exist in the same directory and # both would evaluate, deploy and work. - name = "matrix-ctl presents its own leaf, never the hive's store-wide one"; + name = "matrix-ctl presents its own leaf, never the hive's"; ok = let env =