90 lines
2.9 KiB
Bash
Executable File
90 lines
2.9 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
cd "$(dirname "$0")/.."
|
|
. ./deploy/vector/secret-policy.sh
|
|
|
|
usage() {
|
|
echo "usage: $0 [--env-file OPERATOR_ENV] OLD_SECRET_FILE NEW_SECRET_FILE" >&2
|
|
echo "set THT_VECTOR_OPERATOR_ENV_FILE instead of --env-file when required by automation" >&2
|
|
exit 2
|
|
}
|
|
|
|
operator_env=${THT_VECTOR_OPERATOR_ENV_FILE:-}
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--env-file)
|
|
[ "$#" -ge 2 ] || usage
|
|
operator_env=$2
|
|
shift 2
|
|
;;
|
|
--env-file=*)
|
|
operator_env=${1#--env-file=}
|
|
shift
|
|
;;
|
|
--) shift; break ;;
|
|
-*) usage ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$operator_env" ]; then
|
|
echo "rotation requires --env-file or THT_VECTOR_OPERATOR_ENV_FILE; there is no implicit default" >&2
|
|
exit 2
|
|
fi
|
|
if [ -L "$operator_env" ] || [ ! -f "$operator_env" ] || [ ! -r "$operator_env" ]; then
|
|
echo "operator env must be a readable regular file, not a symlink: $operator_env" >&2
|
|
exit 2
|
|
fi
|
|
operator_env_mode=$(stat -c '%a' "$operator_env" 2>/dev/null || stat -f '%Lp' "$operator_env" 2>/dev/null) || {
|
|
echo "cannot inspect operator env permissions: $operator_env" >&2
|
|
exit 2
|
|
}
|
|
if [ $((0$operator_env_mode & 022)) -ne 0 ]; then
|
|
echo "operator env must not be writable by group or other users: $operator_env" >&2
|
|
exit 2
|
|
fi
|
|
|
|
if [ "$#" -ne 2 ]; then
|
|
usage
|
|
fi
|
|
|
|
absolute_file() {
|
|
directory=$(CDPATH= cd -- "$(dirname -- "$1")" && pwd)
|
|
printf '%s/%s\n' "$directory" "$(basename -- "$1")"
|
|
}
|
|
|
|
operator_env=$(absolute_file "$operator_env")
|
|
|
|
old_secret=$(absolute_file "$1")
|
|
new_secret=$(absolute_file "$2")
|
|
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
|
|
fi
|
|
|
|
project=${COMPOSE_PROJECT_NAME:-thothii}
|
|
replacement=$(mktemp "${old_secret}.rotate.XXXXXX")
|
|
trap 'rm -f "$replacement"' EXIT HUP INT TERM
|
|
cp "$new_secret" "$replacement"
|
|
chmod 0600 "$replacement"
|
|
|
|
docker compose --env-file "$operator_env" -f compose.yaml -f deploy/compose.local-vector.yaml \
|
|
--project-name "$project" --profile local-vector run --rm --no-deps \
|
|
--user 0:0 \
|
|
--entrypoint /opt/venv/bin/python \
|
|
--volume "$old_secret:/run/secrets/bootstrap-old:ro" \
|
|
--volume "$new_secret:/run/secrets/bootstrap-new:ro" \
|
|
--volume "$(pwd)/deploy/vector/rotate-bootstrap-password.py:/opt/thoth/rotate-bootstrap-password.py:ro" \
|
|
core /opt/thoth/rotate-bootstrap-password.py \
|
|
/run/secrets/bootstrap-old /run/secrets/bootstrap-new
|
|
|
|
mv -f "$replacement" "$old_secret"
|
|
trap - EXIT HUP INT TERM
|
|
|
|
echo "Deployment bootstrap secret atomically replaced only after verified database login."
|
|
echo "Re-run with the same operator env file: $operator_env"
|
|
echo "docker compose --env-file OPERATOR_ENV -f compose.yaml -f deploy/compose.local-vector.yaml --project-name $project --profile local-vector up --wait vector-reconcile vector-migrate core"
|