Files
sysmig/migrations/007-postgres-admin-role.sh
T
wan 5d1f641c61 add per-migration status case (read-only drift check), integrate into sysmig status
status convention: print one line, exit 0 OK / 1 DRIFT / 2 unknown (e.g.
needs root). sysmig status now shows [applied ✓/✗/?] per migration and
exits 1 on drift. DB checks fall back to peer auth when non-root.
2026-08-31 16:46:21 +09:00

60 lines
2.3 KiB
Bash

#!/usr/bin/env bash
# 007-postgres-admin-role - Make the iwanhae Linux user a PostgreSQL
# superuser so it can administer the cluster via peer auth (psql with no
# password, like the postgres OS user). Requires 006 (cluster running).
# up: CREATE ROLE iwanhae LOGIN SUPERUSER (idempotent; re-run promotes)
# down: DROP ROLE iwanhae (with hint if it owns objects in some database)
set -euo pipefail
ROLE=iwanhae
role_exists() {
runuser -u postgres -- psql -v ON_ERROR_STOP=1 -tAc \
"SELECT 1 FROM pg_roles WHERE rolname='$ROLE'" | grep -q 1
}
case "${1:-}" in
up)
if role_exists; then
runuser -u postgres -- psql -v ON_ERROR_STOP=1 -qc \
"ALTER ROLE $ROLE WITH LOGIN SUPERUSER"
echo " role $ROLE already existed - promoted to LOGIN SUPERUSER"
else
runuser -u postgres -- psql -v ON_ERROR_STOP=1 -qc \
"CREATE ROLE $ROLE WITH LOGIN SUPERUSER"
echo " role $ROLE created: LOGIN SUPERUSER"
fi
# end-to-end proof: connect over the unix socket as the OS user (peer)
check=$(runuser -u "$ROLE" -- psql -d postgres -tAc \
"SELECT current_user || ' (superuser=' || rolsuper || ')' FROM pg_roles WHERE rolname = current_user")
echo " peer-auth check: $check"
;;
status)
if [[ $EUID -eq 0 ]]; then
q() { runuser -u postgres -- psql -d postgres -v ON_ERROR_STOP=1 -tAc "$1"; }
elif psql -d postgres -tAc 'SELECT 1' >/dev/null 2>&1; then
q() { psql -d postgres -v ON_ERROR_STOP=1 -tAc "$1"; }
else
echo "? needs root or peer DB access to verify"
exit 2
fi
row=$(q "SELECT rolsuper::text || '/' || rolcanlogin FROM pg_roles WHERE rolname='$ROLE'")
[[ -n $row ]] || { echo "DRIFT role $ROLE does not exist"; exit 1; }
[[ $row == true/true ]] || { echo "DRIFT role $ROLE super/login=$row (want true/true)"; exit 1; }
echo "OK role $ROLE exists: superuser + login"
;;
down)
if role_exists; then
if runuser -u postgres -- psql -v ON_ERROR_STOP=1 -qc "DROP ROLE $ROLE"; then
echo " role $ROLE dropped"
else
echo "cannot drop $ROLE - it owns objects. In EVERY database it has objects run:" >&2
echo " runuser -u postgres -- psql -d <db> -c 'DROP OWNED BY $ROLE;'" >&2
exit 1
fi
else
echo " role $ROLE does not exist - nothing to do"
fi
;;
esac