Skip to content

Instantly share code, notes, and snippets.

@blakedrumm
Last active May 13, 2025 15:40
Show Gist options
  • Save blakedrumm/6daac49a41ac9b07ab889b8df443c154 to your computer and use it in GitHub Desktop.
Save blakedrumm/6daac49a41ac9b07ab889b8df443c154 to your computer and use it in GitHub Desktop.
PowerShell script to automate Azure role assignments for a specified user or managed identity across multiple subscriptions. Reads subscription data from a JSON file, verifies role existence, prevents duplicate assignments, and provides clear processing output. Useful for managing RBAC at scale in Azure environments.
<#
.SYNOPSIS
Assigns specified Azure roles to a user or managed identity across multiple subscriptions.
.DESCRIPTION
This script reads subscription IDs from a JSON file and assigns predefined roles at the subscription scope
to a specified principal (user or managed identity). It handles Azure authentication, validates role existence,
checks for existing assignments to avoid duplication, and outputs clear processing results.
The script is designed for environments requiring consistent role assignments across multiple Azure subscriptions.
.PARAMETER JsonFilePath
Path to the JSON file containing a list of subscription IDs under the 'subscription_id' property.
This script will gather all subscription IDs listed (even if there is more than one).
Example JSON format:
[
{
"subscription_id": "abcd1234-ef56-78gh-ijkl-90mnopqrstuv",
"resource_group_name": "test-resource-group-name",
"operation": "unlock"
}
]
.PARAMETER RoleNames
The Azure roles to assign to the specified principal.
.PARAMETER AssigneePrincipalId
The Object ID of the user or managed identity to which the roles will be assigned.
.NOTES
Author : Blake Drumm ([email protected])
Created : 2025-05-13
Version : 1.0
- Requires the Az PowerShell module.
- Principal must have sufficient permissions to assign roles at the subscription level.
- Script output is designed for easy reading and log analysis.
License:
----------------------------------------------------------------------------
Copyright (c) Microsoft Corporation. MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#>
param (
[Parameter(Mandatory = $false)]
[string]$JsonFilePath = "C:\Users\blakedrumm\Downloads\script-json.txt", # Path to the JSON file.
[Parameter(Mandatory = $false)]
[string[]]$RoleNames = @("Locks Contributor", "Contributor"), # Roles to assign.
[Parameter(Mandatory = $false)]
[string]$AssigneePrincipalId = "abcd1234-ef56-78gh-ijkl-90mnopqrstuv" # Principal ID to assign roles to.
)
# =============================== Script Start ===============================
# Validate JSON file existence
if (-not (Test-Path -Path $JsonFilePath)) {
Write-Output "ERROR: JSON file not found at path: $JsonFilePath. Exiting script."
exit 1
}
# Load and parse the JSON content
try {
$jsonContent = Get-Content -Path $JsonFilePath -Raw | ConvertFrom-Json
} catch {
Write-Output "ERROR: Failed to parse JSON content. Error: $_"
exit 1
}
# Ensure the JSON has the 'subscription_id' property
if (-not ($jsonContent | Get-Member -Name 'subscription_id')) {
Write-Output "ERROR: JSON content does not contain 'subscription_id' property. Exiting script."
exit 1
}
# Login to Azure if not already logged in
if (-not (Get-AzContext)) {
try {
Connect-AzAccount -ErrorAction Stop
} catch {
Write-Output "ERROR: Azure login failed. Exiting script. Error: $_"
exit 1
}
}
# Retrieve current tenant context
$currentTenant = (Get-AzContext).Tenant
# Get unique subscription IDs from the JSON content
$uniqueSubscriptions = $jsonContent | Select-Object -ExpandProperty subscription_id -Unique
foreach ($role in $RoleNames) {
foreach ($subscriptionId in $uniqueSubscriptions) {
Write-Output "`n===================================================================="
Write-Output "Processing Subscription: $subscriptionId"
Write-Output "Role: `"$role`""
Write-Output "===================================================================="
# Set the current subscription context
try {
Set-AzContext -Tenant $currentTenant -SubscriptionId $subscriptionId -ErrorAction Stop | Out-Null
} catch {
Write-Output "WARNING: Failed to set context for Subscription: $subscriptionId. Error: $_"
continue
}
# Retrieve Role Definition to verify it exists
$roleDefinition = Get-AzRoleDefinition -Name $role -ErrorAction SilentlyContinue
if (-not $roleDefinition) {
Write-Output "WARNING: Role '$role' not found in Subscription $subscriptionId. Skipping..."
continue
}
# Reset assignment variable
$existingAssignment = $null
# Check if the role assignment already exists
$existingAssignment = Get-AzRoleAssignment -Scope "/subscriptions/$subscriptionId" -ObjectId $AssigneePrincipalId -ErrorAction SilentlyContinue
if ($existingAssignment.RoleDefinitionName -eq $role) {
Write-Output "INFO: Role assignment ($role) already exists for $AssigneePrincipalId. Skipping..."
} else {
try {
New-AzRoleAssignment -ObjectId $AssigneePrincipalId -RoleDefinitionName $role -Scope "/subscriptions/$subscriptionId" -ErrorAction Stop
Write-Output "SUCCESS: Role '$role' successfully assigned to $AssigneePrincipalId."
} catch {
Write-Output "ERROR: Failed to assign role '$role'. Error: $_"
}
}
# Small delay between iterations to avoid API throttling
Start-Sleep -Seconds 2
}
}
Write-Output "`n================== Role assignment process completed successfully. =================="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment