Cloud

Azure WAF Bot Manager : qualifier un bot avant d'ajouter une règle d'autorisation

Un runbook de production pour séparer automatisation légitime, identité usurpée et trafic hostile avant de modifier les actions Azure WAF Bot Manager.

01 oct. 2026 azurewaffront-doorapplication-gatewaybot-managersecuritykqlobservabilityautomationrunbookrollbackproduction

Un crawler partenaire reçoit soudain des réponses 403 derrière Azure Front Door. Son exploitant demande une règle d’autorisation et fournit un user-agent reconnaissable. Dans le même temps, les journaux WAF classent comme bots inconnus d’autres requêtes émises avec la même bibliothèque cliente. Autoriser cette chaîne rétablirait vite l’intégration, mais créerait aussi un contournement réutilisable par un trafic sans rapport.

Le cas fil rouge est une API de production protégée par Azure WAF Bot Manager. Un partenaire lit un endpoint de catalogue borné, tandis que moteurs de recherche, sondes, SDK et scanners hostiles atteignent le même hostname. Le runbook doit prouver si la requête est légitime, si Bot Manager porte réellement le blocage, puis décider de maintenir le blocage, modifier une action gérée, introduire une exception ciblée ou laisser l’application trancher l’autorisation.

Figer le contrat du client automatisé

Ne commencez ni par le user-agent ni par la règle WAF. Décrivez le client comme une dépendance de production : propriétaire, finalité, routes, authentification, enveloppe de trafic et chemin de révocation.

yaml 01-contrat-client-bot.yml
client:
name: partner-catalog-reader
owner: partner-integrations
purpose: read published catalog changes
hostname: api.example.com
methods: [GET]
paths: [/v1/catalog, /v1/catalog/delta]
authentication: oauth2-client-credentials
source_ranges: [203.0.113.0/28]
user_agent: partner-catalog/3.x
expected_rate_per_minute: 60

evidence:
waf_transaction_id: required
application_client_id: required
source_ip: observed_not_assumed
owner_confirmation: required

decision:
no_identity_match: keep_blocking
valid_identity_and_wrong_path: deny
valid_identity_and_expected_path: canary_then_decide
rollback: restore_previous_waf_policy

Un user-agent décrit un client, il ne l’authentifie pas. Une plage source apporte davantage de signal uniquement si le partenaire la maîtrise et documente ses changements. Des credentials applicatifs, le mTLS ou une requête signée fournissent une preuve plus forte, mais le WAF ne sait pas nécessairement les valider. Distinguez clairement ce qui est contrôlé à l’edge de ce qui l’est à l’origine.

Prouver que Bot Manager a pris la décision

Bot Manager classe le trafic en bots malveillants, légitimes ou inconnus. Cette classification est un signal de sécurité, pas une autorisation fonctionnelle. Avant toute modification, conservez version du ruleset, identifiant de règle, action, hostname, chemin, IP cliente et identifiant de transaction.

kusto 02-evenements-bot-manager.kql
let Window = 2h;
let Host = "api.example.com";
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where Category in ("FrontDoorWebApplicationFirewallLog", "ApplicationGatewayFirewallLog")
| extend Hostname=tostring(column_ifexists("host_s", column_ifexists("hostname_s", ""))),
       Path=tostring(column_ifexists("requestUri_s", "")),
       RuleSet=tostring(column_ifexists("ruleSetType_s", "")),
       RuleId=tostring(column_ifexists("ruleId_s", "")),
       Action=tostring(column_ifexists("action_s", "")),
       ClientIp=tostring(column_ifexists("clientIp_s", "")),
       UserAgent=tostring(column_ifexists("userAgent_s", "")),
       TransactionId=tostring(column_ifexists("trackingReference_s", column_ifexists("transactionId_g", "")))
| where Hostname == Host or isempty(Hostname)
| where RuleSet has "Bot" or RuleId startswith "Bot"
| summarize Requests=count(),
          Clients=dcount(ClientIp),
          Paths=make_set(Path, 15),
          UserAgents=make_set(UserAgent, 10),
          FirstSeen=min(TimeGenerated),
          LastSeen=max(TimeGenerated)
by RuleSet, RuleId, Action
| order by Requests desc

Les schémas de diagnostic varient selon la ressource WAF et le mode de table. Vérifiez les colonnes présentes dans le workspace avant d’industrialiser la requête. La chaîne de preuve doit rester stable, pas nécessairement le nom de chaque champ.

La famille de règle apporte du contexte. Bot100xxx signale notamment de la threat intelligence ou une identité falsifiée, Bot200xxx reconnaît des catégories de bons bots, et Bot300xxx couvre des automatisations inconnues : crawlers, clients HTTP, agents de service ou outils de monitoring. Une requête classée Bot300300 parce qu’elle utilise un SDK généraliste n’est ni hostile ni fiable par défaut. Il faut la relier au contexte applicatif.

Corréler classification edge et identité applicative

Utilisez la transaction WAF ou la tracking reference pour retrouver la même requête dans les journaux Front Door, Application Gateway et origine. Comparez ensuite IP source, chemin, méthode, client ID applicatif, réponse et débit. Le seul user-agent ne suffit jamais.

text matrice-correlation-bot.txt
Requête partenaire attendue
Source dans la plage approuvée
Client ID OAuth partner-catalog-reader
Méthode et chemin conformes au contrat
Débit dans l'enveloppe convenue
Horodatages WAF et origine corrélés

Usurpation possible
User-agent conforme mais client ID différent
Source hors de la plage approuvée
Exploration de routes sans rapport
Méthode ou débit hors contrat
Même identité déclarée depuis de nombreux réseaux

Preuve insuffisante
Transaction WAF impossible à relier à l'origine
Résultat d'authentification absent des logs
IP cliente transférée ambiguë
Partenaire incapable de confirmer une fenêtre de test

Ne journalisez ni jeton ni secret pour faciliter la corrélation. Conservez un identifiant client stable, le résultat d’authentification, la route, un identifiant de corrélation et une information source bornée. Si le trafic n’atteint jamais l’origine, organisez un test contrôlé avec un header de corrélation unique et capturez l’événement WAF correspondant.

Relire l’ordre des règles avant l’exception

Les custom rules Azure WAF sont évaluées avant les rulesets gérés. Une action Allow peut donc interrompre les inspections suivantes. Même précise en apparence, une règle peut désactiver des protections qui ne faisaient pas partie de l’incident.

Avant d’accepter l’exception, inventoriez :

  • la policy et la version Bot Manager associées au hostname touché ;
  • les priorités et actions terminales des custom rules ;
  • les overrides Bot Manager du groupe ou de la règle concernée ;
  • l’action du Default Rule Set qui inspecterait normalement la requête ;
  • les autres hostnames qui partagent la même policy WAF.

Passer toute une catégorie de bots inconnus de Block à Allow est rarement proportionné pour un partenaire. Une custom rule fondée uniquement sur le user-agent l’est encore moins. Préférez les contrôles qui conservent l’inspection gérée : authentifier le client dans l’application, garder le signal bot dans les logs, limiter le débit sur la route bornée, ou isoler les intégrations automatisées derrière un hostname et une policy dédiés lorsque leur modèle de trafic diffère réellement.

Rejouer les contrôles positifs et négatifs

La policy candidate doit être testée avec le trafic qui doit passer et avec celui qui ne doit pas hériter de l’exception. L’observation en Detection est utile, mais le canary final doit exercer l’action et l’ordre de règles prévus en production.

yaml 03-rejeu-policy-bot.yml
cases:
- name: approved_partner
  source: approved_range
  client_id: partner-catalog-reader
  path: /v1/catalog/delta
  expected: reach_origin_and_authorize

- name: spoofed_user_agent
  source: unapproved_range
  client_id: none
  path: /v1/catalog/delta
  expected: no_privileged_access

- name: valid_client_wrong_path
  source: approved_range
  client_id: partner-catalog-reader
  path: /admin/export
  expected: deny

- name: hostile_payload_on_allowed_path
  source: approved_test_range
  client_id: test-identity
  path: /v1/catalog
  expected: managed_rules_still_evaluated

- name: volume_breach
  source: approved_test_range
  client_id: test-identity
  path: /v1/catalog
  expected: rate_control_visible

promotion_requires:
- every request tied to a WAF transaction
- origin authentication result recorded
- negative controls retain protection
- no unrelated hostname or route affected
- previous policy version ready for rollback

Rejouez depuis une source contrôlée avec des payloads inoffensifs. Le cas de payload hostile est un contrôle négatif de l’ordre des règles, pas un test offensif contre la production. S’il passe parce qu’une custom rule Allow court-circuite les règles gérées, rejetez le design.

Choisir le changement minimal et défendable

Maintenez le blocage lorsque le trafic correspond à la threat intelligence, falsifie une identité connue, ne peut pas être relié à une identité applicative ou sort des routes et débits déclarés. Un nom de produit crédible ne change pas cette décision.

Conservez plutôt Bot Manager en Log lorsque la classification est utile mais que l’authentification applicative doit autoriser l’accès. Associez-y autorisation par route, quotas et alertes sur les incohérences d’identité. C’est souvent la bonne réponse pour une automatisation interne ou un SDK partenaire classé comme inconnu.

N’utilisez une exception de policy que si le contrat client est stable, les conditions de match sont étroites, les contrôles négatifs prouvent le maintien des protections gérées, et l’exception possède un propriétaire et une date de revue. Si ces conditions ne peuvent pas cohabiter dans une policy partagée, séparez le hostname ou la policy au lieu d’élargir une règle globale.

Valider et revenir en arrière

Déployez le changement en canary sur une route, un hostname ou une association de policy. Pendant la fenêtre d’observation, comparez événements Bot Manager, 403 légitimes, échecs d’authentification à l’origine, débit, latence et détections des règles gérées avec la baseline précédente.

Promouvez uniquement si le client approuvé réussit avec son identité réelle, si ses variantes usurpées n’obtiennent aucun accès, si les autres catégories de bots restent inchangées et si la preuve des règles gérées reste visible. Revenez immédiatement en arrière si l’exception matche un client inattendu, supprime l’inspection gérée, affecte un autre hostname ou augmente le trafic non authentifié à l’origine.

Le rollback consiste à restaurer la version ou l’association de policy précédente, confirmer sa propagation, rejouer la même matrice et révoquer tout credential ou toute exception source temporaire. Revenir en arrière sur le WAF n’annule pas une action déjà acceptée par l’origine pendant la fenêtre : relisez ces requêtes via leur identifiant de corrélation.

Conclusion

Bot Manager indique comment Azure classe un trafic automatisé. Il ne décide pas si ce client est autorisé à utiliser votre API. Classification, identité et permission applicative doivent rester trois contrôles distincts.

La décision de production doit être nette : maintenir le blocage, conserver le logging et imposer l’identité à l’origine, introduire une exception bornée, ou isoler l’automatisation derrière une policy dédiée. Une règle d’autorisation n’est acceptable que si le même rejeu prouve à la fois le rétablissement du client attendu et la résistance à son usurpation la plus simple.