Watch
0
0
Fork
You've already forked hyperhive
0

pull swarm closures through the nix daemon: substituters in the fragment, merged root-only netrc

This commit is contained in:
atlas 2026-11-08 10:29:46 +01:00 • committed by mara
commit ef68baa00f

View file

@ -19,11 +19,7 @@ expect() { # <description> <got> <want>
dir=$(mktemp -d)
mkdir -p "$dir/bin"
# A group other than the primary one when the runner has one, so the group the script sets
# differs from the one a new file gets.
group=$(id -Gn | tr " " "\n" | grep -vx "$(id -gn)" | head -1 || true)
group=${group:-$(id -gn)}
sed -e "s|@DIR@|$dir|g" -e "s|@GROUP@|$group|g" "$SCRIPT" >"$dir/script.sh"
sed -e "s|@DIR@|$dir|g" "$SCRIPT" >"$dir/script.sh"
calls=$dir/calls
export DIR=$dir
@ -51,13 +47,14 @@ STUB
chmod +x "$dir/bin/bao"
# `systemctl` answers for nix-daemon.service: DAEMON_STARTED is when it last
# became active (empty: never) and every restart request is logged.
# became active (empty: never, so it is not running) and every call is logged.
cat >"$dir/bin/systemctl" <<STUB
#!$BASH
echo "systemctl \$*" >>"$dir/systemctl"
case "\$1" in
show) printf '%s\n' "\${DAEMON_STARTED-}" ;;
is-failed) exit 1 ;;
is-active) [ -n "\${DAEMON_STARTED-}" ] ;;
try-restart) ;;
*) echo "unexpected call: \$*" >&2; exit 98 ;;
esac
@ -69,7 +66,7 @@ KEYLEAF=secret_swarm_hives_alpha_attic_public-key
TOKENLEAF=secret_swarm_hives_alpha_attic_pull-token
reset() {
rm -rf "$dir/store" "$dir/attic" "$dir/nix" "$calls" "$dir/systemctl"
rm -rf "$dir/store" "$dir/attic" "$dir/nix" "$dir/host-netrc" "$calls" "$dir/systemctl"
mkdir -p "$dir/store"
: >"$calls"
: >"$dir/systemctl"
@ -90,43 +87,41 @@ mode() { stat -c %a "$1" 2>/dev/null || echo missing; }
ino() { stat -c %i "$1" 2>/dev/null || echo missing; }
body() { cat "$1" 2>/dev/null || echo missing; }
case="first run writes the key and the netrc, each 0600, in a 0700 directory"
case="first run writes the key (0600, in a 0700 directory) and the netrc (0600)"
reset
seed "swarm:S0VZ" "tok-1"
run
expect "exit" $? 0
expect "key" "$(body "$dir/attic/public-key")" "swarm:S0VZ"
expect "netrc" "$(body "$dir/attic/netrc")" "machine cache.example password tok-1"
expect "netrc" "$(body "$dir/nix/netrc")" "machine cache.example password tok-1"
expect "key mode" "$(mode "$dir/attic/public-key")" 600
expect "netrc mode" "$(mode "$dir/attic/netrc")" 600
expect "netrc mode" "$(mode "$dir/nix/netrc")" 600
expect "dir mode" "$(mode "$dir/attic")" 700
expect "fragment is the key and nothing else" "$(body "$dir/nix/cache.conf")" "extra-trusted-public-keys = swarm:S0VZ"
expect "fragment names the cache, the key and the root-only netrc" "$(body "$dir/nix/cache.conf")" "extra-substituters = https://cache.example/swarm
extra-trusted-public-keys = swarm:S0VZ
netrc-file = $dir/nix/netrc"
expect "fragment mode" "$(mode "$dir/nix/cache.conf")" 644
expect "fragment dir mode" "$(mode "$dir/nix")" 755
expect "no secret in the fragment" "$(grep -c tok-1 "$dir/nix/cache.conf")" 0
expect "no substituter or netrc in the fragment" "$(grep -c -E "substituter|netrc" "$dir/nix/cache.conf")" 0
expect "client netrc" "$(body "$dir/nix/netrc")" "machine cache.example password tok-1"
expect "client netrc mode" "$(mode "$dir/nix/netrc")" 640
expect "client netrc group" "$(stat -c %G "$dir/nix/netrc")" "$group"
expect "control: the token is in the netrc" "$(grep -c tok-1 "$dir/nix/netrc")" 1
expect "the netrc the fragment names is root-only" "$(mode "$dir/nix/netrc")" 600
case="a second run with the same facts rewrites nothing"
k=$(ino "$dir/attic/public-key")
n=$(ino "$dir/attic/netrc")
cn=$(ino "$dir/nix/netrc")
n=$(ino "$dir/nix/netrc")
c=$(ino "$dir/nix/cache.conf")
run
expect "exit" $? 0
expect "key untouched" "$(ino "$dir/attic/public-key")" "$k"
expect "netrc untouched" "$(ino "$dir/attic/netrc")" "$n"
expect "netrc untouched" "$(ino "$dir/nix/netrc")" "$n"
expect "fragment untouched" "$(ino "$dir/nix/cache.conf")" "$c"
expect "client netrc untouched" "$(ino "$dir/nix/netrc")" "$cn"
case="a rotated token replaces the netrc and leaves the key"
seed "swarm:S0VZ" "tok-2"
run
expect "exit" $? 0
expect "netrc" "$(body "$dir/attic/netrc")" "machine cache.example password tok-2"
expect "netrc mode" "$(mode "$dir/attic/netrc")" 600
expect "netrc" "$(body "$dir/nix/netrc")" "machine cache.example password tok-2"
expect "netrc mode" "$(mode "$dir/nix/netrc")" 600
expect "key untouched" "$(ino "$dir/attic/public-key")" "$k"
case="a rotated key replaces the key file"
@ -140,12 +135,71 @@ expect "reads" "$(grep -c '^bao kv get' "$calls")" "$(grep -c '^bao kv get -fiel
expect "login first" "$(head -1 "$calls")" "bao login -method=cert -token-only"
expect "something was read" "$([ "$(grep -c '^bao kv get' "$calls")" -ge 2 ] && echo yes || echo no)" yes
# The merged netrc: the cache's entry first, then the host's other entries as
# they are. A missing host file is no entries.
HOSTNETRC='machine git.example login bob password hunter2
machine other.example
login alice
password s3cret'
case="a host netrc with two other machines keeps both, after the cache's entry"
reset
seed "swarm:S0VZ" "tok-1"
printf '%s\n' "$HOSTNETRC" >"$dir/host-netrc"
run
expect "exit" $? 0
expect "merged" "$(body "$dir/nix/netrc")" "machine cache.example password tok-1
$HOSTNETRC"
expect "mode" "$(mode "$dir/nix/netrc")" 600
expect "the host's file is not written" "$(body "$dir/host-netrc")" "$HOSTNETRC"
case="a host entry for the cache's own machine is replaced and the rest is kept"
reset
seed "swarm:S0VZ" "tok-1"
printf '%s\n%s\n' "$HOSTNETRC" "machine cache.example login old password stale" >"$dir/host-netrc"
run
expect "exit" $? 0
expect "merged" "$(body "$dir/nix/netrc")" "machine cache.example password tok-1
$HOSTNETRC"
expect "control: the stale entry was in the host file" "$(grep -c stale "$dir/host-netrc")" 1
case="a multi-line host entry for the cache's machine goes whole"
reset
seed "swarm:S0VZ" "tok-1"
printf '%s\n%s\n' "machine cache.example
login old
password stale" "$HOSTNETRC" >"$dir/host-netrc"
run
expect "exit" $? 0
expect "merged" "$(body "$dir/nix/netrc")" "machine cache.example password tok-1
$HOSTNETRC"
case="an edit to the host netrc reaches the merged file on the next run"
reset
seed "swarm:S0VZ" "tok-1"
printf '%s\n' "$HOSTNETRC" >"$dir/host-netrc"
run
printf '%s\n' "machine new.example login n password p" >>"$dir/host-netrc"
run
expect "exit" $? 0
expect "new entry merged" "$(grep -c new.example "$dir/nix/netrc")" 1
expect "old entries kept" "$(grep -c git.example "$dir/nix/netrc")" 1
case="a netrc left 0640 by an earlier deploy is rewritten 0600 though its content is current"
reset
seed "swarm:S0VZ" "tok-1"
run
chmod 640 "$dir/nix/netrc"
run
expect "exit" $? 0
expect "mode" "$(mode "$dir/nix/netrc")" 600
case="a store with no facts exits cleanly and creates nothing"
reset
run
expect "exit" $? 0
expect "no key" "$(body "$dir/attic/public-key")" missing
expect "no netrc" "$(body "$dir/attic/netrc")" missing
expect "no netrc" "$(body "$dir/nix/netrc")" missing
case="one fact without the other creates nothing"
reset
@ -153,7 +207,7 @@ printf '%s' "swarm:S0VZ" >"$dir/store/$KEYLEAF"
run
expect "exit" $? 0
expect "no key" "$(body "$dir/attic/public-key")" missing
expect "no netrc" "$(body "$dir/attic/netrc")" missing
expect "no netrc" "$(body "$dir/nix/netrc")" missing
# The failure cases start from a good state and an extra file in the directory.
good() {
@ -164,7 +218,7 @@ good() {
}
intact() {
expect "key kept" "$(body "$dir/attic/public-key")" "swarm:S0VZ"
expect "netrc kept" "$(body "$dir/attic/netrc")" "machine cache.example password tok-1"
expect "netrc kept" "$(body "$dir/nix/netrc")" "machine cache.example password tok-1"
expect "other file kept" "$(body "$dir/attic/other")" ""
}
@ -212,6 +266,16 @@ seed "swarm:S0VZ" "tok-1"
run DAEMON_STARTED="Sat 2000-01-01 00:00:00.000000 UTC"
expect "exit" $? 0
expect "restart asked" "$(grep -c '^systemctl try-restart --no-block nix-daemon.service' "$dir/systemctl")" 1
expect "restart claimed" "$(grep -c "cache.conf changed after nix-daemon.service last started — restarting it\$" "$dir/out")" 1
case="a daemon that never ran is not restarted, and nothing claims it was"
reset
seed "swarm:S0VZ" "tok-1"
run DAEMON_STARTED=
expect "exit" $? 0
expect "fragment written" "$(grep -c "^extra-substituters" "$dir/nix/cache.conf")" 1
expect "no restart" "$(restarts)" 0
expect "no change-vs-start claim" "$(grep -c "changed after" "$dir/out")" 0
case="the same facts leave the fragment and the daemon alone"
started=$(now)
@ -225,9 +289,7 @@ started=$(now)
seed "swarm:S0VZ" "tok-2"
run DAEMON_STARTED="$started"
expect "exit" $? 0
expect "netrc" "$(body "$dir/attic/netrc")" "machine cache.example password tok-2"
expect "client netrc follows" "$(body "$dir/nix/netrc")" "machine cache.example password tok-2"
expect "client netrc mode" "$(mode "$dir/nix/netrc")" 640
expect "netrc" "$(body "$dir/nix/netrc")" "machine cache.example password tok-2"
expect "no restart" "$(restarts)" 0
case="a rotated key rewrites the fragment and restarts the daemon"
@ -243,7 +305,6 @@ reset
run DAEMON_STARTED="Sat 2000-01-01 00:00:00.000000 UTC"
expect "exit" $? 0
expect "no fragment" "$(body "$dir/nix/cache.conf")" missing
expect "no client netrc" "$(body "$dir/nix/netrc")" missing
expect "no restart" "$(restarts)" 0
case="a key that is refused writes no fragment"
@ -252,7 +313,6 @@ seed "swarm:S0 VZ" "tok-1"
run
expect "exit" $? 1
expect "no fragment" "$(body "$dir/nix/cache.conf")" missing
expect "no client netrc" "$(body "$dir/nix/netrc")" missing
if [ "$failures" -ne 0 ]; then
echo "$failures of $count checks failed" >&2