- Tutti i riferimenti nis2.certisource.it → nis2.agile.software - Apache vhost HTTP nis2.agile.software attivo su Hetzner - Script setup-nis2-agile-software.sh: certbot SSL + redirect da vecchio dominio - .env server: APP_URL aggiornato a https://nis2.agile.software - CLAUDE.md, docs commerciali, integrazioni, API docs aggiornati DNS da aggiungere in Cloudflare: nis2.agile.software A 135.181.149.254 (proxy OFF) Poi eseguire: bash /opt/devenv/scripts/setup-nis2-agile-software.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
157 lines
12 KiB
HTML
157 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="it">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>AllRisk × NIS2 Agile — Integrazione</title>
|
||
<style>
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
:root {
|
||
--primary: #06b6d4; --amber: #f59e0b;
|
||
--gray-200: #e2e8f0; --gray-500: #64748b; --gray-700: #334155; --gray-900: #0f172a;
|
||
--radius: 8px; --font: -apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;
|
||
--mono: 'Cascadia Code','Consolas',monospace;
|
||
}
|
||
body { background: #f8fafc; font-family: var(--font); color: var(--gray-900); }
|
||
.header { background: linear-gradient(135deg, #78350f, #92400e); padding: 40px 48px; color: #fff; }
|
||
.header-badges { display: flex; gap: 10px; margin-bottom: 16px; }
|
||
.badge { padding: 4px 12px; border-radius: 20px; font-size: 0.75rem; font-weight: 700; }
|
||
.badge-nis2 { background: rgba(6,182,212,0.2); color: #67e8f9; border: 1px solid rgba(6,182,212,0.3); }
|
||
.badge-ar { background: rgba(245,158,11,0.2); color: #fde68a; border: 1px solid rgba(245,158,11,0.3); }
|
||
h1 { font-size: 1.875rem; font-weight: 800; margin-bottom: 8px; }
|
||
.header p { color: #fde68a; font-size: 1rem; }
|
||
.container { max-width: 960px; margin: 0 auto; padding: 40px 24px; }
|
||
h2 { font-size: 1.25rem; font-weight: 700; margin-bottom: 12px; padding-bottom: 10px; border-bottom: 2px solid var(--gray-200); }
|
||
.section { margin-bottom: 48px; }
|
||
p { color: var(--gray-500); font-size: 0.9rem; line-height: 1.7; margin-bottom: 12px; }
|
||
pre { background: #1e293b; color: #e2e8f0; padding: 20px; border-radius: var(--radius); font-family: var(--mono); font-size: 0.8125rem; overflow-x: auto; line-height: 1.7; margin: 12px 0; }
|
||
code { background: #f1f5f9; padding: 2px 6px; border-radius: 4px; font-family: var(--mono); font-size: 0.85em; color: var(--gray-700); }
|
||
.step { display: flex; gap: 16px; margin-bottom: 20px; padding: 18px; background: #fff; border: 1px solid var(--gray-200); border-radius: var(--radius); }
|
||
.step-num { width: 30px; height: 30px; border-radius: 50%; background: var(--amber); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.875rem; flex-shrink: 0; }
|
||
.step-content h3 { font-size: 0.9375rem; font-weight: 700; margin-bottom: 6px; }
|
||
.info-box { padding: 14px 16px; border-radius: var(--radius); margin: 16px 0; font-size: 0.875rem; }
|
||
.info-amber { background: #fffbeb; border-left: 3px solid var(--amber); color: #92400e; }
|
||
.field-map { width: 100%; border-collapse: collapse; }
|
||
.field-map th { padding: 9px 12px; background: #f1f5f9; font-size: 0.8rem; font-weight: 700; text-align: left; }
|
||
.field-map td { padding: 9px 12px; border-bottom: 1px solid var(--gray-200); font-size: 0.8rem; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="header">
|
||
<div class="header-badges">
|
||
<span class="badge badge-ar">AllRisk</span>
|
||
<span>×</span>
|
||
<span class="badge badge-nis2">NIS2 Agile</span>
|
||
</div>
|
||
<h1>Integrazione AllRisk ← NIS2 Agile</h1>
|
||
<p>Esporta il risk register cyber NIS2 verso AllRisk per consolidamento nel registro rischi enterprise. Importazione automatica dei rischi HIGH/CRITICAL tramite API Key.</p>
|
||
</div>
|
||
|
||
<div class="container">
|
||
|
||
<div class="section">
|
||
<h2>Scenario di integrazione</h2>
|
||
<p>AllRisk è il registro rischi enterprise centralizzato. NIS2 Agile gestisce i rischi cyber in ottica normativa (ISO 27005 / NIS2). L'integrazione permette di:</p>
|
||
<div class="step"><div class="step-num">1</div><div class="step-content"><h3>Consolidamento automatico</h3><p>I rischi HIGH/CRITICAL di NIS2 vengono automaticamente importati in AllRisk come rischi di categoria "Cyber/IT" con score e deadline normalizzati.</p></div></div>
|
||
<div class="step"><div class="step-num">2</div><div class="step-content"><h3>Aggiornamento bidirezionale</h3><p>AllRisk notifica NIS2 tramite webhook se un rischio enterprise si trasforma in minaccia cyber (es. incidente supply chain → rischio NIS2).</p></div></div>
|
||
<div class="step"><div class="step-num">3</div><div class="step-content"><h3>Reporting unificato</h3><p>Report rischi enterprise unico che include dimensione NIS2 con compliance score per ogni categoria di rischio cyber (Art.21 domains).</p></div></div>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>Mappatura campi NIS2 → AllRisk</h2>
|
||
<table class="field-map">
|
||
<thead><tr><th>Campo NIS2 Agile</th><th>Campo AllRisk</th><th>Trasformazione</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><code>risk_code</code></td><td><code>external_ref</code></td><td>Prefisso <code>NIS2-</code> + codice</td></tr>
|
||
<tr><td><code>title</code></td><td><code>risk_name</code></td><td>Diretta</td></tr>
|
||
<tr><td><code>risk_level</code></td><td><code>severity</code></td><td>critical→5, high→4, medium→3, low→2</td></tr>
|
||
<tr><td><code>likelihood</code> × <code>impact</code></td><td><code>risk_score</code></td><td>Scala 0–25 → 0–100</td></tr>
|
||
<tr><td><code>category</code></td><td><code>risk_category</code></td><td>Mappato su tassonomia AllRisk "Cyber"</td></tr>
|
||
<tr><td><code>nis2_article</code></td><td><code>regulatory_ref</code></td><td>Prefisso "NIS2 Art."</td></tr>
|
||
<tr><td><code>treatment</code></td><td><code>response_strategy</code></td><td>mitigate→Reduce, accept→Accept, ecc.</td></tr>
|
||
<tr><td><code>review_date</code></td><td><code>next_review</code></td><td>Diretta (ISO 8601)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>Import automatico — Script PHP</h2>
|
||
<pre><span style="color:#7dd3fc;">// AllRisk — import_nis2_risks.php (cron settimanale)</span>
|
||
|
||
<span style="color:#f1fa8c;">$apiKey</span> = getenv(<span style="color:#86efac;">'NIS2_API_KEY'</span>);
|
||
<span style="color:#f1fa8c;">$orgId</span> = getenv(<span style="color:#86efac;">'NIS2_ORG_ID'</span>);
|
||
<span style="color:#f1fa8c;">$baseUrl</span> = <span style="color:#86efac;">'https://nis2.agile.software/api'</span>;
|
||
<span style="color:#f1fa8c;">$allriskOrgId</span> = getenv(<span style="color:#86efac;">'ALLRISK_ORG_ID'</span>);
|
||
|
||
<span style="color:#7dd3fc;">// Fetch rischi HIGH/CRITICAL aperti da NIS2</span>
|
||
<span style="color:#f1fa8c;">$response</span> = nis2Get(<span style="color:#f1fa8c;">$baseUrl</span> . <span style="color:#86efac;">'/services/risks-feed'</span>, [
|
||
<span style="color:#86efac;">'level'</span> => <span style="color:#86efac;">'high'</span>,
|
||
<span style="color:#86efac;">'status'</span> => <span style="color:#86efac;">'open'</span>,
|
||
<span style="color:#86efac;">'limit'</span> => 200,
|
||
], <span style="color:#f1fa8c;">$apiKey</span>, <span style="color:#f1fa8c;">$orgId</span>);
|
||
|
||
<span style="color:#f1fa8c;">$risks</span> = <span style="color:#f1fa8c;">$response</span>[<span style="color:#86efac;">'data'</span>][<span style="color:#86efac;">'risks'</span>] ?? [];
|
||
<span style="color:#f1fa8c;">$imported</span> = 0;
|
||
|
||
foreach (<span style="color:#f1fa8c;">$risks</span> as <span style="color:#f1fa8c;">$risk</span>) {
|
||
<span style="color:#f1fa8c;">$allriskPayload</span> = [
|
||
<span style="color:#86efac;">'external_ref'</span> => <span style="color:#86efac;">'NIS2-'</span> . <span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'risk_code'</span>],
|
||
<span style="color:#86efac;">'risk_name'</span> => <span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'title'</span>],
|
||
<span style="color:#86efac;">'risk_category'</span> => <span style="color:#86efac;">'Cyber/IT'</span>,
|
||
<span style="color:#86efac;">'severity'</span> => mapSeverity(<span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'risk_level'</span>]),
|
||
<span style="color:#86efac;">'risk_score'</span> => round(<span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'risk_score'</span>] / 25 * 100),
|
||
<span style="color:#86efac;">'regulatory_ref'</span> => <span style="color:#86efac;">'NIS2 '</span> . (<span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'nis2_article'</span>] ?? <span style="color:#86efac;">'Art.21'</span>),
|
||
<span style="color:#86efac;">'response_strategy'</span> => mapTreatment(<span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'treatment'</span>]),
|
||
<span style="color:#86efac;">'source_system'</span> => <span style="color:#86efac;">'NIS2 Agile'</span>,
|
||
<span style="color:#86efac;">'organization_id'</span> => <span style="color:#f1fa8c;">$allriskOrgId</span>,
|
||
];
|
||
|
||
<span style="color:#7dd3fc;">// Upsert: aggiorna se external_ref esiste, crea altrimenti</span>
|
||
AllRiskApiClient::upsertRisk(<span style="color:#f1fa8c;">$allriskPayload</span>);
|
||
<span style="color:#f1fa8c;">$imported</span>++;
|
||
}
|
||
|
||
error_log("[NIS2→AllRisk] Importati {<span style="color:#f1fa8c;">$imported</span>} rischi");
|
||
|
||
<span style="color:#f1fa8c;">function</span> mapSeverity(<span style="color:#f1fa8c;">string $level</span>): int {
|
||
return match(<span style="color:#f1fa8c;">$level</span>) { <span style="color:#86efac;">'critical'</span> => 5, <span style="color:#86efac;">'high'</span> => 4, <span style="color:#86efac;">'medium'</span> => 3, default => 2 };
|
||
}
|
||
<span style="color:#f1fa8c;">function</span> mapTreatment(<span style="color:#f1fa8c;">string $t</span>): string {
|
||
return match(<span style="color:#f1fa8c;">$t</span>) {
|
||
<span style="color:#86efac;">'mitigate'</span> => <span style="color:#86efac;">'Reduce'</span>, <span style="color:#86efac;">'accept'</span> => <span style="color:#86efac;">'Accept'</span>,
|
||
<span style="color:#86efac;">'transfer'</span> => <span style="color:#86efac;">'Transfer'</span>, default => <span style="color:#86efac;">'Avoid'</span>
|
||
};
|
||
}</pre>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>Webhook NIS2 → AllRisk (real-time)</h2>
|
||
<p>Configura webhook per importazione immediata dei nuovi rischi HIGH/CRITICAL:</p>
|
||
<pre><span style="color:#7dd3fc;"># Settings → Webhook in NIS2 Agile</span>
|
||
URL: https://allrisk.certisource.it/api/v1/webhooks/nis2
|
||
Events: risk.high_created, compliance.score_changed, incident.significant</pre>
|
||
|
||
<pre><span style="color:#7dd3fc;">// AllRisk — webhook receiver per NIS2</span>
|
||
<span style="color:#f1fa8c;">$payload</span> = verifyAndDecode($_SERVER[<span style="color:#86efac;">'HTTP_X_NIS2_SIGNATURE'</span>], file_get_contents(<span style="color:#86efac;">'php://input'</span>));
|
||
|
||
if (<span style="color:#f1fa8c;">$payload</span>[<span style="color:#86efac;">'event'</span>] === <span style="color:#86efac;">'risk.high_created'</span>) {
|
||
<span style="color:#f1fa8c;">$risk</span> = <span style="color:#f1fa8c;">$payload</span>[<span style="color:#86efac;">'data'</span>][<span style="color:#86efac;">'risk'</span>];
|
||
AllRiskApiClient::upsertRisk([
|
||
<span style="color:#86efac;">'external_ref'</span> => <span style="color:#86efac;">'NIS2-'</span> . <span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'id'</span>],
|
||
<span style="color:#86efac;">'risk_name'</span> => <span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'title'</span>],
|
||
<span style="color:#86efac;">'severity'</span> => <span style="color:#f1fa8c;">$risk</span>[<span style="color:#86efac;">'risk_level'</span>] === <span style="color:#86efac;">'critical'</span> ? 5 : 4,
|
||
<span style="color:#86efac;">'source_system'</span>=> <span style="color:#86efac;">'NIS2 Agile'</span>,
|
||
<span style="color:#86efac;">'alert'</span> => true, <span style="color:#7dd3fc;">// Notifica CRO AllRisk</span>
|
||
]);
|
||
}
|
||
http_response_code(200);</pre>
|
||
</div>
|
||
|
||
<div class="info-box info-amber">
|
||
<strong>Nota architetturale:</strong> Il flusso è unidirezionale NIS2 → AllRisk. Per il flusso inverso (AllRisk → NIS2), AllRisk chiama l'API NIS2 per creare rischi cyber direttamente tramite le API JWT (POST /api/risks/create) usando le credenziali dell'utente integration.
|
||
</div>
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|