Dela via


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

Anteckning

Från och med den 1 juni 2024 kan nyligen skapade appar av typen App Service generera ett unikt standardhostnamn som använder namngivningskonventionen <app-name>-<random-hash>.<region>.azurewebsites.net. Till exempel: myapp-ds27dh7271aah175.westus-01.azurewebsites.net. Befintliga appnamn förblir oförändrade.

Mer information finns i blogginlägget om att skapa en webbapp med ett unikt standardvärdnamn.

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

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 Key Vault-referens kan programkoden använda den som andra appinställningar eller anslutningssträngar. 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 att hantera hemligheter bör de gå in i ett nyckelvalv.

Ge din app åtkomst till ett nyckelvalv

Om du vill läsa hemligheter från ett nyckelvalv måste du först 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. 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 appen använder.

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

    För närvarande måste Linux-program som ansluter till privata slutpunkter uttryckligen konfigureras för att dirigera all trafik via det virtuella nätverket. 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.

Observera att även om du har konfigurerat valvet korrekt för att acceptera trafik från det virtuella nätverket kan valvets granskningsloggar fortfarande visa en misslyckad (403 – förbjuden) SecretGet-händelse från appens offentliga utgående IP-adress. Detta följs av en lyckad SecretGet-händelse från appens privata IP-adress och är avsiktligt.

Få åtkomst till säkerhetsvalv 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 du skapa en användartilldelad identitet och ge den åtkomst till valvet i förväg.

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

  1. Tilldela identiteten till din applikation 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.

Förstå 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 Key Vault-referenserna och växlar om dem var 24:e timme. Varje ändring i konfigurationen av appen orsakar en omstart av appen och en omedelbar hämtning av alla refererade sekretessuppgifter.

Förstå källappsinställningar från Key Vault

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 på vanligt sätt. Inga kodändringar krävs.

Tips

De flesta appinställningar som använder referenser till Key Vault bör markeras som slotsinstä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 bör vara den fullständiga dataplanets URI för en hemlighet i valvet; till exempel https://myvault.vault.azure.net/secrets/mysecret. Du kan också inkludera en version, till exempel https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931.
VaultName=<vaultName>;SecretName=<secretName>;SecretVersion=<secretVersion> Värdet VaultName krävs och är valvnamnet. Värdet SecretName krävs och är det hemliga namnet. Värdet SecretVersion är valfritt, men om det finns anger det den version av hemligheten som ska användas.

En fullständig referens utan en specifik version 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. Om innehållsdelningen inte finns försöker plattformen skapa den. Om plattformen inte kan lokalisera eller skapa innehållsdelningen blockerar den begäran.

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

Varning

Om du hoppar över valideringen och antingen anslutningssträngen eller innehållsresursen är ogiltig, kommer appen inte att starta korrekt och kommer att returnera HTTP 500-felkoder.

Som en del av skapandet av applikationen kan försök att montera innehållsdelningen misslyckas eftersom hanterade identitetsbehörigheter inte överförs 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 det här beteendet. Mer information finns i Azure Resource Manager-distribution senare i den här artikeln. 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 APPINSIGHTS_INSTRUMENTATIONKEY eller APPLICATIONINSIGHTS_CONNECTION_STRING applikationsinställningar för att integrera med Application Insights.

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 överväga att konfigurera dem direkt i stället för att använda Key Vault-referenser.

Azure Resource Manager-driftsättning

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. 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 beroendet är normalt osäkert eftersom appinställningsuppdateringen fungerar asynkront. Men eftersom vi inkluderade programinställningen WEBSITE_ENABLE_SYNC_UPDATE_SITE är uppdateringen synkron. Distributionen av källkontroll påbörjas först 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(...)). Den här situationen 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. Orsaken kan dock också vara att en hemlighet inte längre finns eller att referensen innehåller ett syntaxfel.

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 Key Vault-referens.

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

Så här använder du 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>Webbapp ned.
  4. I sökrutan söker du efter och väljer Diagnostik för Key Vault-programinställningar.

Så här använder du 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>Funktion app ned eller rapporterar fel.
  5. Välj Diagnostik för Key Vault-programinställningar.