Watch
0
0
Fork
You've already forked hyperhive
0

agents: re-pull the agent's own bao mTLS leaf on a timer

swarm-controller re-issues an agent's store leaf at half its validity, but
the running container kept presenting the copy its hive delivered at
start, so a re-issued leaf reached the agent only on its next restart.

hive-agent-bao-identity now seeds a live copy of the pair in its own
runtime directory from the delivered credentials, and re-runs every 10
minutes: it logs in with the live leaf, reads its own
swarm/agents/<agent>/bao-mtls (a read render_agent already grants), and
when the leaf changed, logs in with the new pair and swaps it in only if
the store accepts it.

Every unit in the container that logs in to the store presents the live
pair: hive-agent (queue-identity.nix), hive-matrix-daemon,
hive-subagent-daemon, hive-agent-forge-token, hive-agent-forge-accounts
and hive-agent-github-token. They keep loading the server CA as a
credential. The long-running daemons are ordered after the refresher so
the live pair exists when they start.

It renews only while the held leaf is still valid: the login that reads
the new leaf is made with the current one.

Refs #5017
This commit is contained in:
atlas 2026-10-11 03:05:59 +02:00 • committed by mara
commit c6717bccb0
17 changed files with 308 additions and 166 deletions

View file

@ -21,12 +21,10 @@ let
accounts = config.services.hyperhive.agent.matrixAccounts;
# This agent's own identity at the swarm secret store (./bao.nix). The daemon
# reads each account's token from the store itself, `main` included (the
# swarm mints that one), so the store's coordinates belong on its unit. The
# same three credential ids ./bao.nix and ./forge-token.nix load.
# swarm mints that one), so the store's coordinates belong on its unit: the
# live certificate pair ./bao.nix keeps, and the server CA id it loads.
baoCfg = config.services.hyperhive.agent.bao;
storeConfigured = baoCfg.addr != null;
certCredential = "hive-agent-bao-cert";
keyCredential = "hive-agent-bao-key";
serverCaCredential = "hive-agent-bao-server-ca";
# **The enable signal.** Matrix is on for this agent exactly when it has at
# least one account, because an account is the only thing the daemon has to
@ -308,7 +306,11 @@ in
description = "long-running matrix-sdk Client + MCP daemon";
wantedBy = [ "multi-user.target" ];
before = [ "hive-agent.service" ];
after = [ "network-online.target" ];
# The live certificate pair exists once ./bao.nix's unit has run.
after = [
"network-online.target"
]
++ lib.optional storeConfigured "hive-agent-bao-identity.service";
wants = [ "network-online.target" ];
environment = {
# In-agent todo socket the harness serves (loose-ends v2): the
@ -328,8 +330,8 @@ in
// lib.optionalAttrs storeConfigured {
HIVE_AGENT_NAME = userName;
BAO_ADDR = baoCfg.addr;
BAO_CLIENT_CERT = "%d/${certCredential}";
BAO_CLIENT_KEY = "%d/${keyCredential}";
BAO_CLIENT_CERT = baoCfg.clientCertFile;
BAO_CLIENT_KEY = baoCfg.clientKeyFile;
# Named even when no CA was delivered: a bare `LoadCredential=` is
# non-fatal when absent, and the daemon treats a missing or empty file
# as "use the container's own trust store".
@ -400,14 +402,10 @@ in
User = userName;
Group = userName;
}
# This agent's own certificate, imported by id so systemd materialises it
# under this unit's `User=` — the same bare form ./forge-token.nix uses.
# The store's server CA, imported by id so systemd materialises it under
# this unit's `User=` — the same bare form ./forge-token.nix uses.
// lib.optionalAttrs storeConfigured {
LoadCredential = [
certCredential
keyCredential
serverCaCredential
];
LoadCredential = [ serverCaCredential ];
};
};