- Migration deploy/migrations/2026-04-16_ioda_qualys_missing.sql:
* ALTER applications: 13 colonnes ioda_* (libelle, code_pos, type, statut,
perimetre, dept_domaine, resp_metier, resp_dsi, nb_components, etc.)
* Index unique sur ioda_libelle (cle d'upsert idempotente)
* Nouvelle table qualys_missing_servers avec server_id FK,
reason_category enum (appliance/ot_scada/virtualisation/oubli/...),
status (a_traiter/a_enroler/exempt/enrole/decom), priority 1-5,
trigger updated_at
- tools/import_applications_ioda.py: lit deploy/ServeursAssoci*IODA*.xlsx
sheet "Services Metiers", upsert sur ioda_libelle
- tools/import_qualys_missing.py: lit deploy/comparaison*.xlsx sheet
RECAP, filtre col J (COMP1) sans 'Qualys', categorise auto via
heuristique nom (BAC_/BEU_/... = ot_scada, esx*/vp*esx = virtu,
presence 3 sources sans Qualys = oubli urgent), lien auto vers
servers.id si match hostname/fqdn
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
79 lines
4.7 KiB
PL/PgSQL
79 lines
4.7 KiB
PL/PgSQL
-- Migration 2026-04-16 : enrichissement applications IODA + table qualys_missing_servers
|
|
-- Idempotent (re-jouable sans casse)
|
|
|
|
BEGIN;
|
|
|
|
-- =========================================================================
|
|
-- 1) Extension table applications avec champs IODA
|
|
-- =========================================================================
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_libelle varchar(200);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_lib_court varchar(50);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_code_pos varchar(20);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_type varchar(50);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_statut varchar(50);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_alias text;
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_perimetre varchar(100);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_dept_domaine varchar(200);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_resp_metier varchar(100);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_resp_dsi varchar(100);
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_nb_components integer;
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_commentaire text;
|
|
ALTER TABLE applications ADD COLUMN IF NOT EXISTS ioda_imported_at timestamptz;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS applications_ioda_libelle_uniq
|
|
ON applications (ioda_libelle) WHERE ioda_libelle IS NOT NULL;
|
|
|
|
COMMENT ON COLUMN applications.ioda_libelle IS 'Libellé service métier IODA (clé d''import)';
|
|
COMMENT ON COLUMN applications.ioda_code_pos IS 'Code zone POS IODA (TRA, ADV, …)';
|
|
COMMENT ON COLUMN applications.ioda_resp_metier IS 'Responsable Service Métier (à notifier patching)';
|
|
COMMENT ON COLUMN applications.ioda_resp_dsi IS 'Responsable Service DSI (à notifier patching)';
|
|
|
|
-- =========================================================================
|
|
-- 2) Table qualys_missing_servers (serveurs absents de Qualys + raison)
|
|
-- =========================================================================
|
|
CREATE TABLE IF NOT EXISTS qualys_missing_servers (
|
|
id serial PRIMARY KEY,
|
|
hostname varchar(255) NOT NULL,
|
|
hostname_norm varchar(255) GENERATED ALWAYS AS (lower(hostname)) STORED,
|
|
environnement varchar(50),
|
|
sources_present varchar(100), -- ex: "Cyberark+S1+ITOP"
|
|
in_cyberark boolean DEFAULT false,
|
|
in_sentinel boolean DEFAULT false,
|
|
in_itop boolean DEFAULT false,
|
|
server_id integer REFERENCES servers(id) ON DELETE SET NULL,
|
|
reason_category varchar(30), -- appliance | ot_scada | virtualisation | embedded | oubli | decom | inconnu | other
|
|
reason_detail text,
|
|
status varchar(20) DEFAULT 'a_traiter', -- a_traiter | a_enroler | exempt | enrole | decom
|
|
priority smallint DEFAULT 3, -- 1 (urgent) → 5 (faible)
|
|
notes text,
|
|
source_file varchar(100), -- fichier d'origine
|
|
last_seen_at timestamptz DEFAULT now(),
|
|
created_at timestamptz DEFAULT now(),
|
|
updated_at timestamptz DEFAULT now(),
|
|
CONSTRAINT qms_status_check CHECK (status IN ('a_traiter','a_enroler','exempt','enrole','decom')),
|
|
CONSTRAINT qms_reason_check CHECK (reason_category IS NULL OR reason_category IN
|
|
('appliance','ot_scada','virtualisation','embedded','oubli','decom','inconnu','other'))
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS qms_hostname_norm_uniq ON qualys_missing_servers (hostname_norm);
|
|
CREATE INDEX IF NOT EXISTS qms_status_idx ON qualys_missing_servers (status);
|
|
CREATE INDEX IF NOT EXISTS qms_reason_idx ON qualys_missing_servers (reason_category);
|
|
CREATE INDEX IF NOT EXISTS qms_server_id_idx ON qualys_missing_servers (server_id);
|
|
|
|
COMMENT ON TABLE qualys_missing_servers IS 'Serveurs détectés ailleurs (CA/S1/iTop) mais absents de Qualys + raison';
|
|
COMMENT ON COLUMN qualys_missing_servers.reason_category IS 'appliance, ot_scada, virtualisation (ESXi), embedded, oubli (à enrôler), decom, inconnu, other';
|
|
COMMENT ON COLUMN qualys_missing_servers.status IS 'a_traiter, a_enroler, exempt (légitimement hors Qualys), enrole (fait), decom';
|
|
COMMENT ON COLUMN qualys_missing_servers.priority IS '1 urgent → 5 faible (auto-calc selon sources)';
|
|
|
|
-- Trigger updated_at
|
|
CREATE OR REPLACE FUNCTION qms_set_updated_at() RETURNS trigger AS $$
|
|
BEGIN NEW.updated_at = now(); RETURN NEW; END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS qms_updated_at_trg ON qualys_missing_servers;
|
|
CREATE TRIGGER qms_updated_at_trg
|
|
BEFORE UPDATE ON qualys_missing_servers
|
|
FOR EACH ROW EXECUTE FUNCTION qms_set_updated_at();
|
|
|
|
COMMIT;
|