Più connettori per azienda; ogni connettore ha una api_key dedicata (scope ingest:assets)
che l'agente esterno usa per mappare e auto-popolare NIS2.
- mig 064: discovery_connectors (per-org, multi) + discovery_runs (storico) + network_flows (ID.AM-03).
- DiscoveryConnectorController (org_admin): CRUD connettori + emissione/rotazione api_key
(mostrata 1 volta) + dettaglio con ultimi run.
- ServicesController::ingestAssets esteso: accetta anche "flows" (upsert network_flows,
dedup external_ref) e, se la chiave appartiene a un connettore, registra discovery_run
+ aggiorna last_run del connettore. Auto-scoring rilevanza NIS2 già in bulkUpsert.
- AssetController::bulkUpsert: ora salva anche "dependencies" → popola la Mappa Dipendenze.
- Router: /api/discovery-connectors (list/create/{id}/update/delete/rotateKey).
Smoke E2E (HTTP 201): 2 asset scorati + 1 flusso + run tracciato + dipendenze persistite.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
66 lines
2.8 KiB
PHP
66 lines
2.8 KiB
PHP
<?php
|
|
/**
|
|
* migrate_064_discovery_connectors.php — Connettori discovery + run + flussi di rete. IDEMPOTENTE.
|
|
* Esegui: docker exec nis2-app php /var/www/nis2-agile/application/cli/migrate_064_discovery_connectors.php
|
|
*/
|
|
if (PHP_SAPI !== 'cli') { http_response_code(403); exit("CLI only\n"); }
|
|
require_once __DIR__ . '/../config/env.php';
|
|
require_once __DIR__ . '/../config/database.php';
|
|
$pdo = Database::getInstance();
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS discovery_connectors (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
organization_id INT NOT NULL,
|
|
name VARCHAR(120) NOT NULL,
|
|
connector_type ENUM('network','aws','azure','gcp','cmdb','agent','custom') NOT NULL DEFAULT 'network',
|
|
config JSON NULL,
|
|
api_key_id INT UNSIGNED NULL,
|
|
status ENUM('active','paused','error') NOT NULL DEFAULT 'active',
|
|
schedule ENUM('manual','hourly','daily','weekly') NOT NULL DEFAULT 'manual',
|
|
last_run_at TIMESTAMP NULL,
|
|
last_status VARCHAR(20) NULL,
|
|
last_discovered INT NULL,
|
|
last_message VARCHAR(255) NULL,
|
|
created_by INT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
UNIQUE KEY uq_dc_org_name (organization_id, name),
|
|
INDEX idx_dc_org (organization_id),
|
|
INDEX idx_dc_key (api_key_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
|
|
echo " + discovery_connectors OK\n";
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS discovery_runs (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
connector_id INT UNSIGNED NOT NULL,
|
|
organization_id INT NOT NULL,
|
|
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
finished_at TIMESTAMP NULL,
|
|
status ENUM('running','ok','error') NOT NULL DEFAULT 'ok',
|
|
discovered_assets INT NOT NULL DEFAULT 0,
|
|
discovered_flows INT NOT NULL DEFAULT 0,
|
|
message VARCHAR(255) NULL,
|
|
INDEX idx_dr_conn (connector_id),
|
|
INDEX idx_dr_org (organization_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
|
|
echo " + discovery_runs OK\n";
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS network_flows (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
organization_id INT NOT NULL,
|
|
src VARCHAR(190) NOT NULL,
|
|
dst VARCHAR(190) NOT NULL,
|
|
port INT NULL,
|
|
protocol VARCHAR(12) NULL,
|
|
direction ENUM('internal','inbound','outbound') NOT NULL DEFAULT 'internal',
|
|
discovery_source VARCHAR(40) NOT NULL DEFAULT 'manual',
|
|
external_ref VARCHAR(190) NULL,
|
|
last_seen_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE KEY uq_flow (organization_id, external_ref),
|
|
INDEX idx_flow_org (organization_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
|
|
echo " + network_flows OK\n";
|
|
|
|
echo "Migrazione 064 — connettori discovery OK. Prossima mig=065.\n";
|