131 lines
3.2 KiB
Bash
131 lines
3.2 KiB
Bash
#!/bin/sh
|
||
|
||
set -eu
|
||
|
||
|
||
read_secret_file() {
|
||
secret_path=$1
|
||
|
||
if [ ! -r "$secret_path" ]; then
|
||
echo "Не удалось прочитать обязательный PostgreSQL secret file" >&2
|
||
return 1
|
||
fi
|
||
|
||
# Маркер сохраняет переводы строк внутри command substitution.
|
||
secret_with_marker="$(cat "$secret_path"; printf '\001')"
|
||
secret=${secret_with_marker%?}
|
||
carriage_return="$(printf '\r')"
|
||
newline='
|
||
'
|
||
|
||
case "$secret" in
|
||
*"${carriage_return}${newline}")
|
||
secret=${secret%"${carriage_return}${newline}"}
|
||
;;
|
||
*"${newline}")
|
||
secret=${secret%"${newline}"}
|
||
;;
|
||
*"${carriage_return}")
|
||
secret=${secret%"${carriage_return}"}
|
||
;;
|
||
esac
|
||
|
||
if [ -z "$(printf '%s' "$secret" | tr -d '[:space:]')" ]; then
|
||
echo "PostgreSQL secret file содержит пустое значение" >&2
|
||
return 1
|
||
fi
|
||
|
||
printf '%s' "$secret"
|
||
}
|
||
|
||
|
||
if [ -z "${APP_DB_USER:-}" ]; then
|
||
echo "APP_DB_USER должен содержать имя роли приложения" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [ "$APP_DB_USER" = "$POSTGRES_USER" ]; then
|
||
echo "APP_DB_USER не должен совпадать с PostgreSQL admin role" >&2
|
||
exit 1
|
||
fi
|
||
|
||
app_db_password="$(read_secret_file /run/secrets/db_password)"
|
||
|
||
# Официальный entrypoint уже прочитал secret file и применил собственную
|
||
# нормализацию конечных переводов строк. Сравниваем именно фактический пароль.
|
||
if [ -z "$(printf '%s' "${POSTGRES_PASSWORD:-}" | tr -d '[:space:]')" ]; then
|
||
echo "POSTGRES_PASSWORD должен содержать пароль admin role" >&2
|
||
exit 1
|
||
fi
|
||
|
||
postgres_admin_password=$POSTGRES_PASSWORD
|
||
|
||
if [ "$app_db_password" = "$postgres_admin_password" ]; then
|
||
echo "Пароли PostgreSQL admin и application roles должны различаться" >&2
|
||
exit 1
|
||
fi
|
||
|
||
export DZENTRA_APP_DB_PASSWORD="$app_db_password"
|
||
|
||
psql \
|
||
--no-psqlrc \
|
||
--single-transaction \
|
||
--set ON_ERROR_STOP=1 \
|
||
--username "$POSTGRES_USER" \
|
||
--dbname "$POSTGRES_DB" <<'SQL'
|
||
\getenv app_user APP_DB_USER
|
||
\getenv app_password DZENTRA_APP_DB_PASSWORD
|
||
|
||
SELECT format(
|
||
'CREATE ROLE %I LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB '
|
||
'NOCREATEROLE INHERIT NOREPLICATION NOBYPASSRLS',
|
||
:'app_user',
|
||
:'app_password'
|
||
)
|
||
WHERE NOT EXISTS (
|
||
SELECT 1
|
||
FROM pg_catalog.pg_roles
|
||
WHERE rolname = :'app_user'
|
||
)
|
||
\gexec
|
||
|
||
SELECT format(
|
||
'ALTER ROLE %I WITH LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB '
|
||
'NOCREATEROLE INHERIT NOREPLICATION NOBYPASSRLS',
|
||
:'app_user',
|
||
:'app_password'
|
||
)
|
||
\gexec
|
||
|
||
SELECT format(
|
||
'ALTER DATABASE %I OWNER TO %I',
|
||
current_database(),
|
||
:'app_user'
|
||
)
|
||
\gexec
|
||
|
||
SELECT format(
|
||
'REVOKE ALL ON DATABASE %I FROM PUBLIC',
|
||
current_database()
|
||
)
|
||
\gexec
|
||
|
||
SELECT format(
|
||
'GRANT CONNECT, TEMPORARY ON DATABASE %I TO %I',
|
||
current_database(),
|
||
:'app_user'
|
||
)
|
||
\gexec
|
||
|
||
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
||
SELECT format(
|
||
'GRANT USAGE, CREATE ON SCHEMA public TO %I',
|
||
:'app_user'
|
||
)
|
||
\gexec
|
||
SQL
|
||
|
||
unset DZENTRA_APP_DB_PASSWORD
|
||
unset app_db_password
|
||
unset postgres_admin_password
|