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
|
|
@ -11,52 +11,21 @@ crate.
|
|||
|
||||
## Verbs
|
||||
|
||||
### `mint`
|
||||
### `appservice render`
|
||||
|
||||
Puts the appservice sender account's access token into the swarm's secret store,
|
||||
under an identity of its own. A boot-time oneshot.
|
||||
Mints the swarm appservice registration's tokens when absent and renders the
|
||||
registration tuwunel loads. Runs before the homeserver and needs no network.
|
||||
|
||||
Configured entirely by the `MATRIX_MINT_*` environment the unit sets — no flags.
|
||||
A systemd `Environment=` block is what a nix module can render; a command line
|
||||
full of paths is not. The prefix is scoped to the verb rather than to the binary
|
||||
so the next verb brings its own, instead of widening a shared one nobody can
|
||||
then narrow.
|
||||
### `appservice publish`
|
||||
|
||||
## Why this lives in the matrix container
|
||||
Writes the rendered `as_token` to the swarm secret store for `swarm-controller`,
|
||||
when the store's copy differs.
|
||||
|
||||
The credential `mint` writes is authorised by the appservice `as_token`, and the
|
||||
container already holds that: `nix/host-modules/hive-matrix.nix` bind-mounts the
|
||||
rendered appservice registration into it read-only, because that is how tuwunel
|
||||
itself is handed the registration. Minting anywhere else would mean copying the
|
||||
`as_token` to a second holder — and the point of this component is that the hive
|
||||
stops being one.
|
||||
|
||||
It is not the swarm controller for the same reason, plus a structural one: a
|
||||
homeserver has exactly **one** appservice registration and so one sender
|
||||
account, and a swarm runs one homeserver, so "mint it once" needs no lock, no
|
||||
lease and no trigger surface — it is a property of the thing being minted.
|
||||
|
||||
## Idempotency
|
||||
|
||||
The **store** is the key, not the homeserver. A `mint` run reads
|
||||
`swarm/services/matrix/sender-token` first and returns without touching the
|
||||
homeserver when something is already there. Only an empty path reaches the mint
|
||||
ladder:
|
||||
|
||||
1. `POST /_matrix/client/v3/register` with `"type": "m.login.application_service"`
|
||||
— one round trip, no UIAA.
|
||||
2. `M_USER_IN_USE` (the expected arm on a homeserver that has already loaded the
|
||||
registration, since the account is the appservice's own `sender_localpart`) →
|
||||
`POST /_matrix/client/v3/login` as the appservice, same pinned `device_id`, so
|
||||
the old device is replaced rather than duplicated.
|
||||
3. Write the result to the store.
|
||||
|
||||
A crash between the homeserver call and the store write is recoverable: the next
|
||||
run takes arm 2.
|
||||
Both are configured entirely by the `MATRIX_APPSERVICE_*` environment the units
|
||||
set — no flags. A systemd `Environment=` block is what a nix module can render; a
|
||||
command line full of paths is not.
|
||||
|
||||
## 🩸 A secret is a path, never a value
|
||||
|
||||
Nothing here logs, prints or interpolates a token. The mint ladder's errors are
|
||||
built from the homeserver's _status_ and its `errcode`, never its body, because a
|
||||
`/login` response body is an access token. The one identifier this binary logs is
|
||||
the store path it wrote.
|
||||
Nothing here logs, prints or interpolates a token. The one identifier this
|
||||
binary logs is the store path it wrote.
|
||||
|
|
|
|||
Loading…
Reference in a new issue