' . '

401 — Token richiesto

Accedi con ?t=Nis2Test2026

'; exit; } // ── Router ──────────────────────────────────────────────────────────────────── $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $base = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/'); $slug = ltrim(substr($path, strlen($base)), '/'); if ($slug === 'events') { serveEvents(); exit; } if ($slug === 'status') { serveStatus(); exit; } serveUI(); exit; // ── Commands ────────────────────────────────────────────────────────────────── function getCommands(): array { $php = PHP_BINARY ?: 'php'; $root = PROJECT_ROOT; $api = API_BASE; return [ 'health' => [ 'label' => 'Health Check', 'bash' => "curl -sf {$api}/../api-status.php | python3 -m json.tool", 'cwd' => $root, 'timeout' => 15, 'continue_on_fail' => false, ], 'smoke' => [ 'label' => 'Smoke Tests (curl)', 'bash' => implode(' && ', [ "echo '=== Login demo ===' && curl -sf -X POST {$api}/auth/login -H 'Content-Type: application/json' -d '{\"email\":\"admin@datacore.demo\",\"password\":\"Demo2026!\"}' | python3 -m json.tool || echo '[SKIP] utente non ancora creato'", "echo '=== /api/auth/me (no token) ===' && curl -sf {$api}/auth/me | python3 -m json.tool", "echo '=== /api/dashboard/overview (no token → 401) ===' && curl -sf -w '\\nHTTP %{http_code}\\n' {$api}/dashboard/overview || true", "echo '=== API status ===' && curl -sf {$api}/../api-status.php | python3 -m json.tool", ]), 'cwd' => $root, 'timeout' => 30, 'continue_on_fail' => true, ], 'sim01' => [ 'label' => 'SIM-01 Onboarding + Assessment', 'bash' => "NIS2_SIM=SIM01 {$php} {$root}/simulate-nis2.php", 'cwd' => $root, 'timeout' => 180, 'continue_on_fail' => false, ], 'sim02' => [ 'label' => 'SIM-02 Ransomware Art.23', 'bash' => "NIS2_SIM=SIM02 {$php} {$root}/simulate-nis2.php", 'cwd' => $root, 'timeout' => 120, 'continue_on_fail' => false, ], 'sim03' => [ 'label' => 'SIM-03 Data Breach Supply Chain', 'bash' => "NIS2_SIM=SIM03 {$php} {$root}/simulate-nis2.php", 'cwd' => $root, 'timeout' => 120, 'continue_on_fail' => false, ], 'sim04' => [ 'label' => 'SIM-04 Whistleblowing SCADA', 'bash' => "NIS2_SIM=SIM04 {$php} {$root}/simulate-nis2.php", 'cwd' => $root, 'timeout' => 90, 'continue_on_fail' => false, ], 'sim05' => [ 'label' => 'SIM-05 Audit Chain Verify', 'bash' => "NIS2_SIM=SIM05 {$php} {$root}/simulate-nis2.php", 'cwd' => $root, 'timeout' => 60, 'continue_on_fail' => false, ], 'simulate' => [ 'label' => 'Tutte le Simulazioni (SIM-01→05)', 'bash' => "{$php} {$root}/simulate-nis2.php", 'cwd' => $root, 'timeout' => 600, 'continue_on_fail' => false, ], 'chain-verify' => [ 'label' => 'Verifica Hash Chain Audit', 'bash' => implode(' && ', [ "echo '=== Verifica chain org demo ==='", "curl -sf -H 'Authorization: Bearer \$(cat /tmp/nis2_chain_token 2>/dev/null || echo \"\")' {$api}/audit/chain-verify | python3 -m json.tool || echo '[INFO] Autenticarsi prima con simulate'", ]), 'cwd' => $root, 'timeout' => 30, 'continue_on_fail' => true, ], 'reset' => [ 'label' => 'Reset Dati Demo', 'bash' => "mysql -u nis2_agile_user -p\$(grep DB_PASSWORD {$root}/.env | cut -d= -f2) nis2_agile_db < {$root}/docs/sql/reset-demo.sql", 'cwd' => $root, 'timeout' => 30, 'continue_on_fail' => false, ], 'full-reset-sim' => [ 'label' => '⚡ Reset + Simula + Testa Tutto', 'bash' => implode(' && ', [ "echo '════════════════════════════════════════'", "echo ' FASE 1 — Reset database demo'", "echo '════════════════════════════════════════'", "mysql -u nis2_agile_user -p\$(grep DB_PASSWORD {$root}/.env | cut -d= -f2) nis2_agile_db < {$root}/docs/sql/reset-demo.sql", "echo '[OK] Reset completato. Admin cristiano.benassati@gmail.com preservato.'", "echo ''", "echo '════════════════════════════════════════'", "echo ' FASE 2 — Simulazioni demo (SIM-01→05)'", "echo '════════════════════════════════════════'", PHP_BINARY . " {$root}/simulate-nis2.php", "echo ''", "echo '════════════════════════════════════════'", "echo ' FASE 3 — Smoke tests API'", "echo '════════════════════════════════════════'", "curl -sf " . API_BASE . "/../api-status.php | python3 -m json.tool", "echo '[OK] Suite completa terminata.'", ]), 'cwd' => $root, 'timeout' => 720, 'continue_on_fail' => false, ], 'all' => [ 'label' => 'Full Suite (health + simulate + chain)', 'bash' => implode(' && ', [ "curl -sf " . API_BASE . "/../api-status.php | python3 -m json.tool", PHP_BINARY . " {$root}/simulate-nis2.php", ]), 'cwd' => $root, 'timeout' => 660, 'continue_on_fail' => false, ], ]; } // ── SSE Events handler ──────────────────────────────────────────────────────── function serveEvents(): void { $cmd = $_GET['cmd'] ?? ''; $commands = getCommands(); if (!isset($commands[$cmd])) { http_response_code(400); echo "Comando sconosciuto: {$cmd}"; return; } $def = $commands[$cmd]; header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); header('X-Accel-Buffering: no'); if (ob_get_level()) ob_end_clean(); sseWrite('start', json_encode(['cmd' => $cmd, 'label' => $def['label'], 'ts' => date('c')])); $t0 = microtime(true); runCommand($def, function (string $type, string $line) { sseWrite($type, $line); }); $elapsed = round(microtime(true) - $t0, 2); sseWrite('done', json_encode(['cmd' => $cmd, 'elapsed' => $elapsed])); } function runCommand(array $def, callable $emit): void { $descriptors = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; $env = array_merge($_ENV, getenv() ?: [], ['NIS2_API_BASE' => API_BASE]); $proc = proc_open( $def['bash'], $descriptors, $pipes, $def['cwd'] ?? PROJECT_ROOT, $env ); if (!is_resource($proc)) { $emit('stderr', '[ERRORE] Impossibile avviare il processo'); return; } fclose($pipes[0]); stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); $timeout = $def['timeout'] ?? 120; $deadline = microtime(true) + $timeout; $buf1 = ''; $buf2 = ''; while (true) { if (microtime(true) > $deadline) { $emit('stderr', "[TIMEOUT] Processo terminato dopo {$timeout}s"); proc_terminate($proc, 9); break; } $r = [$pipes[1], $pipes[2]]; $w = null; $e = null; $changed = @stream_select($r, $w, $e, 0, 50000); if ($changed === false) break; foreach ($r as $s) { $chunk = fread($s, 4096); if ($chunk === false || $chunk === '') continue; if ($s === $pipes[1]) { $buf1 .= $chunk; while (($nl = strpos($buf1, "\n")) !== false) { $emit('stdout', rtrim(substr($buf1, 0, $nl))); $buf1 = substr($buf1, $nl + 1); } } else { $buf2 .= $chunk; while (($nl = strpos($buf2, "\n")) !== false) { $emit('stderr', rtrim(substr($buf2, 0, $nl))); $buf2 = substr($buf2, $nl + 1); } } } if (feof($pipes[1]) && feof($pipes[2])) break; if (connection_aborted()) { proc_terminate($proc, 9); break; } // flush heartbeat if (ob_get_level()) ob_flush(); flush(); } if ($buf1 !== '') $emit('stdout', rtrim($buf1)); if ($buf2 !== '') $emit('stderr', rtrim($buf2)); fclose($pipes[1]); fclose($pipes[2]); proc_close($proc); if (ob_get_level()) ob_flush(); flush(); } function sseWrite(string $event, string $data): void { // JSON-encode non-JSON data for transport safety $out = "event: {$event}\ndata: " . $data . "\n\n"; echo $out; if (ob_get_level()) ob_flush(); flush(); } // ── Status JSON ─────────────────────────────────────────────────────────────── function serveStatus(): void { header('Content-Type: application/json'); $api = API_BASE; $up = false; $info = []; $ch = curl_init("{$api}/../api-status.php"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, CURLOPT_SSL_VERIFYPEER => false, ]); $resp = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($code === 200 && $resp) { $up = true; $info = json_decode($resp, true) ?: []; } echo json_encode([ 'api_up' => $up, 'api_url' => $api, 'api_info' => $info, 'php_version'=> PHP_VERSION, 'ts' => date('c'), ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); } // ── UI ──────────────────────────────────────────────────────────────────────── function serveUI(): void { $commands = getCommands(); $cmdsJson = json_encode(array_map(fn($k, $v) => [ 'id' => $k, 'label' => $v['label'], ], array_keys($commands), $commands), JSON_UNESCAPED_UNICODE); $token = ACCESS_TOKEN; $api = API_BASE; $url = "https://nis2.agile.software/test-runner.php?t={$token}"; $demoCredentials = [ ['role' => '★ Super Admin (permanente)', 'email' => 'cristiano.benassati@gmail.com', 'password' => 'Silvia1978!@', 'org' => 'Tutte'], ['role' => 'Admin (DataCore IT)', 'email' => 'admin@datacore.demo', 'password' => 'Demo2026!', 'org' => 'DataCore S.r.l.'], ['role' => 'Compliance (MedClinic)', 'email' => 'compliance@medclinic.demo', 'password' => 'Demo2026!', 'org' => 'MedClinic Italia S.p.A.'], ['role' => 'CISO (EnerNet)', 'email' => 'ciso@enernet.demo', 'password' => 'Demo2026!', 'org' => 'EnerNet Distribuzione S.r.l.'], ]; $credsRows = ''; foreach ($demoCredentials as $c) { $credsRows .= "{$c['role']}{$c['email']}{$c['password']}{$c['org']}"; } $simCards = ''; $simDefs = [ 'sim01' => ['SIM-01', 'Onboarding + Assessment', '3 aziende, gap analysis 80 domande, score iniziale', 'cyan'], 'sim02' => ['SIM-02', 'Ransomware Art.23', 'Incidente critico, timeline 24h/72h, CSIRT notifica', 'orange'], 'sim03' => ['SIM-03', 'Data Breach Supply Chain','Fornitore compromesso, Art.23 + GDPR Art.33 parallelo', 'red'], 'sim04' => ['SIM-04', 'Whistleblowing SCADA', 'Segnalazione anonima, assegnazione, chiusura tracciata', 'purple'], 'sim05' => ['SIM-05', 'Audit Chain Verify', 'Verifica integrità SHA-256, export certificato', 'green'], ]; foreach ($simDefs as $id => [$code, $name, $desc, $col]) { $simCards .= << {$code}
{$name} {$desc}
HTML; } $testBtns = "\n
\n"; $testCmds = ['health', 'smoke', 'simulate', 'chain-verify', 'reset', 'all']; foreach ($testCmds as $id) { $label = $commands[$id]['label'] ?? $id; $extra = in_array($id, ['reset', 'all']) ? ' btn-danger' : ''; $testBtns .= "\n"; } echo << NIS2 Agile — Test Runner
Pronto · seleziona un test o una simulazione
NIS2 Agile Test Runner — pronto. ────────────────────────────────────────────────────────
HTML; }