# Integrazioni Esterne

API, webhook e connettori per sistemi GRC di terze parti

# NIS2 Agile come Provider di Compliance

NIS2 Agile espone una Services API REST che permette a sistemi esterni di leggere score di conformità, rischi, incidenti e controlli in tempo reale. Auth via API Key dedicata, rate limiting 100 req/ora, firma HMAC-SHA256 per webhook outbound.

Provider Disponibili
Disponibile

### 231 Agile (lg231)

Integrazione compliance D.Lgs. 231/2001 + NIS2. Incidenti cyber → OdV, rischi IT → registro 231, score NIS2 nel dashboard aziendale.

Guida integrazione →
Pianificato

### AllRisk Agile

Feed rischi cyber per piattaforma ERM unificata. Risk score NIS2 mappato su categorie ISO 31000.

Pianificato

### SustainAI Agile

Cybersecurity come pillar ESG. Score NIS2 nel report di sostenibilità (CSRD, GRI 418).

Disponibile

### SIEM / SOC Esterni

Webhook su `incident.created` e `risk.created_high` verso qualsiasi endpoint HTTPS (Splunk, Elastic, PagerDuty…).

Catalogo Connettori — Evidence Automation (Continuous Control Monitoring)

Connettori inbound per la raccolta automatica delle evidenze di conformità (NIS2 Art.21) da cloud, identità ed endpoint — costruiti sulla base esistente Services API + Webhook HMAC. Riducono la raccolta manuale e abilitano il monitoraggio continuo dei controlli.

In roadmap

### 🟦 Microsoft 365 / Entra ID

Evidenze automatiche: MFA & conditional access, offboarding utenti, sicurezza mailbox, log di audit. Mappate su Art.21 (controllo accessi, gestione identità).

In roadmap

### 🟩 Google Workspace

Verifica 2SV, policy amministrative, gestione dispositivi e accessi. Evidenze per controllo accessi e sicurezza degli endpoint.

In roadmap

### 🟧 Amazon Web Services

IAM, CloudTrail, Security Hub, cifratura S3/EBS. Raccolta evidenze su crittografia, logging e gestione accessi cloud.

In roadmap

### 🟦 Microsoft Azure

Defender for Cloud, Azure Policy, Network Security Group. Posture di sicurezza cloud → controlli Art.21 e asset critici.

In roadmap

### 🔐 Identity Provider (Okta / Entra / Google)

Enforcement SSO/MFA, lifecycle utenti, revoche accessi. Evidenza continua su gestione identità e accessi privilegiati.

In roadmap

### 🛡️ EDR / XDR (CrowdStrike, SentinelOne, Defender)

Copertura endpoint, rilevamento minacce e stato agenti → popolano gli asset critici e aprono incidenti Art.23 in automatico.

In roadmap

### 📥 SIEM / SOC — Ingestion (inbound)

Alert da Splunk, Microsoft Sentinel, Elastic, Wazuh → apertura automatica di incidenti NIS2 (Art.23) con triage e timeline. Complementare al webhook outbound già disponibile.

In roadmap

### 🎫 Ticketing (Jira / ServiceNow)

Sincronizzazione bidirezionale di non-conformità/CAPA e task di raccolta evidenze. Le azioni correttive NIS2 diventano ticket tracciati.

Endpoint disponibili
Base URL: `https://nis2.agile.software/api/services`
Auth: Header `X-API-Key: nis2_xxxx` — oppure `Authorization: Bearer nis2_xxxx`

Metodo | Endpoint | Scope | Descrizione
--- | --- | --- | ---
POST | `/token` | read:all | Token exchange: API Key → JWT 15 min. lg231 usa questo JWT per le chiamate successive.
POST | `/sso` | sso:login (o read:all) | SSO federato: passa email + ruolo + responsabilità → JWT NIS2 2h. Utente creato se non esiste. Auditato.
GET | `/status` | — | Health check piattaforma, versione, DB. Nessuna auth.
GET | `/compliance-summary` | read:compliance | Score NIS2 aggregato (0-100), domain scores Art.21, rischi aperti, incidenti
GET | `/risks/feed` | read:risks | Registro rischi con livello ISO 27005, status, area. Filtri: `?level=high,critical&status=open`
GET | `/incidents/feed` | read:incidents | Incidenti Art.23: severity, status, notifiche CSIRT, deadline 72h, overdue
GET | `/controls/status` | read:compliance | Stato controlli per dominio: implemented / partial / missing
GET | `/assets/critical` | read:assets | Asset critici con tipo, criticità, dipendenze mappate
GET | `/suppliers/risk` | read:suppliers | Fornitori: risk_level, ultimo assessment, is_flagged
GET | `/policies/approved` | read:policies | Policy approvate: titolo, area, data, versione
GET | `/openapi.json` | — | Specifica OpenAPI 3.0 in JSON

Esempio risposta /compliance-summary
// GET /api/services/compliance-summary // X-API-Key: nis2_Abc123... { "success": true, "data": { "organization": { "id": 5, "name": "Azienda XYZ", "sector": "energia", "nis2_entity_type": "essential" }, "compliance": { "overall_score": 73, "label": "Parziale", "domain_scores": [ { "domain": "Gestione del rischio", "score": 80, "status": "compliant" }, { "domain": "Sicurezza supply chain", "score": 45, "status": "partial" } ] }, "risks": { "total": 12, "open": 8, "high_critical": 3 }, "incidents": { "total": 2, "open": 1, "significant": 1, "overdue": 0 } } }
Headers risposta

Header | Valore
--- | ---
`X-NIS2-API-Version` | 1.0
`X-NIS2-Org-Id` | ID organizzazione (intero)
`X-RateLimit-Limit` | 100 (req/ora per chiave)
`X-RateLimit-Remaining` | Richieste rimaste nella finestra

Sistema Inviti / Licenze B2B: NIS2 Agile genera token di invito che abilitano il provisioning automatico di organizzazioni e utenti. L'e-commerce o il partner riceve l'invito, lo consegna al cliente finale (es. lg231), che lo usa per attivarsi automaticamente. L'accesso si interrompe alla scadenza della licenza.
Chi fa cosa — ruoli nell'ecosistema

Sistema | Ruolo | API usata | Auth
--- | --- | --- | ---
NIS2 Admin o mktg-agile | Genera i token licenza, fissa piano/durata/utenti/prezzo | `POST /api/invites/create` | API Key admin:licenses
E-commerce | Riceve token all'acquisto, lo consegna al cliente con l'ordine | — (semplice consegna token) | API Key admin:licenses
lg231 / partner | Valida il token, fa provisioning automatico per il cliente | `GET /api/invites/validate` `POST /api/services/provision` | invite_token nel body
Cliente finale | Apre invite_url e si registra in autonomia via wizard | `onboarding.html?invite=inv_...` | nessuna auth
NIS2 Admin | Monitora uso licenze, revoca, rigenera | `GET /api/invites/list` `DELETE /api/invites/{id}` | API Key o JWT super_admin

Flusso completo
1. GENERAZIONE NIS2 Admin (super_admin) POST /api/invites → { token: "inv_abc123...", expires_at, plan, max_uses } Il token è visibile UNA SOLA VOLTA. Solo hash SHA-256 in DB. 2. DISTRIBUZIONE NIS2 → E-commerce → lg231 NIS2 Admin passa inv_abc123... all'e-commerce E-commerce lo consegna al cliente con l'ordine lg231 lo riceve (es. in metadata ordine) 3. VALIDAZIONE lg231 prima del provisioning GET /api/invites/validate?token=inv_abc123... → { valid: true, plan: "professional", expires_at, remaining_uses, plan_features } 4. PROVISIONING lg231 attiva automaticamente POST /api/services/provision (body include "invite_token": "inv_abc123...") → { org_id, api_key, access_token, license_expires_at, temp_password } NIS2 marca l'invito come usato (used_count++) 5. SCADENZA Accesso automaticamente revocato Quando expires_at raggiunto: - API key rimane ma licenza_expires_at è nel passato - GET /api/invites/validate → { valid: false, code: "EXPIRED" } - Rinnovo: nuovo invito dal NIS2 Admin → nuovo provisioning
API Inviti (solo super_admin)

Metodo | Endpoint | Auth | Descrizione
--- | --- | --- | ---
POST | `/api/invites/create` | JWT super_admin | Genera 1..50 inviti in batch
GET | `/api/invites/list` | JWT super_admin | Lista con filtri status/channel, auto-scade pending
GET | `/api/invites/{id}` | JWT super_admin | Dettaglio singolo + org usante
DELETE | `/api/invites/{id}` | JWT super_admin | Revoca (non cancella — solo status=revoked)
POST | `/api/invites/{id}/regenerate` | JWT super_admin | Nuovo token, stessa configurazione
GET | `/api/invites/validate?token=inv_...` | — | Anteprima pubblica: piano, scadenza, usi rimasti

Generare un invito (NIS2 Admin)
POST https://nis2.agile.software/api/invites/create Authorization: Bearer {jwt_super_admin} Content-Type: application/json { "plan": "professional", // essentials | professional | enterprise "duration_months": 12, // durata licenza dopo attivazione "invite_expires_days": 30, // giorni di validità dell'invito stesso "max_uses": 1, // 1=one-shot, N=batch (es: 10 per reseller) "label": "lg231 Partner Q1 2026", "channel": "lg231", // lg231 | ecommerce | direct | manual "issued_to": "partner@lg231.it", "notes": "Ordine OPP-2026-042" } // Risposta — token visibile UNA SOLA VOLTA: { "invites": [{ "id": 7, "token": "inv_a1b2c3d4e5f6...", ← SALVARE SUBITO, non recuperabile "plan": "professional", "expires_at": "2026-04-06 12:00:00", "invite_url": "https://nis2.agile.software/onboarding.html?invite=inv_..." }], "warning": "Salva i token subito — non saranno più visibili in chiaro." }
Provisioning con invito (lg231 → NIS2)
// lg231 usa l'invite_token ricevuto per attivare automaticamente il cliente: POST https://nis2.agile.software/api/services/provision Content-Type: application/json { "invite_token": "inv_a1b2c3d4...", ← sostituisce X-Provision-Secret "company": { "ragione_sociale": "Acme S.r.l.", "partita_iva": "02345678901", "ateco_code": "62.01.00", "sector": "ict" }, "admin": { "email": "ciso@acme.it", "first_name": "Marco", "last_name": "Rossi" }, "caller": { "system": "lg231", "company_id": 142, "callback_url": "https://lg231.agile.software/api/integrations/nis2-callback" } } // Risposta (il piano e la durata vengono dall'invito, non dal body): { "provisioned": true, "org_id": 8, "api_key": "nis2_abcdef...", ← salvare in lg231 metadata "access_token": "eyJ...", ← JWT 2h per apertura immediata "temp_password": "NIS2_xxxxxx", ← cambio obbligatorio al primo login "invite_plan": "professional", "license_expires_at": "2027-03-07 12:00:00", "dashboard_url": "https://nis2.agile.software/dashboard.html" }
Validazione preventiva (opzionale)
# lg231 può validare l'invito prima del provisioning: curl "https://nis2.agile.software/api/invites/validate?token=inv_a1b2c3..." // Se valido: { "valid": true, "plan": "professional", "duration_months": 12, "expires_at": "2026-04-06T12:00:00", "remaining_uses": 1, "plan_features": ["Policy Management + AI", "Supply Chain Assessment", ...] } // Se scaduto: { "valid": false, "error": "Invito scaduto il 2026-03-01 00:00:00", "code": "EXPIRED" } // Se già usato: { "valid": false, "error": "Invito già utilizzato", "code": "ALREADY_USED" }
Gestione ciclo di vita

Stato invito | Significato | Azione
--- | --- | ---
`pending` | Valido, non ancora usato | Usabile per provision
`used` | Raggiunto max_uses | Provisioning bloccato
`expired` | expires_at superato | Provisioning bloccato, rinnovare
`revoked` | Revocato da admin | Provisioning bloccato permanente

Per mktg-agile / E-commerce — Quick Start
Chiave API già attiva per mktg-agile: `nis2_mktg_8c8bd38e78fccb9faa749d8601051f42` · Scope: `admin:licenses` · Scade: 2028-03-07 · Doc completa: mktg-api-doc.html · Pannello web: licenseExt.html
# 1. Crea licenza (mktg-agile → NIS2) curl -X POST https://nis2.agile.software/api/invites/create \ -H "X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42" \ -H "Content-Type: application/json" \ -d '{"plan":"professional","duration_months":12,"max_users_per_org":10, "label":"Ordine MKT-001","channel":"ecommerce","price_eur":990}' # → risposta contiene token (inv_xxx) e invite_url # → consegna invite_url al cliente nel messaggio di conferma ordine # 2. Verifica stato licenza in qualsiasi momento curl -H "X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42" \ "https://nis2.agile.software/api/invites/42" # 3. Lista licenze attive per canale ecommerce curl -H "X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42" \ "https://nis2.agile.software/api/invites/list?channel=ecommerce&status=pending"
Sicurezza token: il token `inv_` viene restituito in chiaro UNA SOLA VOLTA alla creazione. Nel DB è conservato solo il hash SHA-256. Il `token_prefix` (es: `inv_a1b2c3...`) è visibile nell'admin panel per identificazione visiva.
Per l'agente Claude di lg231: questo tab descrive esattamente cosa implementare in lg231 Agile per consumare NIS2 come provider di compliance cybersecurity.
Perché integrare 231 con NIS2

Evento NIS2 | Rilevanza D.Lgs. 231/2001
--- | ---
Incidente cybersecurity (Art.23 NIS2) | Reato presupposto art.24-bis — criminalità informatica
Fornitore IT flaggato alto rischio | Rischio complicità in reati informatici via supply chain
Policy sicurezza non approvata | Gap nel MOG — Modello Organizzativo e di Gestione
Score NIS2 < 40% | Indicatore OdV: carenza controlli, escalation consigliata
Whistleblowing sicurezza | Potenziale escalation verso OdV 231

1. Aggiungere NIS2 al provider-config (company-ms)

File: `services/company-ms/public/index.php` — route `PATCH /companies/{id}/provider-config`

// Aggiungere ai $allowed: $allowed = [ 'certisource_pat', 'anthropic_api_key', 'openai_api_key', // ── Nuovo provider NIS2 ── 'nis2_api_key', // chiave da NIS2 → Settings → API Keys 'nis2_org_id', // ID org NIS2 (dal URL dashboard o /api/services/status) 'nis2_enabled', // bool: abilitare pull automatico ];
2. NIS2Client (shared lib o inline)
class Nis2Client { const BASE_URL = 'https://nis2.agile.software/api/services'; public static function get(string $endpoint, string $apiKey, array $query = []): array { $url = self::BASE_URL . $endpoint; if ($query) $url .= '?' . http_build_query($query); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => [ 'X-API-Key: ' . $apiKey, 'Accept: application/json', 'X-Caller: lg231-agile/1.0', ], ]); $body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $code === 200 && $body ? ['success' => true, 'data' => json_decode($body, true)] : ['success' => false, 'http_code' => $code]; } }
3. Widget score NIS2 nella company view
// In company detail view PHP/JS: $nis2Key = $meta['nis2_api_key'] ?? null; if ($nis2Key) { $summary = Nis2Client::get('/compliance-summary', $nis2Key); // Mostrare gauge score + badge essential/important + rischi high // Link: https://nis2.agile.software/dashboard.html }
4. Escalation incidenti → OdV (monitoring-ms)
// Job periodico (cron o hook) nel monitoring-ms: $incidents = Nis2Client::get('/incidents/feed', $apiKey, ['significant' => 1, 'status' => 'open']); foreach (($incidents['data']['incidents'] ?? []) as $inc) { // Crea odv_activity: // type: 'cyber_incident_notifica' // description: 'Incidente NIS2 significativo: ' . $inc['title'] // priority: $inc['overdue'] ? 'urgent' : 'high' // source: 'nis2_agile' // reference_id: $inc['id'] }
3b. SSO federato — apertura diretta NIS2 da lg231
Quando un utente lg231 clicca "Apri NIS2" dal suo dashboard, lg231 chiama `POST /api/services/sso` e redirige l'utente su NIS2 già autenticato, portando con sé ruolo e responsabilità. Ogni accesso SSO è tracciato nell'audit trail.
// In lg231, quando l'utente clicca "Apri NIS2 Agile": $ssoResp = Nis2Client::post('/sso', $apiKey, [ 'user_email' => $currentUser['email'], 'user_name' => $currentUser['first_name'] . ' ' . $currentUser['last_name'], 'user_role' => 'compliance_manager', // mappa da ruolo lg231 'caller_system' => 'lg231', 'caller_user_id' => $currentUser['id'], 'responsibilities' => [ ['area' => 'MOG 231', 'scope' => 'art.24-bis criminalità informatica'], ['area' => 'OdV', 'scope' => 'monitoraggio cyber risk'], ], ]); if ($ssoResp['success']) { $jwt = $ssoResp['data']['data']['token']; $redirectUrl = $ssoResp['data']['data']['redirect_url']; // Redirect con token nel fragment (sicuro, non nel server log) header('Location: ' . $redirectUrl . '#sso_token=' . urlencode($jwt)); }
NIS2 lato frontend: in `dashboard.html` aggiungere:
`const ssoToken = location.hash.match(/#sso_token=([^&]+)/)?.[1];`
`if (ssoToken) { localStorage.setItem('nis2_token', ssoToken); location.hash = ''; }`
5. Provisioning automatico dal portale lg231
Quando un cliente lg231 acquista una licenza NIS2 Agile, lg231 riceve un invite_token dall'e-commerce. Con questo token lg231 chiama `POST /api/services/provision` passando i dati aziendali del cliente. NIS2 crea automaticamente org, admin e API key. Il piano e la durata sono definiti dall'invito (non modificabili dal chiamante).
// Salva in lg231 companies.metadata dopo provisioning: $meta['nis2_api_key'] = $response['api_key']; $meta['nis2_org_id'] = $response['org_id']; $meta['nis2_invite_id'] = $response['invite_id']; $meta['nis2_license_plan'] = $response['invite_plan']; $meta['nis2_expires_at'] = $response['license_expires_at']; $meta['nis2_enabled'] = true; // Controlla scadenza prima di ogni chiamata: if (strtotime($meta['nis2_expires_at'] ?? '1970-01-01') < time()) { // licenza scaduta → mostrare banner rinnovo, non chiamare NIS2 return ['success' => false, 'reason' => 'license_expired']; }
Checklist implementazione lg231

- company-ms: aggiungere `nis2_api_key`, `nis2_org_id`, `nis2_enabled`, `nis2_invite_id`, `nis2_license_plan`, `nis2_expires_at` a provider-config
- shared: creare `Nis2Client` (curl wrapper leggero) con check scadenza licenza
- company-ms: endpoint provisioning — ricevi invite_token, chiama `POST /api/services/provision`, salva risposta in metadata
- UI: widget NIS2 score nella company detail (gauge + badge + rischi high)
- risk-ms: import rischi cyber durante assessment (categoria art.24-bis)
- monitoring-ms: escalation incidenti significativi → odv_activity
- monitoring-ms: policy NIS2 non approvate → alert OdV
- (opz.) endpoint `POST /api/integrations/nis2-webhook` + subscription

Nota CORS: tutte le chiamate a NIS2 devono avvenire server-to-server (PHP cURL), non da browser. NIS2 non accetta origini lg231 in CORS per sicurezza.
NIS2 invia notifiche push su eventi tramite webhook HTTPS firmati HMAC-SHA256. Il sistema esterno riceve la notifica in tempo reale senza polling.
Eventi disponibili
incident.created Nuovo incidente di sicurezza registrato → odv_activity
incident.deadline_warning Scadenza Art.23 (24h/72h) entro 4 ore → alert urgente OdV
risk.created_high Nuovo rischio HIGH o CRITICAL creato → risk register 231
compliance.score_changed Variazione score NIS2 > 5% → aggiorna widget
policy.approved Nuova policy di sicurezza approvata → aggiorna MOG ref
supplier.risk_flagged Fornitore IT flaggato alto rischio → supply chain 231
Registrare una subscription
POST https://nis2.agile.software/api/webhooks/subscriptions Authorization: Bearer {jwt_token} Content-Type: application/json { "url": "https://lg231.agile.software/api/integrations/nis2-webhook", "events": ["incident.created", "incident.deadline_warning", "risk.created_high"], "description": "lg231 Agile integration" } // Risposta: { "id": 1, "secret": "whsec_abc123..." } // Salvare il secret in companies.metadata.nis2_webhook_secret
Verifica firma HMAC (endpoint ricevente)
$secret = $meta['nis2_webhook_secret']; $body = file_get_contents('php://input'); $expected = 'sha256=' . hash_hmac('sha256', $body, $secret); $received = $_SERVER['HTTP_X_NIS2_SIGNATURE'] ?? ''; if (!hash_equals($expected, $received)) { http_response_code(401); exit; } $event = $_SERVER['HTTP_X_NIS2_EVENT'] ?? ''; $payload = json_decode($body, true); switch ($event) { case 'incident.created': // crea odv_activity... break; case 'risk.created_high': // aggiungi a risk register... break; }
Creare la prima API Key

1. Login su NIS2 Agile con ruolo `org_admin` o superiore
2. Vai su Settings → API Keys (sezione Integrazioni)
3. Click "Nuova API Key" → nome descrittivo (es: "lg231 Integration") → scope: `read:all`
4. Copia la chiave — formato `nis2_XXXX...` — visibile una sola volta
5. Nota l'Organization ID dal URL del dashboard (es: `/dashboard.html` dopo login)
6. In lg231: salva via `PATCH /companies/{id}/provider-config` con `nis2_api_key` e `nis2_org_id`

Test rapido (curl)
# 1. Verifica senza auth curl https://nis2.agile.software/api/services/status # 2. Compliance summary curl -H "X-API-Key: nis2_TUA_CHIAVE" \ https://nis2.agile.software/api/services/compliance-summary | python3 -m json.tool # 3. Incidenti significativi aperti curl -H "X-API-Key: nis2_TUA_CHIAVE" \ "https://nis2.agile.software/api/services/incidents/feed?significant=1&status=open" # 4. Rischi high/critical curl -H "X-API-Key: nis2_TUA_CHIAVE" \ "https://nis2.agile.software/api/services/risks/feed?level=high,critical"
Risorse per ogni tipo di integratore

Destinatario | Risorsa | URL
--- | --- | ---
mktg-agile / E-commerce | Documentazione API licenze + Quick Start | mktg-api-doc.html
mktg-agile / E-commerce | Pannello web gestione licenze | licenseExt.html
mktg-agile / E-commerce | Postman Collection (import diretto) | nis2-license-api.postman.json
lg231 / Partner tecnici | Questa pagina — tab Guida lg231 | integrazioniext.html
lg231 (agente Claude) | Spec tecnica completa per implementazione | `docs/integration/lg231-nis2-integration.md`
Tutti | Health check (no auth) | `GET https://nis2.agile.software/api/services/status`
Tutti | App NIS2 Agile | https://nis2.agile.software