Lors d’une mission, j’ai dû auditer les permissions effectives sur un abonnement Azure client.
Objectif simple sur le papier : savoir qui a accès à quoi, avec quel rôle, et à quel niveau de périmètre.
En pratique, l’abonnement avait vécu :
- héritage de rôles multiples,
- affectations historiques jamais nettoyées,
- comptes techniques, groupes, identités managées mélangés.
Il fallait une vue exploitable, exportable, et partageable — sans passer par le portail Azure à la main.
L’approche retenue
Le script s’appuie sur :
Az.Accountspour la sélection du tenant et de l’abonnement,Az.Resourcespour l’inventaire RBAC,- une résolution des principaux (User / Group / SPN / MSI),
- une sortie structurée :
- CSV pour l’outillage brut,
- Excel pour l’analyse et le partage (mise en forme minimale).
Aucune dépendance exotique, hormis le module ImportExcel pour la génération du fichier .xlsx.
Périmètre couvert
Le script audite l’ensemble des affectations RBAC visibles dans le contexte de l’abonnement sélectionné, quel que soit leur niveau :
- abonnement,
- groupes de ressources,
- ressources individuelles.
Chaque affectation expose son périmètre exact via le champ Scope, ce qui permet d’identifier précisément où le rôle est appliqué.
RBAC : affectations vs privilèges effectifs
Le script liste les affectations RBAC déclarées, pas les droits effectifs cumulés. L’héritage (subscription → resource group → ressource) n’est pas recalculé.
L’analyse des privilèges réellement disponibles reste volontairement humaine
(exploitation du champ Scope, filtres Excel, revue ciblée).
Le script PowerShell
La version complète et maintenue est publiée sur GitHub.
Le script ci-dessous est strictement identique à la version source.
<#
.SYNOPSIS
Audit Azure RBAC permissions across a subscription.
.DESCRIPTION
This script collects all visible Azure RBAC role assignments within a selected
Azure subscription, across all scope levels:
- subscription
- resource groups
- individual resources
The output is exported to CSV and Excel formats to support review,
governance analysis, and reporting.
.CONTEXT
- Usage: IAM / RBAC audit
- Environment: Azure subscription
- Scenarios: RSSI/CISO engagement, customer audit, periodic review, MSP context
.PREREQUISITES
- PowerShell modules:
- Az.Accounts
- Az.Resources
- ImportExcel
- Minimum permissions:
- Reader on the subscription
- Azure AD read access (identity resolution)
.LIMITATIONS
- Effective permissions are not calculated (RBAC inheritance is not evaluated).
- PIM-eligible role assignments are not included.
- Visibility depends on the permissions of the executing account.
.OUTPUTS
- Azure-RBAC-Audit.csv
- Azure-RBAC-Audit.xlsx
.AUTHOR
Sébastien Miro
.VERSION
1.0
.LASTUPDATED
2025-01-XX
.SOURCE
https://github.com/<your-account>/azure-rbac-audit
#>
#Requires -Modules Az.Accounts, Az.Resources
param (
[string]$OutputPath = ".\Azure-RBAC-Audit"
)
# --- Pré-requis ---
if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
Write-Error "Le module ImportExcel est requis (Install-Module ImportExcel)."
return
}
# --- Connexion et sélection ---
Connect-AzAccount | Out-Null
$tenant = Get-AzTenant | Out-GridView -Title "Sélection du tenant" -PassThru
Set-AzContext -TenantId $tenant.Id | Out-Null
$subscription = Get-AzSubscription | Out-GridView -Title "Sélection de l'abonnement" -PassThru
Set-AzContext -SubscriptionId $subscription.Id | Out-Null
Write-Host "Audit RBAC sur l'abonnement $($subscription.Name)" -ForegroundColor Cyan
# --- Collecte RBAC ---
$assignments = Get-AzRoleAssignment -IncludeClassicAdministrators
$result = foreach ($a in $assignments) {
$principalType = $a.ObjectType
$displayName = $null
$upn = $null
try {
switch ($principalType) {
"User" {
$u = Get-AzADUser -ObjectId $a.ObjectId
$displayName = $u.DisplayName
$upn = $u.UserPrincipalName
}
"Group" {
$g = Get-AzADGroup -ObjectId $a.ObjectId
$displayName = $g.DisplayName
}
"ServicePrincipal" {
$sp = Get-AzADServicePrincipal -ObjectId $a.ObjectId
$displayName = $sp.DisplayName
}
default {
$displayName = "Inconnu"
}
}
}
catch {
$displayName = "Non résolu"
}
[PSCustomObject]@{
TenantName = $tenant.Name
SubscriptionName = $subscription.Name
Scope = $a.Scope
RoleName = $a.RoleDefinitionName
PrincipalType = $principalType
DisplayName = $displayName
UserPrincipal = $upn
ObjectId = $a.ObjectId
AssignmentId = $a.RoleAssignmentId
}
}
# --- Sorties ---
New-Item -ItemType Directory -Force -Path $OutputPath | Out-Null
$csvPath = Join-Path $OutputPath "Azure-RBAC-Audit.csv"
$xlsxPath = Join-Path $OutputPath "Azure-RBAC-Audit.xlsx"
$result | Sort-Object Scope, RoleName |
Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
$result | Sort-Object Scope, RoleName |
Export-Excel -Path $xlsxPath `
-WorksheetName "RBAC" `
-AutoSize `
-TableName "RBAC_Audit" `
-FreezeTopRow `
-BoldTopRow
Write-Host "Audit terminé." -ForegroundColor Green
Write-Host "CSV : $csvPath"
Write-Host "Excel: $xlsxPath"