Använda Key Vault-referenser som appinställningar i Azure App Service och Azure Functions

Kommentar

Från och med den 1 juni 2024 har alla nyligen skapade App Service-appar möjlighet att generera ett unikt standardvärdnamn med hjälp av namngivningskonventionen <app-name>-<random-hash>.<region>.azurewebsites.net. Befintliga appnamn förblir oförändrade.

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

Mer information finns i Unikt standardvärdnamn för App Service-resurs.

Den här artikeln visar hur du använder hemligheter från Azure Key Vault som värden för appinställningar eller anslutningssträng i App Service- eller Azure Functions-appar.

Azure Key Vault är en tjänst som tillhandahåller centraliserad hantering av hemligheter med fullständig kontroll över åtkomstprinciper och granskningshistorik. När en appinställning eller anslutningssträng är en nyckelvalvsreferens kan programkoden använda den som andra appinställningar eller anslutningssträng. På så sätt kan du bevara hemligheter förutom appens konfiguration. Appinställningarna krypteras säkert i vila, men om du behöver funktioner för hemlig hantering bör de gå in i ett nyckelvalv.

Ge din app åtkomst till ett nyckelvalv

För att kunna läsa hemligheter från ett nyckelvalv måste du skapa ett valv och ge din app behörighet att komma åt det.

  1. Skapa ett nyckelvalv genom att följa snabbstarten för Key Vault.

  2. Skapa en hanterad identitet för ditt program.

    Key Vault-referenser använder appens systemtilldelade identitet som standard, men du kan ange en användartilldelad identitet.

  3. Auktorisera läsåtkomst till hemligheter i nyckelvalvet för den hanterade identitet som du skapade tidigare. Hur du gör det beror på behörighetsmodellen för ditt nyckelvalv:

Åtkomst till nätverksbegränsade valv

Om valvet har konfigurerats med nätverksbegränsningar kontrollerar du att programmet har nätverksåtkomst. Valv bör inte vara beroende av appens offentliga utgående IP-adresser eftersom ursprungs-IP-adressen för den hemliga begäran kan vara annorlunda. I stället ska valvet konfigureras för att acceptera trafik från ett virtuellt nätverk som används av appen.

  1. Kontrollera att programmet har konfigurerat utgående nätverksfunktioner enligt beskrivningen i App Service-nätverksfunktioner och Nätverksalternativ för Azure Functions.

    Linux-program som ansluter till privata slutpunkter måste uttryckligen konfigureras för att dirigera all trafik via det virtuella nätverket. Det här kravet tas bort i en kommande uppdatering. Kör följande kommando för att konfigurera den här inställningen:

    az webapp config set --subscription <sub> -g <group-name> -n <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Kontrollera att valvets konfiguration tillåter det nätverk eller undernät som appen använder för att komma åt det.

Få åtkomst till valv med en användartilldelad identitet

Vissa appar måste referera till hemligheter när de skapas, när en systemtilldelad identitet inte är tillgänglig ännu. I dessa fall kan en användartilldelad identitet skapas och ges åtkomst till valvet i förväg.

När du har beviljat behörighet till den användartilldelade identiteten följer du dessa steg:

  1. Tilldela identiteten till ditt program om du inte redan har gjort det.

  2. Konfigurera appen så att den använder den här identiteten för key vault-referensåtgärder genom att ange keyVaultReferenceIdentity egenskapen till resurs-ID för den användartilldelade identiteten.

    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}
    

Den här inställningen gäller för alla key vault-referenser för appen.

Rotation

Om den hemliga versionen inte anges i referensen använder appen den senaste versionen som finns i nyckelvalvet. När nyare versioner blir tillgängliga, till exempel med en rotationshändelse, uppdateras appen automatiskt och börjar använda den senaste versionen inom 24 timmar. Fördröjningen beror på att App Service cachelagrar värdena för nyckelvalvsreferenser och gör en ny hämtning var 24:e timme. Alla konfigurationsändringar i appen orsakar en omstart av appen och en omedelbar referens av alla refererade hemligheter.

Inställningar för källappar från nyckelvalv

Om du vill använda en key vault-referens anger du referensen som värdet för inställningen. Din app kan referera till hemligheten via dess nyckel som vanligt. Inga kodändringar krävs.

Dricks

De flesta appinställningar med key vault-referenser bör markeras som platsinställningar, eftersom du bör ha separata valv för varje miljö.

En key vault-referens är av formatet @Microsoft.KeyVault({referenceString}), där {referenceString} finns i något av följande format:

Referenssträng beskrivning
SecretUri=secretUri SecretUri ska vara den fullständiga dataplans-URI:n för en hemlighet i valvet, eventuellt inklusive en version, t.ex. https://myvault.vault.azure.net/secrets/mysecret/ ellerhttps://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931
VaultName=vaultName; SecretName=secretName; SecretVersion=secretVersion VaultName krävs och är valvnamnet. SecretName krävs och är det hemliga namnet. SecretVersion är valfritt, men om det finns anger den version av hemligheten som ska användas.

En fullständig referens skulle till exempel se ut som följande sträng:

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

Du kan också:

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

Överväganden för Montering av Azure Files

Appar kan använda programinställningen WEBSITE_CONTENTAZUREFILECONNECTIONSTRING för att montera Azure Files som filsystem. Den här inställningen har verifieringskontroller för att säkerställa att appen kan startas korrekt. Plattformen förlitar sig på att ha en innehållsresurs i Azure Files och förutsätter ett standardnamn om inget anges via inställningen WEBSITE_CONTENTSHARE . För alla begäranden som ändrar de här inställningarna verifierar plattformen om den här innehållsresursen finns och försöker skapa den om inte. Om den inte kan hitta eller skapa innehållsresursen blockerar den begäran.

När du använder key vault-referenser i den här inställningen misslyckas verifieringskontrollen som standard eftersom själva hemligheten inte kan matchas när den inkommande begäran bearbetas. För att undvika det här problemet kan du hoppa över valideringen genom att ange WEBSITE_SKIP_CONTENTSHARE_VALIDATION "1". Den här inställningen uppmanar App Service att kringgå alla kontroller och inte skapar innehållsresursen åt dig. Du bör se till att den skapas i förväg.

Varning

Om du hoppar över valideringen och antingen anslutningssträng eller innehållsresursen är ogiltig kan appen inte starta korrekt och endast hantera HTTP 500-fel.

Som en del av skapandet av appen kan försök att montera innehållsresursen misslyckas på grund av att hanterade identitetsbehörigheter inte sprids eller att integreringen av det virtuella nätverket inte har konfigurerats. Du kan skjuta upp konfigurationen av Azure Files till senare i distributionsmallen för att hantera detta. Mer information finns i Azure Resource Manager-distribution . I det här fallet använder App Service ett standardfilsystem tills Azure Files har konfigurerats och filer kopieras inte över. Du måste se till att inga distributionsförsök görs under övergångsperioden innan Azure Files monteras.

Överväganden för Application Insights-instrumentation

Appar kan använda programinställningarna eller APPLICATIONINSIGHTS_CONNECTION_STRING för att integrera med Application Insights.APPINSIGHTS_INSTRUMENTATIONKEY Portalupplevelserna för App Service och Azure Functions använder också de här inställningarna för att visa telemetridata från resursen. Om dessa värden refereras från Key Vault är dessa funktioner inte tillgängliga och du måste i stället arbeta direkt med Application Insights-resursen för att visa telemetrin. Dessa värden betraktas dock inte som hemligheter, så du kan också överväga att konfigurera dem direkt i stället för att använda key vault-referenser.

Azure Resource Manager-distribution

När du automatiserar resursdistributioner via Azure Resource Manager-mallar kan du behöva sekvensera dina beroenden i en viss ordning för att den här funktionen ska fungera. Se till att definiera dina appinställningar som en egen resurs i stället för att använda en siteConfig egenskap i appdefinitionen. Det beror på att appen måste definieras först så att den systemtilldelade identiteten skapas med den och kan användas i åtkomstprincipen.

Följande pseudomall är ett exempel på hur en funktionsapp kan se ut:

{
    //...
    "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]"
                    }
                }
            ]
        }
    ]
}

Kommentar

I det här exemplet beror distributionen av källkontroll på programinställningarna. Det här är normalt osäkert beteende eftersom uppdateringen av appinställningen fungerar asynkront. Men eftersom vi har inkluderat programinställningen WEBSITE_ENABLE_SYNC_UPDATE_SITE är uppdateringen synkron. Det innebär att distributionen av källkontroll bara påbörjas när programinställningarna har uppdaterats helt. Fler appinställningar finns i Miljövariabler och appinställningar i Azure App Service.

Felsöka key vault-referenser

Om en referens inte matchas korrekt används referenssträngen i stället (till exempel @Microsoft.KeyVault(...)). Det kan orsaka att programmet utlöser fel eftersom det förväntar sig en hemlighet med ett annat värde.

Det går inte att lösa problemet beror ofta på en felkonfiguration av Key Vault-åtkomstprincipen. Men det kan också bero på att en hemlighet inte längre finns eller ett syntaxfel i själva referensen.

Om syntaxen är korrekt kan du visa andra orsaker till fel genom att kontrollera aktuell lösningsstatus i portalen. Gå till Programinställningar och välj "Redigera" för referensen i fråga. Redigeringsdialogrutan visar statusinformation, inklusive eventuella fel. Om du inte ser statusmeddelandet innebär det att syntaxen är ogiltig och inte identifieras som en nyckelvalvsreferens.

Du kan också använda en av de inbyggda detektorerna för att få ytterligare information.

Använda detektorn för App Service

  1. Gå till din app i portalen.
  2. Välj Diagnostisera och lösa problem.
  3. Välj Tillgänglighet och prestanda och välj Webbapp nedåt.
  4. I sökrutan söker du efter och väljer Diagnostik för Key Vault-programinställningar.

Använda detektorn för Azure Functions

  1. Gå till din app i portalen.
  2. Gå till Plattformsfunktioner.
  3. Välj Diagnostisera och lösa problem.
  4. Välj Tillgänglighet och prestanda och välj Funktionsapp eller rapporteringsfel.
  5. Välj Diagnostik för Key Vault-programinställningar.