====== Audit-Logging ====== **Komplexität:** Mittel \\ **Dauer:** 1-2 Stunden Setup \\ **Compliance:** NIS2, ISO 27001, BSI-Grundschutz Compliance-konforme Protokollierung aller PKI-Operationen für Audits und Forensik. ---- ===== Architektur ===== flowchart LR subgraph SOURCES["📝 QUELLEN"] S1[CA Operations] S2[API Requests] S3[Admin Actions] S4[System Events] end subgraph COLLECT["📥 SAMMLUNG"] C1[Syslog] C2[Filebeat] C3[Fluentd] end subgraph STORE["💾 SPEICHERUNG"] ST1[(Elasticsearch)] ST2[(Loki)] ST3[S3/Archive] end subgraph ANALYZE["🔍 ANALYSE"] A1[Kibana] A2[Grafana] end S1 & S2 & S3 & S4 --> C1 & C2 C1 & C2 & C3 --> ST1 & ST2 ST1 --> A1 ST2 --> A2 ST1 & ST2 --> ST3 style ST1 fill:#e3f2fd style A1 fill:#e8f5e9 ---- ===== Audit-Ereignisse ===== | Kategorie | Ereignis | Kritikalität | |-----------|----------|--------------| | **Zertifikat** | Ausgestellt | Info | | **Zertifikat** | Erneuert | Info | | **Zertifikat** | Widerrufen | Hoch | | **CA** | CRL generiert | Info | | **CA** | CA-Schlüssel verwendet | Mittel | | **Admin** | Login | Mittel | | **Admin** | Konfigurationsänderung | Hoch | | **System** | Service Start/Stop | Mittel | | **Security** | Fehlgeschlagene Auth | Hoch | ---- ===== Log-Format ===== ==== Strukturiertes JSON-Format ==== { "timestamp": "2024-12-15T10:30:00.000Z", "level": "INFO", "event_type": "certificate_issued", "source": "ca-service", "actor": { "id": "operator-01", "ip": "10.0.0.50", "role": "pki-operator" }, "subject": { "type": "certificate", "serial": "01:23:45:67:89:AB:CD:EF", "cn": "server.example.com", "validity_days": 365 }, "details": { "algorithm": "ML-DSA-65", "mode": "Hybrid", "issuer_serial": "AA:BB:CC:DD", "request_id": "REQ-2024-12345" }, "result": "success" } ==== Syslog-Format ==== Dec 15 10:30:00 ca-server pki-ca[12345]: [INFO] certificate_issued actor=operator-01 serial=01:23:45:67 cn=server.example.com algo=ML-DSA-65 result=success ---- ===== Linux: Rsyslog + ELK ===== ==== Rsyslog Konfiguration ==== # /etc/rsyslog.d/50-pki.conf # PKI-Logs in separater Datei :programname, isequal, "pki-ca" /var/log/pki/ca.log :programname, isequal, "pki-ocsp" /var/log/pki/ocsp.log # JSON-Template für Elasticsearch template(name="pki-json" type="list") { constant(value="{") constant(value="\"timestamp\":\"") property(name="timereported" dateFormat="rfc3339") constant(value="\",\"host\":\"") property(name="hostname") constant(value="\",\"program\":\"") property(name="programname") constant(value="\",\"message\":\"") property(name="msg" format="json") constant(value="\"}\n") } # An Elasticsearch senden module(load="omelasticsearch") action(type="omelasticsearch" server="elasticsearch.example.com" serverport="9200" template="pki-json" searchIndex="pki-audit" bulkmode="on" queue.type="linkedlist" queue.size="10000" queue.dequeuebatchsize="300" action.resumeRetryCount="-1") ==== Filebeat Konfiguration ==== # /etc/filebeat/filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/pki/*.log json.keys_under_root: true json.add_error_key: true fields: log_type: pki-audit output.elasticsearch: hosts: ["elasticsearch.example.com:9200"] index: "pki-audit-%{+yyyy.MM.dd}" setup.template.name: "pki-audit" setup.template.pattern: "pki-audit-*" ---- ===== Anwendungs-Logging (C#) ===== // PkiAuditLogger.cs using Microsoft.Extensions.Logging; using System.Text.Json; public class PkiAuditLogger { private readonly ILogger _logger; public PkiAuditLogger(ILogger logger) { _logger = logger; } public void LogCertificateIssued( X509Certificate2 cert, string actor, string requestId, CryptoMode mode) { var auditEvent = new { event_type = "certificate_issued", timestamp = DateTimeOffset.UtcNow, actor = new { id = actor }, subject = new { serial = cert.SerialNumber, cn = cert.GetNameInfo(X509NameType.SimpleName, false), not_after = cert.NotAfter }, details = new { algorithm = cert.SignatureAlgorithm.FriendlyName, mode = mode.ToString(), request_id = requestId }, result = "success" }; _logger.LogInformation( "AUDIT: {Event}", JsonSerializer.Serialize(auditEvent)); } public void LogCertificateRevoked( string serial, X509RevocationReason reason, string actor) { var auditEvent = new { event_type = "certificate_revoked", timestamp = DateTimeOffset.UtcNow, actor = new { id = actor }, subject = new { serial }, details = new { reason = reason.ToString() }, result = "success" }; _logger.LogWarning( "AUDIT: {Event}", JsonSerializer.Serialize(auditEvent)); } } ---- ===== Elasticsearch Index Template ===== PUT _index_template/pki-audit { "index_patterns": ["pki-audit-*"], "template": { "settings": { "number_of_shards": 1, "number_of_replicas": 1, "index.lifecycle.name": "pki-audit-policy" }, "mappings": { "properties": { "timestamp": { "type": "date" }, "level": { "type": "keyword" }, "event_type": { "type": "keyword" }, "source": { "type": "keyword" }, "actor.id": { "type": "keyword" }, "actor.ip": { "type": "ip" }, "actor.role": { "type": "keyword" }, "subject.type": { "type": "keyword" }, "subject.serial": { "type": "keyword" }, "subject.cn": { "type": "text" }, "result": { "type": "keyword" } } } } } ==== ILM Policy (Retention) ==== PUT _ilm/policy/pki-audit-policy { "policy": { "phases": { "hot": { "actions": { "rollover": { "max_size": "10GB", "max_age": "7d" } } }, "warm": { "min_age": "30d", "actions": { "shrink": { "number_of_shards": 1 }, "forcemerge": { "max_num_segments": 1 } } }, "cold": { "min_age": "90d", "actions": { "allocate": { "require": { "data": "cold" } } } }, "delete": { "min_age": "365d", "actions": { "delete": {} } } } } } ---- ===== Kibana Dashboards ===== ==== Audit-Übersicht ==== { "title": "PKI Audit Dashboard", "panels": [ { "title": "Events pro Tag", "type": "visualization", "visState": { "type": "line", "aggs": [ { "type": "date_histogram", "field": "timestamp", "interval": "1d" } ] } }, { "title": "Events nach Typ", "type": "visualization", "visState": { "type": "pie", "aggs": [ { "type": "terms", "field": "event_type" } ] } }, { "title": "Widerrufe", "type": "visualization", "visState": { "type": "metric", "aggs": [ { "type": "count", "filter": { "term": { "event_type": "certificate_revoked" } } } ] } } ] } ---- ===== Compliance-Anforderungen ===== | Standard | Anforderung | Umsetzung | |----------|-------------|-----------| | **NIS2 Art. 21** | Incident-Protokollierung | Alle PKI-Events loggen | | **ISO 27001 A.12.4** | Log-Integrität | Tamper-proof Storage | | **BSI C5** | Aufbewahrung | Min. 1 Jahr | | **DSGVO Art. 30** | Verarbeitungsverzeichnis | Zugriffslogs | ---- ===== Log-Archivierung ===== #!/bin/bash # /usr/local/bin/archive-pki-logs.sh # Logs älter als 90 Tage archivieren find /var/log/pki -name "*.log" -mtime +90 -exec gzip {} \; # Archiv nach S3 hochladen aws s3 sync /var/log/pki/*.gz s3://pki-audit-archive/$(date +%Y/%m)/ # Lokale Archive älter als 365 Tage löschen find /var/log/pki -name "*.gz" -mtime +365 -delete ---- ===== Checkliste ===== | # | Prüfpunkt | ✓ | |---|-----------|---| | 1 | Log-Format definiert (JSON) | ☐ | | 2 | Alle PKI-Events geloggt | ☐ | | 3 | Zentrale Sammlung (ELK/Loki) | ☐ | | 4 | Retention Policy konfiguriert | ☐ | | 5 | Dashboard erstellt | ☐ | | 6 | Archivierung eingerichtet | ☐ | | 7 | Compliance-Review | ☐ | ---- ===== Verwandte Dokumentation ===== * [[.:alerting-setup|Alerting Setup]] – Benachrichtigungen * [[de:int:pqcrypt:business:compliance|Compliance]] – Regulatorische Anforderungen * [[de:int:pqcrypt:administrator:betrieb|Betrieb]] – Systemwartung ---- << [[.:revocation-check|← Revocation-Check]] | [[.:alerting-setup|→ Alerting Setup]] >> ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional// {{tag>audit logging elk elasticsearch compliance nis2 operator}}