DefaultAzureCredential lokal statt Verbindungszeichenfolgen
- Matt
Eine Verbindungszeichenfolge mit Kontoschlüssel im Klartext ist die bequemste und die unangenehmste Art, lokal an einen Azure-Dienst zu kommen. Bequem, weil sie sofort funktioniert. Unangenehm, weil sie irgendwann in einer appsettings-Datei landet, dann versehentlich im Repository, und weil ihr nie ansieht, wer sie schon einmal kopiert hat. Zugangsdaten aus dem Repository herauszuhalten hatte ich schon einmal mit User Secrets beschrieben. Der Schlüssel selbst bleibt dabei aber ein Schlüssel. Angenehmer ist, lokal gar keinen zu haben.
Die Kette
DefaultAzureCredential aus dem Paket Azure.Identity ist eine
vorkonfigurierte Kette von Anmeldearten. Sie probiert der Reihe nach durch, bis
eine ein Token liefert: Umgebungsvariablen, Workload Identity, Managed Identity,
Visual Studio, Visual Studio Code, Azure CLI, Azure PowerShell, Azure Developer
CLI und zuletzt der Browser. Der Reiz ist, dass derselbe Code lokal und in Azure
funktioniert. Auf meinem Rechner greift die Anmeldung aus Visual Studio oder aus
az login, in der Cloud die Managed Identity des App Service.
var client = new BlobServiceClient(
new Uri($"https://{konto}.blob.core.windows.net"),
new DefaultAzureCredential());
Kein Schlüssel, keine Verbindungszeichenfolge, nur der Endpunkt. Der Dienst muss mich stattdessen als Benutzer kennen, also braucht mein Konto die passende Rolle, etwa Storage Blob Data Contributor. Das ist der eigentliche Umbau: weg vom Schlüssel, hin zur Rollenzuweisung.
Wo es hakt
Genau hier habe ich Zeit verloren. Der erste Aufruf lief lokal mehrere Sekunden,
bevor überhaupt etwas passierte. Grund war, dass Managed Identity in der Kette
vor der Azure CLI steht und auf meinem Rechner erst in einen Timeout laufen
muss, bevor die nächste Anmeldeart drankommt. Sichtbar wird das nur, wenn man
das Protokoll über einen AzureEventSourceListener mitschreibt. Ohne das
rätselt man, warum ein leerer Aufruf hängt.
Die Lösung ist, die Kette lokal zu kürzen. Über die Umgebungsvariable
AZURE_TOKEN_CREDENTIALS lässt sich seit Azure.Identity 1.15 eine einzelne
Anmeldeart erzwingen, etwa AzureCliCredential, oder mit dem Wert dev alles
Serverseitige ausschließen. Alternativ setzt man die Exclude-Eigenschaften in
den DefaultAzureCredentialOptions.
Was es kostet
Umsonst ist der Komfort nicht. Die Kette verschleiert, welche Anmeldeart am Ende
greift, und beim Fehlersuchen ist das lästig. In Produktion sollte deshalb nicht
DefaultAzureCredential stehen, sondern die konkrete Klasse, also
ManagedIdentityCredential. Sonst hängt das Verhalten der Anwendung an
Umgebungsvariablen, die jemand global auf dem Host gesetzt haben könnte, und
niemand rechnet damit. Lokal nehme ich die Kette gern, deployt lieber die
eindeutige Variante.