Cloud
Azure App Service : diagnostiquer un endpoint privé avant de redéployer
Construire un runbook opérationnel pour les pannes App Service en accès privé en séparant DNS, Private Endpoint, access restrictions, Application Gateway, logs applicatifs et rollback.
Un App Service exposé en privé peut échouer sans que le dernier déploiement applicatif soit responsable. Le nom peut encore résoudre vers l’adresse publique, le Private Endpoint peut être approuvé mais absent du réseau appelant, une access restriction peut bloquer Application Gateway ou APIM, le health check peut viser une route non prête, ou l’application peut répondre 403, 502, 503 avant de produire des logs utiles.
Le cas d’usage est une application interne hébergée sur Azure App Service, appelée depuis un réseau privé via Application Gateway, APIM interne, une probe synthétique ou un service consommateur. L’objectif du runbook est simple : prouver où la requête s’arrête avant de redéployer, d’ouvrir l’accès public ou de modifier une règle WAF trop largement.
Lire App Service comme un chemin de production
Un App Service privé n’est pas seulement un hostname. C’est une chaîne qui combine résolution DNS, Private Link, point d’entrée éventuel, restrictions d’accès, runtime applicatif, identité et observabilité. Le diagnostic doit donc suivre cette chaîne dans l’ordre.
Client interne, APIM ou probe
Résout app.internal.example.com depuis le réseau consommateur
Envoie le bon Host header, un correlation ID et le chemin réel
Point d'entrée éventuel
Application Gateway ou APIM interne
Préserve TLS/SNI, host header et x-correlation-id
Remonte les codes WAF, gateway ou policy sans les mélanger
App Service
Private Endpoint approuvé sur le site Web
Public network access et access restrictions cohérents
Health check aligné avec une route applicative stable
Dépendances
Key Vault, stockage, base de données ou API aval joignables par le chemin attendu
Identité managée autorisée uniquement sur le périmètre nécessaire
Observabilité
AppServiceHTTPLogs, traces applicatives et gateway logs corrélables
Rollback limité à la couche qui a réellement changé Cette carte évite deux réflexes coûteux : redéployer alors que DNS est faux, ou ouvrir l’accès public alors que la requête n’atteint même pas le runtime.
Classer le symptôme avant la correction
La première décision consiste à séparer un échec d’entrée privée d’un échec applicatif. Si la requête n’apparaît pas dans les logs App Service, le code n’est pas encore la piste principale.
Symptôme
DNS retourne une adresse publique
Vérifier zone privatelink.azurewebsites.net, lien VNet et forwarding DNS hybride
Application Gateway retourne 502
Vérifier backend health, host header, TLS/SNI, probe path et access restrictions App Service
APIM ou le client retourne 403
Vérifier access restrictions, public network access, Private Endpoint et source réelle de l'appel
Aucune ligne AppServiceHTTPLogs pour le correlation ID
Revenir à DNS, gateway, APIM, WAF ou restrictions d'accès
Logs App Service présents avec 500 ou exception
Lire traces applicatives, identité managée, Key Vault et dépendances aval
Health check instable après livraison
Valider route de santé, warmup, slot, dépendances critiques et rollback applicatif La règle opérationnelle est volontairement stricte : tant que le correlation ID n’apparaît pas côté App Service, on reste sur réseau, entrée privée et restrictions.
Tester depuis le réseau consommateur
Le test doit partir d’un emplacement qui voit le même DNS et le même routage que le consommateur réel : VM de diagnostic, runner de probe, subnet applicatif, environnement APIM interne ou bastion d’exploitation. Un test depuis un poste public ne valide pas le chemin privé.
HOSTNAME=app.internal.example.com
PATH=/health
CORRELATION_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
curl -vk "https://$HOSTNAME$PATH" -H "x-correlation-id: $CORRELATION_ID" -H "x-naxaya-check: private-app-service"
echo "correlation_id=$CORRELATION_ID" Si DNS ne renvoie pas une adresse privée attendue, corrige la zone ou le forwarding avant d’aller plus loin. Si TLS échoue, regarde SNI, certificat et host header. Si curl retourne 403, vérifie la source réellement vue par App Service ou par le point d’entrée.
Vérifier l’état App Service sans exposer l’application
Les commandes Azure doivent confirmer les dimensions du service sans publier de secret dans le ticket : statut, restrictions, Private Endpoint, health check, identité et paramètres de plateforme utiles.
APP_RG=rg-prod-app
APP_NAME=app-prod-orders
az webapp show -g "$APP_RG" -n "$APP_NAME" --query "{state:state, enabled:enabled, httpsOnly:httpsOnly, hostNames:hostNames, defaultHostName:defaultHostName}" -o jsonc
az webapp config show -g "$APP_RG" -n "$APP_NAME" --query "{alwaysOn:alwaysOn, healthCheckPath:healthCheckPath, publicNetworkAccess:publicNetworkAccess, ftpsState:ftpsState}" -o jsonc
az webapp config access-restriction show -g "$APP_RG" -n "$APP_NAME" -o table
az webapp identity show -g "$APP_RG" -n "$APP_NAME" --query "{type:type, principalId:principalId, tenantId:tenantId}" -o jsonc
az network private-endpoint-connection list --id "$(az webapp show -g "$APP_RG" -n "$APP_NAME" --query id -o tsv)" --query "[].{name:name,status:privateLinkServiceConnectionState.status,description:privateLinkServiceConnectionState.description}" -o table Cette étape permet de repérer les écarts classiques : Private Endpoint non approuvé, access restriction qui ne couvre pas Application Gateway, health check absent ou route de santé dépendante d’un service aval fragile.
Corréler gateway, WAF et App Service en KQL
Une requête corrélée permet de savoir si l’échec se situe avant App Service, dans App Service, ou après l’entrée dans le code. La requête ci-dessous mélange les logs Application Gateway/WAF et App Service autour d’un même host, d’un chemin et d’un correlation ID.
let Window = 2h;
let Host = "app.internal.example.com";
let Path = "/health";
let CorrelationId = "ops-20260612080000";
let Gateway =
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where Category in ("ApplicationGatewayAccessLog", "ApplicationGatewayFirewallLog")
| where host_s has Host or requestUri_s has Path or transactionId_g == CorrelationId
| project TimeGenerated, Source=Category, host=host_s, uri=requestUri_s, status=coalesce(httpStatus_d, status_d), ruleId=ruleId_s, action=action_s, transactionId=tostring(transactionId_g);
let AppService =
AppServiceHTTPLogs
| where TimeGenerated > ago(Window)
| where CsHost has Host or CsUriStem has Path or CsUserAgent has CorrelationId
| project TimeGenerated, Source="AppServiceHTTPLogs", host=CsHost, uri=CsUriStem, status=ScStatus, ruleId="", action=CsMethod, transactionId=CorrelationId;
Gateway
| union AppService
| order by TimeGenerated desc Lecture rapide : logs gateway sans logs App Service orientent vers WAF, backend health, DNS privé, TLS ou restrictions ; logs App Service avec 500 orientent vers code ou dépendance ; absence totale de logs oriente vers DNS, routage ou mauvais point de test.
Choisir le rollback minimal
Le rollback doit restaurer la couche modifiée, pas annuler toute la livraison. Une modification de zone privée, de règle d’accès, de backend pool ou de slot applicatif n’a pas le même retour arrière.
Changement récent
DNS privé ou forwarding
Rollback: restaurer l'ancien record, lien VNet ou forwarder
Preuve: nslookup privé puis requête corrélée visible au bon endroit
Access restriction ou public network access
Rollback: restaurer la règle source précédente
Preuve: AppServiceHTTPLogs voit le correlation ID
Application Gateway backend ou probe
Rollback: revenir au backend setting, host header ou path de probe validé
Preuve: backend health sain et status applicatif cohérent
Slot ou package applicatif
Rollback: swap retour ou package précédent
Preuve: même requête réussie avec logs App Service et traces applicatives Conclusion
Un incident App Service privé se traite comme un incident de chemin, pas comme un incident de code par défaut. DNS, Private Endpoint, access restrictions, Application Gateway, logs App Service et dépendances doivent être isolés avant de toucher au déploiement.
La décision devient plus défendable : si la requête n’atteint pas App Service, on corrige l’entrée privée ; si elle l’atteint et échoue dans les logs, on investigue runtime, identité, dépendances ou code. Cette séparation réduit les ouvertures publiques temporaires, les exceptions WAF trop larges et les rollbacks qui masquent la vraie panne.