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<PkiAuditLogger> 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


« ← Provjera opoziva | → Alerting Setup »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: 30.01.2026. u 06:31