Infrastructure
Identité managée Azure : diagnostiquer l’accès privé avant de changer les droits
Construire un runbook pour qualifier une panne d’accès Key Vault, Storage ou API privée avec identité managée, RBAC, DNS privé, logs et preuve d’exécution réelle.
Une identité managée échoue rarement toute seule. Quand un workload Azure ne lit plus un secret Key Vault, n’écrit plus dans un compte Storage ou ne joint plus une API interne, le diagnostic part souvent trop vite vers le RBAC : ajouter un rôle, élargir une permission, relancer le service. En production, cette réaction peut masquer le vrai problème : mauvais principal, accès testé avec un compte admin, résolution DNS publique, Private Endpoint non joignable, propagation RBAC incomplète ou cache applicatif.
Le cas d’usage est celui d’une application ou d’une automatisation qui s’exécute dans un chemin privé Azure : App Service avec VNet Integration, Function, VM, runner CI, job AWX ou conteneur de diagnostic. Elle utilise une identité managée pour accéder à Key Vault, Storage ou une API protégée. L’objectif du runbook n’est pas seulement de “redonner l’accès”. Il doit prouver quelle identité exécute réellement l’appel, par quel chemin réseau elle passe, quel contrôle refuse la requête et quelle correction reste bornée.
Commencer par l’identité réelle d’exécution
La première erreur consiste à valider l’accès depuis le poste d’un opérateur ou depuis Azure Cloud Shell, puis à conclure que le workload dispose des mêmes droits. Une identité managée est attachée à une ressource ou assignée explicitement. Le runbook doit donc identifier le principal qui fait l’appel en production.
# Depuis le contexte Azure, identifier les identités assignées au workload.
az webapp identity show --resource-group rg-prod-app --name app-private-api --query '{principalId:principalId, tenantId:tenantId, userAssigned:userAssignedIdentities}'
# Pour une VM, vérifier aussi les identités user-assigned.
az vm identity show --resource-group rg-prod-runners --name vm-runner-01 --query '{principalId:principalId, userAssigned:userAssignedIdentities}' Cette étape évite un diagnostic trompeur. Si le pipeline, le worker de nuit et l’application web n’utilisent pas la même identité, un test réussi sur l’un ne prouve rien pour les autres.
Séparer autorisation, réseau et DNS
Un refus d’accès Key Vault ou Storage peut venir de plusieurs couches. Le RBAC dit si l’identité a le droit d’agir. Le pare-feu de la ressource dit si le réseau source est autorisé. Le Private Endpoint et le DNS privé disent si le chemin atteint bien l’adresse privée. L’application, elle, peut encore présenter un token pour le mauvais tenant ou garder une configuration ancienne.
Le runbook doit forcer cette séparation.
Question
Quelle identité émet l'appel ?
Quel rôle RBAC ou access policy couvre l'action ?
Le nom résout-il vers une adresse privée depuis le workload ?
Le firewall de la ressource accepte-t-il ce chemin ?
Les logs montrent-ils un refus réseau ou un refus identité ?
L'application a-t-elle relu sa configuration et son token ?
Décision
Ne pas ajouter de rôle tant que le chemin réseau n'est pas qualifié
Ne pas modifier le DNS tant que le principal réel n'est pas confirmé
Ne pas révoquer l'ancien accès tant que les consommateurs critiques ne sont pas validés Cette grille limite les corrections larges. Elle permet aussi d’expliquer pourquoi une application échoue alors que le même secret est lisible depuis une VM d’administration.
Vérifier le chemin privé depuis le workload
Le test réseau doit partir du même réseau que l’appel applicatif. Si Key Vault ou Storage est protégé par Private Endpoint, la résolution DNS doit pointer vers l’adresse privée attendue. Une résolution publique peut produire un refus réseau qui ressemble à une panne d’identité.
HOST=kv-prod-app.vault.azure.net
nslookup "$HOST"
resolved_ip="$(dig +short "$HOST" | tail -n 1)"
case "$resolved_ip" in
10.*|172.16.*|172.17.*|172.18.*|172.19.*|172.2*|172.30.*|172.31.*|192.168.*)
echo "private_resolution_ok=$resolved_ip"
;;
*)
echo "unexpected_public_or_empty_resolution=$resolved_ip"
exit 2
;;
esac Si ce check échoue, la bonne correction se situe probablement dans la zone DNS privée, le lien VNet, le forwarding hybride ou le point d’exécution du runner. Ajouter un rôle RBAC ne changera rien.
Lire les logs comme preuve, pas comme bruit
Les logs doivent distinguer un refus par identité d’un refus par réseau. Sur Key Vault, les journaux de diagnostic peuvent exposer l’opération, le résultat, l’adresse appelante et l’identité lorsque la plateforme les capture. L’idée n’est pas de dépendre d’un schéma unique, mais de garder une requête de tri utilisable pendant incident.
let Window = 6h;
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where ResourceProvider == "MICROSOFT.KEYVAULT"
| where ResultType !in ("Success", "Succeeded")
| project TimeGenerated,
Resource,
OperationName,
ResultType,
ResultSignature,
CallerIPAddress,
Identity=tostring(Identity),
ClientRequestId
| order by TimeGenerated desc La lecture attendue est simple : si l’identité est absente ou inattendue, revenir au contexte d’exécution. Si l’adresse source est publique ou inconnue, revenir au chemin privé. Si l’identité est correcte et le réseau cohérent, alors seulement le RBAC ou la policy devient le sujet principal.
Construire une correction bornée
Une correction d’urgence doit rester réversible. Ajouter Contributor, ouvrir l’accès public ou désactiver temporairement le firewall peut restaurer le service, mais ces gestes détruisent les preuves et créent souvent une dette silencieuse. Le runbook doit préférer des actions ciblées.
Correction ciblée
Assigner le rôle minimal à l'identité réelle
Corriger le lien de zone DNS privée plutôt que contourner Private Endpoint
Tester depuis le workload ou le runner concerné
Garder l'ancien chemin actif seulement si rollback nécessaire
Supprimer l'exception temporaire avec propriétaire et date limite
Documenter logs, identité, rôle, réseau source et validation Le rollback doit lui aussi être précis. Si une identité précédente reste nécessaire, elle doit être tracée avec une date de retrait. Si un accès réseau temporaire est ouvert, il doit être fermé après validation applicative.
Intégrer le check dans l’automatisation
Pour une plateforme opérée par pipelines ou jobs AWX, le diagnostic doit pouvoir être lancé sans improvisation. Un job contrôlé peut collecter l’identité assignée, tester la résolution DNS, appeler un endpoint de santé et afficher les dernières erreurs Key Vault ou Storage. L’important est de ne jamais exposer de secret dans les logs.
Sortie attendue du job de diagnostic
Workload ou runner testé
PrincipalId utilisé
Nom résolu et adresse obtenue
Ressource cible et opération testée
Derniers refus observés dans les logs
Correction recommandée: identité, DNS, réseau ou RBAC
Aucune valeur secrète affichée Cette sortie transforme un incident flou en décision exploitable. L’équipe sait si elle doit corriger une affectation d’identité, un rôle, une zone DNS privée ou une configuration applicative.
Conclusion
Diagnostiquer une panne d’identité managée ne consiste pas à ajouter des droits jusqu’à ce que l’appel fonctionne. Le bon runbook prouve d’abord l’identité réelle, le chemin réseau, la résolution DNS et le type de refus observé dans les logs.
Cette discipline protège deux choses en même temps : la disponibilité, parce que la correction vise la bonne couche, et la sécurité, parce que les exceptions restent minimales, tracées et réversibles. Une identité managée devient alors un mécanisme exploitable, pas une boîte noire que l’on élargit au moindre incident.