Azure RBAC script

Table Of Contents

Intro

It has been a while since my latest post, primarily due to a lot of presentations at work and the fact that I got into the Microsoft MVP program. I have spent quite a bit of time figuring out what that means and participating in the Microsoft MVP summit. The MVP summit spread over three days, and during those three days, I participated in almost 24 hours of teams meetings with the product teams. Loads of good information, but it does drain the energy as well.

In this post, I want to share a script I have made to create Azure AD groups and use them for Role-based access for Azure management groups and subscriptions. I have shared the script, but use it at your own risk. I cannot be held responsible for what happens if you use it in your environment.

I have used the Microsoft documentation as a guideline for this blog post. You can find all the information on this Microsoft site.

https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-powershell

The idea behind the script

I have been creating Azure environments for some time now. One of the most significant asks from both myself and customers is a streamlined way of providing the correct access to Azure resources for a set of users. Sometimes we need to create custom roles in Azure to have the proper permissions for a group of users, but I will make do with the standard roles for this post. If you want some guidance on creating custom roles, let me know.

The script I have shared on my GitHub runs through all management groups and subscriptions, and for each of them, it will create Azure AD groups for each role you have defined in the parameters. I have added the option for selecting management groups, subscriptions, or both as the scope for the script.

Below is an example of what I have seen in customer environments.

The picture below is more of what I believe is the correct configuration. There are still a few items that are not in a group, but it is at least better than what it was.

Script explanation

In this section, I will explain some of the code to make it more clear.

The code below is the parameters for the script.

“Roles” define which roles you want to create a group. In the example below, it will generate an Owner, Contributor, and Reader group for each management group and subscription.

“MGPrefix” defines what is in front of each group for management groups. In the example, it will be AZ-MG-Tenant Root-Owner.

“MGSuffix” defines what should be after each group for management groups. As an example, here, “Access” is the suffix AZ-MG-Tenant Root-Owner-Access

“SubPrefix” defines what is in front of each group for a subscription. In the example it will be AZ-SUB-Subscription1-Owner

“SubSuffix” defines what should be after each group for subscriptions. As an example, here “Access” is the suffix AZ-SUB-Subscription1-Owner-Access

“Scope” defines whether you want to run the script for management groups, subscriptions, or both.

“ManagementGroupName” defines a single management group to run the script.

“SubscriptionName” defines a single subscription to run the script.

[CmdletBinding()]
param (
    [string[]]$Roles = @("Owner","Contributor","Reader"),
    [string]$MGPrefix = "AZ-MG-",
    [string]$MGSuffix,
    [string]$SubPrefix = "AZ-SUB-",
    [string]$SubSuffix,
    [ValidateSet("ManagementGroups","Subscriptions","Both")]
    $Scope = "Both",
    [string]$ManagementGroupName, 
    [string]$SubscriptionName
)

The script

[CmdletBinding()]
param (
    [string[]]$Roles = @("Owner","Contributor","Reader"),
    [string]$MGPrefix = "AZ-MG-",
    [string]$MGSuffix,
    [string]$SubPrefix = "AZ-SUB-",
    [string]$SubSuffix,
    [ValidateSet("ManagementGroups","Subscriptions","Both")]
    $Scope = "Both",
    [string]$ManagementGroupName, 
    [string]$SubscriptionName
)

If ($Scope -eq "ManagementGroups" -or $Scope -eq "Both") {
    If ($ManagementGroupName -eq $null) {
        $ManagementGroups = Get-AzManagementGroup
    } else {
        $ManagementGroups = Get-AzManagementGroup -GroupName $ManagementGroupName
    }   

    Foreach ($ManagementGroup in $ManagementGroups) {
        foreach($Role in $Roles) {
            Write-Host "Checking if group $($MGPrefix)$($ManagementGroup.DisplayName)$($MGSuffix)-$($Role) already exists"
            $CheckGroup = Get-AzADGroup -DisplayName "$($MGPrefix)$($ManagementGroup.DisplayName)$($MGSuffix)-$($Role)"
            if ($CheckGroup.Length -eq 0) {
                Write-Host "Group not found"
                Write-Host "Creating group: $($MGPrefix)$($ManagementGroup.DisplayName)$($MGSuffix)-$($Role) in Azure AD"
                New-AzADGroup -DisplayName "$($MGPrefix)$($ManagementGroup.DisplayName)$($MGSuffix)-$($Role)" -MailEnabled:$false -SecurityEnabled:$true -MailNickName "NotSet" | Out-Null
            } else {
                Write-Host "Group $($MGPrefix)$($ManagementGroup.DisplayName)$($MGSuffix)-$($Role) found, skipping creation"
            }     
        }
        Write-Host "Waiting 10 seconds for Azure AD Groups to be created"
        Start-Sleep -Seconds 10
        
        foreach($Role in $Roles) {
            Write-Host "Checking if Role assignment present"
            $GroupId = (Get-AzADGroup -DisplayName "$($MGPrefix)$($ManagementGroup.DisplayName)$($MGSuffix)-$($Role)").id
            $CheckRoleAssignment = Get-AzRoleAssignment -ObjectId $GroupId -RoleDefinitionName $Role -Scope "$($ManagementGroup.id)" 
            If ($CheckRoleAssignment.Length -eq 0) {
                Write-Host "Adding role: $($Role) to management group: $($ManagementGroup.DisplayName)"       
                New-AzRoleAssignment -ObjectId $GroupId -RoleDefinitionName $Role -Scope "$($ManagementGroup.id)" | Out-Null 
            } else {
                Write-Host "Role assignment already present"
            }        
        }   
    }
}

If ($Scope -eq "Subscriptions" -or $Scope -eq "Both") {
    If ($SubscriptionName -eq $null) {
        $Subscriptions = Get-AzSubscription
    } else {
        $Subscriptions = Get-AzSubscription -SubscriptionName $SubscriptionName
    }
    

    Foreach ($Subscription in $Subscriptions) {
        foreach($Role in $Roles) {
            Write-Host "Checking if group $($SubPrefix)$($Subscription.Name)$($SubSuffix)-$($Role) already exists"
            $CheckGroup = Get-AzADGroup -DisplayName "$($SubPrefix)$($Subscription.Name)$($SubSuffix)-$($Role)"
            if ($CheckGroup.Length -eq 0) {
                Write-Host "Group not found"
                Write-Host "Creating group: $($SubPrefix)$($Subscription.Name)$($SubSuffix)-$($Role) in Azure AD"
                New-AzADGroup -DisplayName "$($SubPrefix)$($Subscription.Name)$($SubSuffix)-$($Role)" -MailEnabled:$false -SecurityEnabled:$true -MailNickName "NotSet" | Out-Null
            } else {
                Write-Host "Group $($SubPrefix)$($Subscription.Name)$($SubSuffix)-$($Role) found, skipping creation"
            }     
        }
        Write-Host "Waiting 10 seconds for Azure AD Groups to be created"
        Start-Sleep -Seconds 10
        
        foreach($Role in $Roles) {
            Write-Host "Checking if Role assignment present"
            $GroupId = (Get-AzADGroup -DisplayName "$($SubPrefix)$($Subscription.Name)$($SubSuffix)-$($Role)").id
            $CheckRoleAssignment = Get-AzRoleAssignment -ObjectId $GroupId -RoleDefinitionName $Role -Scope "/subscriptions/$($Subscription.id)" 
            If ($CheckRoleAssignment.Length -eq 0) {
                Write-Host "Adding role: $($Role) to management group: $($Subscription.DisplayName)"       
                New-AzRoleAssignment -ObjectId $GroupId -RoleDefinitionName $Role -Scope "/subscriptions/$($Subscription.id)" | Out-Null
            } else {
                Write-Host "Role assignment already present"
            }        
        }  
    }
}

Summary

The script has helped me quickly create groups and RBAC settings for the environments that I support, so I hope it can be helpful for you as well. It is possible to add any custom roles if you need that, and you can also refine the scope for the script to be single management groups or subscriptions. With a bit of customization, you can go down to resource group or resource level, but please try and add permissions to the highest possible level to keep your Azure environment as easy to manage.

I have shared the script on GitHub as well as in this post. You can use it freely, but as stated in the intro, I cannot be held responsible for what it does in your environment.

I hope this post is helpful, and feel free to reach out on Twitter or LinkedIn if you have any questions or feedback.

Comments