67 lines
2.7 KiB
MySQL
67 lines
2.7 KiB
MySQL
|
|
-- =============================================================
|
||
|
|
-- DWH ROLES AUDIT
|
||
|
|
-- Target Database: tracksolid_dwh
|
||
|
|
-- Purpose: Assert that the n8n DWH pipeline's role contract holds:
|
||
|
|
-- - dwh_owner exists (writes bronze + dwh_control)
|
||
|
|
-- - grafana_ro exists (reads bronze + silver + gold + dwh_control)
|
||
|
|
-- - grafana_ro has CONNECT on the database
|
||
|
|
-- - grafana_ro has USAGE on every schema it needs
|
||
|
|
-- Applies after: 260423_dwh_ddl_v1.sql, 261001_dwh_control.sql
|
||
|
|
-- Idempotent: pure assertion, no CREATE ROLE or GRANT statements.
|
||
|
|
--
|
||
|
|
-- Why this file exists: 260423 creates both roles and grants bronze/silver/gold;
|
||
|
|
-- 261001 grants dwh_control. This file is a single checkpoint that verifies
|
||
|
|
-- those prior migrations were applied in the right order, and fails loudly
|
||
|
|
-- if anything is missing before the pipeline goes live.
|
||
|
|
--
|
||
|
|
-- Password rotation and sslmode=require enforcement are out-of-band:
|
||
|
|
-- rotate via ALTER ROLE ... PASSWORD ... in a psql superuser session,
|
||
|
|
-- enforce SSL via the n8n credential (sslmode=require) — not SQL-level.
|
||
|
|
-- =============================================================
|
||
|
|
|
||
|
|
BEGIN;
|
||
|
|
|
||
|
|
DO $$
|
||
|
|
DECLARE
|
||
|
|
missing TEXT := '';
|
||
|
|
r RECORD;
|
||
|
|
BEGIN
|
||
|
|
-- 1. Roles exist
|
||
|
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'dwh_owner') THEN
|
||
|
|
missing := missing || E'\n - role dwh_owner missing (expected from 260423)';
|
||
|
|
END IF;
|
||
|
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN
|
||
|
|
missing := missing || E'\n - role grafana_ro missing (expected from 260423)';
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
-- 2. grafana_ro CONNECT on this database
|
||
|
|
IF NOT has_database_privilege('grafana_ro', current_database(), 'CONNECT') THEN
|
||
|
|
missing := missing
|
||
|
|
|| format(E'\n - grafana_ro lacks CONNECT on database %s',
|
||
|
|
current_database());
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
-- 3. grafana_ro USAGE on every schema the pipeline / dashboards touch
|
||
|
|
FOR r IN
|
||
|
|
SELECT unnest(ARRAY['bronze','silver','gold','dwh_control']) AS schema_name
|
||
|
|
LOOP
|
||
|
|
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = r.schema_name) THEN
|
||
|
|
missing := missing
|
||
|
|
|| format(E'\n - schema %s missing (expected from 260423/261001)',
|
||
|
|
r.schema_name);
|
||
|
|
ELSIF NOT has_schema_privilege('grafana_ro', r.schema_name, 'USAGE') THEN
|
||
|
|
missing := missing
|
||
|
|
|| format(E'\n - grafana_ro lacks USAGE on schema %s',
|
||
|
|
r.schema_name);
|
||
|
|
END IF;
|
||
|
|
END LOOP;
|
||
|
|
|
||
|
|
IF length(missing) > 0 THEN
|
||
|
|
RAISE EXCEPTION E'DWH roles audit FAILED:%s', missing;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
RAISE NOTICE 'DWH roles audit OK: dwh_owner + grafana_ro present with expected grants.';
|
||
|
|
END$$;
|
||
|
|
|
||
|
|
COMMIT;
|