Cloud

Key Vault privé Azure : diagnostiquer DNS, identité managée et accès réseau sans tout mélanger

Une méthode opérationnelle pour analyser les échecs d’accès à Azure Key Vault derrière Private Endpoint en séparant résolution DNS, chemin réseau, identité managée, RBAC et configuration applicative.

31 mai 2026 azurekey-vaultprivate-endpointmanaged-identitydnstroubleshooting

Un Key Vault placé derrière un Private Endpoint est souvent perçu comme un verrou réseau simple : l’application est dans Azure, le coffre est privé, l’identité managée lit les secrets, tout devrait fonctionner. En pratique, les pannes se ressemblent trop. Une erreur d’autorisation, une mauvaise résolution DNS, un subnet mal routé ou une configuration applicative incomplète peuvent produire le même symptôme côté application : impossible de récupérer le secret.

Le scénario traité ici est volontairement courant. Une application hébergée sur App Service ou Azure Functions doit lire un secret dans Azure Key Vault. Le coffre n’est plus exposé publiquement, un Private Endpoint existe dans un subnet dédié, une zone DNS privée privatelink.vaultcore.azure.net est liée au VNet, et l’application utilise une identité managée. Après le passage en privé, les lectures échouent de manière intermittente ou permanente.

L’objectif n’est pas de lister toutes les options Key Vault. L’objectif est de construire une méthode de diagnostic relisible : prouver d’abord le nom résolu, puis le chemin réseau, puis l’identité utilisée, puis les droits réellement accordés. Cette séparation évite de corriger une permission alors que le problème est DNS, ou de rouvrir l’accès public alors que seule l’identité de l’application est mal ciblée.

Poser le modèle attendu avant de tester

Avant de lancer des commandes, il faut écrire le chemin attendu. Le coffre a un nom public, même quand son accès utile passe par une adresse privée. L’application appelle généralement https://<vault-name>.vault.azure.net. La résolution DNS doit renvoyer l’adresse privée du Private Endpoint, pas l’adresse publique du service. Ensuite seulement, l’identité de l’application peut être évaluée par Key Vault.

text key-vault-private-path.txt
Application
App Service ou Function App
Identite managee system-assigned ou user-assigned
Integration VNet si le service doit sortir vers le reseau prive

Resolution DNS attendue
myvault.vault.azure.net
-> CNAME myvault.privatelink.vaultcore.azure.net
-> A record prive dans le VNet

Key Vault
Public network access limite ou desactive selon le design
Private Endpoint approuve
RBAC ou access policy alignee avec l'identite applicative

Ce modèle donne une grille de lecture. Si le nom ne résout pas vers une IP privée, l’identité n’a pas encore d’importance. Si le nom résout correctement mais que le token est émis pour une autre identité, le réseau n’est plus le sujet principal. Si le token est bon mais que Key Vault refuse l’opération, il faut regarder RBAC ou les access policies.

Vérifier que le Private Endpoint existe et qu’il est approuvé

Le premier contrôle reste l’état du Private Endpoint. Un endpoint créé mais non approuvé, supprimé puis recréé, ou attaché à un mauvais coffre, donne une base instable au diagnostic. Il faut aussi distinguer le Private Endpoint lui-même de l’enregistrement DNS qui permet aux clients de le trouver.

bash 01-check-private-endpoint.sh
az network private-endpoint show -g rg-network-prod -n pe-kv-prod --query '{name:name, subnet:subnet.id, state:provisioningState, connections:privateLinkServiceConnections[].privateLinkServiceConnectionState}'

az keyvault show -g rg-app-prod -n kv-prod-app --query '{name:name, publicNetworkAccess:properties.publicNetworkAccess, networkAcls:properties.networkAcls.defaultAction}'

Un Private Endpoint en état approuvé ne garantit pas que l’application l’utilise. Il confirme seulement que le point d’entrée privé existe. La question suivante est donc : depuis le contexte réseau de l’application, quel nom est résolu ?

Tester la résolution DNS depuis le bon endroit

Tester le DNS depuis son poste, depuis Azure Cloud Shell ou depuis une VM quelconque peut donner une fausse confiance. Le test doit être fait depuis un point qui partage le même chemin DNS que l’application, ou au minimum depuis une ressource placée dans le même VNet et soumise aux mêmes liens de zones privées.

Pour App Service et Functions, un endpoint de diagnostic temporaire ou la console Kudu peut aider à tester la résolution. Pour une VM de rebond dans le même VNet, nslookup donne déjà une preuve utile.

bash 02-check-dns.sh
nslookup kv-prod-app.vault.azure.net

# Resultat attendu dans le VNet prive
# kv-prod-app.vault.azure.net canonical name = kv-prod-app.privatelink.vaultcore.azure.net
# Address: 10.42.20.14

Si la réponse pointe vers une adresse publique, le problème est probablement DNS : zone privée non liée au VNet, mauvais resolver, forwarder on-premises incomplet, spoke non lié, ou application qui n’utilise pas le chemin DNS attendu après intégration VNet. Dans ce cas, ajouter un rôle Key Vault à l’identité ne changera rien.

Confirmer les liens de zone privée

Pour Key Vault, la zone privée attendue est généralement privatelink.vaultcore.azure.net. Elle doit contenir l’enregistrement du coffre et être liée aux VNets depuis lesquels les clients résolvent le nom. Dans une architecture hub-and-spoke, il faut décider si les spokes résolvent directement via zone link, via Private Resolver, ou via un chemin DNS centralisé. Le point important est que le design soit explicite.

bash 03-check-private-dns-zone.sh
az network private-dns record-set a list -g rg-network-prod -z privatelink.vaultcore.azure.net --query '[].{name:name, records:aRecords[].ipv4Address}'

az network private-dns link vnet list -g rg-network-prod -z privatelink.vaultcore.azure.net --query '[].{name:name, vnet:virtualNetwork.id, registration:registrationEnabled}'

Un enregistrement correct dans la zone ne suffit pas si le VNet consommateur n’est pas lié, ou si les requêtes passent par un resolver qui ne connaît pas cette zone. À l’inverse, multiplier les liens de zones sans modèle de résolution peut rendre les incidents plus difficiles à expliquer.

Séparer accès réseau et autorisation Key Vault

Une fois la résolution privée confirmée, il faut tester la connectivité HTTPS. Une réponse 403 venant de Key Vault est très différente d’un timeout ou d’une erreur DNS. Le 403 prouve souvent que le service répond, mais que l’identité ou la permission ne convient pas. Un timeout indique plutôt un problème de chemin réseau, de routage, de firewall ou de résolution qui ne mène pas au bon endpoint.

bash 04-read-http-signal.sh
curl -I https://kv-prod-app.vault.azure.net/

# Signaux utiles
# 401 ou 403 : Key Vault repond, regarder l'identite et les droits
# Could not resolve host : regarder DNS
# Connection timed out : regarder chemin reseau, integration VNet, routes, NSG, firewall
# Certificate error : verifier interception TLS, hostname et chemin proxy

Ce test ne valide pas l’accès applicatif complet. Il donne simplement une orientation. Dans un incident, cette orientation évite de tout ouvrir pour “voir si ça passe”.

Identifier l’identité réellement utilisée par l’application

L’identité managée peut être system-assigned ou user-assigned. Une application peut aussi avoir plusieurs identités attachées. Le code, le SDK ou la configuration doivent donc utiliser l’identité attendue. Sinon, les droits peuvent être accordés à la bonne identité sur le papier, mais l’application présente un autre principal à Key Vault.

bash 05-check-managed-identity.sh
az webapp identity show -g rg-app-prod -n app-prod-api --query '{principalId:principalId, tenantId:tenantId, userAssignedIdentities:userAssignedIdentities}'

az functionapp identity show -g rg-app-prod -n func-prod-worker --query '{principalId:principalId, tenantId:tenantId, userAssignedIdentities:userAssignedIdentities}'

Pour une user-assigned managed identity, le code ou la configuration peut devoir préciser un client ID. C’est un point classique quand une application fonctionne en développement avec une identité locale ou une identité par défaut, puis échoue en production parce que la chaîne d’authentification ne sélectionne pas le principal attendu.

Vérifier le modèle de permissions du coffre

Key Vault peut utiliser Azure RBAC ou le modèle historique d’access policies selon la configuration. Le diagnostic doit respecter le modèle actif. Mélanger les deux lectures produit des conclusions fausses : on peut voir une access policy correcte alors que le coffre utilise RBAC, ou chercher un rôle RBAC alors que les access policies pilotent encore les droits.

bash 06-check-key-vault-permissions.sh
az keyvault show -g rg-app-prod -n kv-prod-app --query '{enableRbacAuthorization:properties.enableRbacAuthorization}'

az role assignment list --assignee 00000000-0000-0000-0000-000000000000 --scope /subscriptions/<sub>/resourceGroups/rg-app-prod/providers/Microsoft.KeyVault/vaults/kv-prod-app --query '[].{role:roleDefinitionName, scope:scope}'

az keyvault show -g rg-app-prod -n kv-prod-app --query 'properties.accessPolicies[].{objectId:objectId, permissions:permissions}'

Le rôle ou la policy doit correspondre à l’opération réelle. Lire un secret, lister les secrets, lire une clé ou déchiffrer avec une clé ne sont pas les mêmes actions. Pour réduire le risque, il vaut mieux donner le droit nécessaire à l’application que des permissions larges “pour débloquer”.

Construire une preuve d’incident exploitable

Quand l’incident est résolu, il faut conserver la preuve du diagnostic. Une note courte dans le ticket suffit souvent, à condition qu’elle sépare les couches. Cela aide aussi à éviter la même confusion lors du prochain changement réseau.

text key-vault-incident-evidence.txt
Incident Key Vault prive
Application : app-prod-api
Coffre : kv-prod-app
FQDN teste : kv-prod-app.vault.azure.net
DNS depuis VNet applicatif : 10.42.20.14 via privatelink.vaultcore.azure.net
Private Endpoint : approuve
Signal HTTP : 403 Key Vault, pas timeout
Identite presentee : system-assigned principalId app-prod-api
Cause : role de lecture secret absent sur le coffre
Correction : attribution Key Vault Secrets User au scope du coffre
Controle apres correction : lecture du secret applicatif OK

Ce format rend la conclusion défendable. Il montre que le réseau privé fonctionnait, que Key Vault répondait, et que la correction portait sur l’autorisation plutôt que sur une ouverture réseau.

Erreurs fréquentes à éviter

La première erreur consiste à réactiver l’accès public pour vérifier rapidement. Ce test peut masquer le problème réel et laisser une exception oubliée. Si un contournement temporaire est indispensable, il doit être tracé, limité et retiré.

La deuxième erreur consiste à accorder des droits trop larges à l’identité. Un rôle élevé au niveau du groupe de ressources peut débloquer la lecture, mais il élargit inutilement le périmètre. Le diagnostic doit viser le droit utile au bon scope.

La troisième erreur consiste à tester depuis le mauvais réseau. Un poste administrateur qui résout correctement le coffre ne prouve pas que l’application le résout. Dans une architecture privée, l’endroit d’où l’on teste fait partie du résultat.

La quatrième erreur consiste à oublier les applications serverless. Une Function App ou un App Service qui doit joindre un service privé a besoin d’un design de sortie cohérent : intégration VNet, DNS, routes éventuelles et dépendances de plateforme comprises.

Conclusion

Un Key Vault privé ne se diagnostique pas en bloc. Il faut séparer le nom, le chemin, l’identité et le droit. La résolution DNS prouve que l’application vise le Private Endpoint. Le signal HTTP distingue un service joignable d’un chemin cassé. L’identité managée dit qui parle à Key Vault. RBAC ou access policies décident enfin si cette identité peut lire le secret attendu.

Cette méthode est plus lente qu’un changement à l’aveugle, mais elle produit un résultat exploitable : une correction ciblée, une preuve relisible et un design qui reste privé sans devenir incompréhensible au premier incident.