# `checks.module-eval-agent-github-bao` — see ./lib.nix for the shared # rationale (why this suite exists, naming convention, "evaluates # not executes"). # # The agent side of the swarm-stored GitHub token: ../agent-modules/github-token.nix # fetches it into the file ../agent-modules/github.nix's readers use. { pkgs, lib, self, nixosSystem, }: let inherit (import ./lib.nix { inherit pkgs lib self nixosSystem ; }) agentWith runGroup ; baoAddr = "https://bao.t.local:8200"; # A store, and the integration on by default. agentGithubBao = agentWith { services.hyperhive.agent.bao.addr = baoAddr; }; # No store: the absence arm, and what makes the cases above able to fail. agentGithubNoBao = agentWith { }; # A store, and the integration switched off. agentGithubOff = agentWith { services.hyperhive.agent.bao.addr = baoAddr; services.hyperhive.agent.github.enable = false; }; fetchUnit = machine: machine.systemd.services.hive-agent-github-token; has = machine: machine.systemd.services ? hive-agent-github-token; hasTimer = machine: machine.systemd.timers ? hive-agent-github-token; in let cases = [ { name = "an agent with a store address and the integration on fetches its github token"; ok = has agentGithubBao && hasTimer agentGithubBao; } { name = "an agent with no store address, or with the integration off, fetches none"; ok = !(has agentGithubNoBao) && !(hasTimer agentGithubNoBao) && !(has agentGithubOff) && !(hasTimer agentGithubOff); } { # The nix half of `swarm_secret_client::github::account_path`, and the # file ./github.nix's `gh` wrapper, credential helper and poller read. name = "the fetch reads the agent's own github-token path into its state-dir file"; ok = let name = agentGithubBao.services.hyperhive.agent.user.name; s = (fetchUnit agentGithubBao).script; in lib.hasInfix "bao kv get -format=json secret/swarm/agents/${name}/github-token >" s && lib.hasInfix "token=/agents/${name}/state/github-token" s && lib.hasInfix ".data.data.value | strings" s; } { # The agent user owns its state dir (./user.nix), and the file keeps # its `0600` mode. name = "the fetch runs as the agent, with its own store identity"; ok = let u = fetchUnit agentGithubBao; name = agentGithubBao.services.hyperhive.agent.user.name; in u.serviceConfig.User == name && u.serviceConfig.UMask == "0077" && builtins.elem "hive-agent-bao-cert" u.serviceConfig.LoadCredential && builtins.elem "hive-agent-bao-key" u.serviceConfig.LoadCredential && u.environment.BAO_ADDR == baoAddr && u.environment.BAO_CLIENT_CERT == "%d/hive-agent-bao-cert" && u.environment.BAO_CLIENT_KEY == "%d/hive-agent-bao-key"; } { # A file a hive wrote keeps working until the operator links a token in # the swarm UI. name = "the fetch never deletes the state-dir token, and swaps it in only on a change"; ok = let s = (fetchUnit agentGithubBao).script; in !(lib.hasInfix "rm -f \"$token\"" s) && lib.hasInfix "cmp -s \"$staged\" \"$token\"" s && lib.hasInfix "mv -f \"$staged\" \"$token\"" s; } { # The poller reads the token once at start. name = "the fetch runs before the github poller starts"; ok = builtins.elem "hive-github-notify.service" (fetchUnit agentGithubBao).before; } { name = "the fetch re-runs every two minutes"; ok = agentGithubBao.systemd.timers.hive-agent-github-token.timerConfig.OnUnitInactiveSec == "2min"; } ]; in runGroup "agent-github-bao" cases