Osservabilità: log SIEM con catena di hash e report di rendering
In sintesi
Sezione intitolata “In sintesi”Il modulo Observability è l’implementazione dello stato a runtime: un log eventi SIEM con catena di hash a prova di manomissione, l’aggregazione dei report di rendering e pilot, un log di audit HSM e un insieme completo di implementazioni no-op per metrics e trace, così che la strumentazione sia sempre richiamabile.
Una sola pagina canonica per ciascun argomento. I contratti di osservabilità —
ContextAwareExceptionInterface,SpectrumInterface,JobNotificationInterfacee l’enumDegradationPolicy— sono documentati in Contracts / Observability. Questa pagina documenta l’implementazione concreta dello stato a runtime. Le due pagine sono complementari, non duplicati: consultare la pagina dei contratti per l’SPI e questa per il log SIEM, i report e le superfici di audit.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Panoramica concettuale
Sezione intitolata “Panoramica concettuale”Questo modulo è il punto in cui lo stato a runtime del motore diventa un output durevole e verificabile.
HashChainSiemEventLog è la superficie di livello security. Implementa il contratto SiemEventEmitter e scrive un log JSON-Lines in cui l’hash di ogni record è
SHA-256(prev_hash_bytes || canonical_event_bytes). Questa catena di hash
lineare rende il log a prova di manomissione: modificare un byte qualsiasi, eliminare una riga o riordinare le righe spezza la catena. verifyIntegrity() percorre il file e restituisce l’indice del primo record incoerente, oppure null se la catena è integra. readAll() trasmette i record in streaming. Un flock(LOCK_EX) advisory per processo racchiude la sezione critica leggi-coda-poi-accoda, così che processi PHP concorrenti sullo stesso file non intercalino i record. Il design è esplicito sul proprio limite: è una catena di hash lineare, non un albero di Merkle RFC 6962 — sufficiente come prova di manomissione, non per prove di inclusione efficienti. Il sorgente lo dichiara. SiemEvent trasporta l’evento tipizzato con toCanonicalJson(). SiemEventSeverity e SiemEventType lo classificano. CorrelationContext e CorrelationIdGenerator propagano un id di correlazione tra eventi correlati.
RenderReportBuilder, RenderReport, PilotReportAggregator e PilotSummary costituiscono la superficie dei report (@since 5.1.0). L’aggregatore raccoglie i RenderReport e produce un PilotSummary che viene reso come array, JSON o Markdown — il formato consumato da una revisione operativa.
HsmAuditLogInterface / HsmAuditEvent registrano le operazioni di firma assistite da HSM per il livello di sicurezza. MetricsCounterInterface, MetricsGaugeInterface, MetricsHistogramInterface e TraceSpanInterface definiscono le forme di metrics/trace. Le implementazioni NoOp* forniscono un fallback inerte completo, così che il motore possa emettere metriche e span anche senza un backend configurato.
Stabilità: sperimentale. Il log SIEM è internamente contrassegnato per ciclo anziché portare un
@sincesemver congelato, e la superficie di reportistica è@since 5.1.0. Le superfici sono funzionali e testate, ma le forme dell’API possono evolvere. Considerare il formato del log (JSON canonico + catena di hash) come il contratto stabile e l’API PHP come ancora in fase di assestamento.
Superficie API
Sezione intitolata “Superficie API”| Classe | Membri principali | Ruolo |
|---|---|---|
HashChainSiemEventLog | emit(SiemEvent), verifyIntegrity(): ?int, readAll(): Generator | Log SIEM con catena di hash a prova di manomissione |
SiemEvent | toCanonicalJson() | Evento SIEM tipizzato |
SiemEventSeverity / SiemEventType (enum) | classificazione | Severità e tipo dell’evento |
CorrelationContext / CorrelationIdGenerator | propagazione della correlazione | Correla eventi correlati |
RenderReportBuilder / RenderReport | assemblaggio del report | Report di un singolo rendering (@since 5.1.0) |
PilotReportAggregator | addReport(), count(), getSummary(), toJson(), toMarkdown(), exportReportsJson() | Aggrega i report dei rendering (@since 5.1.0) |
PilotSummary | toArray(), toJson(), toMarkdown() | Sintesi per revisione operativa (@since 5.1.0) |
HsmAuditLogInterface / HsmAuditEvent | Record di audit HSM | Log di audit delle operazioni HSM |
NoOpSiemEventEmitter, NoOpMetricsCounter, NoOpTraceSpan, … | fallback inerti | Implementazioni no-op complete |
Eseguire composer docs:generate-api-php -- --module=Observability per la tabella PHPDoc completa.
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”Emettere un evento e verificare l’integrità del log.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Observability\Siem\HashChainSiemEventLog;use NextPDF\Observability\Siem\SiemEvent;
$log = new HashChainSiemEventLog('/var/log/nextpdf/siem.jsonl');$log->emit(new SiemEvent(/* type, severity, payload */));
$firstBroken = $log->verifyIntegrity();echo $firstBroken === null ? "SIEM chain intact.\n" : "Tamper detected at record {$firstBroken}.\n";Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Incapsulare l’emitter in modo che un errore di logging nel percorso critico di firma resti una decisione locale, non un’eccezione non gestita.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Observability\Siem\HashChainSiemEventLog;use NextPDF\Observability\Siem\Exception\SiemEmitterException;use NextPDF\Observability\Siem\SiemEvent;use Psr\Log\LoggerInterface;
final readonly class AuditedSiemSink{ public function __construct( private HashChainSiemEventLog $log, private LoggerInterface $fallback, ) {}
public function record(SiemEvent $event): void { try { $this->log->emit($event); } catch (SiemEmitterException $e) { // Do not let SIEM I/O abort the signing path; record and continue. $this->fallback->critical('SIEM emit failed; event not chained.', [ 'error' => $e->getMessage(), ]); } }}Casi limite e insidie
Sezione intitolata “Casi limite e insidie”emit()sollevaSiemEmitterExceptionin caso di errore di scrittura. Un chiamante nel percorso critico di firma deve incapsularla e decidere localmente se ignorarla, ritentare o interrompere. L’emitter non decide al posto del chiamante.verifyIntegrity()restituisce l’indice del primo record corrotto, oppurenull. Un risultato non-null significa che il log è compromesso da quel punto in poi — non fidarsi dei record a partire da quel record.- Il
flockadvisory è per processo e sullo stesso file. La concorrenza tra host diversi richiede un sink fuori banda (inoltro a syslog). Non assumere che il blocco del file coordini macchine diverse. - Questa è una catena di hash lineare, non un albero di Merkle. Fornisce prova di manomissione, non prove di inclusione efficienti. Non commercializzarla come tale.
- I fallback
NoOp*sono completi e inerti. Non diramare in base alla disponibilità del backend per “risparmiare lavoro” — il no-op ha già costo nullo.
Prestazioni
Sezione intitolata “Prestazioni”emit() legge l’hash del record precedente e accoda una riga sotto un blocco del file — O(1) per evento più il blocco. verifyIntegrity() è O(n) rispetto al numero di record, perché percorre l’intera catena. Eseguirlo in modo pianificato, non nel percorso critico. L’aggregazione dei report è lineare rispetto al numero di report. Il profilo di riproducibilità è structural: eventi e report portano timestamp e id di correlazione, quindi due esecuzioni differiscono in quei campi mentre la struttura della catena resta deterministica.
Note di sicurezza
Sezione intitolata “Note di sicurezza”Il log SIEM è un controllo di sicurezza. La sua prova di manomissione dipende dalla protezione del file di log e dal passaggio di verifica: archiviare il file su storage append-friendly e con accesso controllato, eseguire verifyIntegrity() in modo pianificato e inoltrare i record fuori banda, così che la compromissione di un host non possa riscrivere silenziosamente la cronologia. Gli eventi possono contenere contesto sensibile. Applicare l’obbligo di scrubbing del log del progetto prima che l’evento sia costruito, non dopo che è stato concatenato, perché una riscrittura ripulita spezzerebbe la catena. Il log di audit HSM registra le operazioni di firma ed è a sua volta rilevante per la sicurezza. Trattarlo con le stesse protezioni. Vedere il threat model del motore in /modules/core/security/.
Conformità
Sezione intitolata “Conformità”Questo modulo non avanza alcuna affermazione normativa relativa alla specifica PDF. Implementa meccanismi di integrità del log e di osservabilità il cui design è allineato alle pratiche di gestione del log e di verifica dell’integrità del NIST SP 800-92 — un allineamento a un framework di controllo documentato nel sorgente, non una citazione PDF ancorata a un chunk. La conformità dei documenti prodotti dal motore è validata dalle suite oracle e golden descritte in /modules/core/conformance/.
Vedi anche
Sezione intitolata “Vedi anche”- Contracts / Observability — l’SPI (eccezione strutturata, Spectrum, policy di degradazione).
- Telemetry module — il bridge OpenTelemetry che alimenta i backend esterni.
- Audit module — l’esportatore di evidenze di conformità associato al log SIEM.
- Security module — le operazioni di firma registrate dal log di audit HSM.
- Conformance overview