forge: external forge accounts live in swarm bao; the agent fetches them itself
An operator now links an agent's external forge account (label, base URL, token) in the swarm UI. swarm-controller stores it at swarm/agents/<agent>/forge/<label>. There is no index: the store's listing of the agent's forge/ directory is the set of accounts. In the agent, hive-agent-forge-accounts (oneshot + 2-minute timer, as the agent user, under its own store certificate) lists swarm/agents/<agent>/forge/ with the `list` #4866 grants an agent on its own metadata subtree, reads each account, and writes <state>/forge-<label>-token and forge-<label>.json in the names and shape hive-forge -f already reads. An empty listing (a 404, which `bao kv list -format=json` answers with `{}` and an empty stderr) is zero accounts; a denial or an unreachable store fails the unit. It never deletes: files for labels not listed, including ones the hive wrote, stay as they are. Removed: the dashboard FORGES tab (credentials.js/html section and its CSS), hive-c0re's extra_forges.rs and its routes, priv_client's extra-forge calls, and hive-priv's WriteAgentExtraForgeAccount / DeleteAgentExtraForgeAccount with their helpers. The GITHUB tab and WriteAgentGithubToken stay. Also: persistence.md's matrix avatar note names the exit-75 restart on a changed account listing, not the dashboard, as what brings a linked account up. Refs #4348
This commit is contained in:
parent
97fb76ce99
commit
2c7e586f47
27 changed files with 815 additions and 748 deletions
|
|
@ -42,6 +42,7 @@ let
|
|||
};
|
||||
|
||||
fetchUnit = machine: machine.systemd.services.hive-agent-forge-token;
|
||||
accountsUnit = machine: machine.systemd.services.hive-agent-forge-accounts;
|
||||
tokenFile = machine: machine.services.hyperhive.agent.forge.tokenFile;
|
||||
in
|
||||
let
|
||||
|
|
@ -164,6 +165,60 @@ let
|
|||
&& !(agentForgeNoBao.systemd.services ? tea-login)
|
||||
&& !(builtins.elem pkgs.tea agentForgeBao.environment.systemPackages);
|
||||
}
|
||||
{
|
||||
name = "an agent with a store address fetches its external forge accounts, and one without does not";
|
||||
ok =
|
||||
agentForgeBao.systemd.services ? hive-agent-forge-accounts
|
||||
&& agentForgeBao.systemd.timers ? hive-agent-forge-accounts
|
||||
&& !(agentForgeNoBao.systemd.services ? hive-agent-forge-accounts)
|
||||
&& !(agentForgeNoBao.systemd.timers ? hive-agent-forge-accounts);
|
||||
}
|
||||
{
|
||||
# The nix half of `swarm_secret_client::forge::{accounts_dir,account_path}`,
|
||||
# and the two file names `hive-forge -f` reads.
|
||||
name = "the account fetch lists the agent's own accounts and reads each into hive-forge's files";
|
||||
ok =
|
||||
let
|
||||
name = agentForgeBao.services.hyperhive.agent.user.name;
|
||||
s = (accountsUnit agentForgeBao).script;
|
||||
in
|
||||
lib.hasInfix "bao kv list -format=json secret/swarm/agents/${name}/forge >" s
|
||||
&& !(lib.hasInfix "/index/" s)
|
||||
&& lib.hasInfix "path=\"secret/swarm/agents/${name}/forge/$label\"" s
|
||||
&& lib.hasInfix "/agents/${name}/state" s
|
||||
&& lib.hasInfix "/forge-$label-token" s
|
||||
&& lib.hasInfix "/forge-$label.json" s
|
||||
&& lib.hasInfix "{base_url: (.data.data.url | strings)}" s;
|
||||
}
|
||||
{
|
||||
# The agent user owns its state dir (./user.nix), and the files keep
|
||||
# the `0600` they have always had.
|
||||
name = "the account fetch runs as the agent, with its own store identity";
|
||||
ok =
|
||||
let
|
||||
u = accountsUnit agentForgeBao;
|
||||
name = agentForgeBao.services.hyperhive.agent.user.name;
|
||||
in
|
||||
u.serviceConfig.User == name
|
||||
&& u.serviceConfig.UMask == "0077"
|
||||
&& builtins.elem "hive-agent-bao-cert" u.serviceConfig.LoadCredential
|
||||
&& u.environment.BAO_CLIENT_CERT == "%d/hive-agent-bao-cert";
|
||||
}
|
||||
{
|
||||
# Files a hive wrote keep working until the operator re-links them.
|
||||
name = "the account fetch never deletes a state-dir file it did not stage";
|
||||
ok =
|
||||
let
|
||||
s = (accountsUnit agentForgeBao).script;
|
||||
in
|
||||
!(lib.hasInfix "rm -f \"$token\"" s)
|
||||
&& !(lib.hasInfix "rm -f \"$sidecar\"" s)
|
||||
&& !(lib.hasInfix "forge-*" s);
|
||||
}
|
||||
{
|
||||
name = "the account fetch re-runs every two minutes";
|
||||
ok = agentForgeBao.systemd.timers.hive-agent-forge-accounts.timerConfig.OnUnitInactiveSec == "2min";
|
||||
}
|
||||
];
|
||||
in
|
||||
runGroup "agent-forge-bao" cases
|
||||
|
|
|
|||
Loading…
Reference in a new issue