Watch
0
0
Fork
You've already forked hyperhive
0

bao: drop matrix-ctl's per-hive sender-token grant

swarm-controller is the only minter of swarm/hives/<hive>/matrix/sender-token
since #4820, so the swarm-matrix-ctl policy's first stanza granted a write no
code performs. The policy keeps its one used stanza, the swarm appservice token
that `swarm-matrix-ctl appservice publish` writes. deploy.bao.matrixCtlHiveName
only named the hive in the dropped stanza and goes with it.

hive-matrix.nix no longer calls the per-hive appservice's as_token hive-c0re's
authority: tuwunel loads the registration and creates the sender account, and
no client presents that token.
This commit is contained in:
atlas 2026-09-30 00:50:39 +02:00 • committed by mara
commit b58a0d8ba9
3 changed files with 19 additions and 64 deletions

View file

@ -55,13 +55,13 @@ let
# with no host-side chown or GID pinning.
matrixSecretCredential = "/run/credentials/tuwunel.service/oidc_client_secret";
# How this hive creates matrix accounts: an appservice registration whose
# `url` is null. Null is a legal `url` (ruma's `Registration` types it
# `Option<String>`), and it is the whole point — with no URL the homeserver
# The hive's appservice registration, whose `url` is null. Null is a legal
# `url` (ruma's `Registration` types it `Option<String>`), and it is the
# whole point — with no URL the homeserver
# never calls out, so there is no HTTP service to run and no daemon to
# operate. What the registration delivers is the `as_token`: hive-c0re's
# standing authority to create, and log in as, the accounts named by the
# namespace below, with no shared registration secret in the picture.
# operate. tuwunel loads the registration and creates its sender account
# (below). No client presents its `as_token`: `swarm-controller` mints the
# sender's token with the swarm registration's.
appserviceId = "hyperhive";
# The appservice's own user, and the account the hive acts as. An

View file

@ -472,36 +472,18 @@ let
# written by the caller — the same trap as the two grants above.
#
# Not `swarm/services/*` like the publisher's: a homeserver is not entitled
# to overwrite Grafana's OIDC client. Each path is spelled to the leaf for
# to overwrite Grafana's OIDC client. The path is spelled to the leaf for
# that reason, not for tidiness.
#
# 🩸 And the leaf now carries a HIVE segment, which is the narrowing that
# matters: the credential used to live at `swarm/services/matrix/sender-token`
# — one value for the whole swarm, under the `services/*` tree every hive's
# own policy grants read on. Under `swarm/hives/<name>/` the only read grant
# that reaches it is that hive's own stanza, so one hive cannot fetch
# another's. `matrixCtlHive` below is the name this principal may write, and
# it is one hive rather than a `hives/*` wildcard for the same reason.
#
# ⚠️ Nothing presenting this identity writes the first stanza's path:
# `swarm-controller` is the sender token's only minter. The stanza is unused.
#
# The second stanza is the swarm appservice's token, which matrix-ctl mints
# inside the container and publishes here for the controller. `read` as well
# as write, unlike either sibling, because publish compares before it writes.
# It is the swarm appservice's token, which matrix-ctl mints inside the
# container and publishes here for the controller. `read` as well as write,
# unlike either sibling, because publish compares before it writes.
matrixCtlPolicyText = ''
path "${credentialMountPath}/data/swarm/hives/${matrixCtlHive}/matrix/sender-token" {
capabilities = ["create", "update", "read"]
}
path "${credentialMountPath}/data/${swarmAppserviceTokenLeaf}" {
capabilities = ["create", "update", "read"]
}
'';
# The hive the unused first stanza above names.
matrixCtlHive = baoDeploy.matrixCtlHiveName;
# The swarm appservice token's leaf, the nix half of
# `swarm_secret_client::matrix::swarm_appservice_token_path`. Under
# `controller/`, the one kind no hive's policy reads: its sender is the
@ -780,9 +762,8 @@ let
# One reader per hive in the swarm directory. Written from the directory
# rather than from this host's own name because the policy is written where
# the STORE is and the reader runs where its hive is — the same split
# `matrixCtlHiveName` above exists to paper over, answered here by naming
# every hive instead of asking the operator which one.
# the STORE is and the reader runs where its hive is, so this host's name is
# not the reader's.
perHiveReaders =
{ rolePrefix, cnPrefix, ... }@spec:
lib.mapAttrsToList (hiveName: _: {
@ -1611,19 +1592,6 @@ in
'';
};
matrixCtlHiveName = lib.mkOption {
type = lib.types.str;
default = toString hyperhiveCfg.hiveName;
defaultText = lib.literalExpression "services.hyperhive.hiveName";
example = "pr1ma";
description = ''
Hive whose matrix sender token the store's matrix-ctl role may write.
Unused: nothing presenting that identity writes the sender token;
`swarm-controller` is its only minter.
'';
};
matrixTokenCommonNamePrefix = lib.mkOption {
type = lib.types.str;
default = "swarm-bao-matrix-token";