관측 가능성: 해시 체인 SIEM 로그와 렌더 보고
한눈에 보기
섹션 제목: “한눈에 보기”관측 가능성 모듈은 런타임 상태를 제공하는 구현체입니다. 변조를 감지할 수 있는 해시 체인 SIEM 이벤트 로그, 렌더 및 파일럿 보고 집계, HSM 감사 로그, 그리고 계측을 언제든 호출할 수 있게 해 주는 완전한 무동작 메트릭 및 트레이스 구현 모음을 제공합니다.
하나의 관심사에는 하나의 정식 페이지가 있습니다. 관측 가능성 계약(contract),
ContextAwareExceptionInterface,SpectrumInterface,JobNotificationInterface, 그리고DegradationPolicy열거형은 Contracts / Observability에 문서화되어 있습니다. 이 페이지는 구체적인 런타임 상태 구현을 다룹니다. 둘은 중복이 아니라 서로 보완합니다. SPI에는 계약 페이지를, SIEM 로그, 보고, 감사 표면에는 이 페이지를 참고하십시오.
composer require nextpdf/core:^3개념 개요
섹션 제목: “개념 개요”이 모듈은 엔진의 런타임 상태를 내구성 있고 검증 가능한 출력으로 전환하는 지점입니다.
HashChainSiemEventLog는 보안 등급 표면입니다. SiemEventEmitter 계약을 구현하며, 각 레코드의
해시가 SHA-256(prev_hash_bytes || canonical_event_bytes)인 JSON-Lines 로그를 기록합니다. 이 선형
해시 체인 덕분에 로그 변조를 감지할 수 있습니다. 어떤 바이트를 변경하거나, 한 줄을 삭제하거나, 줄 순서를 바꾸면 체인이 끊어집니다. verifyIntegrity()는 파일을 순회해 처음 불일치가 발생한 레코드의 인덱스를 반환하며, 체인이 온전하면 null을 반환합니다. readAll()은 레코드를 스트리밍합니다. 프로세스별 권고 잠금인 flock(LOCK_EX)는 꼬리 읽기 후 추가 기록하는 임계 구역을 감싸므로, 같은 파일을 다루는 동시 PHP 프로세스들이 레코드를 서로 섞어 쓰지 않습니다. 이 설계는 자신의 한계를 분명히 합니다. 이는 선형 해시 체인이지 RFC 6962 머클 트리가 아닙니다. 변조 감지에는 충분하지만 효율적인 포함 증명에는 충분하지 않습니다. 소스도 이를 명시합니다. SiemEvent는 toCanonicalJson()와 함께 타입이 지정된 이벤트를 담습니다. SiemEventSeverity와 SiemEventType이 이를 분류합니다. CorrelationContext와 CorrelationIdGenerator는 관련 이벤트에 상관관계 ID를 연결합니다.
RenderReportBuilder, RenderReport, PilotReportAggregator, 그리고 PilotSummary는 보고 표면입니다(@since 5.1.0). 집계기는 RenderReport들을 수집해 배열, JSON 또는 Markdown으로 렌더링되는 PilotSummary를 생성합니다. 이는 운영 리뷰에서 소비하는 형식입니다.
HsmAuditLogInterface / HsmAuditEvent는 보안 계층을 위해 HSM 기반 서명 작업을 기록합니다. MetricsCounterInterface, MetricsGaugeInterface, MetricsHistogramInterface, 그리고 TraceSpanInterface는 metrics/trace 형식을 정의합니다. NoOp* 구현은 완전한 비활성 폴백을 제공하므로, 엔진은 구성된 백엔드 없이도 메트릭과 스팬을 내보낼 수 있습니다.
안정성: 실험적(experimental). SIEM 로그는 내부적으로 사이클 태그가 지정되어 있을 뿐 고정된 semver
@since를 담지 않으며, 보고 표면에는@since 5.1.0이 붙어 있습니다. 이 표면들은 동작하고 테스트도 되어 있지만 API 형태는 변경될 수 있습니다. 로그 형식(정규 JSON + 해시 체인)은 안정적인 계약으로 보고, PHP API는 아직 정착 중인 것으로 취급하십시오.
API 표면
섹션 제목: “API 표면”| 클래스 | 주요 멤버 | 역할 |
|---|---|---|
HashChainSiemEventLog | emit(SiemEvent), verifyIntegrity(): ?int, readAll(): Generator | 변조가 감지되는 해시 체인 SIEM 로그 |
SiemEvent | toCanonicalJson() | 타입이 지정된 SIEM 이벤트 |
SiemEventSeverity / SiemEventType (열거형) | 분류 | 이벤트 심각도 및 유형 |
CorrelationContext / CorrelationIdGenerator | 상관관계 연결 | 관련 이벤트를 상관관계로 묶습니다 |
RenderReportBuilder / RenderReport | 보고서 조립 | 렌더별 보고서 (@since 5.1.0) |
PilotReportAggregator | addReport(), count(), getSummary(), toJson(), toMarkdown(), exportReportsJson() | 렌더 보고서를 집계합니다 (@since 5.1.0) |
PilotSummary | toArray(), toJson(), toMarkdown() | 운영 리뷰 요약 (@since 5.1.0) |
HsmAuditLogInterface / HsmAuditEvent | HSM 감사 레코드 | HSM 작업 감사 로그 |
NoOpSiemEventEmitter, NoOpMetricsCounter, NoOpTraceSpan, … | 비활성 폴백 | 완전한 무동작 구현 |
전체 PHPDoc 표는 composer docs:generate-api-php -- --module=Observability를 실행해 확인하십시오.
코드 샘플 — 빠른 시작
섹션 제목: “코드 샘플 — 빠른 시작”이벤트를 내보내고 로그의 무결성을 검증합니다.
<?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";코드 샘플 — 프로덕션
섹션 제목: “코드 샘플 — 프로덕션”서명 핫 패스에서 발생한 로깅 실패가 잡히지 않은 예외로 번지지 않고, 로컬에서 처리할 수 있는 결정이 되도록 이미터를 감싸십시오.
<?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()은 쓰기 오류 시SiemEmitterException을 던집니다. 서명 핫 패스의 호출자는 이를 감싸고 무시할지, 재시도할지, 중단할지를 로컬에서 결정해야 합니다. 이미터가 대신 결정하지 않습니다.verifyIntegrity()는 처음으로 깨진 레코드의 인덱스를 반환하거나null을 반환합니다. null이 아닌 결과는 로그가 그 지점부터 손상되었음을 의미합니다. 그 위치 또는 그 이후의 레코드를 신뢰하지 마십시오.- 권고형
flock은 프로세스별이며 동일 파일에만 적용됩니다. 호스트 간 동시성에는 대역 외 싱크가 필요합니다(syslog로 전달). 파일 잠금이 머신 간에 조율된다고 가정하지 마십시오. - 이는 선형 해시 체인이지 머클 트리가 아닙니다. 변조 감지는 증명하지만 효율적인 포함 증명은 제공하지 않습니다. 후자로 홍보하지 마십시오.
NoOp*폴백은 완전하고 비활성입니다. “작업을 줄이려고” 백엔드 가용성에 따라 분기하지 마십시오. 무동작은 이미 아무 비용도 들지 않습니다.
emit()은 이전 레코드의 해시를 읽고 파일 잠금 안에서 한 줄을 추가합니다. 이벤트당 O(1)에 잠금 비용이 더해집니다. verifyIntegrity()는 전체 체인을 순회하므로 레코드 수에 대해 O(n)입니다. 핫 패스에서 실행하지 말고 일정에 맞춰 실행하십시오. 보고 집계는 보고서 수에 선형으로 비례합니다. 재현성 프로파일은 structural입니다. 이벤트와 보고서는 타임스탬프와 상관관계 ID를 담으므로, 두 실행은 해당 필드에서 차이가 나지만 체인 구조는 결정적입니다.
보안 참고 사항
섹션 제목: “보안 참고 사항”SIEM 로그는 보안 통제 수단입니다. 로그의 변조 감지 기능은 로그 파일과 검증 단계가 보호되는지에 달려 있습니다. 파일을 추가 기록에 적합하고 접근이 통제되는 저장소에 보관하고, verifyIntegrity()를 일정에 맞춰 실행하며, 호스트 침해가 이력을 조용히 다시 쓸 수 없도록 레코드를 대역 외로 전달하십시오. 이벤트는 민감한 컨텍스트를 담을 수 있습니다. 프로젝트의 로그 스크러빙 의무는 이벤트가 체인에 연결된 후가 아니라 이벤트가 구성되기 전에 적용하십시오. 스크러빙을 위해 다시 쓰면 체인이 끊어지기 때문입니다. HSM 감사 로그는 서명 작업을 기록하며 그 자체로 보안과 관련됩니다. 동일한 보호 수준으로 다루십시오. 엔진 위협 모델은 /modules/core/security/를 참고하십시오.
적합성
섹션 제목: “적합성”이 모듈은 어떠한 PDF 사양에 대해서도 규범적 주장을 하지 않습니다. 이 모듈은 로그 무결성 및 관측 가능성 메커니즘을 구현하며, 그 설계는 NIST SP 800-92의 로그 관리 및 무결성 검증 관행과 부합합니다. 이는 청크에 고정된 PDF 인용이 아니라 소스에 문서화된 통제 프레임워크 정렬입니다. 엔진이 생성하는 문서의 적합성은 /modules/core/conformance/에 설명된 오라클과 골든 스위트로 검증됩니다.
함께 보기
섹션 제목: “함께 보기”- Contracts / Observability — SPI(구조화된 예외, Spectrum, 성능 저하 정책).
- Telemetry 모듈 — 외부 백엔드에 데이터를 공급하는 OpenTelemetry 브리지.
- Audit 모듈 — SIEM 로그와 짝을 이루는 컴플라이언스 증거 내보내기.
- Security 모듈 — HSM 감사 로그가 기록하는 서명 작업.
- 적합성 개요