====== Audit Logging ====== **Složenost:** Srednja \\ **Trajanje:** 1-2 sata postavljanja \\ **Usklađenost:** NIS2, ISO 27001, BSI-Grundschutz Protokoliranje svih PKI operacija usklađeno s propisima za revizije i forenziku. ---- ===== Arhitektura ===== flowchart LR subgraph SOURCES["📝 IZVORI"] S1[CA operacije] S2[API zahtjevi] S3[Admin akcije] S4[Sistemski događaji] end subgraph COLLECT["📥 PRIKUPLJANJE"] C1[Syslog] C2[Filebeat] C3[Fluentd] end subgraph STORE["💾 POHRANA"] ST1[(Elasticsearch)] ST2[(Loki)] ST3[S3/Arhiva] end subgraph ANALYZE["🔍 ANALIZA"] 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 događaji ===== | Kategorija | Događaj | Kritičnost | |------------|---------|------------| | **Certifikat** | Izdan | Info | | **Certifikat** | Obnovljen | Info | | **Certifikat** | Opozvan | Visoka | | **CA** | CRL generiran | Info | | **CA** | CA ključ korišten | Srednja | | **Admin** | Prijava | Srednja | | **Admin** | Promjena konfiguracije | Visoka | | **Sustav** | Start/Stop servisa | Srednja | | **Sigurnost** | Neuspjela autentifikacija | Visoka | ---- ===== Format logova ===== ==== Strukturirani 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 konfiguracija ==== # /etc/rsyslog.d/50-pki.conf # PKI logovi u zasebnoj datoteci :programname, isequal, "pki-ca" /var/log/pki/ca.log :programname, isequal, "pki-ocsp" /var/log/pki/ocsp.log # JSON predložak za 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") } # Slanje u Elasticsearch 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 konfiguracija ==== # /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-*" ---- ===== Aplikacijsko logiranje (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 Dashboardi ===== ==== Pregled audita ==== { "title": "PKI Audit Dashboard", "panels": [ { "title": "Događaji po danu", "type": "visualization", "visState": { "type": "line", "aggs": [ { "type": "date_histogram", "field": "timestamp", "interval": "1d" } ] } }, { "title": "Događaji po tipu", "type": "visualization", "visState": { "type": "pie", "aggs": [ { "type": "terms", "field": "event_type" } ] } }, { "title": "Opozivi", "type": "visualization", "visState": { "type": "metric", "aggs": [ { "type": "count", "filter": { "term": { "event_type": "certificate_revoked" } } } ] } } ] } ---- ===== Zahtjevi usklađenosti ===== | Standard | Zahtjev | Provedba | |----------|---------|----------| | **NIS2 čl. 21** | Protokoliranje incidenata | Logiranje svih PKI događaja | | **ISO 27001 A.12.4** | Integritet logova | Pohrana otporna na manipulaciju | | **BSI C5** | Čuvanje | Min. 1 godina | | **GDPR čl. 30** | Evidencija obrade | Logovi pristupa | ---- ===== Arhiviranje logova ===== #!/bin/bash # /usr/local/bin/archive-pki-logs.sh # Arhiviranje logova starijih od 90 dana find /var/log/pki -name "*.log" -mtime +90 -exec gzip {} \; # Upload arhive na S3 aws s3 sync /var/log/pki/*.gz s3://pki-audit-archive/$(date +%Y/%m)/ # Brisanje lokalnih arhiva starijih od 365 dana find /var/log/pki -name "*.gz" -mtime +365 -delete ---- ===== Kontrolna lista ===== | # | Točka provjere | ✓ | |---|----------------|---| | 1 | Format logova definiran (JSON) | ☐ | | 2 | Svi PKI događaji logirani | ☐ | | 3 | Centralno prikupljanje (ELK/Loki) | ☐ | | 4 | Retention Policy konfigurirana | ☐ | | 5 | Dashboard kreiran | ☐ | | 6 | Arhiviranje postavljeno | ☐ | | 7 | Pregled usklađenosti | ☐ | ---- ===== Povezana dokumentacija ===== * [[.:alerting-setup|Alerting Setup]] – Obavijesti * [[hr:int:pqcrypt:business:compliance|Usklađenost]] – Regulatorni zahtjevi * [[hr:int:pqcrypt:administrator:betrieb|Rad sustava]] – Održavanje sustava ---- << [[.:revocation-check|← Provjera opoziva]] | [[.:alerting-setup|→ Alerting Setup]] >> ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional// {{tag>audit logging elk elasticsearch usklađenost nis2 operator}}