Files
Omika/infra/postgresql/009_diagnostics_clients_grants.sql
2026-10-23 18:46:50 +02:00

104 lines
5.3 KiB
SQL

-- ============================================================
-- Omika Diagnostic Center -- 009_diagnostics_clients_grants.sql
-- T22 : moindre privilège pour la table diagnostics_clients (008).
-- ============================================================
-- TO RUN ON SRV-OMIKA as PostgreSQL superuser (e.g. psql -U postgres -d omika_diagnostics -f 009_...),
-- AFTER 008 (table diagnostics_clients) and AFTER 003/004 (rôles owner/worker/web).
--
-- Guarantees :
-- - PostgreSQL 18 compatible.
-- - Idempotent : re-running is a no-op.
-- - Non destructive : NO DROP, NO DELETE/TRUNCATE, no data removal.
-- - NO password, NO secret (LOGIN role password is set manually via \password).
--
-- Motivations (T22) :
-- 008 crée diagnostics_clients APRÈS 003/004. La table reste donc possédée
-- par le rôle qui exécute 008 (postgres) et ne reçoit AUCUN GRANT applicatif :
-- l'API centrale (authentification ClientCode+ApiKey + last_seen_at_utc) et
-- l'administration Web (/Clients) échoueraient avec leurs comptes de service.
--
-- Rôle AJOUTÉ : omika_diagnostics_api (LOGIN). Le modèle 003 ne prévoyait que
-- owner/worker/web ; Omika.Diagnostics.Api (service distinct du Worker et du
-- Web) n'y figurait pas. Elle n'accède QU'À diagnostics_clients.
--
-- Ownership : même propriétaire logique que les autres tables Diagnostics
-- (omika_diagnostics_owner), comme 003. Les index suivent automatiquement la
-- table ; la séquence BIGSERIAL est transférée explicitement.
--
-- Note portabilité : GRANT CONNECT utilise current_database() — la migration
-- s'applique donc à la base courante (psql -d <base>), sans coder en dur le
-- nom (contrairement à 003 qui, pour ALTER DATABASE, devait le fixer).
-- ============================================================
-- ------------------------------------------------------------
-- 1. Créer le rôle API s'il est absent (aucun mot de passe ici).
-- ------------------------------------------------------------
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'omika_diagnostics_api') THEN
CREATE ROLE omika_diagnostics_api;
END IF;
END
$$;
ALTER ROLE omika_diagnostics_api NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS LOGIN;
-- ------------------------------------------------------------
-- 2. Ownership : omika_diagnostics_owner (comme 003).
-- ------------------------------------------------------------
ALTER TABLE diagnostics_clients OWNER TO omika_diagnostics_owner;
ALTER SEQUENCE diagnostics_clients_id_seq OWNER TO omika_diagnostics_owner;
-- ------------------------------------------------------------
-- 3. Défense PUBLIC (ceinture + bretelles, idempotent) : aucune
-- table Diagnostics n'est accessible à PUBLIC.
-- ------------------------------------------------------------
REVOKE ALL ON TABLE diagnostics_clients FROM PUBLIC;
-- ------------------------------------------------------------
-- 4. Connexion explicite (intention documentée, comme 003) + schéma.
-- ------------------------------------------------------------
DO $$
BEGIN
EXECUTE format('GRANT CONNECT ON DATABASE %I TO omika_diagnostics_api', current_database());
END
$$;
GRANT USAGE ON SCHEMA public TO omika_diagnostics_api;
-- ------------------------------------------------------------
-- 5. API centrale (Omika.Diagnostics.Api) : SELECT (auth : client,
-- enabled, api_key_hash…) + UPDATE(last_seen_at_utc) uniquement.
-- AUCUN INSERT, AUCUN DELETE, AUCUNE modification de enabled /
-- api_key_hash / key_prefix (moindre privilège, anti-falsification
-- de l'autorisation en cas de compromission de l'API).
-- ------------------------------------------------------------
GRANT SELECT ON TABLE diagnostics_clients TO omika_diagnostics_api;
GRANT UPDATE (last_seen_at_utc) ON TABLE diagnostics_clients TO omika_diagnostics_api;
-- ------------------------------------------------------------
-- 6. Web (Omika.Diagnostics.Web, admin /Clients) : liste + création +
-- activation/désactivation + régénération de clé. AUCUN DELETE
-- (aucune opération de suppression n'existe dans le code T19).
-- USAGE séquence : INSERT ... RETURNING id (id BIGSERIAL).
-- ------------------------------------------------------------
GRANT SELECT ON TABLE diagnostics_clients TO omika_diagnostics_web;
GRANT INSERT ON TABLE diagnostics_clients TO omika_diagnostics_web;
GRANT UPDATE (enabled, api_key_hash, key_prefix, key_created_at_utc)
ON TABLE diagnostics_clients TO omika_diagnostics_web;
GRANT USAGE ON SEQUENCE diagnostics_clients_id_seq TO omika_diagnostics_web;
-- ------------------------------------------------------------
-- 7. Worker (Omika.Diagnostics.Worker) : AUCUN droit sur
-- diagnostics_clients (il n'y accède jamais : import JSONL ->
-- diagnostic_event + rétention diagnostic_event uniquement).
-- Rien à accorder. Aucun REVOKE nécessaire : le rôle n'a reçu
-- aucun privilège sur cette table.
-- ------------------------------------------------------------
-- ============================================================
-- END 009. Ordre serveur : 001 -> 002 -> 003 -> 004 -> 005 -> 006
-- -> 007 -> 008 -> 009. Mots de passe posés manuellement (\password),
-- jamais dans un script/log.
-- ============================================================