Cloud

Azure APIM : diagnostiquer une clé d'abonnement avant rotation en production

Un runbook de production pour qualifier des 401/403 Azure API Management avec subscription key, produit, API, consumer, logs, validation et rollback avant de tourner une clé.

14 juil. 2026 azureapi-managementapimsubscription-keysecurityidentityobservabilitykqlrunbookrollbackproduction

Une clé d’abonnement APIM qui expire, fuite ou doit être remplacée pousse souvent à régénérer trop vite la clé primaire ou secondaire. Le risque est simple : un consumer continue d’utiliser l’ancienne valeur, une API n’est pas exposée par le bon produit, une subscription est désactivée, une policy exige un en-tête différent, ou le backend renvoie un 403 qui ressemble à un refus APIM. La rotation devient alors une panne de production déguisée en tâche de sécurité.

Le cas d’usage est une API orders-api publiée dans Azure API Management pour des applications internes et un partenaire. Les appels passent par api.internal.example.com, APIM applique le produit partner-standard, puis appelle un backend déjà sain. Depuis un changement de clé, certains appels retournent 401 ou 403. L’objectif du runbook est de décider si la clé peut être tournée, si le consumer doit être corrigé, si la subscription doit être restaurée, ou si le rollback doit remettre temporairement l’ancienne clé contrôlée.

Figer le contrat du consumer

Commencez par identifier le consumer réel, le produit APIM, l’API, l’en-tête attendu et la fenêtre de changement. Une clé APIM n’est pas un secret isolé : elle relie une application, un produit, des policies, des quotas et des logs.

text apim-subscription-incident.txt
Incident
Hostname: api.internal.example.com
API: orders-api
Product: partner-standard
Subscription: partner-fulfillment-prod
Consumer: partner-orders-worker
Header attendu: Ocp-Apim-Subscription-Key
Symptome: 401 Access denied ou 403 Forbidden
Fenetre: apres rotation planifiee ou regeneration d'urgence
Backend: sain sur probe controlee

Questions avant action
Quelle cle est utilisee: primary ou secondary ?
La subscription est-elle active ?
Le produit contient-il encore l'API appelee ?
Le consumer a-t-il deploye la nouvelle valeur ?
Une policy change-t-elle le nom d'en-tete ou exige-t-elle JWT, mTLS ou IP allowlist ?
Le rollback remet-il une cle ou seulement une configuration applicative ?

Si ces éléments ne sont pas connus, régénérer une clé revient à modifier l’interface de production sans savoir qui l’utilise.

Séparer refus APIM, policy et backend

Un 401 APIM n’a pas la même cause qu’un 403 backend. Avant de toucher à la clé, vérifiez où le refus est produit.

text apim-auth-layer-reading.txt
Lecture par couche
APIM 401
  Cle absente, mauvaise cle, mauvais nom d'en-tete, subscription inactive ou API hors produit

APIM 403
  Subscription valide mais refus policy, produit ferme, quota, rate limit, IP restriction ou validation JWT/mTLS

Backend 401 ou 403
  APIM a accepte la requete, mais le backend refuse l'identite, le token, la cle applicative ou l'adresse source

WAF ou gateway 403
  La requete peut ne jamais atteindre APIM: verifier logs Application Gateway ou Front Door avant APIM

Aucun log APIM
  Mauvais hostname, route, DNS, listener, certificat, WAF ou chemin client

Cette séparation évite de régénérer une clé alors que le problème est un produit APIM, une policy, un quota ou une identité backend.

Lire l’état APIM avant la rotation

Récupérez la subscription, le produit, l’API et les policies associées. L’objectif est de prouver que le contrat APIM attendu existe encore.

bash 01-apim-subscription-state.sh
RG="rg-shared-api-prod"
APIM="apim-prod-core"
SUBSCRIPTION_ID="partner-fulfillment-prod"
PRODUCT_ID="partner-standard"
API_ID="orders-api"

az apim subscription show --resource-group "$RG" --service-name "$APIM" --sid "$SUBSCRIPTION_ID" --query "{state:state,scope:scope,ownerId:ownerId,displayName:displayName,createdDate:createdDate,expirationDate:expirationDate}" --output json

az apim product api list --resource-group "$RG" --service-name "$APIM" --product-id "$PRODUCT_ID" --query "[].{apiId:name,displayName:displayName,path:path}" --output table

az apim api show --resource-group "$RG" --service-name "$APIM" --api-id "$API_ID" --query "{path:path,protocols:protocols,subscriptionRequired:subscriptionRequired}" --output json

Bloquez la rotation si la subscription est désactivée, si l’API n’est plus dans le produit, si le champ subscriptionRequired ne correspond pas au design attendu, ou si la policy a changé sans revue.

Corréler les appels avec KQL

La preuve utile montre le consumer, l’API, le produit, le status, l’opération et le message d’erreur APIM dans la même fenêtre. Ajoutez un identifiant de corrélation côté consumer quand c’est possible.

kusto 02-apim-subscription-errors.kql
let Window = 2h;
let ApiPath = "/orders";
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where ResourceProvider == "MICROSOFT.APIMANAGEMENT"
| where tostring(Url) has ApiPath or tostring(RequestUri) has ApiPath
| project TimeGenerated,
        ServiceName=tostring(Resource),
        ApiId=tostring(ApiId),
        OperationId=tostring(OperationId),
        ProductId=tostring(ProductId),
        SubscriptionId=tostring(SubscriptionId),
        CallerIp=tostring(CallerIPAddress),
        Status=toint(ResponseCode),
        Error=tostring(ErrorMessage),
        CorrelationId=tostring(CorrelationId),
        Url=tostring(Url)
| where Status in (401, 403, 429, 500)
| order by TimeGenerated desc

Si SubscriptionId est vide ou inattendu, le consumer n’utilise probablement pas la clé attendue ou le bon en-tête. Si SubscriptionId est correct mais que le status reste 403, regardez la policy, le quota, l’IP allowlist ou l’authentification backend.

Tester primary et secondary sans casser le consumer

APIM permet une rotation sûre si le consumer peut basculer d’une clé à l’autre. La bonne séquence n’est pas de régénérer les deux clés, mais de prouver quelle clé est utilisée, déployer l’autre, valider, puis seulement régénérer l’ancienne.

text apim-key-rotation-sequence.txt
Sequence de rotation controlee
1. Identifier la cle actuellement utilisee par le consumer
2. Distribuer la cle secondaire si la primaire est active, ou l'inverse
3. Rejouer une requete controlee avec x-correlation-id
4. Verifier APIM logs: subscriptionId, productId, apiId, status 2xx ou erreur attendue
5. Basculer le consumer vers la nouvelle valeur
6. Attendre la fenetre d'observation convenue
7. Regenerer uniquement l'ancienne cle
8. Garder un rollback applicatif documente jusqu'a validation complete

Interdit
Regenerer primary et secondary dans la meme fenetre
Tourner une cle sans savoir quel consumer l'utilise
Corriger un 403 backend par regeneration de subscription key
Supprimer l'ancienne valeur avant preuve APIM et applicative

Pour un incident de fuite, la fenêtre peut être plus courte, mais la décision reste la même : préserver une option de bascule ou assumer explicitement l’interruption.

Rejouer avec une preuve de bout en bout

Le test de validation doit passer par le chemin réel et montrer la même API que les consumers. N’utilisez pas seulement un endpoint de santé non protégé.

bash 03-apim-controlled-replay.sh
HOST="api.internal.example.com"
PATH_TO_TEST="/orders/health"
CORRELATION_ID="apim-key-$(date +%Y%m%d%H%M%S)"
SUBSCRIPTION_KEY="<candidate-key>"

curl -sS -D - "https://${HOST}${PATH_TO_TEST}" -H "Ocp-Apim-Subscription-Key: ${SUBSCRIPTION_KEY}" -H "x-correlation-id: ${CORRELATION_ID}" -o /tmp/apim-response.json

echo "correlation_id=${CORRELATION_ID}"
cat /tmp/apim-response.json

Validez ensuite dans les logs que la requête a traversé le bon produit, la bonne API et la bonne subscription. Un 200 sans SubscriptionId attendu peut signaler que le test a contourné le contrat réel.

Décider rotation, correction ou rollback

La sortie du runbook doit être une décision opérationnelle, pas seulement une hypothèse sur la clé.

text apim-subscription-decision.txt
Tourner la cle
La subscription est active
Le produit expose toujours l'API
Le consumer a valide la cle de remplacement
APIM logs prouvent le bon subscriptionId
Le rollback applicatif est pret

Corriger le consumer
Mauvais en-tete ou ancienne valeur
Mauvaise variable Key Vault ou App Configuration
Deploiement partiel sur un seul worker
Cache applicatif non rafraichi

Corriger APIM
API retiree du produit par erreur
Subscription desactivee ou expiree
Policy a change le contrat d'authentification
Quota ou rate-limit bloque le consumer legitime

Rollbacker ou bloquer
Les deux cles ont ete invalidees
Impossible d'identifier les consumers reels
Les logs ne distinguent pas APIM et backend
La rotation masque un incident de securite non qualifie

Le rollback peut être applicatif, APIM ou secret-management. Il doit préciser quelle valeur est restaurée, où elle est injectée et combien de temps elle reste acceptée.

Garder un artefact de handover

Une rotation de clé réussie doit laisser une trace exploitable pour le prochain incident : owner, consumer, clé active, preuve de bascule et date de régénération de l’ancienne clé.

yaml apim-subscription-handover.yml
apim_subscription_rotation:
api: orders-api
product: partner-standard
subscription: partner-fulfillment-prod
consumer: partner-orders-worker
active_key_after_change: secondary
old_key_regenerated: primary
evidence:
  - apim_logs_show_expected_subscription_id
  - controlled_replay_correlation_id_attached
  - consumer_deployment_version_identified
  - backend_errors_checked_separately
rollback:
  restore_consumer_secret_version: kv://kv-prod/api/apim-key/previous
  do_not_regenerate_secondary_until: 2026-07-15T18:00:00Z
  owner: platform-operations
follow_up:
  - document consumers for the subscription
  - alert on APIM 401/403 by product and subscription
  - avoid shared subscriptions for unrelated consumers

Conclusion

Une subscription key APIM est une frontière d’exploitation. Elle protège une API, mais elle sert aussi de contrat entre APIM, un produit et un consumer réel.

Le bon résultat n’est donc pas seulement une clé régénérée. C’est une rotation prouvée : consumer identifié, refus localisé, logs corrélés, bascule validée et rollback encore possible si la nouvelle valeur ne tient pas en production.