Engineering

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.

Von Krasper Engineering 27. Mai 2026 9 Min. Lesezeit
Dual-Control Policy Publishing — hero

TL;DR. Wenn ein:e einzelne Engineer:in eine Policy-Änderung durchdrücken kann, die Redigierung aufweicht, einen neuen Endpunkt öffnet oder ein Modell freischaltet, ist der Governance-Proxy Theater. Echte Durchsetzung ruht auf signierten Bundles, Vier-Augen-Prinzip bei jedem Publish und Key-Rotation ohne Redeploy. HashiCorp Vault Transit übernimmt die Kryptographie und Ed25519 hält die Verifikation günstig, während ein kleines Set an Publishing-Policies beides zusammenbindet.

Ein Governance-Proxy entscheidet bei jedem 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

  1. Warum Vier-Augen-Prinzip in die Policy-Ebene gehört
  2. Anatomie eines signierten Policy-Bundles
  3. Vault Transit als Signing-Oracle
  4. Der Publish-Workflow von Anfang bis Ende
  5. Verifikation auf Proxy-Ebene
  6. Key-Rotation und das Resigner-Pattern
  7. 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, ein 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. Ein Bundle lädt nur, wenn es eine gültige Signatur von einem Key trägt, dem der Proxy bereits vertraut; eine fehlende Signatur, eine falsche oder eine gültige von einem unbekannten Key lassen es allesamt liegen.

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.

text
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
Deterministisches Bundle-Layout
Inputs
policies/
  • redaction.json: PII-Regeln, Fail-Closed-Defaults
  • routing.json: Modelle + Endpoints pro Mandant
  • content.json: gesperrte Kategorien, Output-Grenzen
Kanonisierung
checksums.txt
SHA-256 jeder Datei, sortiert nach Pfad. Genau diese Bytes signieren die Signer.
Vier-Augen-Prinzip
signatures/
  • primary.sig: Ed25519, Policy-Lead-Identität
  • secondary.sig: Ed25519, Security-Review-Identität
  • Beide erforderlich. Unterschiedliche Menschen, unterschiedliche Vault-Keys.
Deterministisches Archiv
Policy-Bundle
Versioniertes, maschinenlesbares Artefakt, das jeder Proxy lädt.

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.

Die Vier-Augen-Fläche ist genau das: zwei Signaturen, erzeugt von zwei verschiedenen Keys, die zwei verschiedene Menschen halten.

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-Rolle
  • policy-bundle-secondary, gehalten von der Security-Review-Rolle

Beide Keys sind Ed25519 und nicht-exportierbar, und 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:

bash
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
Vault-Transit-Sign-Call (Primary-Key)

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 das Vier-Augen-Prinzip von einer Frage der Teamkonvention zu einer durchgesetzten Eigenschaft des Systems: Eine einzelne Person kann nicht beide Signaturen erzeugen, weil keine einzelne Identität die Vault-Berechtigungen für beide Signing-Endpoints besitzt.

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:

AUTOR:IN REVIEWER VAULT TRANSIT DISTRIBUTOR PROXY-FLOTTE Draft-PR öffnen Kandidaten-Bundle bauen Review + Signatur anfordern Dry-Eval auf Korpus sign(primary) Ed25519/v3 sign(secondary) Ed25519/v2 doppelt signiertes Bundle publishen per Content-Hash verteilen beide Signaturen verifizieren Ed25519 × 2 atomarer Policy-Swap fail-closed wenn Verify fehlschlägt

Konkret:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Distributor publisht das doppelt signierte Bundle in den Artifact-Store unter einem inhaltsadressierten Pfad: bundles/<sha256>.tar.gz. Die Flotte zieht von dort.
  6. 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.

Niemand kann die eigene Änderung genehmigen, und Reviewer:in kann ohne die Primary-Signatur der Autor:in nicht publishen. Der Distributor wiederum akzeptiert nur Bundles, deren Signaturen beide unter dem aktuellen Public-Key-Set verifizieren. Jedes Gate ist ein harter kryptographischer Check und keine bloße UI-Funktion.

5. Verifikation auf Proxy-Ebene

Der Proxy hält ein kleines, versions-gepintes Set an Public-Keys in seiner Konfiguration:

json
{
  "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 }
}
trusted_signers-Konfiguration auf dem Proxy

Die Verifikationsroutine, in einfachen Schritten:

  1. Archiv in ein Scratch-Verzeichnis entpacken.
  2. checksums.txt aus den entpackten Dateien in sortierter Reihenfolge regenerieren.
  3. Mit SHA-256 hashen.
  4. Für jede .sig-Datei den eingebetteten Key-Namen und die Version lesen, in trusted_signers nachschlagen, bei Fehlen fail-closed.
  5. Ed25519-Signatur gegen den regenerierten Hash verifizieren.
  6. Ist require_both gesetzt, müssen beide verifizieren. Sonst Ablehnung.

Ed25519 wurde wegen seiner Verifikationskosten gewählt. Eine einzelne Signaturverifikation läuft im Sub-Millisekundenbereich auf Commodity-Hardware, billig genug, um sie bei jedem Bundle-Reload, beim Health-Check des Proxys und in einer Startup-Probe laufen zu lassen, 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:

bash
vault write -f transit/keys/policy-bundle-primary/rotate
Primary-Signing-Key rotieren

Schmerzhaft ist, was mit bereits deployten Bundles passiert, die mit der alten Key-Version signiert sind. Zwei Optionen:

  1. Ein Re-Publish jedes Bundles, jedes Mandanten, bei jeder Rotation erzwingen. Laut, disruptiv, und beim nächsten Mal verlockend zu überspringen.
  2. 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.

Schritt 01
T+0h
Primary-Key rotieren
  • 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

Schritt 02
T+0–48h
Deployte Bundles neu signieren
  • 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

Schritt 03
T+72h
v_old außer Dienst nehmen
  • 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:

  1. Wer hat diese Änderung autorisiert, und wie belegen Sie das?
  2. Kann die Änderung nach Autorisierung manipuliert worden sein?
  3. Können Sie rekonstruieren, welche Policy zum Zeitpunkt einer beliebigen vergangenen Entscheidung aktiv war?

Signierte Bundles beantworten alle drei:

  • Wer autorisiert hat, beantworten 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, und das Signing-Event zeichnet Zeitstempel, Key-Version und Input-Hash auf.
  • Manipulationsresistenz ergibt sich daraus, dass jede Änderung an einer beliebigen Datei im Bundle checksums.txt verändert, was beide Signaturen invalidiert, sodass der Proxy sich weigert, es zu laden.
  • Historische Rekonstruktion kommt aus dem Feld policy_bundle_sha256, das jeder Request im Audit-Log tragen kann. Referenzieren Sie diesen Hash gegen den Artifact-Store, 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 auf die Signing-Events und diese auf die menschlichen Identitäten dahinter, sodass die Spur auf Aufzeichnungen ruht statt auf verbalen Zusicherungen.

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, und an diesem Punkt hat sie sich mehr oder weniger selbst bezahlt. 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.

Verwandt
Wo wir diese Arbeit leisten
Beratung

Regulatorisches Scoping, Threat Modelling und Zero-Trust-Architektur für Unternehmensgruppen in den Emiraten. Cyber security consulting in Dubai.

Governance

Ein Control-Set, abgebildet auf jedes Rahmenwerk, das Sie bindet, samt der Evidenz-Pipeline dahinter. IT security governance in the UAE.

Audit

Gap-Assessment Control für Control, belegt Feststellung für Feststellung. Information security audit in Dubai.