-- ============================================================ -- 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 ), 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. -- ============================================================