Le message d’erreur indique que votre Function App ne parvient plus à récupérer les secrets depuis le Key Vault parce que le mécanisme d’authentification (DefaultAzureCredential
) ne trouve aucun moyen valide de se connecter. En d’autres termes, quand votre code (dans FunctionStartupBase.ConfigureAppConfiguration
) appelle quelque chose comme :
builder.ConfigurationBuilder
.AddAzureKeyVault(
new Uri(keyVaultUri),
new DefaultAzureCredential());
le DefaultAzureCredential
va essayer, dans l’ordre, plusieurs méthodes d’obtention de jeton (environnement, identité managée, VS/VS Code, Azure CLI, Azure PowerShell), et – dans votre cas – toutes échouent :
- EnvironmentCredential : il n’y a pas (ou plus) de variables d’environnement (
AZURE_CLIENT_ID
,AZURE_TENANT_ID
,AZURE_CLIENT_SECRET
) qui permettent à un client de se faire authentifier.
ManagedIdentityCredential : la Function App n’a pas d’identité managée (vous l’avez supprimée pour tester l’isolated worker), donc l’appel au point de terminaison d’IMDS (169.254.169.254:80
) est bloqué et renvoie une erreur de « socket forbidden ».
VisualStudioCredential / VisualStudioCodeCredential / AzureCliCredential / AzurePowerShellCredential : aucun de ces outils n’est disponible en production (dans Azure Functions), ou bien ils ne sont pas configurés. D’où l’erreur « Azure CLI not installed », « Az.Account module >= 2.2.0 not installed », etc.
- Pourquoi votre Function App fonctionnait avant, et plus maintenant
Avant : vous aviez une identité managée associée à la Function App (soit « System-assigned », soit une identité user-assigned), et vous aviez donné à cette identité les droits « Get » + « List » sur le Key Vault (via une access policy ou via RBAC Key Vault Secrets User).
Dans ce contexte, DefaultAzureCredential
avait accès à l’endpoint géré (IMDS) et obtenait un jeton auprès de l’Azure Instance Metadata Service.
Les fonctions s’exécutaient, les secrets étaient lus, et tout marchait.
**Pendant votre migration (in-process → isolated, .NET 6 → .NET 8)** :
Vous avez **supprimé** l’identité managée (pour « tester » l’isolated worker ou parce que le message de migration vous l’indiquait).
De fait, la Function App n’avait plus d’identité managée, donc `ManagedIdentityCredential` ne pouvait plus fonctionner.
Vous n’aviez pas non plus de variables d’environnement pour un service principal, ni d’autre méthode valide pour que `DefaultAzureCredential` récupère un jeton.
Conséquence : au démarrage, `AddAzureKeyVault(...)` lève `CredentialUnavailableException`.
**Après votre retour au paramétrage initial** :
Vous avez remis la configuration « à l’identique » avant la migration (même code, même version de .NET, mêmes settings), **mais vous n’avez vraisemblablement pas réactivé (ou reparamétré) l’identité managée** dans le portail Azure.
Du coup, même si le code `AddAzureKeyVault` est revenu comme avant, la Function App n’a toujours plus d’identité managée configurée, donc l’authentification échoue toujours.
- Comment résoudre pas à pas
2.1. Réactiver (ou recréer) l’identité managée
Dans le Portail Azure, ouvrez votre Function App concernée.
Allez dans la section Identity (Identité).
Sous « System assigned », passez le commutateur sur On, puis Enregistrer.
Azure alloue alors une identité managée au niveau de la Function App et génère automatiquement un objet principal dans Azure AD.
Notez l’ID d’objet (object ID) si vous devez l’ajouter manuellement aux politiques du Key Vault, mais ce n’est généralement pas nécessaire pour un accès en RBAC.
2.2. Donner les droits sur le Key Vault
Il y a deux manières principales de donner à cette identité managée l’accès aux secrets :
a) Via Access policies (politiques d’accès classiques) – (méthode “Legacy”)
Ouvrez le Key Vault concerné.
Dans le menu latéral, choisissez Access policies.
Cliquez sur + Add Access Policy.
Pour « Secret permissions », sélectionnez au minimum Get et List (voire Set, Delete si votre code en a besoin, mais généralement Get suffit).
Cliquez sur **Select principal**, recherchez le nom de votre Function App (ou l’objet principal créé à l’étape précédente) et validez.
Validez à nouveau pour créer la nouvelle politique d’accès.
N’oubliez pas de cliquer sur **Save** pour enregistrer les modifications.
b) Via Azure RBAC (recommandé pour les nouveaux déploiements)
Ouvrez le Key Vault.
Dans le menu, cliquez sur Access control (IAM).
Cliquez sur + Add > Add role assignment.
Dans Role, choisissez Key Vault Secrets User (ou Key Vault Secrets Officer si vous prévoyez aussi d’écrire des secrets).
Dans **Assign access to**, sélectionnez **Managed identity**.
Cliquez sur **Select members**, cherchez votre Function App, sélectionnez-la, puis validez.
Cliquez sur **Save** (ou **Review + assign**).
Pourquoi RBAC plutôt que Access policies ? À partir de 2024, Microsoft pousse vers l’usage d’Azure RBAC pour Key Vault (cela permet de gérer l’accès via des rôles standards plutôt que des policies héritées). Les deux méthodes fonctionnent, mais si vous utilisez déjà RBAC pour d’autres ressources, c’est plus cohérent.
2.3. Vérifier la configuration de vos settings
Dans la Function App, ouvrez Configuration > Application settings.
Assurez-vous que la variable contenant l’URL du Key Vault est correctement définie ; par exemple, si votre code lit :
var keyVaultUri = Environment.GetEnvironmentVariable("KEY_VAULT_URI");
alors la setting KEY_VAULT_URI doit être égale à quelque chose comme
https://mon-vault-name.vault.azure.net/
Vérifiez également que vous n’avez pas accidentellement renseigné des variables d’environnement incomplètes pour un EnvironmentCredential
(n’insérez pas de AZURE_CLIENT_ID
ou AZURE_CLIENT_SECRET
à moins que vous les ayez créés comme service principal ; autrement, laissez-les vides).
Si vous aviez supprimé l’identité, il se peut qu’il reste des settings propres à l’isolated worker ou un WEBSITE_LOAD_USER_PROFILE
que vous avez modifié ; remettez-les « comme avant » si vous les avez changés.
Vérifiez également la présence de AzureWebJobsStorage (obligatoire à l’exécution) et FUNCTIONS_WORKER_RUNTIME (doit être dotnet-isolated
ou dotnet
selon votre modèle) – mais ça ne concerne pas directement le Key Vault.
2.4. Redéployer et tester
Après avoir réactivé l’identité managée (et donné les droits sur le Key Vault), redémarrez la Function App (bouton Restart).
Consultez les Log Stream (dans Monitoring > Log Stream) pour vérifier que l’erreur CredentialUnavailableException
n’apparaît plus pour le Key Vault.
Vérifiez que vos fonctions sont de nouveau listées dans Functions et que l’URL de chaque fonction inclut bien le ?code=…
(la signature hérité de la Function key).
Si les clés (les host keys
ou les function keys
) ne s’affichent toujours pas, c’est probablement parce que vous aviez modifié un paramètre du runtime lors de la migration vers l’isolated worker.
Dans ce cas, assurez-vous que votre `host.json` n’a pas de section qui désactive la protection par clé, par exemple :
```json
{
"version": "2.0", "extensions": { "http": { "routePrefix": "" } }, "functions": [ "MyFunction1", "MyFunction2" ] } ```
Vérifiez aussi que **Authentication / Authorization** (dans le menu latéral) n’a pas été configuré pour ouvrir librement les endpoints.
- Pourquoi le message « Error building configuration in an external startup class » persiste
Le texte complet indique que c’est le chargement de la configuration (en particulier AzureKeyVaultConfigurationProvider
) qui échoue, précisément au moment où il tente :
var credential = new DefaultAzureCredential();
var builder = new ConfigurationBuilder()
.AddAzureKeyVault(new Uri(keyVaultUri), credential)
.AddEnvironmentVariables();
Tant que DefaultAzureCredential
ne trouve pas au moins un mode valide pour authentifier (identité managée, variables d’environnement, etc.), le provider Key Vault lève une exception, et donc l’host de Azure Functions n’arrive pas à « construire » la configuration, d’où l’erreur globale dans ExternalStartupException
.
En résumé :
Vous avez supprimé l’identité managée, or c’est la voie d’authentification principale en production pour un DefaultAzureCredential
.
Vous n’avez pas compensé en ajoutant un service principal via variables d’environnement (AZURE_CLIENT_ID/TENANT/SECRET).
Même si vous avez remis le code « exactement comme avant », la Function App n’a plus d’identité (laquel ne se réactive pas automatiquement).
Par conséquent, DefaultAzureCredential
ne parvient plus à s’authentifier → erreur persistante.
- Résumé des actions à mener
Réactiver l’identité managée (System-assigned) dans le portail Azure pour votre Function App.
Accorder le rôle « Key Vault Secrets User » (ou « Get + List » via Access policies classiques) à cette identité sur le Key Vault.
Vérifier vos Application Settings :
Que KEY_VAULT_URI
(ou équivalent) pointe bien vers l’URL complète de votre vault (https://…vault.azure.net/
).
Que vous n’avez pas laissé des variables d’environnement partielles pour un `EnvironmentCredential` qui empêcherait la chaîne `DefaultAzureCredential` de « sauter » rapidement sur l’identité managée.
**Redémarrer la Function App**, surveiller le **Log Stream**, et s’assurer que l’erreur `Azure.Identity.CredentialUnavailableException` n’apparaît plus.
Une fois l’authentification à Key Vault rétablie, vos fonctions devraient à nouveau se lister (puisque la configuration a pu se charger). Vous retrouverez aussi les URL protégées par leur clé (ex. `https://…/api/MyFunction?code=XYZ`).
Note sur les URL de fonction (clé de fonction)
Si, dans le portail, vous allez dans Functions > (votre fonction) > Manage, vous devrez voir la « Function key » (la valeur ?code=…
) sous forme, par exemple, de master key ou de function key.
Si ces clés sont toujours absentes, vérifiez que vous n’avez pas, au niveau du host.json
ou d’une extension, désactivé la validation par clé HTTP. Par défaut, Azure Functions exige une clé pour quiconque appelle GET/POST /api/votreFonction
. Si vous la retirez, l’URL peut rester publique, mais ce n’est pas conseillé en production.
- Si, pour une raison spécifique, vous ne voulez pas (ou ne pouvez pas) repasser par l’identité managée
Il existe deux alternatives :
Service Principal + variables d’environnement
Créez un Service Principal dans Azure AD (via az ad sp create-for-rbac --name "mon-sp"
ou équivalent).
Dans le Key Vault, créez une **Access policy** pour ce SP (Get + List).
Dans la Function App, ajoutez dans **Configuration > Application settings** :
```sql
AZURE_CLIENT_ID = <clientId du SP>
AZURE_TENANT_ID = <tenantId> AZURE_CLIENT_SECRET= <secret généré> KEY_VAULT_URI = https://mon-vault-name.vault.azure.net/ ```
`DefaultAzureCredential` va alors détecter ces trois variables et s’authentifier via l’`EnvironmentCredential`.
**Inconvénient** : le secret est stocké dans les App Settings, et il faut le renouveler manuellement si jamais il expire.
**Azure Managed Identity + Browsersync**
Si votre code démarre parfois en local (Visual Studio, VS Code), installez l’extension Azure Account et signez-vous ; ainsi, `VisualStudioCredential` ou `VisualStudioCodeCredential` pourrait fonctionner durant le debug local.
En revanche, en production, il faut à minima l’identité managée ou les variables d’environnement.
- En conclusion
Le cœur du problème : DefaultAzureCredential
ne trouve aucun moyen valide de s’authentifier parce que vous avez supprimé l’identité managée et vous n’avez pas fourni d’EnvironmentCredential
.
La solution la plus simple est de réactiver l’identité managée de la Function App et de redonner les droits d’accès au Key Vault. Après redémarrage, l’authentification se fera automatiquement via cette identité.
Une fois l’accès au Key Vault rétabli, l’erreur « Error building configuration in an external startup class » disparaîtra, vos fonctions seront à nouveau listées, et chaque URL aura bien son ?code=…
(la clé) comme précédemment.
N’hésitez pas à me faire savoir si, après avoir suivi ces étapes, vous rencontrez encore des difficultés ou si un autre message d’erreur apparaît !Le message d’erreur indique que votre Function App ne parvient plus à récupérer les secrets depuis le Key Vault parce que le mécanisme d’authentification (DefaultAzureCredential
) ne trouve aucun moyen valide de se connecter. En d’autres termes, quand votre code (dans FunctionStartupBase.ConfigureAppConfiguration
) appelle quelque chose comme :
builder.ConfigurationBuilder
.AddAzureKeyVault(
new Uri(keyVaultUri),
new DefaultAzureCredential());
le DefaultAzureCredential
va essayer, dans l’ordre, plusieurs méthodes d’obtention de jeton (environnement, identité managée, VS/VS Code, Azure CLI, Azure PowerShell), et – dans votre cas – toutes échouent :
EnvironmentCredential : il n’y a pas (ou plus) de variables d’environnement (AZURE_CLIENT_ID
, AZURE_TENANT_ID
, AZURE_CLIENT_SECRET
) qui permettent à un client de se faire authentifier.
ManagedIdentityCredential : la Function App n’a pas d’identité managée (vous l’avez supprimée pour tester l’isolated worker), donc l’appel au point de terminaison d’IMDS (169.254.169.254:80
) est bloqué et renvoie une erreur de « socket forbidden ».
VisualStudioCredential / VisualStudioCodeCredential / AzureCliCredential / AzurePowerShellCredential : aucun de ces outils n’est disponible en production (dans Azure Functions), ou bien ils ne sont pas configurés. D’où l’erreur « Azure CLI not installed », « Az.Account module >= 2.2.0 not installed », etc.
- Pourquoi votre Function App fonctionnait avant, et plus maintenant
Avant : vous aviez une identité managée associée à la Function App (soit « System-assigned », soit une identité user-assigned), et vous aviez donné à cette identité les droits « Get » + « List » sur le Key Vault (via une access policy ou via RBAC Key Vault Secrets User).
Dans ce contexte, DefaultAzureCredential
avait accès à l’endpoint géré (IMDS) et obtenait un jeton auprès de l’Azure Instance Metadata Service.
Les fonctions s’exécutaient, les secrets étaient lus, et tout marchait.
**Pendant votre migration (in-process → isolated, .NET 6 → .NET 8)** :
Vous avez **supprimé** l’identité managée (pour « tester » l’isolated worker ou parce que le message de migration vous l’indiquait).
De fait, la Function App n’avait plus d’identité managée, donc `ManagedIdentityCredential` ne pouvait plus fonctionner.
Vous n’aviez pas non plus de variables d’environnement pour un service principal, ni d’autre méthode valide pour que `DefaultAzureCredential` récupère un jeton.
Conséquence : au démarrage, `AddAzureKeyVault(...)` lève `CredentialUnavailableException`.
**Après votre retour au paramétrage initial** :
Vous avez remis la configuration « à l’identique » avant la migration (même code, même version de .NET, mêmes settings), **mais vous n’avez vraisemblablement pas réactivé (ou reparamétré) l’identité managée** dans le portail Azure.
Du coup, même si le code `AddAzureKeyVault` est revenu comme avant, la Function App n’a toujours plus d’identité managée configurée, donc l’authentification échoue toujours.
- Comment résoudre pas à pas
2.1. Réactiver (ou recréer) l’identité managée
Dans le Portail Azure, ouvrez votre Function App concernée.
Allez dans la section Identity (Identité).
Sous « System assigned », passez le commutateur sur On, puis Enregistrer.
Azure alloue alors une identité managée au niveau de la Function App et génère automatiquement un objet principal dans Azure AD.
Notez l’ID d’objet (object ID) si vous devez l’ajouter manuellement aux politiques du Key Vault, mais ce n’est généralement pas nécessaire pour un accès en RBAC.
2.2. Donner les droits sur le Key Vault
Il y a deux manières principales de donner à cette identité managée l’accès aux secrets :
a) Via Access policies (politiques d’accès classiques) – (méthode “Legacy”)
Ouvrez le Key Vault concerné.
Dans le menu latéral, choisissez Access policies.
Cliquez sur + Add Access Policy.
Pour « Secret permissions », sélectionnez au minimum Get et List (voire Set, Delete si votre code en a besoin, mais généralement Get suffit).
Cliquez sur **Select principal**, recherchez le nom de votre Function App (ou l’objet principal créé à l’étape précédente) et validez.
Validez à nouveau pour créer la nouvelle politique d’accès.
N’oubliez pas de cliquer sur **Save** pour enregistrer les modifications.
b) Via Azure RBAC (recommandé pour les nouveaux déploiements)
Ouvrez le Key Vault.
Dans le menu, cliquez sur Access control (IAM).
Cliquez sur + Add > Add role assignment.
Dans Role, choisissez Key Vault Secrets User (ou Key Vault Secrets Officer si vous prévoyez aussi d’écrire des secrets).
Dans **Assign access to**, sélectionnez **Managed identity**.
Cliquez sur **Select members**, cherchez votre Function App, sélectionnez-la, puis validez.
Cliquez sur **Save** (ou **Review + assign**).
Pourquoi RBAC plutôt que Access policies ? À partir de 2024, Microsoft pousse vers l’usage d’Azure RBAC pour Key Vault (cela permet de gérer l’accès via des rôles standards plutôt que des policies héritées). Les deux méthodes fonctionnent, mais si vous utilisez déjà RBAC pour d’autres ressources, c’est plus cohérent.
2.3. Vérifier la configuration de vos settings
Dans la Function App, ouvrez Configuration > Application settings.
Assurez-vous que la variable contenant l’URL du Key Vault est correctement définie ; par exemple, si votre code lit :
var keyVaultUri = Environment.GetEnvironmentVariable("KEY_VAULT_URI");
alors la setting KEY_VAULT_URI doit être égale à quelque chose comme
https://mon-vault-name.vault.azure.net/
Vérifiez également que vous n’avez pas accidentellement renseigné des variables d’environnement incomplètes pour un EnvironmentCredential
(n’insérez pas de AZURE_CLIENT_ID
ou AZURE_CLIENT_SECRET
à moins que vous les ayez créés comme service principal ; autrement, laissez-les vides).
Si vous aviez supprimé l’identité, il se peut qu’il reste des settings propres à l’isolated worker ou un WEBSITE_LOAD_USER_PROFILE
que vous avez modifié ; remettez-les « comme avant » si vous les avez changés.
Vérifiez également la présence de AzureWebJobsStorage (obligatoire à l’exécution) et FUNCTIONS_WORKER_RUNTIME (doit être dotnet-isolated
ou dotnet
selon votre modèle) – mais ça ne concerne pas directement le Key Vault.
2.4. Redéployer et tester
Après avoir réactivé l’identité managée (et donné les droits sur le Key Vault), redémarrez la Function App (bouton Restart).
Consultez les Log Stream (dans Monitoring > Log Stream) pour vérifier que l’erreur CredentialUnavailableException
n’apparaît plus pour le Key Vault.
Vérifiez que vos fonctions sont de nouveau listées dans Functions et que l’URL de chaque fonction inclut bien le ?code=…
(la signature hérité de la Function key).
Si les clés (les host keys
ou les function keys
) ne s’affichent toujours pas, c’est probablement parce que vous aviez modifié un paramètre du runtime lors de la migration vers l’isolated worker.
Dans ce cas, assurez-vous que votre `host.json` n’a pas de section qui désactive la protection par clé, par exemple :
```json
{
"version": "2.0", "extensions": { "http": { "routePrefix": "" } }, "functions": [ "MyFunction1", "MyFunction2" ] } ```
Vérifiez aussi que **Authentication / Authorization** (dans le menu latéral) n’a pas été configuré pour ouvrir librement les endpoints.
- Pourquoi le message « Error building configuration in an external startup class » persiste
Le texte complet indique que c’est le chargement de la configuration (en particulier AzureKeyVaultConfigurationProvider
) qui échoue, précisément au moment où il tente :
var credential = new DefaultAzureCredential();
var builder = new ConfigurationBuilder()
.AddAzureKeyVault(new Uri(keyVaultUri), credential)
.AddEnvironmentVariables();
Tant que DefaultAzureCredential
ne trouve pas au moins un mode valide pour authentifier (identité managée, variables d’environnement, etc.), le provider Key Vault lève une exception, et donc l’host de Azure Functions n’arrive pas à « construire » la configuration, d’où l’erreur globale dans ExternalStartupException
.
En résumé :
Vous avez supprimé l’identité managée, or c’est la voie d’authentification principale en production pour un DefaultAzureCredential
.
Vous n’avez pas compensé en ajoutant un service principal via variables d’environnement (AZURE_CLIENT_ID/TENANT/SECRET).
Même si vous avez remis le code « exactement comme avant », la Function App n’a plus d’identité (laquel ne se réactive pas automatiquement).
Par conséquent, DefaultAzureCredential
ne parvient plus à s’authentifier → erreur persistante.
- Résumé des actions à mener
Réactiver l’identité managée (System-assigned) dans le portail Azure pour votre Function App.
Accorder le rôle « Key Vault Secrets User » (ou « Get + List » via Access policies classiques) à cette identité sur le Key Vault.
Vérifier vos Application Settings :
Que KEY_VAULT_URI
(ou équivalent) pointe bien vers l’URL complète de votre vault (https://…vault.azure.net/
).
Que vous n’avez pas laissé des variables d’environnement partielles pour un `EnvironmentCredential` qui empêcherait la chaîne `DefaultAzureCredential` de « sauter » rapidement sur l’identité managée.
**Redémarrer la Function App**, surveiller le **Log Stream**, et s’assurer que l’erreur `Azure.Identity.CredentialUnavailableException` n’apparaît plus.
Une fois l’authentification à Key Vault rétablie, vos fonctions devraient à nouveau se lister (puisque la configuration a pu se charger). Vous retrouverez aussi les URL protégées par leur clé (ex. `https://…/api/MyFunction?code=XYZ`).
Note sur les URL de fonction (clé de fonction)
Si, dans le portail, vous allez dans Functions > (votre fonction) > Manage, vous devrez voir la « Function key » (la valeur ?code=…
) sous forme, par exemple, de master key ou de function key.
Si ces clés sont toujours absentes, vérifiez que vous n’avez pas, au niveau du host.json
ou d’une extension, désactivé la validation par clé HTTP. Par défaut, Azure Functions exige une clé pour quiconque appelle GET/POST /api/votreFonction
. Si vous la retirez, l’URL peut rester publique, mais ce n’est pas conseillé en production.
- Si, pour une raison spécifique, vous ne voulez pas (ou ne pouvez pas) repasser par l’identité managée
Il existe deux alternatives :
Service Principal + variables d’environnement
Créez un Service Principal dans Azure AD (via az ad sp create-for-rbac --name "mon-sp"
ou équivalent).
Dans le Key Vault, créez une **Access policy** pour ce SP (Get + List).
Dans la Function App, ajoutez dans **Configuration > Application settings** :
```sql
AZURE_CLIENT_ID = <clientId du SP>
AZURE_TENANT_ID = <tenantId> AZURE_CLIENT_SECRET= <secret généré> KEY_VAULT_URI = https://mon-vault-name.vault.azure.net/ ```
`DefaultAzureCredential` va alors détecter ces trois variables et s’authentifier via l’`EnvironmentCredential`.
**Inconvénient** : le secret est stocké dans les App Settings, et il faut le renouveler manuellement si jamais il expire.
**Azure Managed Identity + Browsersync**
Si votre code démarre parfois en local (Visual Studio, VS Code), installez l’extension Azure Account et signez-vous ; ainsi, `VisualStudioCredential` ou `VisualStudioCodeCredential` pourrait fonctionner durant le debug local.
En revanche, en production, il faut à minima l’identité managée ou les variables d’environnement.
- En conclusion
Le cœur du problème : DefaultAzureCredential
ne trouve aucun moyen valide de s’authentifier parce que vous avez supprimé l’identité managée et vous n’avez pas fourni d’EnvironmentCredential
.
La solution la plus simple est de réactiver l’identité managée de la Function App et de redonner les droits d’accès au Key Vault. Après redémarrage, l’authentification se fera automatiquement via cette identité.
- Une fois l’accès au Key Vault rétabli, l’erreur « Error building configuration in an external startup class » disparaîtra, vos fonctions seront à nouveau listées, et chaque URL aura bien son
?code=…
(la clé) comme précédemment.