Darkwood Blog Blog
  • Artikel
  • Beobachtung
  • Releases
  • Creators
de
  • en
  • fr
Anmeldung
  • Blog
  • Artikel
  • Beobachtung
  • Releases
  • Creators

🔑 Geheime Schlüssel werden zu Anwendungsdaten

vom 20. September 2026

Anmelden um auf diesen Beitrag zu reagieren

🚀 1

🔑 Geheime Schlüssel werden zu Anwendungsdaten

Die meisten Symfony-Anwendungen, die ich schreibe, behandeln den Modellschlüssel nach wie vor als Teil der Infrastruktur:

ANTHROPIC_API_KEY=...

Diese Zeile ist einfach, weil die Zuständigkeit klar ist. Die Anmeldedaten gehören zur Bereitstellung. Die Betreiber speichern sie in .env.local oder einem Secrets-Tresor. Der Container injiziert sie einmalig beim Start. Die Anwendung muss sie niemals akzeptieren, speichern oder entscheiden, wann sie im Speicher verbleiben darf.

„Bring-your-own-key“ ändert die Eigentumsverhältnisse.

Was passiert, wenn der Schlüssel stattdessen dem Benutzer gehört?

Er wird über HTTP übermittelt. Er ist an eine Anwendungsentität gebunden. Er muss über mehrere Anfragen hinweg erhalten bleiben. Er darf nicht im Klartext gespeichert, nicht in HTML wieder eingebettet und nur dann entschlüsselt werden, wenn tatsächlich ein Anbieter aufgerufen werden muss. Dieser Anbieter kann Geld ausgeben.

.env ist nicht mehr die Lösung. Die Anmeldedaten sind zu Anwendungsdaten geworden.

Das Experiment dieser Woche, navi-key-management, ist eine kleine Symfony-8.2-App, die diesen Lebenszyklus implementiert und anschließend misst. Ich berichte hier über den Lauf vom 19.09.2026: PHP 8.5.4, Symfony 8.2.x-dev, SQLite, lokales Sodium. Symfony KeyManagement ist experimentell. Das geht aus den installierten Docblocks hervor. Betrachten Sie jede Angabe hier als Momentaufnahme und nicht als Versprechen hinsichtlich der stabilen Version 8.2.

BYOK verändert die Abgrenzung

Der von mir programmierte Pfad entspricht dem, den ich lesen wollte:

Benutzer
  ↓
Symfony-Formular
  ↓
Verschlüsselung durch KeyManagement
  ↓
Chiffretext in SQLite
  ↓
Entschlüsselung zur Laufzeit
  ↓
Darkwood Navi
  ↓
Symfony AI
  ↓
Anthropic / Provider

Jeder Pfeil steht für eine andere Art von Aufgabe. Das Formular weiß nicht, wie eine Chat-Anfrage aufgebaut ist. Navi speichert keine Geheimnisse dauerhaft. Symfony AI ist nicht Eigentümer der Datenbankzeile. KeyManagement kommuniziert nicht mit Claude.

Ich habe weder eine Repository-Schicht noch ein zweites KI-SDK hinzugefügt. Die interessanten Abstraktionen waren bereits im Stack vorhanden. Eine davon war leicht falsch zu benennen.

darkwood/navi ist die Workflow-Shell: Action, Context, WorkflowRunner, Event. Es verfügt weder über einen Anthropic-Client noch über einen Typ für einen API-Schlüssel. Symfony AI ist das, was mit dem Modell kommuniziert. Die Ausführungskette in diesem Repository lautet:

AiConnection
    ↓
CredentialProtector::decrypt()
    ↓
WorkflowRunner
    ↓
TestAiConnectionAction
    ↓
Anthropic\Factory::createPlatform($apiKey)
    ↓
provider

Navi koordiniert einen Schritt. Es ersetzt Symfony AI nicht.

Es gab ein Problem bei der Paketierung, das in diese Geschichte gehört, da es tatsächlich existiert. Das Packagist-Paket darkwood/navi ^1.0 erfordert weiterhin Symfony 8.0. Diese App benötigt 8.2.x-dev, daher ist Navi ein Pfad-Repository zum lokalen Monorepo (8.1.x-dev). Das Experimentieren vor der Veröffentlichung sieht so aus: ein Symlink, kein Slogan.

Symfony erhält eine Schlüsselverwaltungs-Primitive

Sobald der Schlüssel Anwendungsdaten sind, ist das erste fehlende Teil nicht ein weiterer AI-Wrapper. Es ist eine Möglichkeit, ein kleines Geheimnis zu verschlüsseln, ohne einen Krypto-Dienst erfinden zu müssen.

Symfony 8.2 KeyManagement ist diese Funktion. Ich habe symfony/key-management und symfony/aws-key-management in 8.2.x-dev installiert und die Schnittstellen verwendet, die der Container tatsächlich automatisch zuordnet:

$ciphertext = $this->encrypter->encrypt($this->keyId, $apiKey);
$connection->setCiphertextBlob(base64_encode($ciphertext->blob));
$connection->setKmsKeyId($ciphertext->keyId);

encrypt() gibt einen Ciphertext zurück, keinen String. Die Zeile hält den Blob und die Schlüssel-ID zusammen. Die Anwendung injiziert EncrypterInterface und DecrypterInterface. Die Envelope-Verschlüsselung ist im selben Bundle vorhanden. Ich habe sie nicht verwendet. Ein API-Schlüssel ist mehrere hundert Bytes groß und liegt damit deutlich unter dem 4-KB-Limit für Direct-Encrypt bei AWS KMS. Die Envelope-Verschlüsselung ist für Dateien und große Dokumente gedacht oder für eine Richtlinie, die vorschreibt, dass KMS niemals den Klartext der Anwendung sehen darf. Sie ist nicht zwingend erforderlich, da die Komponente sie bereits bereitstellt.

Die Konfiguration, bei der ich schließlich gelandet bin, ist nicht der einzeilige DSN, den ich zunächst ausprobiert habe.

key_management:
    clients:
 app: 'sodium://?keys[app-key]=%env(DEV_KMS_KEY)%'
    default_client: app

when@prod:
    key_management:
 clients:
 app: 'aws-kms://default?region=%env(AWS_KMS_REGION)%'

Ein bloßes '%env(KMS_DSN)%' lässt sich nicht kompilieren. Der experimentelle Konfigurationsbaum kennzeichnet den Client-DSN als cannotBeEmpty, und eine vollständig ersetzte Umgebungsvariable wird zur Kompilierungszeit als leer behandelt:

Der Pfad „key_management.clients.app“ darf keine Umgebungsvariable enthalten,
da leere Werte per Definition nicht zulässig sind und validiert werden.

Das Arbeitsmuster behält ein festes Schema bei – sodium:// in dev/test, aws-kms:// in prod – und ersetzt per Umgebungsvariable nur das Schlüsselmaterial oder die Region.

dev / test
    ↓
Sodium ← in diesem Repository getestet

prod
    ↓
AWS KMS ← konfiguriert, nicht aufgerufen

Sodium ist der Grund, warum das Experiment lokal reproduzierbar ist. Der Prozess verfügt über DEV_KMS_KEY. Ich habe ihn mit sodium_crypto_aead_xchacha20poly1305_ietf_keygen() und Base64UrlSafe generiert. Jeder, der diesen Umgebungswert lesen kann, kann jeden gespeicherten API-Schlüssel entschlüsseln. Das ist für eine Laptop-Demo akzeptabel. In der Produktion ist dies jedoch nicht der Fall.

AWS KMS ist die externe Grenze, auf die der Produktions-DSN verweist. Die AWS-Brücke verschlüsselt serverseitig; der Hauptschlüssel soll in KMS verbleiben. Ich habe keine Anfrage an AWS gesendet. Der Produktionsblock ist eine Konfiguration, kein Testergebnis.

Das UI-Symbol wertet den DSN nicht aus. KMS_BACKEND ist eine Bezeichnung (Sodium oder AWS KMS), sodass Schlüsselmaterial niemals zu einer Twig-Variablen wird.

Der in der experimentellen .env-Datei festgeschriebene Entwicklungsschlüssel ist ausschließlich ein Entwicklungsschlüssel. Generieren Sie einen privaten Sodium-Schlüssel, bevor Sie das Muster für echte Zwecke verwenden.

Ein kleines Experiment

Das Modell besteht aus einer Entität, AiConnection: Label, Anbieter, Modell, optionaler Endpunkt, ciphertextBlob, kmsKeyId, Zeitstempel. Es gibt keine Spalte für API-Schlüssel im Klartext.

Die Benutzeroberfläche besteht aus vier Routen und einem dunklen Panel. Sie dient dazu, den Lebenszyklus sichtbar zu machen: eine Liste mit den Badges „verschlüsselt“ und „Backend“, ein Formular, eine Testaktion, eine Ergebnisseite. Es handelt sich nicht um ein Dashboard-Produkt.

GET /
GET|POST   /connections/new
GET|POST   /connections/{id}/edit
POST /connections/{id}/test

Das ist die gesamte Anwendungsoberfläche.

Das Formular ist nun eine Sicherheitsgrenze

Der Schlüssel wurde bisher über dotenv in den Prozess eingegeben. Nun erfolgt die Eingabe über ein Formular. Dadurch wird das Formular Teil des Sicherheitskonzepts und ist nicht mehr nur eine „Hülle“ um ein DTO.

Symfony 8.2 kann den Formulartyp aus der Klasse ableiten, die die Daten enthält. Dieses DTO umfasst fünf Felder. Genau dafür sind die neuen Attribute vorgesehen.

#[AsFormType]
final class AiConnectionInput
{
    #[FormField(ChoiceType::class, [
 'choices' => [
 'Anthropic' => 'anthropic',
 'OpenAI' => 'openai',
 ],
    ])]
    public string $provider = 'anthropic';

 #[FormField(PasswordType::class, [
 'always_empty' => true,
 'attr' => ['autocomplete' => 'new-password'],
    ])]
    #[Assert\NotBlank(groups: ['create'])]
    public ?string $apiKey = null;
}

createForm(AiConnectionInput::class, $input) reicht aus. Es gibt keinen AbstractType. Der kompilierte Name lautet ai_connection_input.

Das von mir gewünschte Sicherheitsverhalten ist in den Attributen und dem Controller zusammen implementiert. Das Feld „key“ ist ein Passwortfeld. always_empty verhindert, dass der Browser einen Wert anzeigt. Beim Bearbeiten kopiert der Controller Label, Provider, Modell und Endpunkt in das DTO und lässt apiKey auf null stehen. Ein leeres Absenden ruft encrypt() nicht auf; der vorhandene Chiffretext bleibt erhalten. NotBlank befindet sich nur in der Gruppe create.

Attributbasierte Formulare haben eine Klasse überflüssig gemacht, die ich sonst geschrieben hätte. Validierungsgruppen oder CSRF wurden dadurch nicht entfernt. Das Flex-Rezept für zustandsloses CSRF ließ value="csrf-token" im HTML stehen und setzte einen Stimulus-Controller voraus, den diese App nicht enthält. Session-CSRF sorgte dafür, dass ein normales Browser-Submit funktionierte. Das ist eine kleine Lektion aus 8.2, die neben der großen steht: Neue Formularattribute eignen sich gut für ein Konfigurations-DTO, und sie machen den Rest des Formular-Stacks nicht überflüssig.

Chiffretext in SQLite

Nach dem Absenden eines gefälschten Schlüssels durch den Browser enthielt SQLite Metadaten sowie einen Blob:

$ sqlite3 var/data.db "SELECT kms_key_id, length(ciphertext_blob), instr(ciphertext_blob, 'sk-ant') FROM ai_connection;"
app-key|96|0

instr(ciphertext_blob, 'sk-ant') = 0. Ein LIKE-Vergleich für den übermittelten Wert ergab ebenfalls 0. Der gespeicherte Text ist ein undurchsichtiger Base64-Code von Ciphertext::$blob.

Das ist der stärkste Beweis für Persistenz in dieser Woche, und er hat eine klare Einschränkung. Er beweist, dass der erkennbare Klartext in dieser Spalte fehlt. Es handelt sich nicht um ein kryptografisches Audit. Es beweist weder, dass es sich bei der Verschlüsselung um Sodium XChaCha handelt, noch die Nonce-Verarbeitung, noch dass ein Angreifer mit dem Entwicklungs-Hauptschlüssel blockiert wird. PHPUnit führt dieselbe Überprüfung auf das Fehlen des Schlüssels in der HTTP-Antwort durch: Der von mir gepostete Schlüssel taucht im HTML-Code nicht wieder auf.

Die Listenseite zeigt verschlüsselt und Sodium an. Der Schlüssel wird nicht angezeigt.

Entschlüsselung im letzten verantwortungsvollen Moment

Das Auflisten einer Verbindung führt zu keiner Entschlüsselung. Das Bearbeiten führt zu keiner Entschlüsselung. Der Schlüssel wird erst rekonstruiert, wenn eine KI-Aktion ihn benötigt.

$apiKey = $this->credentials->decrypt($connection);

try {
    $result = $this->workflows->run(
 Context::fromArray([
 'connection_id' => $connection->getId(),
 'provider' => $connection->getProvider(),
 'model' => $connection->getModel(),
 ]),
        [new TestAiConnectionAction($apiKey, /* provider, model, endpoint */)],
    );
} finally {
    $apiKey = str_repeat("\0", \strlen($apiKey));
    unset($apiKey);
}
gespeicherter Chiffretext
 ↓
Verbindung testen / prüfen
 ↓
entschlüsseln
 ↓
Konstruktor von `TestAiConnectionAction`
 ↓
Factory::createPlatform($apiKey)
 ↓
eine Eingabeaufforderung

Die Aktion kennzeichnet das Konstruktorargument mit #[\SensitiveParameter]. Der Kontext enthält Identifikatoren. Er enthält jedoch nicht das Geheimnis. Das ist beabsichtigt: Der Navi-Context verfügt über toArray(). Würde man den Schlüssel dort ablegen, würde dies den Orchestrierungsstatus zu einer Sicherheitslücke machen.

app:probe-connection meldete nach einem Live-Lauf context_has_secret: no. Navi kann den Aufruf orchestrieren, ohne die Anmeldedaten in den Workflow-Daten offenzulegen.

Innerhalb der Aktion wird Symfony AI zur Laufzeit instanziiert. Ein ANTHROPIC_API_KEY auf Containerebene in ai.yaml hätte das BYOK-Prinzip zunichte gemacht.

AnthropicFactory::createPlatform(
    $this->apiKey,
    $this->httpClient,
    baseUrl: $this->endpoint ?: 'https://api.anthropic.com',
);

Die Eingabeaufforderung besteht aus einer Zeile: Antworte mit dem einzigen Wort „pong“. Wenn der HTTP-Client eine Meldung ausgibt, die den Schlüssel enthält, ersetzt SecretRedactor diesen Teil der Zeichenfolge, bevor der Fehler Twig erreicht.

Eine fehlgeschlagene Anfrage kann uns dennoch Aufschluss geben

Ich habe über app:probe-connection eine lokal verfügbare Anthropic-Anmeldeinformation verwendet. Diese werde ich hier nicht ausgeben.

plaintext_in_ciphertext: no
decrypt_matches: yes
context_has_secret: no
test_ok: false
test_error: Ihr Guthaben reicht nicht aus, um auf die Anthropic-API zuzugreifen. ...

Verschlüsselung und Entschlüsselung stimmten überein. Der Schlüssel fehlte im Navi-Kontext. Die Anfrage verließ den Prozess und erreichte Anthropic. Anthropic antwortete mit einem Abrechnungsfehler.

Ein Abrechnungsfehler ist immer noch ein Hinweis darauf, wie weit die Anfrage gelangt ist. Eine Antwort mit dem Hinweis „Ungültiger Schlüssel“ hätte bedeutet, dass wir uns nie authentifiziert hätten. Dies geht darüber hinaus.

Es handelt sich nicht um einen erfolgreichen Abschluss. Es handelt sich nicht um die Nutzung eines Tokens. Es handelt sich nicht um eine Quittung. Der UI-Pfad mit einem gefälschten Schlüssel zeigte „API-Schlüssel ist ungültig.“ an und enthielt keine vertraulichen Informationen. Beide Fehlerpfade waren nützlich. Keiner von beiden ist ein abgeschlossener Chat.

Schlüssel haben einen wirtschaftlichen Wirkungsradius

Guillaume Moigneus Artikel „Cost of a diff“ ist die Quelle einer Idee, nicht dieses Codes: Eine KI-Aktion hat beobachtbare wirtschaftliche Kosten. Eingabetoken, Ausgabetoken, zwischengespeicherte Token, ein Modell, ein Tarif.

Ein Geheimnis, das den Zugriff auf einen KI-Anbieter freischaltet, dient daher nicht nur der Zugriffskontrolle. Es schützt etwas, das Geld ausgeben kann.

Die Anwendung verfügt über den Abrechnungspfad. „TestAiConnectionAction“ liest das Symfony-AI-„TokenUsageInterface“, wenn das Aufrufergebnis „token_usage“ enthält:

Prompt-Token → Eingabe
Vervollständigungs-Token    → Ausgabe
Cache-Erstellung → cache_write
Cache-Lesezugriff → cache_read
zwischengespeicherte Token → zwischengespeichert

Fehlende Metriken bleiben null und werden als „nicht gemeldet“ dargestellt. AiCostTable wendet dann eine explizite Liste pro 1 Mio. USD vom 19.09.2026 an:

usd = input  × input_rate  / 1_000_000
    + output × output_rate / 1_000_000
    + cache_write × cache_write_rate / 1_000_000   (sofern die Tabelle einen solchen Wert enthält)
    + cache_read  × cache_read_rate  / 1_000_000   (sofern die Tabelle einen solchen Wert enthält)

Claude Sonnet 4.5 in dieser Tabelle kostet $3 / $15 / $3,75 / $0,30. Ein lokaler Testlauf mit fiktiven Zahlen (42 Eingaben, 8 Ausgaben) ergibt $0,000246. Diese Zahl stammt aus einer Tabellenkalkulation. Es handelt sich nicht um eine Quittung des Anbieters.

In dieser Woche wurde kein erfolgreicher kostenpflichtiger Abschluss getätigt. Der Kostenpfad existiert. Er wurde nicht anhand der Nutzungsmetadaten von Anthropic validiert. Ich werde keine Token erfinden, um die Benutzeroberfläche fertig aussehen zu lassen.

Anbieter ist kein Endpunkt

In einer Symfony-AI-Diskussion wurde diese Woche berichtet, dass Claude über ein Azure-AI-Abonnement funktionierte, indem die bestehende Anthropic-Brücke auf eine Anthropic-kompatible Nachrichten-URL verwiesen wurde, anstatt eine neue Azure-Claude-Abstraktion hinzuzufügen.

Die gemeldete Form lautete:

<resource>.services.ai.azure.com/anthropic/v1/messages

Der beschriebene Test umfasste eine vollständige Chat-Runde und das Zwischenspeichern von Prompts. Ich werde keine privaten Identitäten aus diesem Thread wiedergeben.

Die installierte Anthropic-Funktion Factory::createPlatform() verfügt bereits über $baseUrl. ModelClient sendet an {baseUrl}/v1/messages. Der optionale Endpunkt des Formulars ist daher die Azure-Basis ohne dieses Suffix:

https://<resource>.services.ai.azure.com/anthropic

baseUrl ist fest verdrahtet. Azure Anthropic wurde nicht aufgerufen.

Bei Bedrock ist das anders. Es authentifiziert sich mit AWS-Anmeldeinformationen, nicht mit einem Anthropic-Schlüssel plus einem Host. Bei Azure war die Kompatibilität ein Endpunktproblem für das Gateway. Bei Bedrock ist es ein Problem des Authentifizierungsmodells. Ich habe keine Bedrock-Schicht hinzugefügt.

Anbieteridentität, Transport-Endpunkt und Speicherung der Anmeldedaten sind getrennte Belange.

Manchmal ist Kompatibilität eine Frage der Konfiguration und keine weitere Abstraktion. Das entspricht derselben Vorgehensweise, bei der Navi aus der Persistenz und Symfony AI aus dem Formular herausgehalten werden.

Sodium lokal, KMS extern

Ich werde hier kein Kryptografie-Tutorial daraus machen. Der operative Unterschied reicht aus.

Bei Sodium besitzt die Anwendung den Verschlüsselungsschlüssel und kann jede von ihr geschriebene Zeile entschlüsseln. Das Experiment lässt sich ohne AWS-Konto ausführen. Eine Kompromittierung von DEV_KMS_KEY ist eine Kompromittierung der gespeicherten API-Schlüssel.

Bei AWS KMS fragt die Anwendung einen externen Dienst ab. Der Hauptschlüssel soll außerhalb des Anwendungsspeichers verbleiben. Eine Kompromittierung von .env reicht nicht aus; ein Angreifer benötigt weiterhin AWS-Anmeldedaten und eine Schlüsselrichtlinie, die die Entschlüsselung erlaubt.

Das ist eine Verbesserung bei der Schlüsselverwaltung. Es handelt sich jedoch nicht um einen magischen Schutz vor einer kompromittierten Laufzeitumgebung. Wenn die laufende Anwendung decrypt() aufrufen kann, kann ein Angreifer mit ausreichendem Zugriff dies ebenfalls tun. Der Vorteil besteht darin, dass der Hauptschlüssel keine Byte-Zeichenkette ist, die direkt neben dem Chiffretext liegt, und dass das Ver- und Entschlüsseln außerhalb der Anwendung überprüft werden kann. Ich habe den ersten Fall überprüft. Den zweiten habe ich selbst konfiguriert.

KI verändert beide Seiten der Sicherheit

Fabien Potencier schrieb diesen Monat, dass Symfony früher etwa einen Sicherheitsbericht pro Quartal erhielt und nun mindestens einen pro Tag. Agenten scannen eine neue Version, sobald sie veröffentlicht wird. Ein Bericht im Posteingang sollte so behandelt werden, als sei er bereits öffentlich. Embargos gingen davon aus, dass die Aufdeckung kostspielig sei.

Dies ist kein CVE in dieser Anwendung. Ich ordne dieses Experiment keinem nummerierten Sicherheitshinweis zu.

Der nützliche Zusammenhang ist wirtschaftlicher Natur. Agenten senken die Kosten für die Suche in einer Codebasis nach der Stelle, an der ein Geheimnis durchgesickert ist. Gleichzeitig hat eine KI-Anmeldeinformation einen direkten finanziellen Wert: Sie kann ausgegeben werden. Diese beiden Tatsachen zusammen sind der Grund, warum die BYOK-Verwaltung in die Anwendungsarchitektur gehört und nicht in die Administration der Bereitstellung.

Die konkreten Entscheidungen im Repository sind bewusst gewöhnlich gehalten: keine Klartext-Spalte, keine Passworteingabe, keine erneute Anzeige, Entschlüsselung nur zur Ausführung, fehlender Schlüssel im Navi-Kontext, gefälschte .env.example-Datei, Backend-Badge ohne DSN. Die Verschlüsselung übernimmt KeyManagement. Der Rest sind Sicherheitsmaßnahmen, da das Objekt, das wir schützen, nun eine Zeile ist.

Was tatsächlich funktioniert hat

Diese Prüfungen wurden erfolgreich durchgeführt.

Container, Twig und YAML wurden ohne Fehler geprüft.

PHPUnit: 2 Tests, 15 Assertions, OK. Ein Test verschlüsselt und entschlüsselt über Sodium und überprüft, ob der Klartext im Entity-Blob fehlt. Der andere sendet das attributbasierte Formular ab und überprüft, ob der Schlüssel in SQLite und im HTML-Code fehlt.

Im Browser habe ich eine Verbindung hinzugefügt, die Badges für „verschlüsselt“ und „Sodium“ gesehen, die Bearbeitung mit einem leeren API-Schlüssel-Feld geöffnet und eine gefälschte Anmeldeinformation getestet. Der Anbieter antwortete mit API-Schlüssel ist ungültig.

SQLite nach diesem Absenden:

instr(ciphertext_blob, 'sk-ant') = 0

Die Live-Probe von Anthropic:

Verschlüsseln/Entschlüsseln: übereinstimmend
Anmeldedaten im Navi-Kontext: nein
Anbieter erreicht: ja
Ergebnis: Abrechnungsfehler – Guthaben zu gering

Das sind die Schlussfolgerungen, zu denen ich bereit bin zu stehen.

Was ich nicht überprüft habe

AWS KMS war konfiguriert, wurde aber nicht aufgerufen.

Die Azure-Anthropic-baseUrl war verkabelt, wurde aber nicht aufgerufen.

Es gab keinen erfolgreichen kostenpflichtigen Anthropic-Vorgang. Daher gab es keinen echten Token-Erhalt, und die Kostenabrechnung wurde nicht anhand einer erfolgreichen Antwort des Anbieters validiert.

KeyManagement befindet sich weiterhin im Versuchsstadium.

„Implementiert“, „konfiguriert“, „getestet“ und „überprüft“ sind vier verschiedene Begriffe. Diese Woche kamen alle vier zum Einsatz. Ich setze sie nicht gleich.

Fazit

.env ist ein gutes Modell, wenn das Geheimnis zur Bereitstellung gehört.

BYOK ändert die Eigentumsverhältnisse.

Sobald eine Anmeldeinformation einem Anwendungsbenutzer gehört, benötigt sie einen Anwendungslebenszyklus: Eingabe, Verschlüsselung, Persistenz, Ausführung, Beobachtbarkeit und schließlich Rotation. Symfony 8.2 KeyManagement ist eine nützliche Grundkomponente für den Verschlüsselungsschritt. Es ist experimentell, und sein Konfigurationsbaum ist wählerisch bei Umgebungsvariablen, aber die Schnittstellen, die ich getestet habe – Verschlüsselung eines kleinen Geheimnisses, Speicherung eines Ciphertext, Entschlüsselung im letzten Moment – sind genau diejenigen, die BYOK tatsächlich benötigt.

Navi muss kein Secret-Manager werden. Symfony AI muss nicht für die Persistenz zuständig sein. Das Formular muss nicht wissen, wie die KI-Anfrage aufgebaut ist.

Jede Schicht kann klein bleiben. Der Schlüssel ist nicht mehr eine Zeile in .env. Er ist eine Zeile, ein Chiffretext, ein Konstruktorargument und ein Einzelposten. Das ist die gesamte Veränderung.

Anmelden um auf diesen Beitrag zu reagieren

🚀 1

Site

  • Sitemap
  • Kontakt
  • Impressum

Network

  • Hello
  • Blog
  • Apps
  • Photos

Social

Darkwood 2026, alle Rechte vorbehalten