feat(observability): own grafana_reader password via repeatable migration
V68 used to set the role's password in a versioned migration, which Flyway applies exactly once per database. Rotating GRAFANA_DB_PASSWORD therefore had no effect on the DB role — operators would need a manual ALTER ROLE or a `flyway repair` that nobody documented. The shape conflated two lifecycles: schema migration (one-shot, immutable) and credential provisioning (rotatable). Split into: - V68 (versioned, immutable): creates the role and applies SELECT grants on audit_log, documents, transcription_blocks. - R__grafana_reader_password.sql (repeatable): issues ALTER ROLE … PASSWORD with the placeholder. Flyway computes the checksum on the resolved content, so any change to GRAFANA_DB_PASSWORD changes the checksum and re-applies the migration on the next boot. Rotation becomes "bump env var + restart backend". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
-- Repeatable migration: sets the grafana_reader role's password from the
|
||||||
|
-- ${grafanaDbPassword} placeholder (resolved by FlywayConfig from the
|
||||||
|
-- GRAFANA_DB_PASSWORD environment variable). Flyway computes the checksum on
|
||||||
|
-- the resolved migration content, so any change to GRAFANA_DB_PASSWORD changes
|
||||||
|
-- the checksum and re-applies this migration on the next boot. That makes
|
||||||
|
-- password rotation a "change env var + restart" operation — no manual psql.
|
||||||
|
--
|
||||||
|
-- V68 created the role itself (without a usable password). This file owns the
|
||||||
|
-- password lifecycle; nothing else writes it.
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format('ALTER ROLE grafana_reader WITH PASSWORD %L', '${grafanaDbPassword}');
|
||||||
|
END
|
||||||
|
$$;
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
-- Read-only role used by the Grafana PostgreSQL datasource for the PO Overview
|
-- Read-only role used by the Grafana PostgreSQL datasource for the PO Overview
|
||||||
-- dashboard (issue #651). Password is injected at migration time via the Flyway
|
-- dashboard (issue #651). The role is created here without a usable password
|
||||||
-- placeholder ${grafanaDbPassword}, supplied by FlywayConfig from the
|
-- (LOGIN-capable but no password set); R__grafana_reader_password.sql sets the
|
||||||
-- GRAFANA_DB_PASSWORD environment variable.
|
-- password from GRAFANA_DB_PASSWORD on every boot, so rotation is just "bump
|
||||||
|
-- the env var and restart the backend" — see docs/adr/024-* and the rotation
|
||||||
|
-- runbook in docs/DEPLOYMENT.md.
|
||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'grafana_reader') THEN
|
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'grafana_reader') THEN
|
||||||
EXECUTE format('CREATE ROLE grafana_reader WITH LOGIN PASSWORD %L', '${grafanaDbPassword}');
|
CREATE ROLE grafana_reader WITH LOGIN;
|
||||||
ELSE
|
|
||||||
EXECUTE format('ALTER ROLE grafana_reader WITH LOGIN PASSWORD %L', '${grafanaDbPassword}');
|
|
||||||
END IF;
|
END IF;
|
||||||
END
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|||||||
Reference in New Issue
Block a user