====== 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}}