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.
82 lines
3.2 KiB
Nix
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 ];
|
|
};
|
|
}
|