fix(deploy): align vector bootstrap identity policy

This commit is contained in:
2026-07-12 02:04:57 +02:00
parent 144acf2093
commit 1145ae20bc
11 changed files with 114 additions and 26 deletions
+18 -3
View File
@@ -32,6 +32,7 @@ export THT_VECTOR_READER_PASSWORD_SECRET_FILE="$secret_dir/reader"
export THT_VECTOR_WRITER_PASSWORD_SECRET_FILE="$secret_dir/writer"
export THT_VECTOR_READER_PASSWORD="smoke-reader-${smoke_project}"
export THT_VECTOR_WRITER_PASSWORD="smoke-writer-${smoke_project}"
export THT_VECTOR_BOOTSTRAP_USER=thoth_bootstrap_smoke
export THOTH_SMOKE_OWNER="$smoke_owner"
compose() {
@@ -167,7 +168,7 @@ migration_status=$(compose run --rm --no-deps vector-migrate)
printf '%s\n' "$migration_status" | grep -q '"pending": \[\]'
migrator_flags=$(compose run --rm --no-deps --entrypoint sh vector-reconcile -ec '
export PGPASSWORD=$(cat /run/secrets/vector_bootstrap_password)
psql -At --host vector-db --username postgres --dbname thoth \
psql -At --host vector-db --username "$THT_VECTOR_BOOTSTRAP_USER" --dbname thoth \
--command "SELECT (NOT rolcreaterole) AND (NOT rolcreatedb) AND (NOT rolsuper) FROM pg_roles WHERE rolname = '\''thoth_vector_migrator'\''"
')
test "$migrator_flags" = t
@@ -199,6 +200,20 @@ old_bootstrap_password=$(cat "$secret_dir/bootstrap")
printf '%s' "wrong-bootstrap-${smoke_project}" >"$secret_dir/bootstrap-wrong"
printf '%s' "next-bootstrap-'quoted-${smoke_project}" >"$secret_dir/bootstrap-next"
cp "$secret_dir/bootstrap" "$secret_dir/bootstrap-before-negative"
printf 'invalid bootstrap password\n' >"$secret_dir/bootstrap-whitespace"
if COMPOSE_PROJECT_NAME="$smoke_project" \
./scripts/vector-rotate-bootstrap-password.sh \
"$secret_dir/bootstrap" "$secret_dir/bootstrap-whitespace" \
>/dev/null 2>&1; then
echo "bootstrap rotation accepted whitespace in a secret" >&2
exit 1
fi
cmp "$secret_dir/bootstrap" "$secret_dir/bootstrap-before-negative"
compose run --rm --no-deps --entrypoint psql \
-e PGPASSWORD="$old_bootstrap_password" vector-reconcile \
--host vector-db --username "$THT_VECTOR_BOOTSTRAP_USER" --dbname thoth \
--command 'SELECT 1' >/dev/null
if COMPOSE_PROJECT_NAME="$smoke_project" \
./scripts/vector-rotate-bootstrap-password.sh \
"$secret_dir/bootstrap-wrong" "$secret_dir/bootstrap-next" \
@@ -215,14 +230,14 @@ new_bootstrap_password=$(cat "$secret_dir/bootstrap")
test "$new_bootstrap_password" != "$old_bootstrap_password"
if compose run --rm --no-deps --entrypoint psql \
-e PGPASSWORD="$old_bootstrap_password" vector-reconcile \
--host vector-db --username postgres --dbname thoth --command 'SELECT 1' \
--host vector-db --username "$THT_VECTOR_BOOTSTRAP_USER" --dbname thoth --command 'SELECT 1' \
>/dev/null 2>&1; then
echo "old bootstrap credential still works after rotation" >&2
exit 1
fi
compose run --rm --no-deps --entrypoint psql \
-e PGPASSWORD="$new_bootstrap_password" vector-reconcile \
--host vector-db --username postgres --dbname thoth --command 'SELECT 1' \
--host vector-db --username "$THT_VECTOR_BOOTSTRAP_USER" --dbname thoth --command 'SELECT 1' \
>/dev/null
compose run --rm vector-reconcile
bootstrap_rotation_status=$(compose run --rm --no-deps vector-migrate)
+18 -2
View File
@@ -10,7 +10,7 @@ log="$tmp/docker.log"
cat >"$fake" <<'SH'
#!/bin/sh
set -eu
printf '%s\n' "$*" >>"$FAKE_DOCKER_LOG"
printf '%s:%s\n' "${THT_VECTOR_BOOTSTRAP_USER:-unset}" "$*" >>"$FAKE_DOCKER_LOG"
exit "${FAKE_DOCKER_EXIT:-0}"
SH
chmod 0755 "$fake"
@@ -19,6 +19,21 @@ printf '%s' old-password >"$tmp/old"
printf '%s' "new-'quoted-\$-password" >"$tmp/new"
cp "$tmp/old" "$tmp/original"
printf 'invalid password\n' >"$tmp/whitespace"
: >"$log"
if PATH="$tmp:$PATH" FAKE_DOCKER_LOG="$log" THT_VECTOR_BOOTSTRAP_USER=custom_admin \
./scripts/vector-rotate-bootstrap-password.sh "$tmp/old" "$tmp/whitespace" \
>"$tmp/out" 2>"$tmp/err"; then
echo "rotation accepted a whitespace-containing secret" >&2
exit 1
fi
cmp "$tmp/old" "$tmp/original"
test ! -s "$log"
if find "$tmp" -name 'old.rotate.*' -print | grep -q .; then
echo "rotation staged a deployment file before secret validation" >&2
exit 1
fi
if PATH="$tmp:$PATH" FAKE_DOCKER_LOG="$log" FAKE_DOCKER_EXIT=1 \
./scripts/vector-rotate-bootstrap-password.sh "$tmp/old" "$tmp/new" \
>"$tmp/out" 2>"$tmp/err"; then
@@ -28,12 +43,13 @@ fi
cmp "$tmp/old" "$tmp/original"
: >"$log"
PATH="$tmp:$PATH" FAKE_DOCKER_LOG="$log" \
PATH="$tmp:$PATH" FAKE_DOCKER_LOG="$log" THT_VECTOR_BOOTSTRAP_USER=custom_admin \
./scripts/vector-rotate-bootstrap-password.sh "$tmp/old" "$tmp/new" \
>"$tmp/out" 2>"$tmp/err"
cmp "$tmp/old" "$tmp/new"
grep -q '/run/secrets/bootstrap-old:ro' "$log"
grep -q '/run/secrets/bootstrap-new:ro' "$log"
grep -q '^custom_admin:' "$log"
grep -q 'atomically replaced only after verified database login' "$tmp/out"
echo "bootstrap rotation ordering and no-config-change failure contracts passed."
+24
View File
@@ -0,0 +1,24 @@
#!/bin/sh
set -eu
cd "$(dirname "$0")/.."
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
. ./deploy/vector/secret-policy.sh
: >"$tmp/empty"
printf 'has newline\n' >"$tmp/newline"
printf 'has space' >"$tmp/space"
printf 'safe-quoted-\047-dollar-$' >"$tmp/valid"
for invalid in empty newline space; do
if validate_secret_file "$tmp/$invalid" "$invalid" >/dev/null 2>&1; then
echo "secret policy accepted $invalid" >&2
exit 1
fi
done
validate_secret_file "$tmp/valid" valid
test "$(read_secret_file "$tmp/valid" valid)" = "safe-quoted-'-dollar-$"
echo "shared vector secret policy contracts passed."
+3 -6
View File
@@ -2,6 +2,7 @@
set -eu
cd "$(dirname "$0")/.."
. ./deploy/vector/secret-policy.sh
if [ "$#" -ne 2 ]; then
echo "usage: $0 OLD_SECRET_FILE NEW_SECRET_FILE" >&2
@@ -15,12 +16,8 @@ absolute_file() {
old_secret=$(absolute_file "$1")
new_secret=$(absolute_file "$2")
for secret in "$old_secret" "$new_secret"; do
if [ ! -f "$secret" ] || [ ! -r "$secret" ] || [ ! -s "$secret" ]; then
echo "secret file must be a readable, non-empty regular file: $secret" >&2
exit 2
fi
done
validate_secret_file "$old_secret" old_bootstrap_secret
validate_secret_file "$new_secret" new_bootstrap_secret
if [ "$old_secret" -ef "$new_secret" ]; then
echo "old and new secret files must be distinct" >&2
exit 2