Verwenden von Key Vault-Verweisen als App-Einstellungen in Azure App Service und Azure Functions

Hinweis

Ab dem 1. Juni 2024 haben alle neu erstellten App Service-Apps die Möglichkeit, einen eindeutigen Standardhostnamen mit der Namenskonvention <app-name>-<random-hash>.<region>.azurewebsites.net zu erstellen. Vorhandene App-Namen bleiben unverändert.

Beispiel: myapp-ds27dh7271aah175.westus-01.azurewebsites.net

Ausführlichere Informationen finden Sie unter Eindeutiger Standardhostname für App Service-Ressourcen.

In diesem Artikel erfahren Sie, wie Sie Geheimnisse aus Azure Key Vault als Werte von App-Einstellungen oder Verbindungszeichenfolgen in Ihren App Service- oder Azure Functions-Apps verwenden.

Azure Key Vault ist ein Dienst, der eine zentralisierte Verwaltung von Geheimnissen mit voller Kontrolle über Zugriffsrichtlinien und Überprüfungsverlauf ermöglicht. Wenn eine App-Einstellung oder Verbindungszeichenfolge ein Key Vault-Verweis ist, kann Ihr Anwendungscode sie wie jede andere App-Einstellung oder Verbindungszeichenfolge verwenden. Auf diese Weise können Sie Geheimnisse abgesehen von der Konfiguration Ihrer App getrennt verwalten. App-Einstellungen sind im Ruhezustand sicher verschlüsselt, aber wenn Sie Funktionen zum Verwalten von Geheimnissen benötigen, sollten sie in einem Schlüsseltresor platziert werden.

Gewähren des Zugriffs auf einen Schlüsseltresor für Ihre App

Um Geheimnisse aus einem Schlüsseltresor lesen zu können, müssen Sie einen Tresor erstellen und Ihrer App die Berechtigung für den Zugriff darauf erteilen.

  1. Erstellen Sie einen Schlüsseltresor anhand dieser Key Vault-Schnellstartanleitung.

  2. Erstellen Sie eine verwaltete Identität für Ihre App.

    Key Vault-Verweise verwenden standardmäßig die systemseitig zugewiesene Identität der App, aber Sie können auch eine benutzerseitig zugewiesene Identität angeben.

  3. Autorisieren Sie den Lesezugriff auf Geheimnisse in Ihrem Schlüsseltresor für die zuvor erstellte verwaltete Identität. Wie Sie hierzu vorgehen, hängt vom Berechtigungsmodell Ihres Schlüsseltresors ab:

Zugriff auf Werte mit Netzwerkeinschränkungen

Wenn Ihr Tresor mit Netzwerkeinschränkungen konfiguriert ist, stellen Sie außerdem sicher, dass die Anwendung über Netzwerkzugriff verfügt. Tresore sollten nicht von den ausgehenden öffentlichen IP-Adressen der App abhängen, da die Ursprungs-IP-Adresse der Geheimnisanforderung abweichen könnte. Stattdessen sollte der Tresor so konfiguriert werden, dass er Datenverkehr aus einem virtuellen Netzwerk akzeptiert, das von der App verwendet wird.

  1. Stellen Sie sicher, dass für die Anwendung ausgehende Netzwerkfunktionen konfiguriert sind, wie in App Service-Netzwerkfunktionen und Azure Functions-Netzwerkoptionen beschrieben.

    Linux-Anwendungen, die eine Verbindung mit privaten Endpunkten herstellen, müssen explizit so konfiguriert sein, dass der gesamte Datenverkehr über das virtuelle Netzwerk geleitet wird. Diese Anforderung entfällt in einem bevorstehenden Update. Um diese Einstellung zu konfigurieren, führen Sie den folgenden Befehl aus:

    az webapp config set --subscription <sub> -g <group-name> -n <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Stellen Sie sicher, dass die Konfiguration des Tresors das Netzwerk oder Subnetz zulässt, über das Ihre App darauf zugreift.

Zugriff auf Tresore mit einer benutzerseitig zugewiesenen Identität

Einige Apps müssen zum Erstellungszeitpunkt auf Geheimnisse verweisen, wenn eine systemseitig zugewiesene Identität noch nicht verfügbar ist. In diesen Fällen kann eine benutzerseitig zugewiesene Identität erstellt und im Voraus Zugriff auf den Tresor gewährt werden.

Nachdem Sie der benutzerseitig zugewiesenen Identität Berechtigungen erteilt haben, führen Sie die folgenden Schritte aus:

  1. Weisen Sie die Identität Ihrer Anwendung zu, sofern noch nicht erfolgt.

  2. Konfigurieren Sie die App so, dass sie diese Identität für Key Vault-Verweisvorgänge verwendet, indem Sie die Eigenschaft keyVaultReferenceIdentity auf die Ressourcen-ID der benutzerseitig zugewiesenen Identität festlegen.

    identityResourceId=$(az identity show --resource-group <group-name> --name <identity-name> --query id -o tsv)
    az webapp update --resource-group <group-name> --name <app-name> --set keyVaultReferenceIdentity=${identityResourceId}
    

Diese Einstellung gilt für alle Key Vault-Verweise für die App.

Drehung

Wenn die Geheimnisversion nicht im Verweis angegeben ist, verwendet die App die neueste Version, die im Schlüsseltresor vorhanden ist. Sobald neuere Versionen verfügbar werden, z. B. bei einem Rotationsereignis, wird die App automatisch aktualisiert und beginnt innerhalb von 24 Stunden mit der Nutzung der neuesten Version. Die Verzögerung liegt daran, dass App Service die Werte der Schlüsseltresorverweise zwischenspeichert und alle 24 Stunden erneut abruft. Alle Konfigurationsänderungen an der App verursachen einen Neustart sowie eine sofortige Neuabfrage aller Geheimnisse, auf die verwiesen wird.

Quell-App-Einstellungen aus Schlüsseltresor

Um einen Key Vault-Verweis zu verwenden, legen Sie den Verweis als Wert der Einstellung fest. Ihre App kann wie gewohnt durch seinen Schlüssel auf das Geheimnis verweisen. Es sind keine Codeänderungen erforderlich.

Tipp

Die meisten App-Einstellungen, die Key Vault-Verweise verwenden, sollten als Slot-Einstellungen markiert werden, da Sie für jede Umgebung gesonderte Tresore verwenden sollten.

Ein Key Vault-Verweis hat die Form @Microsoft.KeyVault({referenceString}), wobei {referenceString} in einem der folgenden Formate ist:

Verweiszeichenfolge BESCHREIBUNG
SecretUri=secretUri SecretUri ist die vollständige URI der Datenebene eines Geheimnisses im Tresor (z. B. https://myvault.vault.azure.net/secrets/mysecret). Schließen Sie optional eine Version ein (z. B. https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931).
VaultName=vaultName;SecretName=secretName;SecretVersion=secretVersion VaultName ist erforderlich und der Tresorname. SecretName ist erforderlich und der Geheimnisname. SecretVersion ist optional, gibt aber, sofern vorhanden, die zu verwendende Version des Geheimnisses an.

Ein vollständiger Verweis ohne spezifische Version sieht beispielsweise wie folgt aus:

@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret)

Alternativ:

@Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret)

Überlegungen zum Einbinden von Azure Files

Apps können die WEBSITE_CONTENTAZUREFILECONNECTIONSTRING-Anwendungseinstellung verwenden, um Azure Files als Dateisystem einzubinden. Diese Einstellung verfügt über Überprüfungen, um sicherzustellen, dass die App ordnungsgemäß gestartet werden kann. Die Plattform benötigt eine Inhaltsfreigabe in Azure Files und setzt einen Standardnamen voraus, es sei denn, ein Name wird über die WEBSITE_CONTENTSHARE-Einstellung angegeben. Bei Anforderungen, die diese Einstellungen ändern, überprüft die Plattform, ob diese Inhaltsfreigabe vorhanden ist, und versucht, sie zu erstellen, falls nicht. Wenn die Inhaltsfreigabe nicht gefunden oder erstellt werden kann, wird die Anforderung blockiert.

Wenn Sie Key Vault-Verweise in dieser Einstellung verwenden, schlägt die Überprüfung standardmäßig fehl, da das Geheimnis selbst beim Verarbeiten der eingehenden Anforderung nicht aufgelöst werden kann. Um dieses Problem zu vermeiden, können Sie die Überprüfung überspringen, indem Sie WEBSITE_SKIP_CONTENTSHARE_VALIDATION auf „1“ festlegen. Diese Einstellung weist App Service an, alle Überprüfungen zu umgehen, und erstellt die Inhaltsfreigabe nicht für Sie. Stellen Sie sicher, dass sie im Voraus erstellt wird.

Achtung

Wenn Sie die Überprüfung überspringen und entweder die Verbindungszeichenfolge oder die Inhaltsfreigabe ungültig ist, kann die App nicht ordnungsgemäß gestartet werden und gibt nur HTTP 500-Fehler aus.

Im Rahmen der Erstellung der App kann der Einbindungsversuch der Inhaltsfreigabe fehlschlagen, weil Berechtigungen für verwaltete Identitäten nicht weitergegeben oder die VNet-Integration nicht eingerichtet wurde. Um dies zu berücksichtigen, können Sie die Einrichtung von Azure Files bis zu einem späteren Zeitpunkt in der Bereitstellungsvorlage verzögern. Weitere Informationen finden Sie unter Azure Resource Manager-Bereitstellung. In diesem Fall verwendet App Service ein Standarddateisystem, bis Azure Files eingerichtet ist, und es werden keine Dateien kopiert. Sie müssen sicherstellen, dass in der Zwischenzeit vor der Einbindung von Azure Files keine Bereitstellungsversuche unternommen werden.

Überlegungen zur Application Insights-Instrumentierung

Apps können die APPINSIGHTS_INSTRUMENTATIONKEY- oder APPLICATIONINSIGHTS_CONNECTION_STRING-Anwendungseinstellungen zur Integration mit Application Insights verwenden. Die Portalfunktionen für App Service und Azure Functions verwenden diese Einstellungen auch, um Telemetriedaten aus der Ressource anzuzeigen. Wenn von Key Vault auf diese Werte verwiesen wird, sind diese Funktionen nicht verfügbar, und Sie müssen stattdessen direkt mit der Application Insights-Ressource arbeiten, um die Telemetriedaten anzuzeigen. Diese Werte gelten jedoch nicht als Geheimnisse, sodass Sie sie alternativ auch eventuell direkt konfigurieren können, anstatt Key Vault-Verweise zu verwenden.

Azure Resource Manager-Bereitstellung

Wenn Sie Ressourcenbereitstellungen über Azure Resource Manager-Vorlagen automatisieren, müssen Sie möglicherweise Ihre Abhängigkeiten in einer bestimmten Reihenfolge sortieren, damit diese Funktion funktioniert. Stellen Sie sicher, dass Sie Ihre Anwendungseinstellungen als eine eigene Ressource definieren, anstatt eine siteConfig-Eigenschaft in der App-Definition zu verwenden. Grund dafür ist, dass zuerst die App definiert werden muss, damit die systemseitig zugeordnete Identität gleichzeitig erstellt und in der Zugriffsrichtlinie verwendet werden kann.

Die folgende Pseudovorlage ist ein Beispiel dafür, wie eine Funktions-App aussehen könnte:

{
    //...
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            //...
        },
        {
            "type": "Microsoft.Insights/components",
            "name": "[variables('appInsightsName')]",
            //...
        },
        {
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "identity": {
                "type": "SystemAssigned"
            },
            //...
            "resources": [
                {
                    "type": "config",
                    "name": "appsettings",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]"
                    ],
                    "properties": {
                        "AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyName')).secretUriWithVersion, ')')]",
                        "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true"
                        //...
                    }
                },
                {
                    "type": "sourcecontrols",
                    "name": "web",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]"
                    ],
                }
            ]
        },
        {
            "type": "Microsoft.KeyVault/vaults",
            "name": "[variables('keyVaultName')]",
            //...
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
            ],
            "properties": {
                //...
                "accessPolicies": [
                    {
                        "tenantId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.tenantId]",
                        "objectId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.principalId]",
                        "permissions": {
                            "secrets": [ "get" ]
                        }
                    }
                ]
            },
            "resources": [
                {
                    "type": "secrets",
                    "name": "[variables('storageConnectionStringName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
                    ],
                    "properties": {
                        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2019-09-01').key1)]"
                    }
                },
                {
                    "type": "secrets",
                    "name": "[variables('appInsightsKeyName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
                    ],
                    "properties": {
                        "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2019-09-01').InstrumentationKey]"
                    }
                }
            ]
        }
    ]
}

Hinweis

In diesem Beispiel hängt die Bereitstellung der Quellcodeverwaltung von den Anwendungseinstellungen ab. Dies ist normalerweise ein unsicheres Verhalten, da sich das App-Einstellungsupdate asynchron verhält. Da wir aber die Anwendungseinstellung WEBSITE_ENABLE_SYNC_UPDATE_SITE integriert haben, verläuft das Update synchron. Dies bedeutet, dass die Bereitstellung der Quellcodeverwaltung erst dann beginnt, wenn die Anwendungseinstellungen vollständig aktualisiert wurden. Weitere App-Einstellungen finden Sie unter Umgebungsvariablen und App-Einstellungen in Azure App Service.

Problembehandlung von Key Vault-Verweisen

Wenn ein Verweis nicht ordnungsgemäß aufgelöst wird, wird stattdessen die Verweiszeichenfolge verwendet (z. B @Microsoft.KeyVault(...)). Dies kann dazu führen, dass die Anwendung Fehler auslöst, weil sie ein Geheimnis eines anderen Werts erwartet.

Für Auflösungsfehler ist die Ursache meist eine fehlerhafte Konfiguration der Key Vault-Zugriffsrichtlinie. Ursache kann jedoch auch sein, dass ein Geheimnis nicht mehr vorhanden ist, oder dass ein Syntaxfehler im Verweis vorliegt.

Ist die Syntax richtig, können Sie weitere Fehlerursachen anzeigen, indem Sie den aktuellen Auflösungsstatus im Portal überprüfen. Navigieren Sie zu Anwendungseinstellungen, und wählen Sie „Bearbeiten“ für den fraglichen Verweis aus. Im Dialogfeld „Bearbeiten“ werden Statusinformationen angezeigt, einschließlich aller Fehler. Wenn die Statusmeldung nicht angezeigt wird, bedeutet dies, dass die Syntax ungültig ist und nicht als Key Vault-Verweis erkannt wird.

Sie können auch einen der integrierten Detektoren verwenden, um zusätzliche Informationen abzurufen.

Verwenden der Erkennung für App Service

  1. Navigieren Sie im Portal zu Ihrer App.
  2. Wählen Sie Probleme diagnostizieren und beheben aus.
  3. Wählen Sie Verfügbarkeit und Leistung und dann Web-App nicht aktiv (Web App Down) aus.
  4. Suchen Sie im Suchfeld nach Key Vault-Anwendungseinstellungsdiagnose, und wählen Sie sie aus.

Verwenden der Erkennung für Azure Functions

  1. Navigieren Sie im Portal zu Ihrer App.
  2. Navigieren Sie zu Plattformfeatures.
  3. Wählen Sie Probleme diagnostizieren und beheben aus.
  4. Wählen Sie Verfügbarkeit und Leistung aus, und wählen Sie „Funktions-App nicht aktiv oder meldet Fehler (Function App Down or Reporting Errors) aus.
  5. Wählen Sie Key Vault-Anwendungseinstellungsdiagnose aus.