[FEAT] Simulazioni Demo + Audit Trail Certificato SHA-256
- 5 scenari reali: Onboarding, Ransomware Art.23, Data Breach Supply Chain, Whistleblowing SCADA, Audit Hash Chain Verification - simulate-nis2.php: 3 aziende (DataCore/MedClinic/EnerNet), 10 fasi, CLI+SSE - AuditService.php: hash chain SHA-256 stile lg231 (prev_hash+entry_hash) - Migration 010: prev_hash, entry_hash, severity, performed_by su audit_logs - AuditController: GET chain-verify + GET export-certified - reset-demo.sql: reset dati demo idempotente - public/simulate.html: web runner SSE con console dark-theme - Sidebar: link Simulazione Demo + Integrazioni Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b23bbc55fd
commit
874eabb6fc
@@ -238,4 +238,79 @@ class AuditController extends BaseController
|
||||
echo $csv;
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/audit/chain-verify
|
||||
* Verifica l'integrità dell'hash chain per l'organizzazione corrente.
|
||||
* Risponde con: valid, total, hashed, coverage_pct, broken_at, last_hash
|
||||
*/
|
||||
public function chainVerify(): void
|
||||
{
|
||||
$this->requireOrgRole(['org_admin', 'auditor']);
|
||||
$orgId = $this->getCurrentOrgId();
|
||||
|
||||
$db = Database::getInstance();
|
||||
$result = AuditService::verifyChain($db, $orgId);
|
||||
|
||||
// Se la catena è rotta, registra la violazione
|
||||
if (!$result['valid'] && $result['broken_at'] !== null) {
|
||||
$performer = $this->currentUser['email'] ?? 'system';
|
||||
try {
|
||||
$ins = $db->prepare(
|
||||
"INSERT INTO audit_violations
|
||||
(organization_id, detected_by, broken_at_id, chain_length, notes)
|
||||
VALUES (:org, :by, :bid, :len, :notes)"
|
||||
);
|
||||
$ins->execute([
|
||||
'org' => $orgId,
|
||||
'by' => $performer,
|
||||
'bid' => $result['broken_at'],
|
||||
'len' => $result['total'],
|
||||
'notes' => 'Violazione rilevata tramite API chain-verify',
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
error_log('[AuditController] chain violation log error: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$this->logAudit('audit.chain_broken', 'audit_logs', $result['broken_at'], [
|
||||
'total' => $result['total'],
|
||||
'coverage_pct' => $result['coverage_pct'],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->jsonSuccess($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/audit/export-certified
|
||||
* Genera un export JSON certificato con hash SHA-256 dell'intero contenuto.
|
||||
* Adatto per ispezioni ACN, audit NIS2 Art.32, certificazione ISO 27001.
|
||||
*/
|
||||
public function exportCertified(): void
|
||||
{
|
||||
$this->requireOrgRole(['org_admin', 'auditor']);
|
||||
$orgId = $this->getCurrentOrgId();
|
||||
$userId = $this->getCurrentUserId();
|
||||
$email = $this->currentUser['email'] ?? 'system';
|
||||
|
||||
$db = Database::getInstance();
|
||||
$result = AuditService::exportCertified(
|
||||
$db,
|
||||
$orgId,
|
||||
$userId,
|
||||
$email,
|
||||
$_GET['purpose'] ?? 'export_certificato',
|
||||
$_GET['from'] ?? null,
|
||||
$_GET['to'] ?? null
|
||||
);
|
||||
|
||||
$this->logAudit('audit.export_certified', 'audit_logs', null, [
|
||||
'records_count' => $result['records_count'],
|
||||
'chain_valid' => $result['chain_valid'],
|
||||
'export_hash' => $result['export_hash'],
|
||||
]);
|
||||
|
||||
header('Content-Disposition: attachment; filename="nis2_audit_certified_' . date('Y-m-d') . '.json"');
|
||||
$this->jsonSuccess($result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
require_once APP_PATH . '/config/database.php';
|
||||
require_once APP_PATH . '/services/AuditService.php';
|
||||
|
||||
class BaseController
|
||||
{
|
||||
@@ -533,16 +534,23 @@ class BaseController
|
||||
*/
|
||||
protected function logAudit(string $action, ?string $entityType = null, ?int $entityId = null, ?array $details = null): void
|
||||
{
|
||||
Database::insert('audit_logs', [
|
||||
'user_id' => $this->getCurrentUserId(),
|
||||
'organization_id' => $this->currentOrgId,
|
||||
'action' => $action,
|
||||
'entity_type' => $entityType,
|
||||
'entity_id' => $entityId,
|
||||
'details' => $details ? json_encode($details) : null,
|
||||
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
|
||||
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
|
||||
]);
|
||||
$orgId = $this->currentOrgId;
|
||||
$userId = $this->getCurrentUserId();
|
||||
$severity = AuditService::resolveSeverity($action, $details);
|
||||
$email = $this->currentUser['email'] ?? null;
|
||||
|
||||
AuditService::log(
|
||||
$orgId ?? 0,
|
||||
$userId,
|
||||
$action,
|
||||
$entityType,
|
||||
$entityId,
|
||||
$details,
|
||||
$_SERVER['REMOTE_ADDR'] ?? '',
|
||||
$_SERVER['HTTP_USER_AGENT'] ?? null,
|
||||
$severity,
|
||||
$email
|
||||
);
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user