Partager via


Utiliser des références Key Vault comme paramètres d’application dans Azure App Service et Azure Functions

Cet article vous montre comment utiliser des secrets d’Azure Key Vault comme valeurs de paramètres d’application ou de chaînes de connexion dans vos applications Azure App Service ou Azure Functions.

Key Vault est un service qui fournit une gestion centralisée des secrets, avec un contrôle total sur les stratégies d’accès et l’historique d’audit. Lorsqu’un paramètre d’application ou une chaîne de connexion est une référence Key Vault, votre code d’application peut l’utiliser comme n’importe quel autre paramètre d’application ou chaîne de connexion. De cette façon, vous pouvez conserver les secrets en dehors de la configuration de votre application. Les paramètres d'application sont chiffrés de manière sécurisée lorsqu'ils sont inactifs, mais si vous avez besoin de fonctionnalités pour la gestion des secrets, ils doivent être placés dans un coffre de clés.

Autoriser votre application à accéder à un coffre de clés

Pour lire des secrets à partir d’un coffre de clés, vous devez d’abord créer un coffre et accorder à votre application l’autorisation d’y accéder :

  1. Créez un coffre de clés en suivant le Guide de démarrage rapide de Key Vault.

  2. Créez une identité managée pour votre application.

    Les références Key Vault utilisent l’identité attribuée par le système de l’application par défaut, mais vous pouvez spécifier une identité attribuée par l’utilisateur.

  3. Autorisez l’accès en lecture aux secrets de votre coffre de clés pour l’identité managée que vous avez créée. La façon dont vous procédez dépend du modèle d’autorisations de votre coffre de clés :

Accéder aux coffres restreints du réseau

Si votre coffre est configuré avec des restrictions réseau, assurez-vous que l’application dispose d’un accès réseau. Les coffres ne doivent pas dépendre des adresses IP sortantes publiques de l’application, car l’adresse IP d’origine de la requête secrète peut être différente. Au lieu de cela, le coffre doit être configuré pour accepter le trafic à partir d’un réseau virtuel utilisé par l’application.

  1. Vérifiez que l’application dispose de fonctionnalités de mise en réseau sortantes configurées, comme décrit dans les fonctionnalités de mise en réseau App Service et les options de mise en réseau Azure Functions.

    Actuellement, les applications Linux qui se connectent à des points de terminaison privés doivent être configurées explicitement pour router tout le trafic via le réseau virtuel. Pour configurer ce paramètre, exécutez la commande suivante :

    az webapp config set --resource-group <group-name>  --subscription <subscription> --name <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Assurez-vous que la configuration du coffre autorise le réseau ou le sous-réseau utilisé par votre application à y accéder.

Notez que même si vous avez correctement configuré le coffre pour accepter le trafic de votre réseau virtuel, les journaux d’audit du coffre peuvent toujours afficher un événement SecretGet (403 - Interdit) ayant échoué à partir de l’adresse IP sortante publique de l’application. Cela sera suivi d’un événement SecretGet réussi à partir de l’adresse IP privée de l’application, et cela est intentionnel.

Accédez aux coffres avec une identité attribuée par l’utilisateur

Certaines applications doivent faire référence aux secrets au moment de la création, lorsqu’une identité affectée par le système n’est pas encore disponible. Dans ces cas, créez une identité affectée par l’utilisateur et donnez-lui accès au coffre à l’avance.

Après avoir accordé des autorisations à l’identité affectée par l’utilisateur, procédez comme suit :

  1. Affectez l’identité à votre application.

  2. Configurez l’application pour utiliser cette identité pour les opérations de référence Key Vault en définissant la keyVaultReferenceIdentity propriété sur l’ID de ressource de l’identité attribuée par l’utilisateur :

    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}
    

Ce paramètre s’applique à toutes les références Key Vault pour l’application.

Comprendre la rotation

Si la version du secret n’est pas spécifiée dans la référence, l’application utilise la dernière version qui existe dans le coffre de clés. Lorsque des versions plus récentes sont disponibles, telles que la rotation, l’application est automatiquement mise à jour et commence à utiliser la dernière version dans les 24 heures.

Le délai est dû au fait que App Service met en cache les valeurs des références Key Vault et les refetches toutes les 24 heures. Toute modification de la configuration de l’application entraîne un redémarrage de l’application et une récupération immédiate de tous les secrets référencés.

Pour forcer la résolution des références Key Vault de votre application, effectuez une requête POST authentifiée au point de terminaison https://management.azure.com/[Resource ID]/config/configreferences/appsettings/refresh?api-version=2022-03-01de l’API.

Comprendre les paramètres de l’application source à partir de Key Vault

Pour utiliser une référence Key Vault, définissez la référence comme valeur du paramètre. Votre application peut référencer le secret par le biais de sa clé comme d’habitude. Le code n’a pas besoin d’être modifié.

Conseil

Étant donné que vous devez disposer de coffres distincts pour chaque environnement, la plupart des paramètres d’application qui utilisent les références Key Vault doivent être marqués comme paramètres d’emplacement.

Une référence Key Vault est de la forme @Microsoft.KeyVault({referenceString}), où {referenceString} se trouve dans l’un des formats suivants :

Chaîne de référence Descriptif
SecretUri=<secretUri> Le SecretUri doit être l’URI complet du plan de données d’un secret dans le coffre. Par exemple : https://myvault.vault.azure.net/secrets/mysecret. Si vous le souhaitez, incluez une version, telle que https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931.
VaultName=<vaultName>;SecretName=<secretName>;SecretVersion=<secretVersion> La valeur VaultName est requise et correspond au nom du coffre. La SecretName valeur est requise et correspond au nom du secret. La SecretVersion valeur est facultative, mais, si elle est présente, indique la version du secret à utiliser.

Par exemple, une référence complète sans version spécifique ressemblerait à la chaîne suivante :

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

Sinon :

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

Considérations relatives au montage de Azure Files

Les applications peuvent utiliser le paramètre d’application WEBSITE_CONTENTAZUREFILECONNECTIONSTRING pour monter Azure Files en tant que système de fichiers. Ce paramètre a des contrôles de validation pour garantir que l’application peut être démarrée correctement.

La plateforme s’appuie sur un partage de contenu dans Azure Files. La plateforme suppose un nom par défaut, sauf si un nom est spécifié à l’aide du WEBSITE_CONTENTSHARE paramètre. Pour toutes les demandes qui modifient ces paramètres, la plateforme valide que ce partage de contenu existe. Si le partage de contenu n’existe pas, la plateforme tente de la créer. Si la plateforme ne peut pas localiser ou créer le partage de contenu, elle bloque la demande.

Lorsque vous utilisez des références Key Vault dans ce paramètre, la vérification de validation échoue par défaut, car le secret ne peut pas être résolu pendant le traitement de la requête entrante. Pour éviter ce problème, vous pouvez ignorer la validation en définissant WEBSITE_SKIP_CONTENTSHARE_VALIDATION sur 1. Ce paramètre indique à App Service de contourner toutes les vérifications et ne crée pas le partage de contenu pour vous. Vous devez vous assurer que le partage de contenu est créé à l’avance.

Attention

Si vous ignorez la validation et que la chaîne de connexion ou le partage de contenu n’est pas valide, l’application ne démarre pas correctement et crée des erreurs HTTP 500.

Dans le cadre de la création de l’application, la tentative de montage du partage de contenu peut échouer, car les autorisations d’identité managée ne sont pas propagées ou l’intégration du réseau virtuel n’est pas configurée. Vous pouvez différer la configuration d’Azure Files jusqu’à plus tard dans le modèle de déploiement pour prendre en charge ce comportement. Pour plus d’informations, consultez le déploiement d’Azure Resource Manager plus loin dans cet article.

Dans ce cas, App Service utilise un système de fichiers par défaut jusqu’à ce qu’Azure Files soit configuré, et les fichiers ne sont pas copiés. Vous devez vous assurer qu’aucune tentative de déploiement ne se produit pendant la période intermédiaire avant le montage d’Azure Files.

Considérations relatives à l’instrumentation Application Insights

Les applications peuvent utiliser les paramètres d’application APPINSIGHTS_INSTRUMENTATIONKEY ou APPLICATIONINSIGHTS_CONNECTION_STRING pour s’intégrer à Application Insights.

Pour App Service et Azure Functions, le portail Azure utilise également ces paramètres pour exposer les données de télémétrie à partir de la ressource. Si ces valeurs sont référencées à partir de Key Vault, cette approche n’est pas disponible. Au lieu de cela, vous devez travailler directement avec la ressource Application Insights pour afficher les données de télémétrie. Toutefois, ces valeurs ne sont pas considérées comme des secrets. Vous pouvez donc envisager de les configurer directement au lieu d’utiliser des références Key Vault.

Déploiement Azure Resource Manager

Lorsque vous automatisez les déploiements de ressources via des modèles Azure Resource Manager, vous devrez peut-être séquencer vos dépendances dans un ordre particulier. Veillez à définir vos paramètres d’application comme étant leur propre ressource, au lieu d’utiliser une propriété siteConfig dans la définition de l’application. L’application doit d’abord être définie afin que l’identité affectée par le système soit créée avec elle et puisse être utilisée dans la stratégie d’accès.

Le pseudo-modèle suivant est un exemple d’application de fonction :

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

Remarque

Dans cet exemple, le déploiement du contrôle de code source varie selon les paramètres d’application. Cette dépendance est normalement dangereuse, car la mise à jour du paramètre d’application se comporte de manière asynchrone. Toutefois, étant donné que vous avez inclus le WEBSITE_ENABLE_SYNC_UPDATE_SITE paramètre d’application, la mise à jour est synchrone. Le déploiement du contrôle de code source commence uniquement une fois que les paramètres de l’application sont entièrement mis à jour. Pour plus d’informations sur les paramètres d’application, consultez Variables d’environnement et paramètres d’application dans Azure App Service.

Résoudre les problèmes de références Key Vault

Si une référence n’est pas résolue correctement, la chaîne de référence est utilisée à la place, par exemple @Microsoft.KeyVault(...). Cette situation peut provoquer des erreurs dans l'application, car elle attend un secret d'une valeur différente.

Un échec de résolution est généralement dû à une configuration incorrecte de la stratégie d’accès à Key Vault. Toutefois, la raison peut également être qu’un secret n’existe plus ou que la référence contient une erreur de syntaxe.

Si la syntaxe est correcte, vous pouvez afficher d’autres causes d’erreur en vérifiant l’état de résolution actuel dans le portail Azure. Accédez aux paramètres de l’application et sélectionnez Modifier pour la référence en question. La boîte de dialogue de modification affiche les informations d’état, y compris les erreurs éventuelles. Si vous ne voyez pas le message d’état, cela signifie que la syntaxe n’est pas valide et n’est pas reconnue comme référence Key Vault.

Vous pouvez également utiliser l’un des détecteurs intégrés pour obtenir plus d’informations.

Pour utiliser le détecteur pour App Service :

  1. Dans le portail Azure, accédez à votre application.
  2. Sélectionnez Diagnostiquer et résoudre les problèmes.
  3. Sélectionnez Disponibilité et performance>Application web en panne.
  4. Dans la zone de recherche, recherchez et sélectionnez Diagnostics des paramètres d’application Key Vault.

Pour utiliser le détecteur pour Azure Functions :

  1. Dans le portail Azure, accédez à votre application.
  2. Accédez aux fonctionnalités de la plateforme.
  3. Sélectionnez Diagnostiquer et résoudre les problèmes.
  4. Sélectionnez Disponibilité et Performance>L'application de fonction est en panne ou signale des erreurs.
  5. Sélectionnez Diagnostics des paramètres d’application Key Vault.