Vier-Augen-Policy-Publishing mit HashiCorp Vault Transit
Ein signiertes Policy-Bundle ist das einzige Artefakt, dem ein Governance-Proxy trauen sollte. So publishen wir Bundles im Vier-Augen-Prinzip, rotieren Keys ohne Downtime und beweisen Integrität bei jedem Request — mit HashiCorp Vault Transit und Ed25519-Signaturen.
TL;DR. Wenn ein:e einzelne Engineer:in eine Policy-Änderung durchdrücken kann, die Redigierung aufweicht, einen neuen Endpunkt erlaubt oder ein Modell freischaltet, ist der Governance-Proxy Theater. Echte Durchsetzung beginnt mit signierten Bundles, Vier-Augen-Prinzip bei jedem Publish und Key-Rotation ohne Redeploy. HashiCorp Vault Transit übernimmt die Kryptographie; Ed25519 hält Verifikation günstig; ein kleines Set an Publishing-Policies schließt den Kreis.
Ein Governance-Proxy entscheidet — pro Request —, ob ein Prompt das Perimeter verlassen darf, ob PII redigiert wird, ob die Antwort Code enthalten darf, welche Modelle überhaupt erreichbar sind. Diese Entscheidungsgrenze setzt ein Policy-Bundle durch: ein versioniertes, maschinenlesbares Artefakt, kompiliert aus deklarativen Regeln. Wer dieses Bundle ändern kann, kontrolliert das Perimeter.
Dieser Beitrag zeigt das Modell, mit dem wir Policy-Bundles in Raigate publishen: wie Ed25519-Signaturen über HashiCorp Vault Transit ausgestellt werden, wie Vier-Augen-Prinzip im Publishing-Schritt durchgesetzt wird (nicht in der IDE), wie der Proxy Bundles beim Laden verifiziert und wie wir Signing-Keys ohne Wartungsfenster rotieren.
Inhalt
- Warum Vier-Augen-Prinzip in die Policy-Ebene gehört
- Anatomie eines signierten Policy-Bundles
- Vault Transit als Signing-Oracle
- Der Publish-Workflow von Anfang bis Ende
- Verifikation auf Proxy-Ebene
- Key-Rotation und das Resigner-Pattern
- Compliance-Sicht — wonach Auditor:innen tatsächlich fragen
1. Warum Vier-Augen-Prinzip in die Policy-Ebene gehört
Die meisten Teams setzen Vier-Augen-Prinzip irgendwo durch — Produktiv-Deployments, Datenbank-Migrationen, IAM-Änderungen. Policy-Bundles eines KI-Governance-Proxys verdienen dieselbe Behandlung, aus einem einfachen Grund: das Bundle ist die Policy.
Eine einzeilige Änderung an einem JSON-Prädikat kann:
- PII-Redigierung für einen Mandanten stillschweigend deaktivieren,
- einen neuen ausgehenden Endpunkt erlauben, der Prompts exfiltriert,
- ein nicht freigegebenes Modell mit schwächerer Safety-Alignment freischalten,
- Fail-Closed-Defaults in Fail-Open verwandeln.
Code-Review allein reicht nicht. Ein:e Reviewer:in, die:der den PR genehmigt, ist nicht dasselbe wie ein:e kryptographische:r Co-Signer:in, die:der das tatsächlich deployte Artefakt attestiert. Beide können auseinanderdriften — durch Rebase, Merge-Konflikt, last-minute "winziges" Amend nach Approval oder einen kompromittierten CI-Runner.
Lösung: die Trust-Boundary vom Source-Repo auf das signierte Artefakt verschieben. Jeder laufende Proxy verifiziert eine Signatur, bevor er ein Bundle lädt. Keine Signatur, kein Load. Falsche Signatur, kein Load. Richtige Signatur vom falschen Key, kein Load.
2. Anatomie eines signierten Policy-Bundles
Ein Bundle ist ein deterministisches Archiv. Inputs rein, ein kanonischer Byte-Stream raus, dieser Byte-Stream wird gehasht und signiert. Determinismus zählt, weil dieselbe logische Policy auf jeder Maschine denselben Hash produzieren muss — sonst wird Signaturverifikation zur Flake statt zur Garantie.
bundle/
├── manifest.json # version, created_at, source commit, framework refs
├── policies/
│ ├── redaction.json # PII handling rules, fail-closed defaults
│ ├── routing.json # which models, which endpoints, per tenant
│ └── content.json # blocked categories, output constraints
├── checksums.txt # SHA-256 of every file above, sorted by path
└── signatures/
├── primary.sig # Ed25519 over checksums.txt
└── secondary.sig # Ed25519 over checksums.txt, different signer
- redaction.json — PII-Regeln, Fail-Closed-Defaults
- routing.json — Modelle + Endpoints pro Mandant
- content.json — gesperrte Kategorien, Output-Grenzen
- primary.sig — Ed25519, Policy-Lead-Identität
- secondary.sig — Ed25519, Security-Review-Identität
- Beide erforderlich. Unterschiedliche Menschen, unterschiedliche Vault-Keys.
checksums.txt ist der Kanonisierungspunkt. Dateien werden alphabetisch gelistet; jede Zeile ist <sha256> <path>. Die Signer signieren nie das Rohformat — sie signieren checksums.txt. Das hält Signaturen über Archivformate und Tooling-Versionen hinweg stabil und gibt dem Verifier einen schnellen Pfad: Dateien hashen, checksums.txt regenerieren, gegen das tatsächlich Signierte vergleichen.
Zwei Signaturen, zwei verschiedene Keys, zwei verschiedene Menschen. Das ist die Vier-Augen-Fläche.
3. Vault Transit als Signing-Oracle
Wir halten niemals rohe Private Keys auf Entwicklungs-Rechnern oder CI-Runnern. Vault Transit stellt Signing als API bereit; das Schlüsselmaterial bleibt in Vault und kann rotiert, versioniert oder widerrufen werden, ohne dass ein Client geändert werden muss.
Zwei benannte Keys liegen im Transit-Backend:
policy-bundle-primary— gehalten von der Policy-Engineering-Lead-Rollepolicy-bundle-secondary— gehalten von der Security-Review-Rolle
Beide sind Ed25519. Beide sind nicht-exportierbar. Beide haben Versioning aktiviert.
Eine Signatur auszustellen ist ein einziger API-Call gegen Vault — Input ist der base64-codierte SHA-256 von checksums.txt, Output ist eine base64-Signatur plus die Key-Version, die sie erzeugt hat:
vault write transit/sign/policy-bundle-primary/sha2-256 \
input="$(sha256sum checksums.txt | awk '{print $1}' | xxd -r -p | base64)" \
prehashed=true \
signature_algorithm=pkcs1v15
Der Signing-Call wird durch eine Vault-Policy gegated, die sowohl eine authentifizierte menschliche Identität als auch ein aktives Approval-Ticket verlangt. Kein Service-Account kann transit/sign/policy-bundle-primary direkt aufrufen. Dasselbe gilt — mit anderer Policy und anderer Identity-Group — für den Secondary-Key.
Genau hier wird Vier-Augen-Prinzip mechanisch statt kulturell: Eine einzelne Person kann nicht beide Signaturen erzeugen, weil keine einzelne Identität die Vault-Berechtigungen für beide Signing-Endpoints hat.
4. Der Publish-Workflow von Anfang bis Ende
Das Signing-Oracle ist das Herzstück, aber der Workflow drumherum macht das System sicher betreibbar. Der Pfad einer Policy-Änderung von Draft bis Deployed:
Konkret:
- Autor:in öffnet eine Policy-Änderung als normalen PR. CI baut ein Candidate-Bundle und postet seinen SHA-256 als Status-Check. Der PR kann nicht gemerged werden, ohne dass dieser Hash dem letzten Commit auf dem Branch entspricht.
- Reviewer:in öffnet das Candidate-Bundle im Policy-Studio, fährt eine Dry-Evaluation gegen einen Regression-Korpus (abgespielter historischer Traffic plus kuratierte Red-Team-Prompts) und lehnt ab oder markiert das Bundle als publish-ready. Reviewer:in ist nicht Autor:in.
- Primary-Signatur wird angefordert. Das System zieht das Candidate-Bundle, regeneriert
checksums.txt, ruft Vault Transit mit der Autor:innen-Identität auf, die die Primary-Signing-Policy beansprucht. Die Signatur wird angehängt. - Secondary-Signatur wird unter der Reviewer:innen-Identität gegen den Secondary-Key angefordert. Fehlt eine Signatur oder ist sie ungültig, verlässt das Bundle die Build-Umgebung nie.
- Distributor publisht das doppelt signierte Bundle in den Artifact-Store unter einem inhaltsadressierten Pfad:
bundles/<sha256>.tar.gz. Die Flotte zieht von dort. - Proxy-Flotte verifiziert beide Signaturen gegen die gepinten Public-Keys für die aktuellen Key-Versionen und tauscht dann atomar die aktive Policy. Ein Load-Fehler lässt das vorherige Bundle aktiv — fail-closed bis ganz unten.
Autor:in kann sich nicht selbst genehmigen. Reviewer:in kann ohne Primary-Signatur der Autor:in nicht publishen. Distributor akzeptiert nur Bundles, deren Signaturen beide unter dem aktuellen Public-Key-Set verifizieren. Jedes Gate ist ein harter kryptographischer Check, keine UI-Funktion.
5. Verifikation auf Proxy-Ebene
Der Proxy hält ein kleines, versions-gepintes Set an Public-Keys in seiner Konfiguration:
{
"trusted_signers": [
{
"name": "policy-bundle-primary",
"key_versions": {
"v2": "MCowBQYDK2VwAyEA<...base64 ed25519 public key...>",
"v3": "MCowBQYDK2VwAyEA<...base64 ed25519 public key...>"
}
},
{
"name": "policy-bundle-secondary",
"key_versions": {
"v1": "MCowBQYDK2VwAyEA<...base64 ed25519 public key...>",
"v2": "MCowBQYDK2VwAyEA<...base64 ed25519 public key...>"
}
}
],
"require_both": true,
"min_key_versions": { "primary": 2, "secondary": 1 }
}
Die Verifikationsroutine, in einfachen Schritten:
- Archiv in ein Scratch-Verzeichnis entpacken.
checksums.txtaus den entpackten Dateien in sortierter Reihenfolge regenerieren.- Mit SHA-256 hashen.
- Für jede
.sig-Datei den eingebetteten Key-Namen und die Version lesen, intrusted_signersnachschlagen, bei Fehlen fail-closed. - Ed25519-Signatur gegen den regenerierten Hash verifizieren.
- Ist
require_bothgesetzt, müssen beide verifizieren. Sonst Ablehnung.
Ed25519 wurde wegen Verifikationskosten gewählt. Eine einzelne Signaturverifikation läuft sub-Millisekunde auf Commodity-Hardware — billig genug, um sie bei jedem Bundle-Reload zu machen, billig genug für den Health-Check des Proxys, billig genug für eine Startup-Probe, die den Pod erst dann "ready" markiert, wenn das aktive Bundle erneut verifiziert.
Der Proxy vertraut niemals einem Key, von dem er nicht in Kenntnis gesetzt wurde. Neue Key-Versionen erfordern ein Config-Update — das selbst denselben Review-und-Deploy-Pfad wie jede Produktiv-Änderung durchläuft.
6. Key-Rotation und das Resigner-Pattern
Ed25519-Keys schwächen nicht über die Zeit, aber das operative Prinzip bleibt: Jeder Key, der lange genug signiert hat, sollte rotiert werden. Das Risiko ist nicht der Algorithmus — es sind Custody, Personalfluktuation und die langsame Akkretion von Identitäten, die über ein Mehrjahres-Fenster einen Signing-Endpoint berührt haben könnten.
Der schmerzhafte Teil der Rotation ist nicht das Generieren eines neuen Keys. Vault Transit macht das in einem Call:
vault write -f transit/keys/policy-bundle-primary/rotate
Schmerzhaft ist, was mit bereits deployten Bundles passiert, die mit der alten Key-Version signiert sind. Zwei Optionen:
- Ein Re-Publish jedes Bundles, jedes Mandanten, bei jeder Rotation erzwingen. Laut, disruptiv, und beim nächsten Mal verlockend zu überspringen.
- Bestehende Bundles in-place mit einem kontrollierten Batch-Prozess neu signieren.
Wir nutzen Option zwei. Der Resigner ist ein kurzlebiger Job, der gegen den Artifact-Store läuft: Er lädt jedes aktuell deployte Bundle, verifiziert die existierenden Signaturen erneut (die alten Key-Versionen werden im Überlappungsfenster weiterhin vertraut), fordert dann eine neue Primary-Signatur unter der rotierten Key-Version an und schreibt das Bundle mit beiden Signaturen zurück.
- Vault Transit erzeugt neue Key-Version (v_new)
- Alte Version (v_old) bleibt zur Verifikation gültig
- Proxy-Trust-Konfig akzeptiert beide Versionen
ZustandZwei Key-Versionen im Umlauf; für deployte Bundles ändert sich noch nichts
- Resigner-Job listet jedes Bundle im Artifact-Store
- Pro Bundle: verify(v_old) + verify(secondary), dann sign(v_new)
- Bundle mit neuer Primary-Signatur überschrieben, Secondary erhalten
- Resigner-Identität ausschließlich für diesen Workflow berechtigt
ZustandJedes deployte Bundle trägt jetzt eine v_new-Primary-Signatur
- v_old aus Proxy-Trust-Konfig entfernen
- v_old aus Vault Transit entfernen
- Audit-Log bewahrt beide Signing-Events für historische Bundles
Zustandv_old wird nirgendwo mehr vertraut; Rotation ohne Downtime abgeschlossen
Zwei Hinweise:
- Die Secondary-Signatur bleibt unverändert. Würden wir beide Keys gleichzeitig rotieren, würde die Vier-Augen-Evidenz auf jedem historischen Bundle gelöscht. Wir rotieren versetzt.
- Der Resigner läuft mit einer eigenen, dedizierten Identität, die ausschließlich den Resign-Workflow aufrufen darf — er kann keine neuen Bundles autoren, keine novellen Policy-Änderungen publishen, keine Signaturen entfernen. Er darf ein bereits von zwei Menschen signiertes Bundle an die aktuelle Primary-Key-Version rebinden. Diese eng begrenzte Reichweite ist der einzige Grund, warum er sicher automatisiert werden kann.
7. Compliance-Sicht — wonach Auditor:innen tatsächlich fragen
EU AI Act Art. 12 (Aufzeichnungspflichten), ISO 27001 Anhang A.12.4 (Logging), SOC 2 CC7.2 (Change-Management) — alle konvergieren auf dieselben drei Fragen bei KI-Governance-Policy:
- Wer hat diese Änderung autorisiert, und wie belegen Sie das?
- Kann die Änderung nach Autorisierung manipuliert worden sein?
- Können Sie rekonstruieren, welche Policy zum Zeitpunkt einer beliebigen vergangenen Entscheidung aktiv war?
Signierte Bundles beantworten alle drei:
- Wer — zwei verschiedene Vault-Identitäten, jede mit einem eigenen, audit-geloggten Signing-Event im Vault-Audit-Device. Die Identitäten sind über Ihren IdP an Menschen gebunden. Das Signing-Event zeichnet Zeitstempel, Key-Version und Input-Hash auf.
- Manipulationsresistenz — jede Änderung an einer beliebigen Datei im Bundle verändert
checksums.txt, was beide Signaturen invalidiert. Der Proxy weigert sich, es zu laden. - Historische Rekonstruktion — jeder Request, den der Proxy bedient, kann ein Feld
policy_bundle_sha256im Audit-Log tragen. Mit diesem Hash gegen den Artifact-Store kreuzreferenzieren — und Sie haben exakt das Bundle, mit exakt seinen Signaturen, das diesen Request entschieden hat.
Die Audit-Kette läuft end-to-end: Das Request-Log zeigt auf das Bundle, das Bundle zeigt auf die Signing-Events, die Signing-Events zeigen auf die menschlichen Identitäten. Keine verbalen Zusicherungen nötig.
Abschluss
Vier-Augen-Prinzip beim Policy-Publishing ist eine jener Engineering-Investitionen, die wie Overhead aussehen — bis sie das erste Mal eine schlechte Änderung am Ausrollen hindern. Dann sind die kompletten Kosten an einem Nachmittag amortisiert. Die Kryptographie ist gut verstanden, das Tooling existiert, und Ed25519-Verifikation ist billig genug, dass es kein Performance-Argument dagegen gibt, sie bei jedem Bundle-Load durchzuführen.
Schwieriger ist die operative Arbeit: die zwei Signing-Rollen definieren, die richtigen Vault-Policies vor die Keys legen, einen Resigner bauen, dem man unbeaufsichtigt vertraut — und der Versuchung widerstehen, einen "Break-Glass"-Pfad einzubauen, der das ganze Modell aushebelt.
Wir veröffentlichen als nächstes die EU-AI-Act-Compliance-Checkliste — dieselbe Kontrollfläche, Artikel für Artikel gemappt, mit expliziten Verweisen darauf, welches Artefakt (signiertes Bundle, Audit-Log, Key-Rotation-Datensatz) welche Anforderung erfüllt.
Weiterlesen
- HashiCorp Vault — Transit Secrets Engine Dokumentation
- RFC 8032 — Edwards-Curve Digital Signature Algorithm (EdDSA)
- ISO/IEC 27001:2022 — Anhang A.12.4 (Logging und Überwachung)
- Verordnung (EU) 2024/1689 — Artikel 12, 15, 26
Bereit, Ihre
Unternehmensinfrastruktur abzusichern?
Vereinbaren Sie ein technisches Briefing. Kein Sales-Pitch — nur Architekten und Ihr Team.