From e072adb7178420d3d1ad10ea8f544ee11856f3cb Mon Sep 17 00:00:00 2001 From: Admin MPCZ Date: Tue, 14 Apr 2026 20:13:11 +0200 Subject: [PATCH] Add import_ips_from_qualys: fallback IPs depuis Qualys pour serveurs sans IP iTop --- tools/import_ips_from_qualys.py | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tools/import_ips_from_qualys.py diff --git a/tools/import_ips_from_qualys.py b/tools/import_ips_from_qualys.py new file mode 100644 index 0000000..fa59ba2 --- /dev/null +++ b/tools/import_ips_from_qualys.py @@ -0,0 +1,63 @@ +"""Fallback IPs depuis qualys_assets.ip_address pour les serveurs sans IP. + +Utilise les IPs de scan Qualys pour combler les serveurs iTop qui n'ont pas +d'Interface Réseau / d'IP directe renseignée. + +Usage: + python tools/import_ips_from_qualys.py [--dry-run] +""" +import os +import argparse +from sqlalchemy import create_engine, text + +DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \ + or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo" + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--dry-run", action="store_true") + args = parser.parse_args() + + engine = create_engine(DATABASE_URL) + print(f"[INFO] DB: {DATABASE_URL.split('@')[-1]}") + conn = engine.connect().execution_options(isolation_level="AUTOCOMMIT") + + # Match qualys_assets -> servers via server_id (prioritaire) ou hostname + rows = conn.execute(text(""" + SELECT s.id as sid, s.hostname, qa.ip_address + FROM servers s + JOIN qualys_assets qa ON (qa.server_id = s.id + OR LOWER(qa.hostname) = LOWER(s.hostname)) + WHERE qa.ip_address IS NOT NULL + AND qa.ip_address != '' + AND NOT EXISTS (SELECT 1 FROM server_ips si WHERE si.server_id = s.id) + """)).fetchall() + print(f"[INFO] {len(rows)} serveurs candidates (sans IP, avec Qualys asset)") + + inserted = skipped = 0 + for r in rows: + ip = r.ip_address.split(",")[0].strip() # 1ere IP si plusieurs + if not ip: + skipped += 1 + continue + if args.dry_run: + print(f" DRY: {r.hostname:20s} <- {ip}") + inserted += 1 + continue + try: + conn.execute(text(""" + INSERT INTO server_ips (server_id, ip_address, ip_type, description) + VALUES (:sid, CAST(:ip AS inet), 'primary', 'Qualys scan') + """), {"sid": r.sid, "ip": ip}) + inserted += 1 + except Exception as e: + print(f" [ERR] {r.hostname} {ip}: {str(e)[:120]}") + skipped += 1 + + conn.close() + print(f"\n[DONE] Inserts: {inserted} | Skip: {skipped}") + + +if __name__ == "__main__": + main()