Inhaltsverzeichnis

Preverjanje preklica

Kompleksnost: Nizka
Trajanje: 30 minut nastavitve
Cilj: Zagotoviti razpoložljivost CRL/OCSP

Spremljanje informacij o preklicu (CRL in OCSP) za delujoč PKI.


Arhitektura

flowchart LR subgraph CHECK["PREVERJANJE"] C1[Prenos CRL] C2[Razčlenjevanje CRL] C3[OCSP zahteva] end subgraph VALIDATE["VALIDACIJA"] V1[Podpis OK?] V2[Ni potekel?] V3[Dosegljiv?] end subgraph ALERT["OPOZORILO"] A1[CRL potekel] A2[OCSP časovna omejitev] A3[CDP ni dosegljiv] end C1 --> V1 & V2 C3 --> V3 V1 -->|Ne| A1 V2 -->|Ne| A1 V3 -->|Ne| A2 style A1 fill:#ffebee style A2 fill:#ffebee


Nadzor CRL

Preverjanje statusa CRL

#!/bin/bash
# /usr/local/bin/check-crl.sh
 
CRL_URLS=(
    "http://crl.example.com/intermediate.crl"
    "http://crl.example.com/root.crl"
)
 
WARN_HOURS=72    # Opozorilo ko < 3 dni do naslednje posodobitve
CRIT_HOURS=24    # Kritično ko < 1 dan do naslednje posodobitve
 
for url in "${CRL_URLS[@]}"; do
    echo "Preverjam: $url"
 
    # Prenos CRL
    crl_data=$(curl -sf --max-time 10 "$url")
    if [ $? -ne 0 ]; then
        echo "NAPAKA: CRL ni dosegljiv - $url"
        continue
    fi
 
    # Razčlenjevanje CRL (DER ali PEM)
    if [[ "$crl_data" == *"-----BEGIN"* ]]; then
        crl_info=$(echo "$crl_data" | openssl crl -text -noout)
    else
        crl_info=$(echo "$crl_data" | openssl crl -inform DER -text -noout)
    fi
 
    # Ekstrakcija naslednje posodobitve
    next_update=$(echo "$crl_info" | grep "Next Update" | sed 's/.*: //')
    next_epoch=$(date -d "$next_update" +%s)
    now_epoch=$(date +%s)
    hours_left=$(( (next_epoch - now_epoch) / 3600 ))
 
    # Številka CRL
    crl_number=$(echo "$crl_info" | grep -A1 "CRL Number" | tail -1 | tr -d ' ')
 
    # Izpis statusa
    if [ "$hours_left" -lt 0 ]; then
        echo "KRITIČNO: CRL je potekel! - $url"
    elif [ "$hours_left" -lt "$CRIT_HOURS" ]; then
        echo "KRITIČNO: CRL poteče čez $hours_left ur - $url"
    elif [ "$hours_left" -lt "$WARN_HOURS" ]; then
        echo "OPOZORILO: CRL poteče čez $hours_left ur - $url"
    else
        echo "OK: CRL veljaven še $hours_left ur - $url (CRL#: $crl_number)"
    fi
 
    # Število preklicanih certifikatov
    revoked_count=$(echo "$crl_info" | grep -c "Serial Number:")
    echo "  Preklicani: $revoked_count certifikatov"
    echo ""
done

Prometheus Exporter za CRL

#!/bin/bash
# crl-exporter.sh - Generira Prometheus metrike
 
METRICS_FILE="/var/lib/node_exporter/textfile_collector/crl.prom"
 
cat /dev/null > "$METRICS_FILE"
 
CRL_URLS=(
    "intermediate|http://crl.example.com/intermediate.crl"
    "root|http://crl.example.com/root.crl"
)
 
for entry in "${CRL_URLS[@]}"; do
    IFS='|' read -r name url <<< "$entry"
 
    crl_data=$(curl -sf --max-time 10 "$url" 2>/dev/null)
    if [ $? -ne 0 ]; then
        echo "crl_reachable{name=\"$name\"} 0" >> "$METRICS_FILE"
        continue
    fi
 
    echo "crl_reachable{name=\"$name\"} 1" >> "$METRICS_FILE"
 
    next_update=$(echo "$crl_data" | openssl crl -inform DER -nextupdate -noout 2>/dev/null | cut -d= -f2)
    if [ -n "$next_update" ]; then
        next_epoch=$(date -d "$next_update" +%s)
        echo "crl_next_update_timestamp{name=\"$name\"} $next_epoch" >> "$METRICS_FILE"
    fi
 
    revoked=$(echo "$crl_data" | openssl crl -inform DER -text -noout 2>/dev/null | grep -c "Serial Number:")
    echo "crl_revoked_count{name=\"$name\"} $revoked" >> "$METRICS_FILE"
done

Pravilo opozorila:

- alert: CRLExpiringSoon
  expr: crl_next_update_timestamp - time() < 86400
  labels:
    severity: critical
  annotations:
    summary: "CRL {{ $labels.name }} poteče v < 24h"

- alert: CRLUnreachable
  expr: crl_reachable == 0
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "CRL {{ $labels.name }} ni dosegljiv"

Nadzor OCSP

Preverjanje OCSP odzivnika

#!/bin/bash
# /usr/local/bin/check-ocsp.sh
 
OCSP_URL="http://ocsp.example.com"
ISSUER_CERT="/etc/pki/CA/intermediate-ca.pem"
TEST_CERT="/etc/ssl/certs/test-server.pem"
 
echo "Preverjanje OCSP odzivnika: $OCSP_URL"
 
# Pošiljanje OCSP zahteve
start_time=$(date +%s%N)
response=$(openssl ocsp \
    -issuer "$ISSUER_CERT" \
    -cert "$TEST_CERT" \
    -url "$OCSP_URL" \
    -resp_text 2>&1)
end_time=$(date +%s%N)
 
# Izračun odzivnega časa (ms)
response_time=$(( (end_time - start_time) / 1000000 ))
 
# Ekstrakcija statusa
if echo "$response" | grep -q "good"; then
    status="good"
elif echo "$response" | grep -q "revoked"; then
    status="revoked"
else
    status="error"
fi
 
# Izpis
echo "Status: $status"
echo "Odzivni čas: ${response_time}ms"
 
if [ "$status" = "error" ]; then
    echo "NAPAKA: OCSP odzivnik ne deluje"
    exit 1
fi
 
if [ "$response_time" -gt 2000 ]; then
    echo "OPOZORILO: OCSP odzivni čas > 2s"
fi

OCSP Prometheus Exporter

#!/bin/bash
# ocsp-exporter.sh
 
METRICS_FILE="/var/lib/node_exporter/textfile_collector/ocsp.prom"
 
OCSP_ENDPOINTS=(
    "intermediate|http://ocsp.example.com|/etc/pki/CA/intermediate.pem|/etc/ssl/certs/test.pem"
)
 
cat /dev/null > "$METRICS_FILE"
 
for entry in "${OCSP_ENDPOINTS[@]}"; do
    IFS='|' read -r name url issuer cert <<< "$entry"
 
    start_time=$(date +%s%N)
    response=$(openssl ocsp -issuer "$issuer" -cert "$cert" -url "$url" -resp_text 2>&1)
    exit_code=$?
    end_time=$(date +%s%N)
 
    response_time=$(( (end_time - start_time) / 1000000 ))
    echo "ocsp_response_time_ms{name=\"$name\"} $response_time" >> "$METRICS_FILE"
 
    if [ $exit_code -eq 0 ]; then
        echo "ocsp_up{name=\"$name\"} 1" >> "$METRICS_FILE"
    else
        echo "ocsp_up{name=\"$name\"} 0" >> "$METRICS_FILE"
    fi
 
    if echo "$response" | grep -q "good"; then
        echo "ocsp_status{name=\"$name\"} 0" >> "$METRICS_FILE"  # 0=good
    elif echo "$response" | grep -q "revoked"; then
        echo "ocsp_status{name=\"$name\"} 1" >> "$METRICS_FILE"  # 1=revoked
    else
        echo "ocsp_status{name=\"$name\"} 2" >> "$METRICS_FILE"  # 2=unknown/error
    fi
done

Pravila opozoril:

- alert: OCSPResponderDown
  expr: ocsp_up == 0
  for: 2m
  labels:
    severity: critical
  annotations:
    summary: "OCSP odzivnik {{ $labels.name }} ni dosegljiv"

- alert: OCSPResponseSlow
  expr: ocsp_response_time_ms > 2000
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "OCSP {{ $labels.name }} počasen: {{ $value }}ms"

Blackbox Exporter

# blackbox.yml
modules:
  tls_connect:
    prober: tcp
    timeout: 5s
    tcp:
      tls: true
      tls_config:
        insecure_skip_verify: false

  http_crl:
    prober: http
    timeout: 10s
    http:
      method: GET
      valid_status_codes: [200]
      fail_if_body_not_matches_regexp: ["-----BEGIN X509 CRL-----|^\x30"]

  ocsp_check:
    prober: http
    timeout: 5s
    http:
      method: POST
      headers:
        Content-Type: application/ocsp-request

PowerShell (Windows)

# Check-Revocation.ps1
 
param(
    [string]$OcspUrl = "http://ocsp.example.com",
    [string]$CrlUrl = "http://crl.example.com/intermediate.crl"
)
 
# Preverjanje CRL
Write-Host "=== Preverjanje CRL ===" -ForegroundColor Cyan
try {
    $crlResponse = Invoke-WebRequest -Uri $CrlUrl -TimeoutSec 10
    Write-Host "CRL dosegljiv: OK ($($crlResponse.StatusCode))" -ForegroundColor Green
 
    # Razčlenjevanje CRL (zahteva dodatna orodja ali .NET)
    $crlBytes = $crlResponse.Content
    # ... razčlenjevanje CRL tukaj
}
catch {
    Write-Host "CRL NAPAKA: $_" -ForegroundColor Red
}
 
# Preverjanje OCSP (poenostavljeno preko openssl)
Write-Host "`n=== Preverjanje OCSP ===" -ForegroundColor Cyan
try {
    $certPath = "C:\certs\test.pem"
    $issuerPath = "C:\certs\intermediate.pem"
 
    $ocspResult = & openssl ocsp -issuer $issuerPath -cert $certPath -url $OcspUrl -text 2>&1
    if ($ocspResult -match "good") {
        Write-Host "OCSP status: GOOD" -ForegroundColor Green
    }
    elseif ($ocspResult -match "revoked") {
        Write-Host "OCSP status: REVOKED" -ForegroundColor Yellow
    }
    else {
        Write-Host "OCSP status: ERROR" -ForegroundColor Red
    }
}
catch {
    Write-Host "OCSP NAPAKA: $_" -ForegroundColor Red
}

Kontrolni seznam

# Kontrolna točka
—————–
1 URL-ji CRL definirani
2 Prenos CRL deluje
3 Opozorilo o izteku CRL konfigurirano
4 URL OCSP definiran
5 OCSP odziv deluje
6 Prometheus Exporter aktiven
7 Opozorila konfigurirana

Povezana dokumentacija


« ← Nadzor izteka | → Revizijsko beleženje »


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