gendesign/ops/db-bootstrap/set_tradein_fdw_password.sql
lekss361 08a8cf51b3 fix(deploy): mute psql set_config stdout — prevent password leak in CI logs
Review-bot PR #510 нашёл P0: `set_config(name,value,is_local)` возвращает
установленное значение, psql печатает rows на stdout без `-q`/`-A`/`-t`,
итог — фактический pw появляется в Forgejo Actions deploy logs (retained,
visible всем с repo read access).

Fix: оборачиваем оба `SELECT set_config(...)` в `\o /dev/null` / `\o`
brackets. Output mutes только для этих строк — NOTICE-сообщения из DO block
(idempotency signal 'tradein_fdw_reader password set') остаются видимыми.

Также добавлен rollback hint в комментарии: НЕ revert файл (вернёт сломанный
:'pw' внутри $$), а unset GENDESIGN_FDW_PASSWORD в .env.runtime на VPS.
2026-05-24 14:21:36 +03:00

51 lines
2.8 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Set tradein_fdw_reader password from env.
-- Applied by .forgejo/workflows/deploy.yml after main DB migrations:
-- psql -v pw="$GENDESIGN_FDW_PASSWORD" -f ops/db-bootstrap/set_tradein_fdw_password.sql
--
-- Idempotent: ALTER if role exists, NOTICE and continue if missing
-- (migration 100_tradein_fdw_role.sql might not have applied yet on first deploy).
-- Password is NEVER stored in this file or in git — only the variable name.
--
-- Format %L escapes the password as a SQL string literal — safe even with quotes.
-- Combined with the regex whitelist on the backend side (fdw.py _PASSWORD_RE)
-- this gives defense-in-depth.
--
-- psql variable substitution (:'pw') НЕ интерполируется внутри dollar-quoted
-- блока ($$...$$) — это правило psql, не bug. Поэтому password передаём в DO
-- через сессионный GUC (set_config), который psql интерполирует ВНЕ dollar
-- quote, и читаем внутри через current_setting().
-- Reference incident: deploy 2026-05-24 (post-merge PR #503) упал на
-- "syntax error at or near ':'" в LINE 4 этого файла — :'pw' дошёл до сервера
-- as literal вместо интерполяции.
--
-- ⚠️ `set_config(name, value, is_local) -> text` ВОЗВРАЩАЕТ установленное
-- значение. Без `\o /dev/null` бы psql напечатал password на stdout → leak в
-- Forgejo Actions deploy logs (retained, visible всем с repo read access).
-- Поэтому оборачиваем оба set_config вызова в `\o /dev/null` / `\o` brackets
-- — output mutes только для этих строк, NOTICE-сообщения из DO block
-- (idempotency signal) остаются видимыми.
--
-- Rollback path: НЕ revert этого файла (вернёт сломанный `:'pw'` внутри $$).
-- Корректный rollback — unset GENDESIGN_FDW_PASSWORD в /opt/gendesign/backend
-- /.env.runtime на VPS, deploy.yml тогда пропустит этот шаг полностью.
\o /dev/null
SELECT set_config('app.fdw_pw', :'pw', false);
\o
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'tradein_fdw_reader') THEN
EXECUTE format('ALTER ROLE tradein_fdw_reader WITH PASSWORD %L', current_setting('app.fdw_pw'));
RAISE NOTICE 'tradein_fdw_reader password set';
ELSE
RAISE NOTICE 'tradein_fdw_reader role missing — migration 100_tradein_fdw_role.sql not applied yet';
END IF;
END $$;
-- Clear GUC after use (defense-in-depth — не оставляем password в session state
-- даже на short connection). Same \o trick — set_config return value is empty
-- string here, но всё равно лишний row в stdout не нужен.
\o /dev/null
SELECT set_config('app.fdw_pw', '', false);
\o