Veröffentlicht am

TPM Attestation: Kubernetes-Node-Integrität absichern

Teilen:
Authors

TPM Attestation in Kubernetes: Node-Integritaet kryptografisch absichern

TL;DR

  • TPM 2.0 misst den Boot-Prozess eines Nodes kryptografisch und speichert die Hashes in Platform Configuration Registers (PCRs)
  • Remote Attestation vergleicht diese PCR-Werte mit einer bekannten Good-Known-Configuration -- stimmen sie nicht ueberein, ist der Node kompromittiert
  • Keylime ist das gaengigste Open-Source-Tool, um TPM Attestation in Kubernetes zu integrieren
  • Ueber Node Labels und Admission Controller koennen Sie erzwingen, dass sensible Workloads nur auf attestierten Nodes laufen
  • Der Performance-Overhead ist vernachlaessigbar, da die Messungen hauptsaechlich beim Boot stattfinden

Das Problem: Vertrauen in die Node-Ebene

Die meisten Kubernetes-Security-Massnahmen setzen oberhalb des Betriebssystems an: RBAC, Network Policies, Pod Security Standards, Image Signing. Das ist notwendig, aber nicht ausreichend.

Wenn ein Angreifer die Firmware oder den Kernel eines Worker Nodes kompromittiert, kann er alles umgehen, was darauf laeuft. Ein Rootkit im Kernel sieht den Container-Traffic, manipuliert Prozesse und bleibt fuer userspace-basierte Security-Tools unsichtbar. Die Container-Isolation greift nicht mehr, wenn das Betriebssystem selbst nicht vertrauenswuerdig ist.

TPM-basierte Remote Attestation loest genau dieses Problem. Sie prueft die Integritaet eines Nodes von der Hardware aufwaerts -- vom UEFI ueber den Bootloader bis zum Kernel. Erst wenn diese Pruefung bestanden ist, darf der Node Workloads ausfuehren.

Wie TPM Attestation funktioniert

Der Boot-Prozess und PCR-Messungen

Ein TPM 2.0 Chip ist ein separater Mikrocontroller auf dem Mainboard (oder als Firmware-TPM in der CPU). Beim Systemstart passiert Folgendes:

  1. Die UEFI-Firmware wird geladen. Ihr Hash wird in PCR 0 geschrieben.
  2. Der Bootloader (z.B. GRUB2) wird geladen. Sein Hash landet in PCR 4.
  3. Der Linux-Kernel wird geladen. Hash in PCR 8.
  4. Die initramfs und kritische Kernel-Module werden gemessen. PCR 9.

Jede Messung wird an den bestehenden PCR-Wert angehaengt (extend). Das bedeutet: Aendert sich auch nur ein Byte in einer der gemessenen Komponenten, aendert sich der gesamte PCR-Wert. Die Kette ist kryptografisch verkettet.

PCRs koennen nicht direkt geschrieben werden -- nur extended. Ein Angreifer kann einen PCR-Wert nicht auf den erwarteten Wert setzen, ohne den gesamten Boot-Prozess exakt zu reproduzieren.

Remote Attestation: PCR-Werte ueberpruefen

Remote Attestation bedeutet: Ein externer Verifier fragt den TPM eines Nodes nach seinen aktuellen PCR-Werten. Der TPM signiert diese Werte mit seinem Attestation Identity Key (AIK), zusammen mit einer Nonce, die Replay-Angriffe verhindert.

Der Verifier vergleicht die signierten PCR-Werte mit einer vordefinierten Good-Known-Configuration (GKC). Stimmen sie ueberein, ist der Node integer. Weichen sie ab, wurde etwas am Boot-Prozess veraendert.

KomponenteFunktionWo laeuft sie
TPM 2.0Misst Boot-Prozess, signiert Attestation QuotesHardware auf jedem Node
Attestation AgentSammelt PCR-Werte, sendet Quotes an VerifierDaemonSet auf jedem Node
VerifierPrueft Quotes gegen GKC, meldet StatusZentraler Service (eigener Pod oder extern)
GKC (Whitelist)Erwartete PCR-Werte fuer korrekte NodesConfigMap, Git-Repo oder Datenbank
Admission ControllerBlockiert Pods auf nicht-attestierten NodesControl Plane

Keylime: TPM Attestation in der Praxis

Keylime ist ein CNCF-Sandbox-Projekt und die verbreitetste Open-Source-Loesung fuer TPM-basierte Attestation. Es besteht aus drei Komponenten: Registrar, Verifier und Agent.

Keylime auf Kubernetes-Nodes installieren

Der Agent laeuft auf jedem Node. Am einfachsten deployen Sie ihn als DaemonSet, wobei der Agent Zugriff auf das TPM-Device braucht.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: keylime-agent
  namespace: keylime-system
spec:
  selector:
    matchLabels:
      app: keylime-agent
  template:
    metadata:
      labels:
        app: keylime-agent
    spec:
      hostPID: true
      hostNetwork: true
      nodeSelector:
        node.kubernetes.io/tpm: "true"
      tolerations:
      - operator: Exists
      containers:
      - name: agent
        image: quay.io/keylime/keylime_agent:latest
        securityContext:
          privileged: true
        volumeMounts:
        - name: tpm-device
          mountPath: /dev/tpmrm0
        - name: ima-log
          mountPath: /sys/kernel/security/ima
          readOnly: true
        - name: keylime-config
          mountPath: /etc/keylime
        env:
        - name: KEYLIME_AGENT_CONTACT_IP
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
      volumes:
      - name: tpm-device
        hostPath:
          path: /dev/tpmrm0
          type: CharDevice
      - name: ima-log
        hostPath:
          path: /sys/kernel/security/ima
          type: Directory
      - name: keylime-config
        configMap:
          name: keylime-agent-config

Wichtige Punkte zu dieser Konfiguration:

  • privileged: true ist notwendig, weil der Agent auf das TPM-Device und IMA-Logs zugreifen muss. Das ist einer der wenigen legitimen Anwendungsfaelle fuer privilegierte Container.
  • hostPID und hostNetwork sind erforderlich, damit der Agent die Host-Prozesse messen und mit dem Verifier kommunizieren kann.
  • Der nodeSelector stellt sicher, dass der Agent nur auf Nodes mit TPM laeuft. Labeln Sie Ihre Nodes entsprechend.

Node-Label basierend auf Attestation-Status setzen

Der Verifier meldet, ob ein Node integer ist. Diese Information muessen Sie in Kubernetes einfliessen lassen. Ein einfacher Ansatz: Ein Controller-Pod, der den Keylime-Verifier pollt und entsprechende Labels setzt.

#!/bin/bash
# Einfaches Skript, das den Keylime Verifier abfragt und Node-Labels setzt.
# In der Praxis wuerde man das als Custom Controller implementieren.

VERIFIER_URL="https://keylime-verifier.keylime-system.svc:8881"
INTERVAL=30

while true; do
  for node in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do
    agent_id=$(kubectl get node "$node" -o jsonpath='{.metadata.annotations.keylime\.dev/agent-id}')
    if [ -z "$agent_id" ]; then
      continue
    fi

    status=$(curl -sk "$VERIFIER_URL/v2/agents/$agent_id" | jq -r '.results.operational_state')

    if [ "$status" = "Get Quote" ] || [ "$status" = "Provide V" ]; then
      kubectl label node "$node" security.kubernetes.io/tpm-attested=true --overwrite
    else
      kubectl label node "$node" security.kubernetes.io/tpm-attested=false --overwrite
      kubectl taint node "$node" security.kubernetes.io/not-attested=true:NoSchedule --overwrite 2>/dev/null
    fi
  done
  sleep $INTERVAL
done

Admission Controller: Workloads schuetzen

Der letzte Schritt ist ein Validating Webhook, der verhindert, dass sensible Pods auf nicht-attestierten Nodes starten.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: tpm-attestation-webhook
webhooks:
- name: attestation.security.kubernetes.io
  clientConfig:
    service:
      name: attestation-webhook
      namespace: keylime-system
      path: "/validate"
    caBundle: ${CA_BUNDLE}
  rules:
  - operations: ["CREATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  namespaceSelector:
    matchLabels:
      security.kubernetes.io/requires-attestation: "true"
  sideEffects: None
  admissionReviewVersions: ["v1"]
  failurePolicy: Fail
  timeoutSeconds: 5

Durch den namespaceSelector wirkt der Webhook nur auf Namespaces mit dem Label requires-attestation: "true". Das ist wichtig, damit System-Pods (kube-system) nicht blockiert werden.

Good-Known-Configuration pflegen

Die GKC ist die Achillesferse des ganzen Systems. Wenn Sie Ihre Referenz-PCR-Werte nicht aktuell halten, schlagen legitime Nodes nach einem Kernel-Update fehl.

In der Praxis loest man das so:

  1. Goldene Images: Bauen Sie Ihre Node-Images mit Packer oder einem aehnlichen Tool. Beim Build extrahieren Sie die PCR-Werte und committen sie ins Git-Repo.
  2. CI-Integration: Jedes Kernel-Update oder Firmware-Update triggert einen neuen Image-Build mit neuen Referenz-Werten.
  3. Staging-First: Neue GKC-Werte werden zuerst auf Staging-Nodes getestet, bevor sie in Production uebernommen werden.

Wer tiefer in Secure Boot und die Absicherung der Boot-Kette einsteigen will, findet unter Kubernetes Secure Boot weiterfuehrende Informationen.

Vergleich: TPM Attestation vs. andere Node-Security-Ansnahmen

AnsatzSchutz-EbeneErkennt Firmware-ManipulationRuntime-OverheadKomplexitaet
TPM Remote AttestationBoot-Prozess bis KernelJaMinimalHoch
IMA (Integrity Measurement Architecture)Dateisystem-IntegritaetNeinMittelMittel
Secure Boot (allein)Nur signierte Bootloader/KernelTeilweiseKeinerNiedrig
Runtime Security (Falco, Tetragon)Syscalls und ProzesseNeinMittelMittel
Confidential Computing (SEV, TDX)Gesamte VM/Container-IsolationJaMittel-HochSehr hoch

TPM Attestation ersetzt die anderen Ansaetze nicht -- es ergaenzt sie. Die beste Kombination fuer Hochsicherheits-Workloads: Secure Boot + TPM Attestation + Runtime Security (z.B. Falco). Mehr zur Absicherung der Kubernetes-Runtime finden Sie unter Kubernetes Runtime Security.

Haeufige Stolpersteine bei der Implementierung

GKC-Drift nach Updates. Der haeufigste Grund fuer fehlgeschlagene Attestierungen ist eine veraltete Good-Known-Configuration. Nach einem Kernel-Update aendern sich die PCR-Werte. Wenn die GKC nicht aktualisiert wird, markiert der Verifier alle geupdateten Nodes als kompromittiert. Loesung: GKC-Updates in die gleiche Pipeline wie OS-Updates integrieren.

vTPM in Cloud-Umgebungen. Cloud-Provider bieten virtuelle TPMs (vTPM) fuer VMs an. Azure Trusted Launch, AWS NitroTPM und GCE Shielded VMs unterstuetzen alle TPM 2.0 in virtuellen Maschinen. Die Attestation funktioniert identisch, aber Sie vertrauen dem Cloud-Provider, dass der vTPM korrekt implementiert ist. Fuer regulierte Branchen kann das ein Problem sein -- dann fuehrt kein Weg an physischen TPMs in On-Premise-Clustern vorbei.

IMA-Messungen sind gross. Die Integrity Measurement Architecture (IMA) des Linux-Kernels kann jede geladene Datei messen. Das ist gruendlich, aber die IMA-Logs werden bei laenger laufenden Systemen sehr gross. Filtern Sie auf die relevanten Dateien (Kernel-Module, kritische Binaries) und vermeiden Sie es, jede einzelne Datei zu messen.

Latenz des Verifiers. Wenn der Verifier langsam antwortet, verzoegert sich das Labeling der Nodes. In der Zwischenzeit koennten Pods auf noch nicht attestierten Nodes starten. Loesung: Konfigurieren Sie den Admission Controller so, dass er Pods blockiert, bis der Attestierungsstatus vorliegt, oder verwenden Sie Taints, die erst nach erfolgreicher Attestierung entfernt werden.

Secure Boot Schluessel-Management. Secure Boot erfordert, dass Ihre Kernel und Bootloader signiert sind. Bei Custom-Kerneln (z.B. mit speziellen Treibern) muessen Sie eigene Signing Keys in die UEFI-Firmware eintragen. Das ist machbar, aber ein zusaetzlicher Wartungsaufwand, den Sie einplanen sollten.

Wann lohnt sich TPM Attestation?

Nicht jeder Cluster braucht TPM Attestation. Der Aufwand fuer Setup und GKC-Pflege ist real. Sinnvoll ist es in diesen Szenarien:

  • Finanz- und Gesundheitsbranche: Regulatorische Anforderungen (BaFin, BSI) verlangen nachweisbare Integritaet der Infrastruktur.
  • Multi-Tenant-Cluster: Wenn mehrere Teams oder Kunden auf demselben Cluster arbeiten, schuetzt Attestation gegen kompromittierte Nodes.
  • CI/CD-Build-Nodes: Build-Nodes sind ein attraktives Angriffsziel. Attestation stellt sicher, dass Build-Artefakte auf integren Systemen erstellt werden.
  • On-Premise-Cluster: Ohne die Sicherheitsgarantien eines Cloud-Providers muessen Sie die physische Integritaet selbst verifizieren.

Fuer einen einfachen Development-Cluster oder nicht-kritische Workloads ist der Aufwand in der Regel nicht gerechtfertigt.

Hardware-Voraussetzungen pruefen

Bevor Sie mit der Implementierung beginnen, pruefen Sie die TPM-Faehigkeit Ihrer Nodes:

# Pruefen, ob ein TPM 2.0 vorhanden ist
ls -la /dev/tpmrm0

# TPM-Version und Hersteller auslesen (tpm2-tools muss installiert sein)
tpm2_getcap properties-fixed | grep -A1 "TPM2_PT_FAMILY_INDICATOR"

# Secure Boot Status pruefen
mokutil --sb-state

Wenn /dev/tpmrm0 nicht existiert, hat der Node entweder kein TPM oder es ist im BIOS deaktiviert. Bei Cloud-VMs muessen Sie vTPM explizit beim Erstellen der Instanz aktivieren.

Fazit

TPM-basierte Remote Attestation schliesst eine Luecke, die viele Kubernetes-Security-Strategien uebersehen: die Integritaet des Hosts selbst. Mit Keylime, Node Labels und einem Admission Controller laesst sich ein System aufbauen, das kryptografisch verifiziert, ob ein Node vertrauenswuerdig ist, bevor er Workloads ausfuehrt.

Der groesste Aufwand liegt nicht in der initialen Implementierung, sondern in der Pflege der GKC. Planen Sie das von Anfang an in Ihre CI/CD-Pipeline ein, dann bleibt der Betriebsaufwand ueberschaubar.

Fuer eine detaillierte Analyse, ob TPM Attestation fuer Ihren Cluster sinnvoll ist, und Hilfe bei der Implementierung koennen Sie sich jederzeit an uns wenden unter /kontakt. Einen breiteren Ueberblick ueber Kubernetes-Security-Themen bietet unser Artikel zu Kubernetes Network Security.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen