Infrastructure
Azure RBAC : diagnostiquer une dérive d'autorisations avant d'élargir un rôle
Un runbook de production pour qualifier une dérive Azure RBAC avec identité réelle, scope, PIM, role assignments, deny assignments, logs, validation et rollback avant d'ajouter des droits.
Un refus Azure RBAC arrive souvent au mauvais moment : un pipeline ne peut plus déployer, une identité managée ne lit plus une ressource, un opérateur perd l’accès à un groupe de ressources ou une automatisation échoue sur une action pourtant déjà validée. Le réflexe dangereux consiste à ajouter rapidement un rôle plus large pour débloquer la situation. En production, cette correction peut masquer une dérive de scope, une activation PIM manquante, une suppression de role assignment, un deny assignment, une identité d’exécution différente ou une propagation encore incomplète.
Le cas d’usage est une plateforme Azure exploitée par des équipes produit, plateforme et sécurité. Des déploiements passent par des identités fédérées ou managées, certaines permissions sont activées via PIM, et les changements RBAC sont gérés par IaC ou par workflow d’approbation. Un incident apparaît : une action légitime retourne AuthorizationFailed, mais l’équipe ne sait pas encore si le problème vient du rôle, du scope, de l’identité, du timing ou d’une policy de sécurité. Le but du runbook est de diagnostiquer avant d’élargir les droits.
Fixer l’action refusée
Avant de parler de rôle, isolez l’action exacte. Azure RBAC autorise une combinaison : principal, action, ressource, scope et condition éventuelle. Si l’un de ces éléments est flou, la correction risque d’être trop large.
Incident
Symptome: AuthorizationFailed pendant un deploiement
Operation: Microsoft.Web/sites/config/write
Ressource: /subscriptions/.../resourceGroups/rg-prod/providers/Microsoft.Web/sites/app-orders-prod
Principal attendu: mi-platform-deploy-prod
Principal observe: a confirmer dans les logs
Scope attendu: resource group rg-prod
Fenetre: 2026-06-27 09:00-09:30 UTC
Questions avant correction
Quelle action exacte est refusee ?
Quel principal a vraiment appele Azure ?
Le refus porte-t-il sur la ressource cible ou sur une dependance ?
Le role manquant est-il permanent, eligible PIM ou gere par IaC ?
Existe-t-il un deny assignment ou une policy qui bloque l'action ? Cette étape évite de corriger au niveau subscription un refus qui concerne seulement une ressource enfant, ou d’ajouter un rôle à la mauvaise identité.
Prouver l’identité réelle
Le principal déclaré dans le runbook n’est pas toujours celui qui appelle Azure. Un pipeline peut utiliser une fédération OIDC différente, un job peut basculer vers une identité système, un script local peut utiliser le compte de l’opérateur, et une automatisation peut conserver un ancien service principal.
az account show --query "{subscription:id, tenant:tenantId, user:user.name, type:user.type}" --output json
az ad signed-in-user show --query "{id:id,userPrincipalName:userPrincipalName}" --output json
az role assignment list --assignee "$PRINCIPAL_ID" --include-inherited --all --query "[].{role:roleDefinitionName,scope:scope,principalType:principalType}" --output table Pour une identité managée ou fédérée, récupérez aussi l’objectId réellement utilisé dans les logs d’authentification, pas seulement le nom affiché. Le nom peut être réutilisé, déplacé ou confondu entre environnements.
Lire le refus dans les journaux
Le message d’erreur côté outil est rarement suffisant. L’Activity Log donne l’opération, le statut, le caller et le scope effectif. Les sign-in logs ou traces de pipeline permettent de relier le refus à l’identité d’exécution.
let window = 6h;
AzureActivity
| where TimeGenerated > ago(window)
| where ActivityStatusValue =~ "Failure"
| where OperationNameValue has_any ("WRITE", "DELETE", "ACTION")
| where Properties has "AuthorizationFailed" or StatusValue has "Forbidden"
| project TimeGenerated,
OperationNameValue,
ActivityStatusValue,
Caller,
ResourceGroup,
ResourceProviderValue,
ResourceId,
CorrelationId,
Properties
| order by TimeGenerated desc Si l’environnement centralise les logs Entra ID, ajoutez les échecs de connexion, les claims OIDC et les événements PIM. Le diagnostic doit répondre à une question simple : l’identité a-t-elle été authentifiée correctement puis refusée par RBAC, ou l’échec est-il plus haut dans la chaîne ?
Comparer les role assignments attendus et effectifs
Un rôle manquant n’est qu’une hypothèse. Comparez l’état attendu avec l’état effectif, en tenant compte de l’héritage, des groupes, des assignments temporaires, des conditions et des suppressions récentes.
SCOPE="/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod"
PRINCIPAL_ID="11111111-1111-1111-1111-111111111111"
az role assignment list --scope "$SCOPE" --assignee "$PRINCIPAL_ID" --include-inherited --all --query "[].{role:roleDefinitionName,scope:scope,condition:condition,createdOn:createdOn,updatedOn:updatedOn}" --output json
az role assignment list --scope "$SCOPE" --include-groups --all --query "[?principalId=='$PRINCIPAL_ID' || contains(principalName, 'platform')].{principal:principalName,role:roleDefinitionName,scope:scope}" --output table Archivez cette capture avant correction. Si un rollback est nécessaire, il faudra savoir quel assignment a été ajouté, modifié ou supprimé.
Chercher PIM, deny assignments et conditions
Les incidents RBAC ne se limitent pas aux roleAssignments. Une activation PIM expirée, une affectation éligible non activée, un deny assignment posé par un service managé ou une condition ABAC peuvent produire le même symptôme opérationnel.
Controles a verifier
PIM: role eligible mais non active
PIM: activation expiree ou scope different
Groupe: appartenance non propagee ou mauvais groupe
Deny assignment: ressource protegee par service managé ou blueprint historique
Condition: role assignment limite par attribut ou type de ressource
Management group: role herite plus haut que le scope observe
IaC: correction manuelle qui sera retiree au prochain apply
Propagation: changement trop recent pour conclure Un rôle plus large ne corrige pas toujours ces contrôles. Il peut même créer une exception durable qui disparaîtra au prochain déploiement IaC ou contournera le modèle d’accès attendu.
Qualifier le besoin minimal
La bonne correction part de l’action refusée, pas du rôle le plus confortable. Construisez une matrice qui relie l’opération au rôle minimal acceptable, puis vérifiez si le scope doit être ressource, groupe de ressources ou subscription.
Action a autoriser
Operation: Microsoft.Web/sites/config/write
Ressource cible: app-orders-prod
Justification: mise a jour configuration applicative par pipeline
Role candidat: Website Contributor ou role custom existant
Scope prefere: ressource ou resource group rg-prod
Duree: permanent via IaC ou temporaire via PIM selon le mode d'exploitation
Refuser comme correction rapide
Contributor sur subscription
Owner pour contourner un refus de write
Affectation directe a un utilisateur si le runbook attend une identite de pipeline
Role manuel non declare dans IaC
Ajout sans preuve de l'identite appelante Si le rôle minimal n’existe pas, la décision peut être de créer ou corriger un rôle custom. Mais ce choix doit rester explicite : il n’est pas équivalent à ouvrir Contributor pour gagner dix minutes.
Décider : attendre, corriger ou rollbacker
Le diagnostic doit produire une décision exploitable. Certaines situations demandent seulement d’attendre la propagation ou d’activer PIM. D’autres exigent une correction RBAC limitée. D’autres encore imposent un rollback du changement d’accès récent.
Attendre ou rejouer
Role assignment correct et tres recent
Propagation RBAC plausible
Aucun changement de scope ou d'identite
Rejeu controle disponible sans impact utilisateur
Corriger au scope minimal
Identite reelle confirmee
Action refusee comprise
Role manquant identifie
Scope cible borne
Changement declare dans IaC ou ticket d'acces
Activer PIM
Role eligible deja approuve
Fenetre d'exploitation limitee
Justification et approbateur presents
Trace d'activation conservee
Rollbacker
Suppression RBAC recente non justifiee
Changement de groupe ou de role casse plusieurs consommateurs
Deny assignment ou policy introduit par erreur
Correction rapide elargirait trop les droits La règle pratique : n’élargissez pas un rôle tant que l’identité réelle, l’action refusée et le scope minimal ne sont pas prouvés.
Valider après correction
Une correction RBAC ne se valide pas seulement par un déploiement qui repasse. Il faut prouver que l’action attendue fonctionne et que les droits ne débordent pas.
Validation minimale
Le meme principal execute la meme action sans AuthorizationFailed
Le scope de l'affectation correspond au besoin
Aucun role large n'a ete ajoute par raccourci
Les logs montrent l'appel reussi et le caller attendu
Les tests de non-regression passent pour les autres consommateurs
Le changement est capture dans IaC, PIM ou ticket approuve
Rollback propre
Retirer uniquement l'assignment ajoute
Restaurer l'assignment supprime si la cause vient d'un retrait
Rejouer l'action de validation
Conserver correlationId, caller, role et scope dans le ticket
Ajouter le cas au runbook d'acces si l'incident etait reproductible Si la correction a été faite manuellement pour débloquer l’incident, planifiez immédiatement sa reprise dans le mécanisme normal : Terraform, Bicep, workflow IAM ou PIM. Sinon, la dérive reviendra.
Automatiser les garde-fous
Une bonne automatisation RBAC ne doit pas seulement créer des assignments. Elle doit empêcher les corrections trop larges et conserver les preuves qui permettront de diagnostiquer le prochain refus.
guardrails:
before_apply:
- capture_denied_operation
- prove_runtime_principal
- list_effective_assignments
- check_pim_and_deny_assignments
- map_action_to_minimal_role
block_when:
- contributor_or_owner_at_subscription_without_exception
- runtime_identity_unknown
- manual_assignment_not_reconciled_with_iac
- missing_rollback_plan
after_apply:
- replay_denied_action
- query_activity_log_for_success
- confirm_no_broader_scope_added
- attach_evidence_to_access_ticket Le but n’est pas de ralentir chaque accès. Le but est d’éviter qu’un incident d’autorisation devienne une dette de sécurité permanente.
Conclusion
Un refus Azure RBAC doit être traité comme un incident de contrôle d’accès, pas comme une invitation à ajouter un rôle plus large. La séquence saine consiste à isoler l’action refusée, prouver l’identité réelle, comparer les assignments effectifs, vérifier PIM, deny assignments et conditions, puis décider.
La bonne issue est simple : attendre si la propagation explique le symptôme, activer PIM si le droit existe déjà, corriger au scope minimal si le manque est prouvé, ou rollbacker si une dérive récente a cassé l’accès. C’est ce qui permet de débloquer la production sans transformer l’urgence en permission durablement excessive.