Zum Hauptinhalt springen

Secret Encryption Key Ring

Werte von Secret-Attributen werden mit einem Key Ring verschlüsselt, den jeder Service mit Engine über seine Konfiguration erhält. Dieser Leitfaden richtet sich an den Betrieb: was der Schlüssel ist, wie er ausgeliefert wird, wie er gesichert und rotiert wird, wie bestehende Klartext-Zugangsdaten migriert werden und wie das Ergebnis überwacht wird.

Verfügbarkeit

Der Key Ring wird ab dem System-CK-Modell 2.5.0 und dem Engine-Release verwendet, das den Werttyp Secret ausliefert, zusammen mit dem Secret-Sweep der Bot Services, den octo-cli-Befehlen SecretStatus / ReprotectSecrets / DeleteSecretSweepDump und den MCP-Tools get_secret_status / start_secret_sweep.

Niemals echte Schlüssel in Tickets, Chats oder Dokumente

Alle Beispiele auf dieser Seite verwenden <base64-32-bytes> als Platzhalter. Ein Schlüssel besteht aus 32 zufälligen Bytes, Base64-kodiert (openssl rand -base64 32).

Der Schlüssel​

  • Algorithmus: AES-256-GCM mit zufälliger Nonce pro Wert.
  • Gespeicherte Form: enc:v2:<kid>:<base64url(nonce ‖ tag ‖ ciphertext)>. Der Header enc:v2:<kid>: nennt die Key-ID (kid) und wird als zusätzliche Daten authentifiziert. Tenant-ID und Entitäts-ID sind nicht enthalten, sodass Wiederherstellungen in eine umbenannte Datenbank, Tenant-Kopien und Child-Tenant-Wiederherstellungen weiter funktionieren.
  • Erster Schlüssel k1: der bestehende Instance Secret Key des Clusters (Vault instance_secret_key). Er verschlüsselt bereits secret-markierte Value Overrides und Passwörter von Helm-Repositories im älteren Format enc:v1: (ohne Key-ID). Für den Start muss kein neuer Schlüssel erzeugt werden.
  • Legacy-Schlüssel: Werte im alten Format enc:v1: werden mit LegacyV1Key entschlüsselt, also demselben Instance Secret Key.
  • Helm Value Overrides: Der Endpunkt encrypt-value des Communication Controllers liefert weiterhin enc:v1 und lehnt enc:v2-Eingaben ab. Secret-Helm-Overrides gehören in den Secret-Record-Member ValueOverride.SecretValue (System.Communication 3.41, Record-Key Path, eindeutig unter den Overrides mit SecretValue; Clients schreiben dort Klartext und rufen encrypt-value nicht mehr auf). Bestehende Einträge mit einem enc:v1-Wert in Value werden weiter ausgerollt, sind aber veraltet.

Da k1 den Instance Secret Key wiederverwendet, legt ein Leck dieses Schlüssels sowohl die alten enc:v1-Daten als auch die neuen Secrets offen. Die Key-ID im neuen Format ermöglicht den Wechsel auf einen neuen Schlüssel mit einem einzigen Re-Protect-Sweep (siehe Rotation).

Konfiguration​

Der Key Ring wird aus dem Konfigurationsabschnitt SecretEncryption von jedem Service mit Engine gebunden (Asset Repository, Communication Controller, Mesh Adapter, Bot, Identity, Platform, Report, AI und MCP Services).

KonfigurationsschlüsselUmgebungsvariableWert
SecretEncryption:Keys:<kid>OCTO_SECRETENCRYPTION__KEYS__<kid> (z. B. OCTO_SECRETENCRYPTION__KEYS__k1)Base64, 32 Bytes. Ein Eintrag pro Key-ID
SecretEncryption:ActiveKeyIdOCTO_SECRETENCRYPTION__ACTIVEKEYIDKey-ID für neue Werte, z. B. k1. Muss einen Schlüssel des Rings benennen
SecretEncryption:LegacyV1KeyOCTO_SECRETENCRYPTION__LEGACYV1KEYBase64, 32 Bytes. Entschlüsselt enc:v1:-Werte. Entfernen, sobald kein enc:v1-Wert mehr existiert
SecretEncryption:StrictModeOCTO_SECRETENCRYPTION__STRICTMODEtrue / false (Standard false). Lehnt das Lesen von Legacy-Klartext ab, siehe Strikter Modus

Hinweise:

  • Key-IDs bestehen aus 1–32 Kleinbuchstaben oder Ziffern (von den Helm-Charts erzwungen). Die Key-ID behält im Variablennamen ihre Schreibweise, weil sie die ID ist, die in den Envelope-Header geschrieben wird.
  • Ohne Key Ring startet ein Service trotzdem und beantwortet Ist-gesetzt-Abfragen (gespeicherte geschützte Werte melden dann keyMissing). Das Schreiben eines Secrets schlägt mit SecretEncryptionNotConfiguredException fehl. Clients lesen keyRingConfigured aus dem Umgebungsstatus, um Secret-Eingaben zu deaktivieren.
  • Alle Services einer Installation müssen denselben Ring verwenden. Ein Service, der eine Key-ID nicht kennt, kann damit geschriebene Werte nicht lesen: Solche Werte bleiben gespeichert, gelten als nicht gesetzt mit keyMissing: true und werden lesbar, sobald die Key-ID hinzugefügt wird (siehe Nicht lesbare Secrets).

Auslieferung​

Kubernetes: Core Services (Chart octo-mesh)​

Es ist kein neuer Wert nötig. Das Chart leitet den Ring aus dem bestehenden secrets.communicationInstanceSecretKey ab (aus Vault instance_secret_key): k1 = dieser Schlüssel, aktiver Schlüssel k1, Legacy-Schlüssel = dieser Schlüssel. Die Variablen werden in den gemeinsamen Block octo-mesh.system-env gerendert, sodass Identity, Asset Repository, Bot, Communication Controller, Platform Services und AI Services sie erhalten. Die Schlüsselwerte liegen im Backend-Secret (secretEncryptionKey-<kid>).

Für eine Rotation akzeptiert das Chart eine Überschreibung, die den abgeleiteten Ring ersetzt:

secrets:
communicationInstanceSecretKey: <base64-32-bytes> # unchanged, stays k1 and the legacy key
secretEncryptionKeys:
k1: <base64-32-bytes> # list k1 as long as it is still needed
k2: <base64-32-bytes>
secretEncryptionActiveKeyId: k2 # empty = k1

Kubernetes: vom Operator ausgerollte Workloads​

Workloads, die der Communication Operator ausrollt (Mesh Adapter und andere Adapter), erhalten den Ring nur, wenn ihr Adapter ReceivesClusterSecrets=true hat. Setzen Sie den Wert im Operator-Chart auf denselben Instance Secret Key:

operator:
clusterSecrets:
instanceSecretKey: <base64-32-bytes> # same value as the core chart; becomes k1 and the legacy key
# optional rotation override, replaces the derived ring:
secretEncryptionKeys: {}
secretEncryptionActiveKeyId: ""

Der Operator bindet diese als OPERATOR__CLUSTERSECRETS__SECRETENCRYPTIONKEYS__<kid>, OPERATOR__CLUSTERSECRETS__SECRETENCRYPTIONACTIVEKEYID und OPERATOR__CLUSTERSECRETS__SECRETENCRYPTIONLEGACYV1KEY (ClusterSecretsOptions) und injiziert sie als secrets.secretEncryption.keys.<kid>, secrets.secretEncryption.activeKeyId und secrets.secretEncryption.legacyV1Key in den Workload; das Mesh-Adapter-Chart rendert daraus die Variablen OCTO_SECRETENCRYPTION__*. Ist instanceSecretKey leer, wird kein Ring injiziert: Adapter starten, aber das Lesen oder Schreiben eines Secret-Attributs schlägt fehl.

Kubernetes: Reporting-, MCP- und AI-Charts​

Die separat paketierten Charts für Reporting (octo-mesh-reporting ≥ 0.3.0), MCP (octo-mesh-mcp ≥ 0.2.0) und AI (octo-mesh-ai ≥ 0.24.0) enthalten ebenfalls die Runtime-Engine und rendern dieselben Variablen. Setzen Sie denselben Wert wie im Core-Chart:

secrets:
communicationInstanceSecretKey: <base64-32-bytes> # same value as the octo-mesh chart; becomes k1 and the legacy key
secretEncryptionKeys: {} # optional rotation override, replaces the derived ring
secretEncryptionActiveKeyId: "" # empty = k1

Die Werte liegen im Backend-Secret des Charts. Ist der Schlüssel leer, wird nichts gerendert: Der Service startet, nur das Lesen oder Schreiben eines Secret-Attributs schlägt fehl. Das AI-Chart greift auf aiInstanceSecretKey zurück (als derselbe Wert dokumentiert).

Abdeckung

Edge-Operator-Pipelines und Services mit Engine, die über andere Charts ausgerollt werden, benötigen dieselben Variablen. Prüfen Sie jeden Service mit Engine einer Installation, bevor dort Secret-Attribute verwendet werden.

Lokale Entwicklung​

Start-Octo (octo-tools) setzt den Ring für lokal gestartete Services aus dem gemeinsamen Entwicklungsschlüssel (Get-OctoDevInstanceSecretKey): OCTO_SECRETENCRYPTION__KEYS__k1, OCTO_SECRETENCRYPTION__ACTIVEKEYID=k1 und OCTO_SECRETENCRYPTION__LEGACYV1KEY. Es entfernt jede andere OCTO_SECRETENCRYPTION__KEYS__*-Variable aus einer früheren Sitzung. Deploy-OctoOperator übergibt denselben Schlüssel als operator.clusterSecrets.instanceSecretKey, sodass Adapter im lokalen kind-Cluster lesen, was die lokalen Services geschrieben haben. Test-OctoEncryption prüft, ob der Ring vorhanden und konsistent ist. Der Entwicklungsschlüssel ist nur für die lokale Verwendung bestimmt.

Sicherung und der Provisionierungsschutz​

Geht der Schlüssel verloren, muss jeder Secret-Wert des Clusters neu eingegeben werden. Betroffen sind nur externe Zugangsdaten — es gehen keine Geschäftsdaten verloren —, aber jede Verbindung, die sie verwendet, funktioniert bis dahin nicht. Die verschlüsselten Werte des Communication Controllers (enc:v1) hängen am selben Schlüssel.

Disaster Recovery = Datenbank-Dump + Sicherung des Key Rings. Ein Dump allein stellt die Secrets nur als nicht lesbare Werte (KEY_MISSING) wieder her; zusammen mit dem Key Ring aus Vault oder Keeper sind sie wieder lesbar.

  • Bewahren Sie eine Kopie des Instance Secret Key jedes Clusters und jeder zusätzlichen Key-ID in Vault und in Keeper auf. Legen Sie den Keeper-Eintrag an, wenn der Schlüssel erzeugt wird, und prüfen Sie ihn erneut, wenn sich der Vault-Eintrag ändert. Eine Vault-Wiederherstellung allein ist keine ausreichende Sicherung.
  • Das Vault-Provisionierungs-Playbook weigert sich, einen bestehenden instance_secret_key mit einem anderen Wert zu überschreiben. Behalten Sie diesen Schutz bei. Rotieren Sie nie durch Überschreiben des Schlüssels — das macht jeden enc:v1- und enc:v2:k1-Wert auf einen Schlag unlesbar.

Rotation​

Eine Rotation ersetzt nie den Instance Secret Key; sie fügt einen neuen Schlüssel daneben hinzu.

  1. k2 hinzufügen. Einen neuen Schlüssel erzeugen, in Vault und Keeper ablegen und an jeden Service mit Engine ausliefern, während k1 aktiv bleibt (die Überschreibungen in Core- und Operator-Chart listen k1 und k2, secretEncryptionActiveKeyId: k1). Prüfen, ob alle Services mit beiden Schlüsseln neu gestartet sind.
  2. Aktiven Schlüssel wechseln. secretEncryptionActiveKeyId: k2 in beiden Charts setzen und ausrollen. Neue Werte werden als enc:v2:k2: geschrieben; k1-Werte lassen sich weiter entschlüsseln.
  3. Re-Protect. Den Reprotect-Sweep über alle Tenants ausführen (octo-cli -c ReprotectSecrets -a -y -w), danach mit octo-cli -c SecretStatus -a prüfen, bis kein Tenant mehr einen Wert mit kid=k1 meldet (octo.secrets.values{kid="k1"} = 0).
  4. k1 entfernen. k1 aus beiden Überschreibungen entfernen und ausrollen. Die Wiederherstellung eines Dumps von vor der Rotation bringt k1-Werte zurück — behalten Sie k1, bis keine solche Wiederherstellung mehr zu erwarten ist.
  5. LegacyV1Key entfernen, erst wenn ein Verify-Sweep zeigt, dass kein enc:v1-Wert mehr existiert, und keine andere Komponente (etwa die eigenen enc:v1-Daten des Communication Controllers) mehr davon abhängt.
warnung

Rollen Sie Schritt 2 nie aus, bevor Schritt 1 jeden Service mit Engine erreicht hat, einschließlich der vom Operator ausgerollten Workloads. Ein Service, der k2 nicht kennt, kann damit geschriebene Werte nicht lesen.

Sweep​

Der Sweep durchläuft alle Secret-Attribute eines Tenants und meldet Anzahlen pro gespeicherter Form (notSet, placeholder (Legacy-Klartext-Platzhalter), plaintext, encV1, encV2 pro Key-ID, unknownKeyId pro Key-ID, failed) — gesamt und pro CK-Typ und Attributpfad — sowie die Liste der nicht lesbaren Werte (Key-ID nicht im Ring) als Neueingabe-Aufgaben. Er läuft pro Tenant, einschließlich des System-Tenants und der Child-Tenants, und wird von den Bot Services ausgeführt.

ModusWirkungBestätigung
VerifyNur lesend. Meldet Anzahlen pro Form und Key-ID und die nicht lesbaren Werte—
EncryptVerschlüsselt Klartext- und enc:v1-Werte mit dem aktiven Schlüssel (enc:v2:<aktive kid>). Legacy-Klartextwerte, die exakt ein Platzhalter sind (TODO_SET_<UPPER_SNAKE> oder ein einzelnes <…>), werden einmalig auf „nicht gesetzt“ umgestellt (placeholdersNormalized). Nicht lesbare Werte werden gemeldet, nie gelöschtErforderlich
ReprotectVerschlüsselt jeden Wert neu, dessen Key-ID nicht der aktive Schlüssel ist (nach einer Rotation oder nach dem Hinzufügen eines Quellschlüssels für einen Restore). Nur CLI / Betrieb, nicht im Studio angebotenErforderlich
CleanupUnreadableEntfernt Werte, deren Key-ID der Ring nicht kennt, und listet sie in cleared[]. Unumkehrbar, außer über den Pre-Sweep-Dump. enc:v1-Werte, die nur deshalb nicht lesbar sind, weil LegacyV1Key nicht konfiguriert ist, bleiben erhalten (stattdessen den Legacy-Schlüssel konfigurieren) und stehen weiter in unreadable[]. Erfordert die Rolle SecretManagementErforderlich

Keine API (Bot, octo-cli, MCP) bietet einen Entschlüsselungs- oder Klartext-Exportmodus; eine Decrypt-Anfrage wird mit 400 abgelehnt. Siehe Rollback.

Jeder schreibende Sweep (Encrypt, Reprotect, CleanupUnreadable) erstellt zuerst einen frischen Dump des Tenants (ausgenommen der Encrypt-Schritt nach einer Wiederherstellung, dessen Ausgangszustand das wiederhergestellte Backup selbst ist). Gelingt das nicht, wird der Tenant mit dem Grund im Bericht übersprungen. Diese Dumps enthalten die Secrets im Zustand vor dem Sweep (eventuell Klartext): Sie liegen in einem eigenen Verzeichnis, sind nie herunterladbar (kein Endpunkt), erscheinen mit ihrem Zustand in der Liste der Sweep-Läufe und werden nach BackupRetentionDays (7 Tage) gelöscht oder früher von einem Benutzer mit SecretManagement.

Bot-Konfiguration​

Abschnitt Bot:SecretSweep der Bot Services (Umgebungsvariablen OCTO_BOT__SECRETSWEEP__*). Der Key Ring selbst ist der Engine-Abschnitt SecretEncryption oben.

SchlüsselStandardBedeutung
VerifyCron0 3 * * *Cron (UTC) des wiederkehrenden Verify-Sweeps über alle Tenants. Leer deaktiviert ihn
RequirePreSweepBackuptrueVor jedem schreibenden Sweep einen Tenant-Dump erstellen; scheitert das, wird der Tenant übersprungen. Nur bewusst auf false setzen (z. B. lokal ohne MongoDB-Database-Tools)
BackupStoragePath<temp>/octo-bot/secret-backupsVerzeichnis der Dumps vor dem Sweep. Darf nicht in den tus- oder Dump-Verzeichnissen liegen; in Kubernetes ein persistentes Volume verwenden
BackupRetentionDays7Tage, die ein Dump aufbewahrt wird, bevor die stündliche Bereinigung ihn löscht
BatchSize500Pro Repository-Aufruf gelesene Entitäten
RunAfterRestoretrueDie Secret-Schritte nach einer Repository-Wiederherstellung ausführen (siehe Wiederherstellung über Umgebungen hinweg)
StrictModeSinceleerBeginn des strikten Modus für diese Umgebung (UTC, z. B. 2026-11-15T00:00:00Z). Ab dann protokolliert jeder Sweep, der noch Legacy-Werte findet, einen Fehler und meldet den Tenant in octo.secrets.strict_mode.violations

Bot-Endpunkte​

EndpunktRolleAntwortSDK (IBotServicesClient)
GET {tenantId}/v1/secrets/statusJeder Benutzer mit Tenant-ZugriffSecretEnvironmentStatusDtoGetSecretEnvironmentStatusAsync
POST {tenantId}/v1/jobs/secret-sweep?mode=Verify|Encrypt|Reprotect|CleanupUnreadable&confirm=trueSecretManagementJobResponseDto { id }; 400 ConfirmationRequired für einen schreibenden Modus ohne confirm=true; 400 für DecryptStartSecretSweepAsync(tenantId, mode, confirm)
GET {tenantId}/v1/jobs/secret-sweep/reportAdminPanelManagementLetzter Bericht des Tenants; 404, wenn keiner existiertGetSecretSweepReportAsync
GET {tenantId}/v1/secrets/sweep-runs?limit=20AdminPanelManagementSecretSweepRunDto[], neueste zuerst (die letzten 50 pro Tenant werden aufbewahrt)GetSecretSweepRunsAsync
DELETE {tenantId}/v1/secrets/sweep-runs/{runId}/dumpSecretManagement204; 404 unbekannter Lauf oder kein Dump; 409 Dump bereits gelöschtDeleteSecretSweepDumpAsync
POST system/v1/secrets/sweep?mode=…Admins des System-TenantsJobResponseDto (alle Tenants)StartSecretSweepAllTenantsAsync
GET system/v1/secrets/reportsAdmins des System-TenantsLetzter Bericht jedes TenantsGetSecretSweepReportsAsync

Eine fehlende Rolle wird mit 403 beantwortet. Job-Status: GET system/v1/jobs?id=…. Enums werden als Namen serialisiert, JSON in camelCase.

Umgebungsstatus (SecretEnvironmentStatusDto, bis auf lastVerifyAt in jedem Tenant gleich):

{
"keyRingConfigured": true, // false: Secret-Schreibvorgänge scheitern mit SecretEncryptionNotConfigured
"activeKeyId": "k1", // null, wenn nicht konfiguriert
"knownKeyIds": ["k1"],
"legacyV1KeyConfigured": true,
"strictMode": false,
"strictModeSince": null, // ISO-8601, wenn der strikte Modus geplant oder aktiv ist
"recurringVerifyCron": "0 3 * * *", // null, wenn deaktiviert
"lastVerifyAt": "2026-10-06T03:00:12Z", // letzter Verify-Lauf dieses Tenants, null, wenn keiner
"warnings": [] // "NoKeyRing", "NoLegacyV1Key" (siehe unten)
}

warnings enthält Codes: NoKeyRing, wenn kein Schlüsselring konfiguriert ist (keyRingConfigured: false; Studio zeigt ein deutlich sichtbares Banner, Secret-Eingaben sind deaktiviert, Encrypt wird übersprungen), und NoLegacyV1Key, wenn der letzte abgeschlossene Sweep des Tenants enc:v1-Werte gefunden hat, LegacyV1Key aber nicht konfiguriert ist.

Sweep-Lauf (SecretSweepRunDto):

{
"runId": "<job id>",
"mode": "Encrypt", // Verify | Encrypt | Reprotect | CleanupUnreadable
"trigger": "Manual", // Manual | Recurring | Restore
"outcome": "Succeeded", // Succeeded | CompletedWithFailures | Skipped | Failed | Running
"startedAt": "…", "completedAt": "…",
"triggeredBy": "Benutzername oder null",
"totals": { /* Anzahlen pro Form wie im Bericht */ },
"placeholdersNormalized": 0,
"unreadableCount": 0,
"dump": { // null für Verify (kein Dump)
"fileName": "…presweep.tar.gz",
"exists": true,
"sizeBytes": 123456,
"createdAt": "…",
"expiresAt": "…", // createdAt + 7 Tage
"deletedAt": null, // gesetzt, wenn vorzeitig gelöscht oder abgelaufen
"deletedBy": null
}
}

Bericht (SecretSweepReport): tenantId, mode, trigger, outcome, reason, startedAt, completedAt, backupFileName, activeKeyId, strictModeActive, strictModeViolation, remainingLegacyValues, placeholdersNormalized, steps[] (pro Schritt: totals, slots[], cleared[], failures[]), unreadable[] (ckTypeId, rtId, attributePath, keyId — die Neueingabe-Liste) und cleared[] (nur von CleanupUnreadable befüllt). Er enthält nie Werte.

octo-cli-Befehle​

Die generierte Befehlsreferenz enthält die vollständige Hilfe.

SecretStatus — gibt den Umgebungsstatus aus (Key Ring konfiguriert, aktive Key-ID, bekannte Key-IDs, Legacy-v1-Schlüssel, strikter Modus und seit wann, Cron des wiederkehrenden Verify, letzter Verify), die letzten 10 Sweep-Läufe mit ihrem Dump-Zustand (vorhanden, Größe, Ablauf, gelöscht) und den letzten Sweep-Bericht: Anzahlen pro Form und Key-ID, eine Tabelle pro CK-Typ und Attributpfad, Strict-Mode-Kennzeichen, placeholdersNormalized und die nicht lesbaren, neu einzugebenden Werte. Gibt nie Werte aus.

ArgumentErforderlichBeschreibung
-tid, --tenantIdNeinTenant, über den berichtet wird (Standard: Tenant des Kontexts)
-a, --allNeinEine Zeile pro Tenant (System-API, gegen den System-Tenant ausführen). Nicht zusammen mit -tid
-j, --jsonNeinJSON-Ausgabe: { environment, recentRuns, report } für einen Tenant, mit -a die rohen Berichte
octo-cli -c SecretStatus -tid "mytenant"
octo-cli -c SecretStatus -a

ReprotectSecrets — startet einen Sweep-Job und gibt die Job-ID aus.

ArgumentErforderlichBeschreibung
-tid, --tenantIdNeinZu bearbeitender Tenant (Standard: Tenant des Kontexts)
-a, --allNeinAlle Tenants (System-Endpunkt system/v1/secrets/sweep). Nicht zusammen mit -tid
-m, --modeNeinReprotect (Standard), Encrypt, CleanupUnreadable oder Verify. Decrypt wird abgelehnt
-y, --yesNeinBestätigt einen schreibenden Modus. Verify braucht keine Bestätigung; Reprotect und Encrypt fragen interaktiv nach, sofern -y fehlt; CleanupUnreadable wird ohne -y abgelehnt (keine Abfrage). Nach der Bestätigung sendet die CLI confirm=true an den Bot
-w, --waitNeinAuf den Job warten und den Bericht ausgeben
# after switching the active key
octo-cli -c ReprotectSecrets -tid "mytenant" -w

# fresh status of one tenant (read-only, no confirmation)
octo-cli -c ReprotectSecrets -tid "mytenant" -m Verify -w

# encrypt remaining legacy values in all tenants (CI/CD)
octo-cli -c ReprotectSecrets -a -m Encrypt -y

# remove values whose key id is unknown (irreversible except via the pre-sweep dump)
octo-cli -c ReprotectSecrets -tid "mytenant" -m CleanupUnreadable -y -w

DeleteSecretSweepDump — löscht den Pre-Sweep-Dump eines Sweep-Laufs vor seinem Ablauf (Rolle SecretManagement).

ArgumentErforderlichBeschreibung
-tid, --tenantIdNeinTenant des Laufs (Standard: Tenant des Kontexts)
-r, --runIdJaLauf-ID, wie von SecretStatus aufgeführt
-y, --yesNeinBestätigungsabfrage überspringen

Ein unbekannter Lauf oder ein Lauf ohne Dump ist ein Fehler; ein bereits gelöschter Dump erzeugt nur eine Warnung.

octo-cli -c DeleteSecretSweepDump -tid "mytenant" -r "1234" -y

MCP-Tools​

  • get_secret_status (niedriges Risiko) — allTenants (Standard false), tenantId. Liefert den Umgebungsstatus, die 10 letzten Sweep-Läufe mit ihrem Dump-Zustand, den/die letzten Bericht(e) mit den nicht lesbaren Werten und eine kompakte Zusammenfassung pro Tenant.
  • start_secret_sweep (hohes Risiko) — mode (Verify Standard, Encrypt, Reprotect, CleanupUnreadable), allTenants, confirm (Pflicht für Encrypt, Reprotect und CleanupUnreadable; wird an den Server weitergegeben), waitForCompletion, waitTimeoutMinutes (Standard 30), tenantId. Decrypt wird abgelehnt.
  • Die Secrets-Übersicht (Inventar) ist über die GraphQL-Abfrage secrets { inventory … } des Asset Repository verfügbar; ein MCP-Tool dafür ist geplant.

Strikter Modus​

Der strikte Modus ist Phase 5 der Migration und wird pro Umgebung 14 Tage nach der Meldung von null Klartextwerten aktiviert:

  • Services mit Engine: SecretEncryption:StrictMode=true. Das Lesen eines Secret-Werts, der noch Klartext ist, schlägt fehl (LegacyPlaintextSecretRejectedException) und erhöht octo.secrets.strict_mode.rejected_reads. enc:v1 bleibt lesbar, solange LegacyV1Key konfiguriert ist. Der Encrypt-/Reprotect-Sweep und der Schreibpfad wandeln verbleibenden Klartext weiterhin um.
  • Bot Services: Bot:SecretSweep:StrictModeSince=<Datum>. Sweeps, die noch Legacy-Werte finden (Klartext oder enc:v1), melden den Tenant im Gauge octo.secrets.strict_mode.violations{tenant} und setzen strictModeViolation im Bericht.

Migration bestehender Zugangsdaten​

Zugangsdaten-Attribute, die noch String sind, werden in Phasen auf Secret umgestellt. Jede Umgebung durchläuft die Phasen in der Reihenfolge lokal → Test → Staging → Produktion und geht erst weiter, wenn der Sweep null Klartextwerte meldet.

PhaseInhalt
0Zugangsdaten rotieren, die in die Versionskontrolle eingecheckt wurden, und durch leere Werte ersetzen
1Engine-Release mit dem Werttyp Secret, Key Ring (k1 = Instance Secret Key), Legacy-Lesen, Schreibregeln, Sweep, System-2.5-Gate. Key Ring an jeden Service mit Engine ausliefern
2Konsumenten verarbeiten Chiffretext vor jeder Modelländerung: Der Communication Controller entschlüsselt Secrets für die Adapter-Konfiguration, der Mesh Adapter verarbeitet Secret-Attribute und bietet RevealSecret@1, Studio und andere Clients selektieren keine Secret-Werte mehr. Alle Clients laufen mit der neuen Engine
3Modelländerungen (Minor): Zugangsdaten-Attribute werden valueType: Secret. Ab hier projiziert nichts mehr den Wert, auch wenn er noch als Klartext gespeichert ist
4Sweep: einmal Encrypt über alle Tenants (ReprotectSecrets -a -m Encrypt), danach der wiederkehrende Verify (VerifyCron). Jeder schreibende Lauf beginnt mit einem frischen Tenant-Dump (7 Tage aufbewahrt). Adapter-Service-Accounts wechseln auf Impersonation mit einem Adapter-Zugang auf Installationsebene (Folgearbeit AB#5551); ihre gespeicherten Secrets werden gelöscht
5Strikter Modus, 14 Tage nachdem der Sweep null Klartextwerte gemeldet hat: Legacy-Klartext ist nicht mehr lesbar
6Rotation von Zugangsdaten, die vor der Migration offengelegt waren

Gates:

  • Phase 2 vor Phase 3. Clients, die ein Secret noch als String selektieren, brechen bei der Modelländerung. Der Code aus Phase 2 muss ein Release vor Phase 4 ausgeliefert worden sein.
  • Der strikte Modus wird pro Umgebung 14 Tage nach der Meldung von null Klartextwerten aktiviert.
  • Dumps vor dem Sweep werden 7 Tage aufbewahrt, als Secret-Material behandelt und danach gelöscht.
  • Pipelines, die Zugangsdaten mit GetRtEntities* lesen, erhalten nach Phase 3 nur noch eine Ist-gesetzt-Markierung; stellen Sie sie in Phase 2 auf RevealSecret@1 um.
  • Die Adapter-Konfiguration wird bis zum nächsten Deployment zwischengespeichert: Nach dem Ändern eines Secrets den Data Flow neu ausrollen (außer dort, wo RevealSecret@1 den Wert bei Bedarf liest).

Rollback​

Die Phasen 1–3 betreffen nur Code und lassen sich mit den Binaries zurückrollen. Nach Phase 4 können ältere Binaries die verschlüsselten Werte nicht lesen. Der Notfallweg ist dann eine Engine-interne Entschlüsselung mit dem Schlüssel, kein Binary-Rollback. Keine API (Bot-Endpunkte, octo-cli, MCP) bietet Entschlüsselung oder einen Klartext-Export an: Es ist eine Operation auf Engine-Ebene (ISecretMaintenanceService mit ausdrücklicher Entschlüsselungsbestätigung), die als geplante Notfalländerung ausgeführt werden muss.

Wiederherstellung über Umgebungen hinweg​

Dumps behalten ihr Format und enthalten nach Phase 4 die verschlüsselten Werte. Eine Wiederherstellung behält den Chiffretext: Nichts wird entschlüsselt oder gelöscht. Mit Bot:SecretSweep:RunAfterRestore=true (Standard) führt jede Repository-Wiederherstellung diese Schritte auf dem wiederhergestellten Tenant aus und speichert das Ergebnis als Bericht mit dem Trigger Restore:

  1. Verify — zählt die Formen im wiederhergestellten Zustand.
  2. Encrypt — wandelt Klartext- und enc:v1-Werte aus älteren Dumps auf den aktiven Schlüssel um. Es wird kein zusätzlicher Dump erstellt: Das hochgeladene, wiederhergestellte Backup ist der Zustand vor dem Sweep.
  3. Verify — die abschließenden Anzahlen und die Liste der nicht lesbaren Werte.

Werte, deren Key-ID nicht im Ziel-Ring ist, bleiben verschlüsselt mit der Form KEY_MISSING gespeichert: Sie gelten als isSet: false, keyMissing: true, erscheinen in unreadable[] des Berichts und in der Secrets-Übersicht als Neueingabe-Aufgaben und werden automatisch lesbar, wenn die Key-ID dem Ring hinzugefügt wird.

  • Gleiche Umgebung: nichts zu tun; die Schritte finden keine unbekannte Key-ID.
  • Bot ohne Schlüsselring: Es läuft nur ein schlüsselfreies Verify. Es klassifiziert ohne zu entschlüsseln: Jeder enc:v2-Wert (seine Key-ID ist nicht im leeren Ring) und jeder enc:v1-Wert, solange kein LegacyV1Key konfiguriert ist (Key-ID enc:v1), gilt als „Schlüssel fehlt“ und steht zur Neueingabe in unreadable[]; Klartext bleibt Klartext. Es wird nichts geschrieben. Der Lauf endet mit Succeeded und dem Grund „No key ring configured: secrets were classified only; set the key ring and run Encrypt“ — Schlüsselring konfigurieren, danach Encrypt ausführen.
  • Andere Umgebung, Tenant-Kopie, Child-Tenant-Wiederherstellung (Standard): Die Secrets kommen nicht lesbar an und werden neu eingegeben (Studio, API, set_entity_secrets). Prüfen Sie octo-cli -c SecretStatus -tid <tenant> oder secrets { inventory(needsReEntry: true) }. Ist alles neu eingegeben, lassen sich die verbleibenden nicht lesbaren Werte mit dem Admin-Sweep CleanupUnreadable entfernen (octo-cli -c ReprotectSecrets -tid <tenant> -m CleanupUnreadable -y; vorher wird ein Pre-Sweep-Dump erstellt).
  • Optionaler Betriebsschritt statt Neueingabe: Den Schlüssel der Quellumgebung vorübergehend in den Ziel-Ring aufnehmen (an jeden Service mit Engine ausgeliefert, nicht aktiv), wiederherstellen, Reprotect ausführen (octo-cli -c ReprotectSecrets -tid <tenant> -y -w), damit die Werte auf den aktiven Schlüssel wechseln, mit SecretStatus prüfen, bis kein Wert mit der Quell-Key-ID mehr übrig ist, und den Quellschlüssel danach wieder aus dem Ring entfernen.

Siehe auch Repository-Backup & -Wiederherstellung.

Monitoring​

Die Metriken werden auf dem Meter Meshmakers.Octo.Secrets ausgegeben. Keine davon enthält einen Wert.

MetrikTypLabelsBedeutung
octo.secrets.decryptCountertenant, ckType, attribute, service, formJede serverseitige Entschlüsselung (Adapter-Konfiguration, RevealSecret@1)
octo.secrets.plaintext_readsCountertenant, ckType, attribute, service, formEin Legacy-Klartextwert wurde aus einem Secret-Attribut gelesen. Muss nach dem Sweep bei 0 bleiben
octo.secrets.envelope_not_allowedCountertenant, ckType, attribute, serviceEin enc:v2-Envelope, der als einfacher String in einem Secret-Slot gespeichert war, wurde abgelehnt statt entschlüsselt. Nichts Legitimes erzeugt so etwas — jeden Zählerstand untersuchen
octo.secrets.strict_mode.rejected_readsCountertenant, ckType, attribute, serviceVom strikten Modus abgelehnte Lesevorgänge von Legacy-Klartext
octo.secrets.unreadableCounterreason (unknown_key_id, corrupt, decrypt_failed), tenant, ckType, attribute, serviceEin gespeicherter Wert war nicht lesbar und wurde als nicht gesetzt behandelt (z. B. nach einem Restore aus einer anderen Umgebung)
octo.secrets.sweep.rewrittenCountertenant, mode (verify, encrypt, reprotect, cleanup_unreadable)Vom Sweep geänderte Werte
octo.secrets.sweep.failedCountertenant, modeWerte, die der Sweep nicht verarbeiten konnte
octo.secrets.valuesGaugetenant, model, form (not_set, placeholder, plaintext, enc_v1, enc_v2, unknown_kid), kidVom letzten Sweep jedes Tenants gefundene Formen (von den Bot Services gemeldet; env stammt aus der OTel-Resource)
octo.secrets.strict_mode.violationsGaugetenantVom letzten Sweep gefundene Legacy-Werte, solange StrictModeSince gilt (0 = konform)

Alerts: octo.secrets.strict_mode.violations > 0 (gleichwertig: octo.secrets.values{form="plaintext"} > 0 nach Aktivierung des strikten Modus) sowie jeder Anstieg von octo.secrets.strict_mode.rejected_reads oder octo.secrets.sweep.failed. Während einer Rotation zeigt octo.secrets.values{kid="k1"} den Fortschritt des Re-Protect-Sweeps.

Siehe auch​