Premiere commit - Omika

This commit is contained in:
2026-10-23 18:46:50 +02:00
commit 8ea76c1b24
2155 changed files with 984301 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
-- ============================================================
-- Omika Diagnostic Center -- 003_diagnostics_roles.sql (Phase 5B2B.3)
-- PostgreSQL hardening : least privilege (Worker / Web / Owner).
-- ============================================================
-- TO RUN ON SRV-OMIKA as PostgreSQL superuser (e.g. psql -U postgres),
-- BEFORE Phase 5C. DO NOT run from the development PC.
--
-- Guarantees :
-- - PostgreSQL 18 compatible.
-- - Idempotent : re-running is a no-op.
-- - Non destructive : NO DROP, no role/object/data removal.
-- - NO password, NO secret (LOGIN role passwords are set manually via
-- \password, never in this file).
--
-- Role model :
-- omika_diagnostics_owner NOLOGIN : owner of DB/schema/tables/sequences/indexes.
-- omika_diagnostics_worker LOGIN : Worker runtime (JSONL import).
-- omika_diagnostics_web LOGIN : Web runtime (read only).
-- omika_diagnostics_app (existing) : KEPT (controlled transition),
-- NOT disabled here.
--
-- Server apply order : 001 (schema) -> 002 (actor_key) -> 003 (roles).
-- ============================================================
-- ------------------------------------------------------------
-- 1. Create roles if absent (NO password here).
-- ------------------------------------------------------------
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'omika_diagnostics_owner') THEN
CREATE ROLE omika_diagnostics_owner;
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'omika_diagnostics_worker') THEN
CREATE ROLE omika_diagnostics_worker;
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'omika_diagnostics_web') THEN
CREATE ROLE omika_diagnostics_web;
END IF;
END
$$;
-- ------------------------------------------------------------
-- 2. Secure attributes (idempotent).
-- All: NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS.
-- ------------------------------------------------------------
ALTER ROLE omika_diagnostics_owner NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS NOLOGIN;
ALTER ROLE omika_diagnostics_worker NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS LOGIN;
ALTER ROLE omika_diagnostics_web NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS LOGIN;
-- ------------------------------------------------------------
-- 3. Ownership transfer (explicit -- no global REASSIGN OWNED).
-- Only Omika Diagnostics objects are targeted.
-- ------------------------------------------------------------
ALTER DATABASE omika_diagnostics OWNER TO omika_diagnostics_owner;
ALTER SCHEMA public OWNER TO omika_diagnostics_owner;
ALTER TABLE diagnostic_event OWNER TO omika_diagnostics_owner;
ALTER TABLE telemetry_metric_hourly OWNER TO omika_diagnostics_owner;
ALTER SEQUENCE diagnostic_event_id_seq OWNER TO omika_diagnostics_owner;
ALTER SEQUENCE telemetry_metric_hourly_id_seq OWNER TO omika_diagnostics_owner;
-- PostgreSQL 18:
-- Index ownership follows table ownership.
-- No ALTER INDEX OWNER is required.
-- (Sequences are NOT auto-transferred by ALTER TABLE: the ALTER SEQUENCE
-- OWNER commands above are therefore kept and required.)
-- ------------------------------------------------------------
-- 4. Schema "public" hardening.
-- Decision : YES, REVOKE CREATE -- the database is dedicated to the
-- Diagnostic Center; only the owner/admin should create objects.
-- (PostgreSQL 15+ already revokes it for new databases; this is an
-- idempotent belt-and-suspenders.)
-- ------------------------------------------------------------
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
-- ------------------------------------------------------------
-- 5. MINIMUM runtime privileges (from real code audit).
--
-- WORKER (omika_diagnostics_worker):
-- * diagnostic_event : INSERT only
-- (INSERT ... ON CONFLICT (event_id) DO NOTHING -- dedup).
-- * sequence diagnostic_event_id_seq : USAGE (id BIGSERIAL).
-- * NO SELECT/UPDATE/DELETE (60-day retention is NOT implemented;
-- telemetry_metric_hourly upsert is registered but has NO caller).
--
-- WEB (omika_diagnostics_web): SELECT ONLY on diagnostic_event
-- (QueryAsync count+page, GetByTraceId, GetByOperationId, IsAvailableAsync).
--
-- NO privilege granted on telemetry_metric_hourly while no code uses it
-- (least privilege).
-- ------------------------------------------------------------
-- Explicit connection intent (PUBLIC keeps default CONNECT; documented only,
-- not hardened beyond requested scope).
GRANT CONNECT ON DATABASE omika_diagnostics TO omika_diagnostics_worker, omika_diagnostics_web;
GRANT USAGE ON SCHEMA public TO omika_diagnostics_worker, omika_diagnostics_web;
-- Worker : JSONL import -> diagnostic_event.
GRANT INSERT ON TABLE diagnostic_event TO omika_diagnostics_worker;
GRANT USAGE ON SEQUENCE diagnostic_event_id_seq TO omika_diagnostics_worker;
-- Web : read only.
GRANT SELECT ON TABLE diagnostic_event TO omika_diagnostics_web;
-- ------------------------------------------------------------
-- 6. Legacy role omika_diagnostics_app : KEPT (no DROP, no NOLOGIN here).
-- After transfer it owns no Diagnostics object and has no object privilege;
-- disabling it (ALTER ROLE ... NOLOGIN) is an EXPLICIT administrator action
-- AFTER validating the new roles.
-- ------------------------------------------------------------
-- ============================================================
-- END 003. Manual next steps (outside this script):
-- 1. Set passwords: psql -> \password omika_diagnostics_worker
-- then \password omika_diagnostics_web (never in script/log/history).
-- 2. Point Worker: Username=omika_diagnostics_worker ; Web:
-- Username=omika_diagnostics_web (ConnectionStrings__DiagnosticsDatabase).
-- 3. Validate Worker (INSERT) and Web (SELECT), then only after,
-- disable omika_diagnostics_app (ALTER ROLE ... NOLOGIN) if desired.
-- ============================================================