matrix: swarm-controller is the only minter
Every hive is in a swarm and every swarm runs matrix, so every swarm has a swarm-controller, and since #4810 its hive_sender pass mints each hive's @hive-<hive>: sender token into the store every five minutes. The two other minters of that token go: - swarm-matrix-ctl mint: the systemd.services.swarm-matrix-ctl unit in the hive-matrix container, Command::Mint and src/mint.rs. The binary, its appservice render/publish verbs, ctlPackage, ctlActive and the ctl cert role stay. bao-matrix-reader's checks on the deleted unit are removed; the leaf-identity and no-token-in-env checks now look at swarm-matrix-appservice-publish, which runs under the same identity. - the hive-side mint ladder in hive-c0re's ensure_hive_user (register/appservice-login/password-login with the local as_token), with read_appservice_token, paths::matrix_appservice_token and the helpers only it used. ensure_hive_user now takes the store's token, keeps the file when the store has none or can't be reached, and fails otherwise. - hivectl matrix sync-admin: the verb, HostRequest::MatrixSyncAdmin and handle_matrix_sync_admin. The periodic MatrixSweep (ensure_all) is unchanged apart from no longer reading the local as_token. This removes the double-mint race #4810's review flagged: two minters logging in on one pinned device could leave a dead token in the store until the next pass. Closes #4813 Closes #4814
This commit is contained in:
parent
91e47732a6
commit
ddb7d7196d
22 changed files with 187 additions and 1162 deletions
|
|
@ -471,10 +471,9 @@ let
|
|||
# `secret/data/` is KV v2's ACL prefix, inserted by the engine rather than
|
||||
# written by the caller — the same trap as the two grants above.
|
||||
#
|
||||
# Not `swarm/services/*` like the publisher's: this principal produces
|
||||
# exactly one secret, its own hive's matrix sender account access token, and
|
||||
# a homeserver is not entitled to overwrite Grafana's OIDC client. The path
|
||||
# is spelled to the leaf for that reason, not for tidiness.
|
||||
# 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
|
||||
# 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`
|
||||
|
|
@ -484,16 +483,12 @@ let
|
|||
# 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.
|
||||
#
|
||||
# `read` as well as write, unlike either sibling, and it is what makes "and
|
||||
# only once" mechanical: matrix-ctl's first act is to read this path back and
|
||||
# stop if something is there, so without the capability every container
|
||||
# restart would mint a second access token and invalidate the hive's. A read
|
||||
# here recovers one secret this principal itself wrote, which is a much
|
||||
# narrower grant than the publisher's would have been.
|
||||
# ⚠️ 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` for the
|
||||
# same reason: publish compares before it writes.
|
||||
# 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"]
|
||||
|
|
@ -504,15 +499,7 @@ let
|
|||
}
|
||||
'';
|
||||
|
||||
# Which hive matrix-ctl mints for. This host's own by default, which is right
|
||||
# whenever the store and the homeserver are co-located and is the shape the
|
||||
# `mkDefault` deployments produce; an operator running them apart names the
|
||||
# homeserver's hive here, because the policy is written where the store is
|
||||
# and the container runs where the homeserver is.
|
||||
#
|
||||
# A wrong value is loud rather than silent: matrix-ctl's write comes back 403
|
||||
# with the store's own message and the hive falls back to minting its account
|
||||
# locally, which is the same degrade a store that was never deployed gives.
|
||||
# The hive the unused first stanza above names.
|
||||
matrixCtlHive = baoDeploy.matrixCtlHiveName;
|
||||
|
||||
# The swarm appservice token's leaf, the nix half of
|
||||
|
|
@ -1460,8 +1447,8 @@ in
|
|||
example = "swarm-matrix-ctl.svc";
|
||||
description = ''
|
||||
Subject the store's matrix-ctl cert-auth role accepts — the
|
||||
identity the oneshot inside the matrix container presents when it
|
||||
publishes the appservice sender account's access token.
|
||||
identity the matrix container's `swarm-matrix-appservice-publish`
|
||||
unit presents when it publishes the swarm appservice's token.
|
||||
|
||||
A **third** identity rather than reuse of either sibling above, and
|
||||
the narrowest of the three: its grant is one path, that
|
||||
|
|
@ -1632,20 +1619,8 @@ in
|
|||
description = ''
|
||||
Hive whose matrix sender token the store's matrix-ctl role may write.
|
||||
|
||||
The sender account's access token is **per hive**: it lives at
|
||||
`swarm/hives/<name>/matrix/sender-token`, and the only read grant that
|
||||
reaches it is that hive's own. So matrix-ctl's write grant names one
|
||||
hive too — the hive whose homeserver container it runs in.
|
||||
|
||||
Defaults to this host's own {option}`services.hyperhive.hiveName`,
|
||||
which is correct whenever the store and the homeserver are co-located.
|
||||
Set it when they are not: the policy is written where the store runs,
|
||||
and the oneshot runs where the homeserver does.
|
||||
|
||||
A wrong value degrades rather than breaks — matrix-ctl's write is
|
||||
refused with the store's own message and the hive mints its account
|
||||
locally instead, the same fallback a swarm that never deployed the
|
||||
store already uses.
|
||||
Unused: nothing presenting that identity writes the sender token;
|
||||
`swarm-controller` is its only minter.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue