Watch
0
0
Fork
You've already forked hyperhive
0

attic-init: replace the stored public key with the one the cache reports

a re-created cache signs with a new key; the fact was only created once, so
every hive then rejected the swarm's closures. the cache's grant gains update
on that one leaf, and a store that refuses it leaves the key as it was.

Closes #6181
This commit is contained in:
atlas 2026-11-07 07:32:28 +01:00 • committed by mara
commit b0f6ccaa64

View file

@ -48,6 +48,8 @@ case "\$1 \$2" in
f=\$(file "\$path")
echo "bao put cas=\$cas \$path" >>"$calls"
value=\$(cat)
# UPDATE_FAIL is what the store says to a put that replaces a value.
if [ "\$cas" = 0 ] && [ -n "\${UPDATE_FAIL:-}" ]; then echo "\$UPDATE_FAIL" >&2; exit 1; fi
if [ "\${RACE_PATH:-}" = "\$path" ] && [ ! -f "\$f" ]; then
printf '%s' raced >"\$f"
fi
@ -85,7 +87,7 @@ token=\$(cat "\$tokenfile")
echo "attic \$* | token=\$token" >>"$calls"
case "\$1 \$2" in
"cache info")
[ -f "\$DIR/cache-exists" ] && echo " Public Key: grid:FAKEKEY" >&2
[ -f "\$DIR/cache-exists" ] && echo " Public Key: \$(cat "\$DIR/live-key" 2>/dev/null || echo grid:FAKEKEY)" >&2
;;
"cache create") touch "\$DIR/cache-exists" ;;
*) exit 1 ;;
@ -122,7 +124,7 @@ run() {
}
reset() {
rm -rf "$dir/store" "$dir/secrets" "$dir/cache-exists" "$calls"
rm -rf "$dir/store" "$dir/secrets" "$dir/cache-exists" "$dir/live-key" "$calls"
mkdir -p "$dir/store" "$dir/secrets"
: >"$calls"
}
@ -134,6 +136,7 @@ PUSH=secret_swarm_services_attic_push-token
URL=secret_swarm_services_attic_url
CACHE=secret_swarm_services_attic_cache
KEY=secret_swarm_services_attic_public-key
KEY_PATH=secret/swarm/services/attic/public-key
ENVFILE=$dir/secrets/server.env
expect() { # <description> <got> <want>
@ -208,12 +211,12 @@ expect "exit status" $? 0
expect "no token minted" "$(n '^atticadm')" 0
expect "no create call" "$(n '^bao put')" 0
expect "no cache create" "$(n '^attic cache create')" 0
expect "the pull token looked the cache up" "$(n "^attic cache info local:grid | token=$pull")" 1
expect "the pull token looked the cache up, and read its key" "$(n "^attic cache info local:grid | token=$pull")" 2
expect "pull token unchanged" "$(stored $PULL)" "$pull"
expect "push token unchanged" "$(stored $PUSH)" "$push"
expect "address, name and key unchanged" "$(stored $URL)$(stored $CACHE)$(stored $KEY)" "http://cache.examplegridgrid:FAKEKEY"
case="values the operator stored over the minted ones are kept"
case="values the operator stored over the minted ones are kept, except the public key"
for leaf in $PULL $PUSH $URL $CACHE $KEY; do
printf '%s' "operator-$leaf" >"$dir/store/$leaf"
done
@ -221,12 +224,14 @@ done
run "$PROVISION"
expect "exit status" $? 0
expect "no token minted" "$(n '^atticadm')" 0
expect "nothing written" "$(n '^bao put')" 0
expect "only the public key is written" "$(n '^bao put')" 1
expect "the put replaces, it does not create" "$(n "^bao put cas=0 $KEY_PATH")" 1
expect "the operator's push token is still stored" "$(stored $PUSH)" "operator-$PUSH"
expect "the operator's pull token is still stored" "$(stored $PULL)" "operator-$PULL"
expect "the operator's address, name and key are still stored" \
"$(stored $URL)$(stored $CACHE)$(stored $KEY)" "operator-${URL}operator-${CACHE}operator-${KEY}"
expect "the cache lookup used the operator's pull token" "$(n "^attic cache info local:grid | token=operator-$PULL")" 1
expect "the operator's address and name are still stored" \
"$(stored $URL)$(stored $CACHE)" "operator-${URL}operator-${CACHE}"
expect "the key is the cache's, not the operator's" "$(stored $KEY)" "grid:FAKEKEY"
expect "the cache lookup used the operator's pull token, twice" "$(n "^attic cache info local:grid | token=operator-$PULL")" 2
printf '%s' "$pull" >"$dir/store/$PULL"
printf '%s' "$push" >"$dir/store/$PUSH"
printf '%s' http://cache.example >"$dir/store/$URL"
@ -243,6 +248,48 @@ expect "no secret rewritten" "$(n '^bao put')" 0
expect "cache created" "$(n '^attic cache create')" 1
expect "pull token unchanged" "$(stored $PULL)" "$pull"
case="a cache created again with another key replaces the stored key"
rm -f "$dir/cache-exists"
printf '%s' grid:NEWKEY >"$dir/live-key"
: >"$calls"
run "$PROVISION"
expect "exit status" $? 0
expect "cache created" "$(n '^attic cache create')" 1
expect "the stored key is the new cache's" "$(stored $KEY)" "grid:NEWKEY"
expect "one key written, replacing" "$(n "^bao put cas=0 $KEY_PATH")" 1
expect "nothing else written" "$(n '^bao put')" 1
expect "pull token unchanged" "$(stored $PULL)" "$pull"
case="a stored key equal to the cache's is not written again"
: >"$calls"
run "$PROVISION"
expect "exit status" $? 0
expect "nothing written" "$(n '^bao put')" 0
expect "the key is still the new one" "$(stored $KEY)" "grid:NEWKEY"
case="a store that refuses the update keeps the key and the unit succeeds"
printf '%s' grid:FAKEKEY >"$dir/store/$KEY"
: >"$calls"
run "$PROVISION" 'UPDATE_FAIL=Error making API request. Code: 403. Errors: * 1 error occurred: * permission denied'
expect "exit status" $? 0
expect "the update was tried" "$(n "^bao put cas=0 $KEY_PATH")" 1
expect "the old key stays" "$(stored $KEY)" "grid:FAKEKEY"
expect "the refusal is said" "$(grep -c 'refuses to update' "$dir/err" || true)" 1
case="any other failure of the update fails the unit"
: >"$calls"
run "$PROVISION" UPDATE_FAIL="connection refused"
expect "exit status" $? 1
expect "the old key stays" "$(stored $KEY)" "grid:FAKEKEY"
case="a cache that reports no key fails the unit and writes nothing"
printf '' >"$dir/live-key"
: >"$calls"
run "$PROVISION"
expect "exit status" $? 1
expect "nothing written" "$(n '^bao put')" 0
rm -f "$dir/live-key"
case="no tokens are minted while the server is down"
reset
run "$ENSURE_JWT"
@ -277,7 +324,7 @@ run "$ENSURE_JWT"
run "$PROVISION"
expect "no token among the client's arguments" "$(grep -c -- '^attic [^|]*tok-' "$calls" || true)" 0
# The control: the client did see tokens, through its config file.
expect "tokens seen through the config file" "$(grep -c -- '| token=tok-' "$calls" || true)" 4
expect "tokens seen through the config file" "$(grep -c -- '| token=tok-' "$calls" || true)" 5
if [ "$failures" -ne 0 ]; then
echo "$failures of $count checks failed" >&2