Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/nix/agent-modules/logs.nix
atlas 0f53e9be6c swarm-logs: authenticate as the agent with its own queue secret
swarm-logs reads `swarm/agents/<agent>/queue` from the swarm secret
store with the agent's own store certificate (the read hive-agent makes
for its queue connection) and presents it as
`Bearer swarm-agent.<agent>.<secret>`, which the gateway's
swarm-logs-auth checks. On a 401 it reads the secret again and retries
once, so a secret re-minted between the read and the check does not
fail the query.

The OIDC mint against the hive's shared `hive-<h>-agent` client is gone
from swarm-logs, along with the unused `HIVE_AGENT_OIDC_CA_FILE` anchor.
logs.nix now gates on the store address instead of the queue's token
endpoint and wraps the binary with the paths queue-identity.nix gives
the harness; the host forwards the query URL wherever it forwards a
store identity.

The shared client is still delivered into containers; removing that is

Part of #4459.
2026-10-13 08:38:05 +02:00

82 lines
3.2 KiB
Nix

# `swarm-logs` on this agent's PATH, configured for this swarm's log store.
#
# The binary reads its coordinates from the environment and defaults nothing
# (see `swarm-logs/README.md`), so it is installed **wrapped** rather than
# bare — the same shape `swarm-controller.nix` installs `swarmctl` in, and for
# the same reason: every value here is derived from an option a module owns,
# and a default inside the binary would be an address we hope points at
# something.
#
# ⚠️ Gated on the secret store's address as well as on the query URL, because
# the identity this CLI presents is the agent's own queue secret, read from the
# store with the certificate ./bao.nix keeps. Without a store there is nothing
# to authenticate as, and a binary that can only fail would read its 401 as
# "no logs".
{
lib,
pkgs,
config,
...
}:
let
cfg = config.services.hyperhive.agent.logs;
baoCfg = config.services.hyperhive.agent.bao;
configured = cfg.queryUrl != null && baoCfg.addr != null;
# The same store coordinates ./queue-identity.nix gives the harness, except
# the CA: `%d` expands only inside a unit, so it is spelled as the harness
# unit's credentials directory, which the agent user's shells can read.
#
# 🩸 Paths and a name only. A value in `--set` lands in the wrapper script,
# which is in the world-readable nix store.
wrapperEnv = {
HIVE_AGENT_LOGS_QUERY_URL = cfg.queryUrl;
HIVE_AGENT_NAME = config.services.hyperhive.agent.user.name;
BAO_ADDR = baoCfg.addr;
BAO_CLIENT_CERT = baoCfg.clientCertFile;
BAO_CLIENT_KEY = baoCfg.clientKeyFile;
BAO_CACERT = "/run/credentials/hive-agent.service/hive-agent-bao-server-ca";
};
# Same shape `swarm-controller.nix` wraps `swarmctl` in — `symlinkJoin` +
# `wrapProgram`, not a `writeShellScriptBin` shim, because the wrapper has
# to leave the binary's `--help`, its exit status and its streams intact.
# The whole point of the CLI is that its stdout pipes into `grep`.
swarmLogsConfigured = pkgs.symlinkJoin {
name = "swarm-logs-configured";
paths = [ config.services.hyperhive.agent.packages.swarm-logs ];
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/swarm-logs ${
lib.concatStringsSep " " (
lib.mapAttrsToList (name: value: "--set ${name} ${lib.escapeShellArg value}") wrapperEnv
)
}
'';
};
in
{
options.services.hyperhive.agent.logs = {
queryUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "https://logs.example.com/select/logsql/query";
description = ''
The swarm log store's LogsQL query endpoint, as this container
reaches it — the machine route `swarm-victorialogs.nix` puts on the
gateway, not the browser one at `/`.
Set by the generated meta flake from the host's own
{option}`services.hyperhive.swarm.victorialogs.domain`.
`null` means this hive has not been given the log store's address for
its agents, and `swarm-logs` is then not installed at all. Deliberately
not defaulted: a guessed address resolves cleanly to the wrong place.
'';
};
};
config = lib.mkIf configured {
environment.systemPackages = [ swarmLogsConfigured ];
};
}