Lewati ke konten

Observabilitas: log SIEM dengan rantai hash dan pelaporan render

Modul Observability menyediakan implementasi runtime-state: log peristiwa security information and event management (SIEM) dengan rantai hash yang tahan-rusak (tamper-evident), agregasi laporan render dan pilot, log audit hardware security module (HSM), serta implementasi metrik dan trace no-op yang lengkap sehingga instrumentasi selalu dapat dipanggil.

Satu halaman kanonis per topik. Kontrak observability — ContextAwareExceptionInterface, SpectrumInterface, JobNotificationInterface, dan enum DegradationPolicy — didokumentasikan di Contracts / Observability. Halaman ini mendokumentasikan implementasi runtime-state yang konkret. Kedua halaman ini saling melengkapi, bukan duplikat: gunakan halaman kontrak untuk service provider interface (SPI), dan gunakan halaman ini untuk permukaan log SIEM, pelaporan, dan audit.

Terminal window
composer require nextpdf/core:^3

Modul ini mengubah runtime state mesin menjadi keluaran yang tahan lama dan dapat diverifikasi.

HashChainSiemEventLog adalah permukaan kelas keamanan. Kelas ini mengimplementasikan kontrak SiemEventEmitter dan menulis log JavaScript Object Notation (JSON) Lines, dengan hash setiap rekaman berupa SHA-256(prev_hash_bytes || canonical_event_bytes). Rantai hash linear tersebut membuat log tahan-rusak (tamper-evident): jika ada byte yang berubah, ada baris yang dihapus, atau baris-baris diurutkan ulang, rantai akan rusak. verifyIntegrity() menelusuri berkas dan mengembalikan indeks rekaman pertama yang tidak konsisten, atau null ketika rantai utuh. readAll() mengalirkan (stream) rekaman. Kunci advisory flock(LOCK_EX) per-proses melindungi bagian kritis baca-ekor-lalu-tambah (read-tail-then-append), sehingga proses PHP bersamaan yang menulis ke berkas yang sama tidak menyisipkan rekaman secara saling-silang. Batasannya eksplisit: ini adalah rantai hash linear, bukan pohon Merkle Request for Comments (RFC) 6962. Ini cukup untuk tamper-evidence, bukan untuk inclusion proof yang efisien. Demikian dinyatakan oleh sumbernya. SiemEvent membawa peristiwa bertipe dengan toCanonicalJson(). SiemEventSeverity dan SiemEventType mengklasifikasikannya. CorrelationContext dan CorrelationIdGenerator membawa correlation id melintasi peristiwa-peristiwa terkait.

RenderReportBuilder, RenderReport, PilotReportAggregator, dan PilotSummary membentuk permukaan pelaporan (@since 5.1.0). Agregator mengumpulkan RenderReport dan menghasilkan PilotSummary yang dirender ke array, JSON, atau Markdown, dalam format yang dapat digunakan untuk tinjauan operasi.

HsmAuditLogInterface / HsmAuditEvent mencatat operasi penandatanganan berbasis HSM untuk lapisan keamanan. MetricsCounterInterface, MetricsGaugeInterface, MetricsHistogramInterface, dan TraceSpanInterface mendefinisikan bentuk metrik dan trace. Implementasi NoOp* menyediakan fallback inert yang lengkap, sehingga mesin dapat memancarkan metrik dan span tanpa backend yang dikonfigurasi.

Stabilitas: experimental. Log SIEM diberi tag siklus secara internal alih-alih membawa @since semantic versioning (semver) yang dibekukan, dan permukaan pelaporan bersifat @since 5.1.0. Permukaan ini fungsional dan teruji, tetapi bentuk application programming interface (API) dapat berkembang. Perlakukan format log (JSON kanonis + rantai hash) sebagai kontrak yang stabil dan API PHP sebagai sesuatu yang masih dalam pematangan.

KelasAnggota utamaPeran
HashChainSiemEventLogemit(SiemEvent), verifyIntegrity(): ?int, readAll(): GeneratorLog SIEM berantai hash yang tahan-rusak (tamper-evident)
SiemEventtoCanonicalJson()Peristiwa SIEM bertipe
SiemEventSeverity / SiemEventType (enum)klasifikasiMengklasifikasikan tingkat keparahan dan tipe peristiwa
CorrelationContext / CorrelationIdGeneratorpenautan korelasiMenautkan korelasi melintasi peristiwa-peristiwa terkait
RenderReportBuilder / RenderReportperakitan laporanMembangun laporan per-render (@since 5.1.0)
PilotReportAggregatoraddReport(), count(), getSummary(), toJson(), toMarkdown(), exportReportsJson()Mengagregasi laporan render (@since 5.1.0)
PilotSummarytoArray(), toJson(), toMarkdown()Meringkas keluaran tinjauan operasi (@since 5.1.0)
HsmAuditLogInterface / HsmAuditEventRekaman audit HSMMencatat audit operasi HSM
NoOpSiemEventEmitter, NoOpMetricsCounter, NoOpTraceSpan, …fallback inertMenyediakan implementasi no-op yang lengkap

Jalankan composer docs:generate-api-php -- --module=Observability untuk menghasilkan tabel PHPDoc lengkap.

Pancarkan peristiwa dan verifikasi integritas 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";

Bungkus emitter agar kegagalan logging di hot path penandatanganan tetap menjadi keputusan lokal, alih-alih berubah menjadi exception yang tidak tertangkap.

<?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(),
]);
}
}
}
  • emit() melempar SiemEmitterException saat terjadi kesalahan tulis. Pemanggil di hot path penandatanganan harus membungkusnya dan memutuskan secara lokal apakah akan menelan, mencoba ulang, atau membatalkan. Emitter tidak memutuskan untuk Anda.
  • verifyIntegrity() mengembalikan indeks rekaman rusak yang pertama, atau null. Hasil non-null berarti log terkompromi mulai dari titik tersebut. Jangan memercayai rekaman pada atau setelah titik itu.
  • Kunci advisory flock berlaku per-proses dan per-berkas. Konkurensi lintas-host membutuhkan sink out-of-band, seperti penerusan syslog. Jangan berasumsi bahwa kunci berkas mengoordinasikan antarmesin.
  • Ini adalah rantai hash linear, bukan pohon Merkle. Ini menyediakan tamper-evidence, bukan inclusion proof yang efisien. Jangan memasarkannya sebagai inclusion proof.
  • Fallback NoOp* lengkap dan inert. Jangan bercabang berdasarkan ketersediaan backend untuk “menghemat kerja”. No-op memang tidak memerlukan biaya apa pun.

emit() membaca hash rekaman sebelumnya dan menambahkan satu baris saat memegang kunci berkas: O(1) per peristiwa ditambah overhead kunci. verifyIntegrity() bersifat O(n) terhadap jumlah rekaman karena menelusuri seluruh rantai. Jalankan sesuai jadwal, bukan di hot path. Agregasi pelaporan bersifat linear terhadap jumlah laporan. Profil reproduksibilitas adalah structural: peristiwa dan laporan membawa stempel waktu dan correlation id, sehingga dua proses dapat berbeda pada bidang-bidang tersebut, sementara struktur rantai tetap deterministik.

Log SIEM adalah kontrol keamanan. Tamper-evidence-nya bergantung pada perlindungan terhadap berkas log dan langkah verifikasi: simpan berkas pada penyimpanan yang ramah-tambah (append-friendly) dengan kontrol akses, jalankan verifyIntegrity() sesuai jadwal, dan teruskan rekaman secara out-of-band sehingga host yang terkompromi tidak dapat menulis ulang riwayat secara diam-diam. Peristiwa dapat membawa konteks sensitif. Terapkan kewajiban penyaringan log (log-scrubbing) proyek sebelum membangun peristiwa, bukan setelah merantainya, karena penulisan ulang untuk penyaringan akan merusak rantai. Log audit HSM mencatat operasi penandatanganan dan dengan sendirinya relevan terhadap keamanan. Perlakukan dengan perlindungan yang sama. Lihat model ancaman mesin di /modules/core/security/.

Modul ini tidak membuat klaim normatif apa pun tentang spesifikasi PDF. Modul ini mengimplementasikan mekanisme integritas log dan observabilitas yang desainnya selaras dengan praktik manajemen log dan verifikasi integritas dalam NIST SP 800-92. Penyelarasan kerangka kontrol tersebut didokumentasikan dalam sumber; ini bukan kutipan PDF yang dipasangkan dengan chunk. Konformansi dokumen yang dihasilkan mesin divalidasi oleh suite oracle dan golden yang dijelaskan di /modules/core/conformance/.