61 lines
2.7 KiB
Bash
61 lines
2.7 KiB
Bash
# Temporarily deploy BFF/frontend and shorten the role lifetime. Always restore it.
|
|
rotation() (
|
|
exec 9> "$STATE/bootstrap.lock"
|
|
flock -n 9 || fail 'Another local bootstrap or rotation check is running'
|
|
vault database/roles/bff | jq '.data' > "$WORK/original-role"
|
|
compose ps --services --status running > "$WORK/running"
|
|
workers=''
|
|
restore() {
|
|
touch "$WORK/stop"
|
|
for pid in $workers; do wait "$pid" || true; done
|
|
restore_failed=0
|
|
vault database/roles/bff POST < "$WORK/original-role" >/dev/null || { echo 'ERROR: restore BFF role TTL manually' >&2; restore_failed=1; }
|
|
for service in frontend bff; do
|
|
if ! grep -qx "$service" "$WORK/running"; then compose stop "$service"; compose rm -f "$service"; fi
|
|
done
|
|
return "$restore_failed"
|
|
}
|
|
trap restore EXIT
|
|
trap 'exit 130' INT
|
|
trap 'exit 143' TERM
|
|
jq '.+{default_ttl:"12s",max_ttl:"24s"}' "$WORK/original-role" | vault database/roles/bff POST >/dev/null
|
|
compose up -d --no-deps --force-recreate --wait --wait-timeout 90 bff frontend
|
|
process=$(compose exec -T bff pidof service)
|
|
for worker in 1 2 3 4; do
|
|
(
|
|
while [ ! -f "$WORK/stop" ]; do
|
|
# 43 characters passes syntax validation, executes a Mongo transaction/read,
|
|
# and returns invalid-token without creating users or sending email.
|
|
token=$(openssl rand -hex 22 | cut -c1-43)
|
|
code=$(printf '{"token":"%s"}' "$token" | https -o "$WORK/body-$worker" -w '%{http_code}' \
|
|
-H 'Content-Type: application/json' -H 'Origin: https://localhost:5126' \
|
|
-H 'X-Auth-Transport: cookie' -H 'X-CSRF-Protection: 1' --data-binary @- \
|
|
https://localhost:5126/api/v1/accounts/verification/confirm) || code=0
|
|
if [ "$code" = 400 ] && grep -q 'Verification is invalid or already used' "$WORK/body-$worker"; then
|
|
echo ok >> "$WORK/results-$worker"
|
|
else echo fail >> "$WORK/results-$worker"; fi
|
|
sleep 0.03
|
|
done
|
|
) &
|
|
workers="$workers $!"
|
|
done
|
|
count=0; attempt=0
|
|
while [ "$attempt" -lt 40 ]; do
|
|
sleep 1
|
|
[ "$(compose exec -T bff pidof service)" = "$process" ] || fail 'BFF restarted during rotation'
|
|
compose logs --no-color bff > "$WORK/logs"
|
|
count=$(grep -c 'Database pool replaced without restarting service' "$WORK/logs" || true)
|
|
[ "$count" -lt 3 ] || break
|
|
attempt=$((attempt+1))
|
|
done
|
|
touch "$WORK/stop"
|
|
for pid in $workers; do wait "$pid"; done
|
|
workers=''
|
|
[ "$count" -ge 3 ] || fail 'Three pool rotations were not observed'
|
|
cat "$WORK"/results-* > "$WORK/results"
|
|
! grep -q fail "$WORK/results" || fail 'Unexpected HTTP responses during rotation'
|
|
count=$(wc -l < "$WORK/results")
|
|
[ "$count" -ge 100 ] || fail 'Insufficient rotation traffic'
|
|
echo "PASS: three real Vault rotations, unchanged BFF PID, $count transaction-backed HTTP requests, zero failures"
|
|
)
|