report the real error when the granter role's bootstrap step fails, and retry on a standby store
This commit is contained in:
parent
3ff4dc7be0
commit
cb5a9b2bd7
3 changed files with 186 additions and 32 deletions
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
# The stub `bao` for ./granter-login.nix. `FAKE_BAO_LOGIN` picks the login's
|
||||
# The stub `bao` for ./granter-login.nix and ./lib/bootstrap-auth-list.nix. `FAKE_BAO_LOGIN` picks the login's
|
||||
# answer, in openbao's wording: `ok`, `standby` (500, a node that is not active
|
||||
# yet), `no-role` (400, no trusted chain), `no-chain-match` (400, a chain that
|
||||
# no role accepts), `sealed` (503). `FAKE_BAO_STATUS_RC` is `status`'s exit
|
||||
# status. `FAKE_BAO_LOGIN_FIRST`, when set, answers the first login with it and
|
||||
# later ones with `FAKE_BAO_LOGIN`; `FAKE_BAO_COUNT` is the file counting them.
|
||||
# `auth list` is answered per the `auth)` arm below.
|
||||
echo "$*" >>"$FAKE_BAO_LOG"
|
||||
case "$1" in
|
||||
login)
|
||||
|
|
@ -33,6 +34,31 @@ case "$1" in
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
auth)
|
||||
# `FAKE_BAO_LIST` picks `auth list`'s answer: `ok`, `standby` (500),
|
||||
# `denied` (403, a token the store refuses), `sealed` (503).
|
||||
# `FAKE_BAO_LIST_FIRST` answers only the first one with it.
|
||||
n=$(($(cat "$FAKE_BAO_LIST_COUNT" 2>/dev/null || echo 0) + 1))
|
||||
echo "$n" >"$FAKE_BAO_LIST_COUNT"
|
||||
answer=${FAKE_BAO_LIST-ok}
|
||||
if [ "$n" = 1 ] && [ -n "${FAKE_BAO_LIST_FIRST-}" ]; then answer=$FAKE_BAO_LIST_FIRST; fi
|
||||
url='URL: GET https://bao.t.local:8200/v1/sys/auth'
|
||||
case "$answer" in
|
||||
ok) printf '{"cert/":{},"oidc/":{}}' ;;
|
||||
standby)
|
||||
printf 'Error listing enabled authentications: Error making API request.\n\n%s\nCode: 500. Errors:\n\n* local node not active but active cluster node not found\n' "$url" >&2
|
||||
exit 2
|
||||
;;
|
||||
denied)
|
||||
printf 'Error listing enabled authentications: Error making API request.\n\n%s\nCode: 403. Errors:\n\n* permission denied\n' "$url" >&2
|
||||
exit 2
|
||||
;;
|
||||
sealed)
|
||||
printf 'Error listing enabled authentications: Error making API request.\n\n%s\nCode: 503. Errors:\n\n* Vault is sealed\n' "$url" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
[ "${FAKE_BAO_STATUS_RC-0}" = 0 ] || {
|
||||
echo "fake bao: status: Vault is sealed" >&2
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
# cases are in ./granter-login.sh and the stub is ./granter-login-fake-bao.sh.
|
||||
#
|
||||
# What runs is the rendered login, with the same `baoStoreUp` text the unit
|
||||
# passes, rendered once with the bootstrap-token hint and once without.
|
||||
# passes, rendered once with the bootstrap-token hint and once without. The
|
||||
# bootstrap token's `auth list` step (../host-modules/lib/bootstrap-auth-list.nix)
|
||||
# is rendered the same way and run against the same stub.
|
||||
{
|
||||
pkgs,
|
||||
...
|
||||
|
|
@ -31,6 +33,16 @@ pkgs.runCommand "hyperhive-script-test-granter-login"
|
|||
{
|
||||
LOGIN = render false;
|
||||
LOGIN_WITH_TOKEN = render true;
|
||||
BOOTSTRAP_LIST = pkgs.writeText "bootstrap-auth-list.sh" (
|
||||
import ../host-modules/lib/bootstrap-auth-list.nix {
|
||||
inherit (pkgs) lib;
|
||||
bootstrapTokenFile = "/tmp/granter-bootstrap-test.token";
|
||||
granterClientCertFile = "/nonexistent/granter.crt";
|
||||
granterClientKeyFile = "/nonexistent/granter.key";
|
||||
baoStoreUp = ''HOME=/var/empty bao status >/dev/null 2>>"$err"'';
|
||||
setupSteps = [ "bao policy write bao-bootstrap /etc/bootstrap.hcl" ];
|
||||
}
|
||||
);
|
||||
FAKE_BAO_BIN = "${fakeBao}/bin";
|
||||
nativeBuildInputs = [
|
||||
pkgs.coreutils
|
||||
|
|
|
|||
|
|
@ -99,5 +99,75 @@ err_has "the store is sealed or unreachable; retrying."
|
|||
err_has "Vault is sealed"
|
||||
err_lacks "role is not set up"
|
||||
|
||||
# The bootstrap token's `auth list` step: the rendered snippet runs under
|
||||
# `set -e` with the scratch file the unit makes. Sets $rc, $got (the listing it
|
||||
# left in `mounted`) and $dir/err.
|
||||
token=/tmp/granter-bootstrap-test.token
|
||||
|
||||
setup_list() {
|
||||
setup "$1"
|
||||
export FAKE_BAO_LIST_COUNT=$dir/list-count FAKE_BAO_LIST=ok
|
||||
unset FAKE_BAO_LIST_FIRST
|
||||
echo dead >"$token"
|
||||
}
|
||||
|
||||
run_list() {
|
||||
got=$(
|
||||
(
|
||||
set -e
|
||||
PATH="$FAKE_BAO_BIN:$PATH"
|
||||
err=$(mktemp)
|
||||
# shellcheck source=/dev/null
|
||||
. "$BOOTSTRAP_LIST"
|
||||
echo "$mounted"
|
||||
) 2>"$dir/err"
|
||||
)
|
||||
rc=$?
|
||||
}
|
||||
|
||||
setup_list "a listing that succeeds leaves it in mounted and prints nothing"
|
||||
run_list
|
||||
expect 0 '{"cert/":{},"oidc/":{}}'
|
||||
if [ -s "$dir/err" ]; then fail "printed: $(cat "$dir/err")"; fi
|
||||
|
||||
setup_list "a standby store fails the listing with its own error, does not blame the token, keeps the token file, and the next attempt succeeds"
|
||||
export FAKE_BAO_LIST_FIRST=standby
|
||||
run_list
|
||||
expect 1 ""
|
||||
err_has "local node not active but active cluster node not found"
|
||||
err_has "listing its auth mounts failed without a refused token"
|
||||
err_lacks "refused the bootstrap token"
|
||||
err_lacks "one-time step"
|
||||
if [ ! -e "$token" ]; then fail "token file deleted"; fi
|
||||
run_list
|
||||
expect 0 '{"cert/":{},"oidc/":{}}'
|
||||
|
||||
setup_list "a refused token with no working granter names the token and the setup steps, then bao's error, and exits 4"
|
||||
export FAKE_BAO_LIST=denied FAKE_BAO_LOGIN=no-role
|
||||
run_list
|
||||
expect 4 ""
|
||||
err_has "the store refused the bootstrap token in /tmp/granter-bootstrap-test.token"
|
||||
err_has "one-time step, as root on this host"
|
||||
err_has " bao policy write bao-bootstrap /etc/bootstrap.hcl"
|
||||
err_has "permission denied"
|
||||
if [ ! -e "$token" ]; then fail "token file deleted"; fi
|
||||
|
||||
setup_list "a refused token beside a working granter exits 0 and deletes the token"
|
||||
export FAKE_BAO_LIST=denied FAKE_BAO_LOGIN=ok
|
||||
run_list
|
||||
expect 0 "granter role already in place; bootstrap token not needed"
|
||||
err_lacks "refused the bootstrap token"
|
||||
if [ -e "$token" ]; then fail "token file kept"; fi
|
||||
|
||||
setup_list "a sealed store is reported as sealed or unreachable, with bao's error"
|
||||
export FAKE_BAO_LIST=sealed FAKE_BAO_STATUS_RC=2
|
||||
run_list
|
||||
expect 1 ""
|
||||
err_has "the store is sealed or unreachable; retrying."
|
||||
err_has "Vault is sealed"
|
||||
err_lacks "refused the bootstrap token"
|
||||
|
||||
rm -f "$token"
|
||||
|
||||
echo "granter-login: $count cases, $failures failures"
|
||||
[ "$failures" = 0 ]
|
||||
|
|
|
|||
Loading…
Reference in a new issue