Cloud
Publier une application métier avec Azure Application Gateway, mTLS et WAF dédié
Un retour opérationnel sur la publication contrôlée d’une application métier derrière Azure Application Gateway, avec listeners HTTPS dédiés, authentification mutuelle, WAF spécifique, backend HTTPS et points de validation réseau.
Publier une application métier vers un système externe ne devrait jamais se limiter à ajouter un nom DNS sur une IP publique. Dès qu’un flux applicatif arrive depuis une plateforme SaaS, un partenaire ou un système B2B, il faut séparer plusieurs sujets qui sont souvent mélangés dans les premières discussions : qui a le droit d’appeler l’application, comment le client est authentifié, quel chemin TLS est réellement utilisé, quelle politique WAF s’applique, comment le backend est validé, et comment l’équipe d’exploitation diagnostique un échec sans tout confondre.
Azure Application Gateway répond assez bien à ce besoin quand l’architecture attendue reste une publication HTTPS contrôlée, avec routage vers des machines virtuelles ou des backends privés existants. Il n’est pas toujours nécessaire d’ajouter API Management si le besoin ne porte pas sur le cycle de vie complet d’une API, les abonnements, les produits, le throttling applicatif avancé ou la transformation des payloads. Dans un cas plus direct, Application Gateway peut servir de point d’entrée unique, terminer le TLS côté frontend, imposer une authentification mutuelle par certificat client, appliquer une politique WAF dédiée, puis joindre le backend en HTTPS.
Le schéma cible reste volontairement simple.
Client SaaS ou partenaire externe
↓
IP publique Azure Application Gateway
↓
Listener HTTPS dédié par nom applicatif
↓
Authentification mTLS stricte
↓
Politique WAF dédiée à l’application
↓
Backend pool vers VM applicative
↓
Backend setting HTTPS avec hostname explicite
↓
Nginx ou reverse proxy local
↓
Application métier Cette simplicité est justement ce qui rend le modèle exploitable. Chaque objet Application Gateway porte une intention claire. Le listener représente un nom public. La règle de routage représente le lien entre ce nom et un backend. Le backend setting décrit le comportement HTTP ou HTTPS vers le serveur applicatif. Le probe valide la santé réelle du backend. La politique WAF est isolée pour éviter de réutiliser des exceptions conçues pour une autre application. Le profil SSL matérialise le contrôle mTLS.
Le périmètre utilisé dans l’exemple
L’exemple ci dessous expose trois environnements d’une même application à travers une Application Gateway déjà existante. Les noms et adresses sont anonymisés.
DEV
FQDN : app-dev.example.com
Backend VM : vm-app-dev-01
Backend IP : 10.10.54.137
QA
FQDN : app-qa.example.com
Backend VM : vm-app-qa-01
Backend IP : 10.10.54.69
PRD
FQDN : app.example.com
Backend VM : vm-app-prd-01
Backend IP : 10.10.54.8 La passerelle d’application et son frontend public existent déjà.
export RG="rg-network-hub-prod"
export AGW="agw-internet-prod-001"
export PUBLIC_IP="203.0.113.10"
export FRONTEND_IP="appGwPublicFrontendIpIPv4"
export FRONTEND_PORT_443="port_443" Le DNS public doit pointer les trois noms vers la même IP publique. Dans un environnement d’entreprise, cette zone peut être gérée par une équipe DNS séparée. Il faut donc traiter cette étape comme un prérequis de changement, pas comme un détail à valider à la fin.
app-dev.example.com -> 203.0.113.10
app-qa.example.com -> 203.0.113.10
app.example.com -> 203.0.113.10 La validation se fait depuis un résolveur qui voit le DNS public, pas uniquement depuis une machine interne dont le comportement peut être modifié par des forwarders ou des zones privées.
nslookup app-dev.example.com
nslookup app-qa.example.com
nslookup app.example.com Clarifier les deux chaînes TLS avant de créer les objets
Ce type de design contient deux connexions TLS différentes.
La première connexion va du client externe vers Application Gateway. Le client valide le certificat serveur présenté par le listener. Dans l’exemple, un certificat wildcard couvre les noms publiés.
Certificat serveur côté listener : *.example.com
Noms couverts :
app-dev.example.com
app-qa.example.com
app.example.com La deuxième connexion va d’Application Gateway vers la VM applicative. Si le backend setting est en HTTPS, la passerelle doit pouvoir établir une connexion TLS correcte vers le serveur backend. Le hostname utilisé dans le backend setting doit donc correspondre au certificat présenté par Nginx ou par le reverse proxy local. C’est un point important quand le backend pool contient des adresses IP. Il ne faut pas compter sur pickHostNameFromBackendAddress avec des IP privées. Le nom doit être explicitement défini dans le backend setting.
L’authentification mTLS ajoute un troisième sujet, mais côté frontend uniquement. Le client externe présente un certificat client. Application Gateway vérifie ce certificat contre une chaîne d’autorité de certification cliente approuvée attachée au profil SSL. En mode strict, si le certificat client est absent ou invalide, la négociation échoue avant même que la requête soit routée vers le backend.
La chaîne de confiance du certificat client doit être préparée proprement. Le certificat client lui même reste du côté client. La clé privée ne doit pas être envoyée à Azure. Ce qui est chargé dans Application Gateway, c’est la chaîne d’autorité de certification approuvée qui permet de valider le certificat client.
Côté client externe
- CSR générée par le client ou la plateforme SaaS
- Certificat client signé par une CA de confiance
- Clé privée conservée côté client
- Certificat client configuré dans la plateforme appelante
Côté Application Gateway
- Chaîne CA publique ou privée qui a signé le certificat client
- Profil SSL avec authentification client activée
- Profil SSL attaché uniquement aux listeners de cette application Préparer les variables de déploiement
Le jeu de variables suivant permet de garder les commandes lisibles. Les noms sont volontairement génériques, mais ils restent suffisamment proches d’un standard d’exploitation pour être réutilisables.
export RG="rg-network-hub-prod"
export AGW="agw-internet-prod-001"
export FRONTEND_IP="appGwPublicFrontendIpIPv4"
export FRONTEND_PORT_443="port_443"
export SERVER_CERT_NAME="wildcard-example-com"
export WAF_POLICY="waf-agw-app-publication"
export SSL_PROFILE="sslprof-app-mtls-001"
export TRUSTED_CLIENT_CA_NAME="ca-client-app-chain"
export DEV_HOST="app-dev.example.com"
export QA_HOST="app-qa.example.com"
export PRD_HOST="app.example.com"
export DEV_IP="10.10.54.137"
export QA_IP="10.10.54.69"
export PRD_IP="10.10.54.8" Avant de créer les listeners, il faut identifier le nom exact du certificat serveur déjà présent sur l’Application Gateway.
az network application-gateway ssl-cert list -g "$RG" --gateway-name "$AGW" -o table Cette vérification évite de créer des listeners avec un mauvais objet certificat ou de réimporter inutilement un certificat déjà géré par l’équipe réseau.
Créer les backend pools
Chaque environnement reçoit son propre backend pool. Même si les trois backends servent la même application, les isoler simplifie le diagnostic et évite qu’une modification QA touche accidentellement la production.
az network application-gateway address-pool create -g "$RG" --gateway-name "$AGW" -n "bp-app-dev" --servers "$DEV_IP"
az network application-gateway address-pool create -g "$RG" --gateway-name "$AGW" -n "bp-app-qa" --servers "$QA_IP"
az network application-gateway address-pool create -g "$RG" --gateway-name "$AGW" -n "bp-app-prd" --servers "$PRD_IP" Le choix d’utiliser des IP privées dans les backend pools est acceptable pour des VM, mais il impose d’être explicite sur le hostname TLS envoyé au backend. Sans cela, les erreurs de certificat deviennent vite trompeuses.
Créer les probes HTTPS
Les probes doivent tester le même comportement que celui attendu par la passerelle. Si le backend répond en HTTPS et présente un certificat pour app-qa.example.com, le probe QA doit utiliser ce hostname.
az network application-gateway probe create -g "$RG" --gateway-name "$AGW" -n "probe-app-dev" --protocol Https --host "$DEV_HOST" --path "/" --interval 60 --timeout 60 --threshold 3 --match-status-codes "200-399"
az network application-gateway probe create -g "$RG" --gateway-name "$AGW" -n "probe-app-qa" --protocol Https --host "$QA_HOST" --path "/" --interval 60 --timeout 60 --threshold 3 --match-status-codes "200-399"
az network application-gateway probe create -g "$RG" --gateway-name "$AGW" -n "probe-app-prd" --protocol Https --host "$PRD_HOST" --path "/" --interval 60 --timeout 60 --threshold 3 --match-status-codes "200-399" Le chemin / n’est qu’un exemple. En production, un endpoint de santé applicatif explicite est préférable si l’application le fournit. Il doit toutefois rester stable, rapide et représentatif. Un probe qui dépend d’un service tiers ou d’une logique métier lourde crée de faux incidents.
Créer les backend settings HTTPS
Le backend setting est l’objet où beaucoup d’erreurs se cachent. Le port et le protocole ne suffisent pas. Le hostname est déterminant pour le TLS backend.
az network application-gateway http-settings create -g "$RG" --gateway-name "$AGW" -n "bhs-app-dev" --protocol Https --port 443 --host-name "$DEV_HOST" --probe "probe-app-dev" --timeout 60
az network application-gateway http-settings create -g "$RG" --gateway-name "$AGW" -n "bhs-app-qa" --protocol Https --port 443 --host-name "$QA_HOST" --probe "probe-app-qa" --timeout 60
az network application-gateway http-settings create -g "$RG" --gateway-name "$AGW" -n "bhs-app-prd" --protocol Https --port 443 --host-name "$PRD_HOST" --probe "probe-app-prd" --timeout 60 Une vérification ciblée permet de détecter immédiatement un mauvais setting.
az network application-gateway http-settings show -g "$RG" --gateway-name "$AGW" -n "bhs-app-qa" --query "{hostName:hostName,pickHostNameFromBackendAddress:pickHostNameFromBackendAddress,protocol:protocol,port:port,probe:probe.id}" -o json Le résultat attendu doit ressembler à ceci.
{
"hostName": "app-qa.example.com",
"pickHostNameFromBackendAddress": false,
"port": 443,
"protocol": "Https"
} Si hostName est vide ou si la passerelle tente de déduire le nom depuis une IP privée, il faut corriger avant d’aller plus loin. La suite du déploiement ne réparera pas un backend TLS mal nommé.
Créer une politique WAF dédiée
Réutiliser une politique WAF existante parce qu’elle fonctionne déjà pour une autre application est une mauvaise économie. Une politique WAF finit souvent par accumuler des exclusions, des règles custom et des réglages liés au comportement d’une application précise. La réutiliser pour une intégration partenaire revient à transporter des décisions de sécurité qui n’ont peut être rien à voir avec le nouveau flux.
Créer une politique dédiée garde le périmètre clair.
az network application-gateway waf-policy create -g "$RG" -n "$WAF_POLICY" --type OWASP --version 3.2
az network application-gateway waf-policy policy-setting update -g "$RG" --policy-name "$WAF_POLICY" --mode Prevention --state Enabled --request-body-check true Le mode Prevention est cohérent pour un flux restreint et attendu. En revanche, il doit être validé avec de vrais appels applicatifs. Certaines applications anciennes ou certains payloads métier peuvent déclencher des règles OWASP de manière inattendue. Le bon compromis consiste souvent à commencer avec la politique dédiée, observer les logs pendant les tests QA, puis n’ajouter que les exclusions justifiées et documentées.
Restreindre l’accès aux IP du client externe
Le mTLS valide l’identité cryptographique du client, mais il ne remplace pas un filtrage réseau. Si les plages de sortie du partenaire ou de la plateforme SaaS sont connues, une règle WAF custom peut bloquer tout ce qui ne vient pas de ces ranges.
CLIENT_IP_RANGES=(
"198.51.100.0/24"
"198.51.101.0/24"
"203.0.113.0/25"
"203.0.113.128/25"
)
az network application-gateway waf-policy custom-rule create -g "$RG" --policy-name "$WAF_POLICY" -n "deny-non-approved-client-ranges" --priority 10 --rule-type MatchRule --action Block
az network application-gateway waf-policy custom-rule match-condition add -g "$RG" --policy-name "$WAF_POLICY" --name "deny-non-approved-client-ranges" --match-variables RemoteAddr --operator IPMatch --values "${CLIENT_IP_RANGES[@]}" --negation-condition true La logique est volontairement inversée.
Si l’adresse source n’appartient pas aux plages approuvées, bloquer la requête. Ce type de règle doit être maintenu. Les plages IP d’un fournisseur SaaS peuvent évoluer. Si ce contrôle devient critique pour la production, il faut prévoir une revue régulière des ranges et un processus de mise à jour qui ne dépend pas d’une personne unique.
Charger la chaîne CA cliente approuvée
Application Gateway ne doit pas recevoir le certificat client complet avec sa clé privée. Elle doit recevoir la chaîne d’autorité de certification nécessaire pour vérifier le certificat présenté par le client.
az network application-gateway client-cert add -g "$RG" --gateway-name "$AGW" -n "$TRUSTED_CLIENT_CA_NAME" --data "./client-mtls-ca-chain.cer" Le fichier doit contenir la CA racine et, si nécessaire, les intermédiaires. Si la chaîne est refusée, il faut vérifier le format, la taille, l’ordre de la chaîne et le fait que la racine soit bien présente. Dans certains contextes, l’équipe sécurité préfère charger uniquement une racine dédiée ou une chaîne intermédiaire contrôlée pour réduire le risque de faire confiance trop largement.
La validation de l’objet chargé se fait simplement.
az network application-gateway client-cert list -g "$RG" --gateway-name "$AGW" -o table Créer le profil SSL mTLS
Le profil SSL relie la configuration TLS et l’authentification client. Pour un mode strict, il faut activer l’authentification client et référencer la chaîne CA approuvée.
az network application-gateway ssl-profile add -g "$RG" --gateway-name "$AGW" --name "$SSL_PROFILE" --client-auth-configuration true --trusted-client-certificates "$TRUSTED_CLIENT_CA_NAME" --min-protocol-version TLSv1_2 Selon la version Azure CLI, le nom exact de certains paramètres peut varier légèrement ou être exposé différemment. C’est pour cette raison qu’il faut toujours valider l’aide locale de l’environnement qui exécutera le changement.
az network application-gateway ssl-profile --help
az network application-gateway http-listener create --help
az network application-gateway http-listener update --help Si la CLI disponible dans le poste d’administration ou la pipeline ne permet pas de définir proprement tous les paramètres mTLS, il vaut mieux créer cette partie via le portail, PowerShell ou Infrastructure as Code plutôt que d’improviser une commande partielle. L’important est le résultat final : un profil SSL dédié, avec authentification client activée, attaché uniquement aux listeners de cette application.
Créer les listeners HTTPS
Chaque environnement a son propre listener. Les trois listeners utilisent le même frontend public et le même port 443, mais se distinguent par le hostname.
az network application-gateway http-listener create -g "$RG" --gateway-name "$AGW" -n "ln-https-app-dev" --frontend-ip "$FRONTEND_IP" --frontend-port "$FRONTEND_PORT_443" --host-name "$DEV_HOST" --ssl-cert "$SERVER_CERT_NAME"
az network application-gateway http-listener create -g "$RG" --gateway-name "$AGW" -n "ln-https-app-qa" --frontend-ip "$FRONTEND_IP" --frontend-port "$FRONTEND_PORT_443" --host-name "$QA_HOST" --ssl-cert "$SERVER_CERT_NAME"
az network application-gateway http-listener create -g "$RG" --gateway-name "$AGW" -n "ln-https-app-prd" --frontend-ip "$FRONTEND_IP" --frontend-port "$FRONTEND_PORT_443" --host-name "$PRD_HOST" --ssl-cert "$SERVER_CERT_NAME" Il est possible d’attacher le WAF policy et le profil SSL dès la création si les paramètres sont disponibles dans la version CLI utilisée, ou de les appliquer après coup.
WAF_POLICY_ID=$(az network application-gateway waf-policy show -g "$RG" -n "$WAF_POLICY" --query id -o tsv)
SSL_PROFILE_ID=$(az network application-gateway ssl-profile show -g "$RG" --gateway-name "$AGW" --name "$SSL_PROFILE" --query id -o tsv)
az network application-gateway http-listener update -g "$RG" --gateway-name "$AGW" -n "ln-https-app-dev" --waf-policy "$WAF_POLICY_ID" --ssl-profile-id "$SSL_PROFILE_ID"
az network application-gateway http-listener update -g "$RG" --gateway-name "$AGW" -n "ln-https-app-qa" --waf-policy "$WAF_POLICY_ID" --ssl-profile-id "$SSL_PROFILE_ID"
az network application-gateway http-listener update -g "$RG" --gateway-name "$AGW" -n "ln-https-app-prd" --waf-policy "$WAF_POLICY_ID" --ssl-profile-id "$SSL_PROFILE_ID" Il ne faut pas attacher cette politique WAF globalement à l’Application Gateway si elle ne concerne que cette application. Le contrôle doit rester au niveau des listeners concernés. C’est ce qui évite d’impacter d’autres publications existantes sur la même passerelle.
Créer les règles de routage
Les règles de routage lient listener, backend pool et backend setting. Les priorités doivent être choisies dans une plage non utilisée par les règles existantes.
az network application-gateway rule create -g "$RG" --gateway-name "$AGW" -n "rule-app-dev" --http-listener "ln-https-app-dev" --address-pool "bp-app-dev" --http-settings "bhs-app-dev" --priority 400
az network application-gateway rule create -g "$RG" --gateway-name "$AGW" -n "rule-app-qa" --http-listener "ln-https-app-qa" --address-pool "bp-app-qa" --http-settings "bhs-app-qa" --priority 410
az network application-gateway rule create -g "$RG" --gateway-name "$AGW" -n "rule-app-prd" --http-listener "ln-https-app-prd" --address-pool "bp-app-prd" --http-settings "bhs-app-prd" --priority 420 Avant de créer ces règles dans un environnement chargé, il est utile de lister les priorités existantes.
az network application-gateway rule list -g "$RG" --gateway-name "$AGW" --query "[].{name:name,priority:priority,listener:httpListener.id}" -o table Ne pas oublier le chemin réseau retour
Un backend healthy ne dépend pas seulement d’Application Gateway. Les flux doivent être autorisés jusqu’aux VM, et le retour doit suivre le chemin attendu. Dans les architectures avec firewall central, appliance réseau ou routage forcé, l’asymétrie peut provoquer des symptômes qui ressemblent à un problème TLS ou applicatif.
Le flux minimal à autoriser ressemble à ceci.
Source : subnet Application Gateway
Destination : 10.10.54.137
Service : TCP 443
Action : Allow
Source : subnet Application Gateway
Destination : 10.10.54.69
Service : TCP 443
Action : Allow
Source : subnet Application Gateway
Destination : 10.10.54.8
Service : TCP 443
Action : Allow Depuis chaque VM backend, vérifier la route vers les IP privées des instances Application Gateway ou vers le subnet concerné permet d’éviter beaucoup de faux diagnostics.
ip route get 10.20.141.36
ip route get 10.20.141.37 Si un doute persiste, la capture réseau reste le moyen le plus direct de distinguer un problème de chemin IP d’un problème TLS ou applicatif.
sudo tcpdump -ni eth0 "host 10.20.141.36 or host 10.20.141.37" Le handshake TCP attendu est simple.
Application Gateway -> VM : SYN
VM -> Application Gateway : SYN,ACK
Application Gateway -> VM : ACK Si le SYN arrive mais que le SYN ACK ne revient jamais au bon endroit, ce n’est pas un problème de certificat. C’est un problème de routage, de firewall ou de retour asymétrique.
Configurer le backend Nginx avec une chaîne complète
Le backend doit présenter un certificat cohérent avec le hostname envoyé par Application Gateway. Dans cet exemple QA, le backend setting utilise app-qa.example.com. Nginx doit donc servir un certificat dont le CN ou les SAN couvrent ce nom.
server {
listen 443 ssl;
server_name app-qa.example.com;
ssl_certificate /etc/nginx/ssl/wildcard.example.com.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/wildcard.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ /index.html =404;
}
location /api/external/status/ {
fastcgi_param APP_ENV qa;
fastcgi_param INSTANCE_TYPE api;
fastcgi_param ENV_NAME qa;
alias /opt/app/backend/www;
try_files $uri $uri/ /index.php$is_args$args;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
} Après modification, tester puis recharger Nginx.
sudo nginx -t
sudo systemctl reload nginx La chaîne servie par le backend doit être complète. Un certificat serveur sans intermédiaire peut fonctionner depuis un navigateur ou une machine qui a déjà certaines chaînes en cache, mais échouer côté Application Gateway.
openssl s_client -connect 10.10.54.69:443 -servername app-qa.example.com -showcerts </dev/null Le résultat attendu doit montrer le certificat serveur et les intermédiaires nécessaires.
0 CN=*.example.com
1 CN=Intermediate TLS CA
2 CN=Root CA Si le backend présente uniquement le certificat serveur, il faut corriger le fichier fullchain.pem avant de chercher ailleurs.
Valider la santé backend dans Application Gateway
La validation principale après création des objets consiste à regarder la santé backend.
az network application-gateway show-backend-health -g "$RG" -n "$AGW" -o table
az network application-gateway show-backend-health -g "$RG" -n "$AGW" -o jsonc Le résultat attendu est clair.
bp-app-dev / 10.10.54.137 : Healthy
bp-app-qa / 10.10.54.69 : Healthy
bp-app-prd / 10.10.54.8 : Healthy Si le backend est unhealthy, il faut lire le message précis. Les causes les plus fréquentes sont un hostname de probe incorrect, une chaîne TLS incomplète, une route manquante, un firewall intermédiaire, un timeout applicatif ou un endpoint de santé qui ne répond pas comme attendu.
Valider les logs d’accès et WAF
Les logs Application Gateway doivent être consultables dès les tests QA. C’est aussi pour cette raison que les listeners, règles et policies doivent avoir des noms explicites.
AGWAccessLogs
| where TimeGenerated > ago(2h)
| where Host has "app"
| project TimeGenerated, Host, RequestUri, ClientIp, HttpStatus, RuleName, TransactionId
| order by TimeGenerated desc Les logs WAF permettent de distinguer une requête bloquée par l’allowlist IP, une règle OWASP ou une autre condition.
AGWFirewallLogs
| where TimeGenerated > ago(2h)
| where Hostname has "app"
| project TimeGenerated, Hostname, RequestUri, ClientIp, Action, RuleId, Message, Details, TransactionId
| order by TimeGenerated desc Dans certains environnements, les logs sont encore exposés via AzureDiagnostics.
AzureDiagnostics
| where TimeGenerated > ago(2h)
| where Category in ("ApplicationGatewayAccessLog", "ApplicationGatewayFirewallLog")
| where host_s has "app" or hostname_s has "app"
| order by TimeGenerated desc Un bon test applicatif doit produire un triplet lisible : une entrée access log, éventuellement une entrée WAF si une règle est déclenchée, et une trace applicative côté backend. Sans corrélation par heure, hostname, URI et transaction ID, le dépannage devient trop lent.
Tester le flux attendu depuis le client externe
Le scénario de test attendu ressemble à ceci.
URL appelée : https://app-qa.example.com/api/external/status/506
Résultat attendu :
- l’adresse source appartient aux plages autorisées
- le client présente son certificat mTLS
- Application Gateway valide la chaîne CA cliente
- la politique WAF ne bloque pas le payload attendu
- la règle QA route vers le backend pool QA
- Application Gateway ouvre une connexion HTTPS vers 10.10.54.69
- Nginx présente une chaîne certificat complète
- l’application retourne une réponse valide Un test manuel peut être fait avec curl si le certificat client et la clé privée sont disponibles dans un environnement de test. En production, la clé privée appartient souvent à la plateforme externe et ne doit pas circuler.
curl -v --cert ./client-test.crt --key ./client-test.key https://app-qa.example.com/api/external/status/506 Ce test ne remplace pas un appel réel depuis la plateforme externe, mais il permet d’isoler rapidement la partie TLS et mTLS.
Les erreurs les plus fréquentes
Un 403 Forbidden indique souvent une action WAF. Dans ce design, la première hypothèse à vérifier est l’allowlist IP. Si l’adresse source vue par Application Gateway ne correspond pas aux ranges autorisées, la règle custom bloque la requête. Il faut regarder les logs WAF avant de chercher côté application.
Un message du type No required SSL certificate was sent indique que le listener mTLS attend un certificat client, mais que le client ne l’a pas présenté. Le problème peut venir de la configuration de la plateforme externe, du mauvais certificat configuré côté client, ou d’un test manuel lancé sans certificat.
Un 502 Bad Gateway est plus large. Il peut venir d’un backend unhealthy, d’une absence de route, d’un firewall, d’un certificat backend invalide, d’un hostname incorrect dans le backend setting, d’un probe mal défini ou d’un timeout applicatif. Il faut commencer par show-backend-health, pas par le code applicatif.
Une erreur de chaîne intermédiaire manquante côté backend signifie généralement que Nginx sert seulement le certificat serveur. Il faut utiliser un fichier fullchain qui contient le certificat serveur et les intermédiaires nécessaires.
Une erreur de CN ou SAN mismatch apparaît quand le hostname utilisé par Application Gateway ne correspond pas au certificat présenté par le backend. Avec des backend pools en IP privée, ce problème est courant si le backend setting n’a pas de host-name explicite.
Les objets finaux à retrouver
À la fin du changement, l’inventaire Application Gateway doit être lisible. Pour l’exemple, les objets attendus sont les suivants.
WAF policy
waf-agw-app-publication
SSL profile
sslprof-app-mtls-001
Trusted client CA
ca-client-app-chain
Listeners
ln-https-app-dev
ln-https-app-qa
ln-https-app-prd
Backend pools
bp-app-dev
bp-app-qa
bp-app-prd
Backend settings
bhs-app-dev
bhs-app-qa
bhs-app-prd
Probes
probe-app-dev
probe-app-qa
probe-app-prd
Rules
rule-app-dev
rule-app-qa
rule-app-prd Cette liste n’est pas cosmétique. Elle sert à vérifier que le changement est resté borné. Si une politique globale a été modifiée, si un listener existant a été réutilisé sans raison ou si une règle commune a été altérée, le changement a dépassé son périmètre.
Ce qu’il faut décider avant de généraliser ce modèle
Ce pattern est propre quand l’application exposée a peu de consommateurs, des plages IP connues, un contrat HTTPS stable et un besoin clair d’authentification client. Il devient moins adapté si l’organisation veut gérer des dizaines de consommateurs, publier des versions d’API, imposer des quotas par client, transformer les requêtes ou produire un portail développeur. Dans ce cas, API Management redevient un composant naturel.
Il faut aussi décider qui possède chaque élément dans la durée. Le DNS public, le certificat serveur wildcard, la chaîne CA cliente, les ranges IP du partenaire, la politique WAF, les règles firewall internes et la configuration Nginx ne sont pas toujours administrés par la même équipe. Si cette responsabilité n’est pas claire, l’incident arrivera au renouvellement de certificat, au changement de ranges SaaS ou à la première exception WAF demandée en urgence.
Le vrai gain de cette approche n’est donc pas seulement technique. Le gain vient du découpage. Un listener par nom, un backend pool par environnement, un probe par backend, une politique WAF dédiée, un profil SSL limité au périmètre applicatif, et des validations observables à chaque couche. C’est ce découpage qui rend la publication exploitable au lieu d’être simplement fonctionnelle.