RBAC lo sai leggere. Quello che si sbaglia in produzione è il resto: quali ruoli sono privilegiati anche quando il nome non lo dice, dove un ruolo personalizzato smette di essere assegnabile, e come si trova il privilegio ereditato da tre livelli più su.
Tre pezzi, quattro livelli, due limiti
Un’assegnazione è un principal (utente, gruppo, service principal o identità gestita), una definizione di ruolo e uno scope. Gli scope sono quattro — management group, sottoscrizione, gruppo di risorse, risorsa — con ereditarietà verso il basso.
Per assegnare serve Microsoft.Authorization/roleAssignments/write, per rimuovere Microsoft.Authorization/roleAssignments/delete, entrambi allo scope su cui operi. Se assegna un service principal e ottieni “Insufficient privileges”, spesso non è RBAC: non riesce a leggere la directory per risolvere l’assegnatario, e la scorciatoia è passare l’object ID.
I due numeri da ricordare: 4000 assegnazioni per sottoscrizione (comprese quelle su gruppi di risorse e risorse; le eleggibili e quelle pianificate non contano) e 500 per management group. È anche il motivo tecnico della regola “assegna ai gruppi, non alle persone”. E negli script usa l’ID del ruolo: il nome può cambiare, l’ID no.
Job function contro privileged administrator
I ruoli predefiniti si dividono in due famiglie. I job function role gestiscono risorse specifiche: parti dal più restrittivo che fa il lavoro — per leggere blob è Storage Blob Data Reader, non Contributor né Storage Blob Data Owner.
I privileged administrator role sono cinque e valgono su tutti i tipi di risorsa: Owner, Contributor, Reservations Administrator, Role Based Access Control Administrator e User Access Administrator. Contributor gestisce tutte le risorse ma non assegna ruoli. RBAC Administrator e User Access Administrator gestiscono l’accesso e possono assegnare Owner a sé stessi o ad altri: non sono una versione mite di Owner. La differenza: RBAC Administrator non può gestire l’accesso per altre vie, per esempio con Azure Policy.
Le contromisure documentate: massimo tre owner per sottoscrizione (Defender for Cloud lo monitora), scope stretto quando un ruolo privilegiato è inevitabile, e una condizione sull’assegnazione per limitare quali ruoli un delegato può assegnare a sua volta.
Ruoli personalizzati Azure: dove smettono di funzionare
Un ruolo personalizzato ha Actions e NotActions per il control plane, DataActions e NotDataActions per il piano dati, e AssignableScopes. Il malinteso classico è su NotActions: sottrae azioni dalle Actions di quel ruolo, non è una negazione globale. Per escludere accesso concesso altrove servono le deny assignment.
I vincoli che fanno fallire i deployment: massimo 5000 ruoli personalizzati per tenant, AssignableScopes non può essere la radice / né contenere wildcard, al massimo 2000 voci e un solo management group; un ruolo con DataActions non si può assegnare a livello di management group, anche se puoi assegnarlo alle sottoscrizioni che stanno dentro. Un solo wildcard per stringa di azione, e meglio elencare le azioni esplicitamente: un * eredita anche i permessi futuri.
Chi può crearlo o aggiornarlo deve avere Microsoft.Authorization/roleDefinitions/write su tutti gli AssignableScopes. E prima di eliminarlo devi togliere ogni assegnazione che lo usa, incluse quelle eleggibili in PIM, altrimenti ottieni RoleDefinitionHasAssignments.
Ruoli personalizzati Entra: sistema diverso, licenza diversa
I ruoli Microsoft Entra governano le risorse della directory (utenti, gruppi, applicazioni) via Microsoft Graph; i ruoli Azure governano le risorse ARM. I permessi non sono intercambiabili fra i due sistemi.
I ruoli Entra predefiniti sono gratuiti, ma i ruoli personalizzati richiedono Entra ID P1 per ogni utente che ne ha uno assegnato, e li crea un Privileged Role Administrator. Possono contenere solo permessi abilitati per l’uso custom: registrazioni di app, applicazioni enterprise, consent, dispositivi, utenti e gruppi.
Lo scope può essere il tenant, un’unità amministrativa o una singola risorsa: un gruppo, un’enterprise app, una registrazione di app. Attenzione alla semantica: un ruolo assegnato su un contenitore vale sugli oggetti contenuti, non sul contenitore stesso. Infine, Azure CLI non supporta le assegnazioni di ruolo Entra: admin center, Microsoft Graph PowerShell o Graph API.
Trovare il privilegio in eccesso, e toglierlo davvero
In Access control (IAM), la scheda Role assignments ha un tab Privileged che conta le assegnazioni privilegiate a quello scope; da “View assignments” le rimuovi o le vincoli con una condizione. Check access mostra, per un principal, quello che ha a quello scope e quello che eredita — ma non le assegnazioni sugli scope figli: quella lacuna è il motivo per cui gli audit “puliti” a livello di sottoscrizione mancano il resource group con l’Owner dimenticato.
Per l’inventario usa Download role assignments in CSV o JSON, con le caselle Inherited, At current scope e Children (Children è disabilitata a livello di management group). Due caveat: le assegnazioni con principal cancellato non ci sono, e senza permessi di lettura sulla directory le colonne con nome e tipo restano vuote. Con licenza P2 o Governance la colonna State distingue Active permanent, Active time-bound, Eligible permanent ed Eligible time-bound: è così che ti accorgi che un’assegnazione non è permanente.
La rimozione ha una regola che sorprende: un’assegnazione ereditata non si rimuove dal figlio. Il portale lo dice e il link accanto a “(Inherited)” apre lo scope giusto. Da riga di comando indica sempre lo scope, altrimenti ricevi “The provided information does not map to a role assignment”; e un template ARM non rimuove assegnazioni.
Remove-AzRoleAssignment -ObjectId OBJID -RoleDefinitionName "Reader" -Scope "/subscriptions/SUB"
La riduzione strutturale non è cancellare righe: è assegnare ai gruppi, scendere di scope e rendere eleggibili i ruoli privilegiati invece che permanenti.