Cloud

Azure Storage : diagnostiquer un endpoint privé sans ouvrir le compte

Un runbook opérationnel pour qualifier les pannes Azure Storage en accès privé en séparant DNS, Private Endpoint, firewall, identité, logs et rollback.

13 juin 2026 azurestorageprivate-endpointdnskqllogsmonitoringrunbookidentityrollbackautomation

Un compte Azure Storage placé derrière un Private Endpoint peut devenir indisponible sans que le service consommateur, le pipeline ou l’application soient directement responsables. La panne peut venir d’une résolution DNS publique, d’un sous-service Storage oublié, d’une règle firewall trop stricte, d’une identité managée sans rôle, d’un changement Terraform incomplet ou d’un client qui utilise encore l’endpoint public.

Le cas d’usage est volontairement courant : une application interne, un job d’automatisation ou une Function doit lire un blob, écrire un fichier ou accéder à une queue via un chemin privé. L’objectif du runbook est de prouver où l’accès échoue avant de rouvrir le compte Storage à tous les réseaux, d’ajouter un rôle trop large ou de relancer un déploiement applicatif.

Lire Storage comme plusieurs endpoints

Un compte Storage n’a pas un seul chemin réseau. Blob, queue, table, file et dfs peuvent chacun avoir leur propre Private Endpoint et leur propre enregistrement DNS. Un diagnostic fiable commence donc par nommer le sous-service réellement appelé.

text storage-private-path.txt
Consommateur
Application, Function, pipeline CI, runbook ou VM de diagnostic
Résout le nom Storage depuis le même réseau que le workload
Envoie un correlation ID ou un client request ID exploitable

DNS privé
privatelink.blob.core.windows.net pour Blob
privatelink.queue.core.windows.net pour Queue
privatelink.table.core.windows.net pour Table
privatelink.file.core.windows.net pour File
privatelink.dfs.core.windows.net pour ADLS Gen2

Compte Storage
Private Endpoint approuvé pour le bon sous-service
Public network access et firewall cohérents avec le design cible
Diagnostic settings activés pour les logs utiles

Identité
Managed identity, service principal ou SAS explicite
Rôle limité au conteneur, à la queue ou au compte nécessaire

Rollback
Restaurer DNS, firewall, rôle ou configuration client selon la couche modifiée

Cette lecture évite une erreur fréquente : valider blob alors que l’application utilise dfs, ou tester depuis un poste qui ne voit pas le même DNS que le workload.

Classer le symptôme avant la correction

Le premier tri consiste à distinguer une panne de chemin privé d’une panne d’autorisation ou d’usage applicatif. Les codes HTTP Storage sont utiles, mais ils doivent être lus avec le point de test et le sous-service.

text storage-private-symptoms.txt
Symptôme
DNS retourne une adresse publique
  Vérifier zone privatelink du sous-service, lien VNet et forwarding DNS hybride

Timeout ou connection refused
  Vérifier Private Endpoint, NSG, route effective et test depuis le réseau consommateur

403 avec AuthenticationFailed ou AuthorizationPermissionMismatch
  Vérifier identité réelle, rôle RBAC, scope et délai de propagation

403 avec firewall ou network rules
  Vérifier public network access, selected networks, trusted services et source réelle

Logs Storage absents pour le client request ID
  Revenir à DNS, routage, endpoint public ou mauvais sous-service

Echec après changement Terraform
  Comparer Private Endpoint, private DNS zone group, firewall et rôle appliqué

La règle est simple : tant que le nom ne résout pas en privé depuis le réseau consommateur, la correction applicative est prématurée.

Tester depuis le réseau consommateur

Le test doit partir d’une VM de diagnostic, d’un runner privé, du subnet applicatif ou d’un bastion d’exploitation qui utilise le même DNS que la charge réelle. Il doit aussi cibler le sous-service exact.

bash 01-storage-private-check.sh
ACCOUNT=stprodorders
SERVICE=blob
HOSTNAME="$ACCOUNT.$SERVICE.core.windows.net"
CONTAINER=health
CLIENT_REQUEST_ID="ops-$(date +%Y%m%d%H%M%S)"

nslookup "$HOSTNAME"
dig +short "$HOSTNAME"

openssl s_client -connect "$HOSTNAME:443" -servername "$HOSTNAME" </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer

az storage blob list --account-name "$ACCOUNT" --container-name "$CONTAINER" --auth-mode login --only-show-errors --debug 2>&1 | tee "storage-$CLIENT_REQUEST_ID.log"

echo "client_request_id=$CLIENT_REQUEST_ID"

Si le test utilise --auth-mode login, il valide aussi l’identité Azure CLI connectée. Pour un workload, il faut ensuite confirmer l’identité runtime réelle : managed identity de l’application, service principal CI, fédération OIDC ou SAS explicitement fourni.

Vérifier le compte sans élargir l’accès

Les commandes suivantes donnent une vue opérationnelle sans exposer de secret. Elles séparent état réseau, Private Endpoints, DNS privé et autorisations.

bash 02-storage-platform-checks.sh
RG=rg-prod-data
ACCOUNT=stprodorders

az storage account show -g "$RG" -n "$ACCOUNT" --query "{kind:kind, sku:sku.name, publicNetworkAccess:publicNetworkAccess, allowBlobPublicAccess:allowBlobPublicAccess, defaultAction:networkRuleSet.defaultAction}" -o jsonc

az storage account network-rule list -g "$RG" -n "$ACCOUNT" -o jsonc

STORAGE_ID=$(az storage account show -g "$RG" -n "$ACCOUNT" --query id -o tsv)

az network private-endpoint-connection list --id "$STORAGE_ID" --query "[].{name:name,status:privateLinkServiceConnectionState.status,groupIds:groupIds,description:privateLinkServiceConnectionState.description}" -o table

az network private-dns zone list --query "[?contains(name, 'privatelink') && contains(name, 'core.windows.net')].name" -o table

az role assignment list --scope "$STORAGE_ID" --query "[].{principal:principalName, role:roleDefinitionName, scope:scope}" -o table

Les écarts fréquents sont visibles ici : Private Endpoint approuvé pour blob mais pas pour dfs, firewall en Deny sans source privée valide, zone privée non liée au VNet consommateur, ou rôle RBAC posé au mauvais scope.

Corréler les accès Storage en KQL

Les logs Storage doivent permettre de séparer refus réseau, refus d’autorisation et client qui appelle le mauvais endpoint. La requête ci-dessous part d’un compte, d’un sous-service et d’une fenêtre courte.

kusto 03-storage-private-access-correlation.kql
let Window = 2h;
let Account = "stprodorders";
StorageBlobLogs
| where TimeGenerated > ago(Window)
| where AccountName == Account
| project TimeGenerated, AccountName, OperationName, StatusCode, StatusText, AuthenticationType, RequesterObjectId, Uri, CallerIpAddress, UserAgentHeader, ClientRequestId
| order by TimeGenerated desc

Lecture rapide : absence de logs avec un test corrélé oriente vers DNS, routage ou mauvais sous-service ; 403 avec identité visible oriente vers RBAC ou SAS ; 403 sans identité utile oriente souvent vers firewall, endpoint public ou signature invalide.

Choisir le rollback minimal

Le rollback ne doit pas rouvrir tout le compte Storage par réflexe. Il doit restaurer la couche qui a changé et fournir une preuve observable.

text storage-private-rollback-matrix.txt
Changement récent
Private DNS zone ou zone group
  Rollback: restaurer l'ancien record, lien VNet ou zone group
  Preuve: résolution privée depuis le workload et log Storage corrélé

Firewall ou public network access
  Rollback: revenir à la règle réseau précédente
  Preuve: même client request ID visible avec status attendu

Rôle RBAC ou identité managée
  Rollback: restaurer le rôle au scope précédent
  Preuve: même identité réussit sans élargir au compte complet si le scope fin suffit

Changement client ou variable d'environnement
  Rollback: restaurer endpoint, sous-service ou credential précédent
  Preuve: le client appelle le hostname privé attendu

Conclusion

Un incident Storage privé se résout rarement par un seul bouton. Il faut nommer le sous-service, tester depuis le bon réseau, prouver la résolution privée, lire les Private Endpoints et corréler les logs avant de toucher au code ou d’ouvrir le firewall.

Cette méthode garde la décision exploitable : corriger DNS quand le chemin est public, corriger Private Endpoint quand le sous-service manque, corriger RBAC quand l’identité est vue mais refusée, et limiter le rollback à la couche réellement modifiée.