Practical Tip #02 - automatically update Conditional Access rules for admin roles
Problem: Conditional access rules are applied specifically to roles that include the word “Administrator” in their names. Microsoft is constantly adding new roles, but these are not automatically included in such rules.
Task: Automate the addition of new roles using scripts.
Script structure
You can find the complete script in my Script Nest. The following sections explain how it works in detail.
Choose options
At the beginning of the script, two variables need to be modified. These determine whether the script runs in test mode or in production mode (i.e., with actual changes). It is recommended that you run the script at least once in test mode to verify its behavior in your own environment.
In addition, the script can be run either interactively (i.e., with a user login) or automatically (using Azure Automation).
The variables are created with the $Script: scope so that they can be accessed within all functions.
# Choose simulation mode: Set to $true to only simulate changes. Set to $false to apply changes live.
$Script:WhatIf = $true
# Choose authentication mode: Set to 'Interactive' for user prompt or 'Automated' for service principal authentication.
$Script:ExecutionMode = 'Interactive'PowerShellChecking and installing the necessary modules
The CheckModules function verifies whether the PowerShell modules required for execution (Microsoft.Graph.Authentication, Microsoft.Graph.Identity.SignIns) are installed. This is only necessary if the script is run interactively. In Azure Automation, a suitable runtime environment must be created for the script that includes the necessary modules.
function CheckModules
{
# Check if needed modules are installed and install, if not
if (!(Get-InstalledModule -Name Microsoft.Graph.Authentication))
{
Write-Host 'Module Microsoft.Graph.Authentication is not installed. Installing for current user...' -ForegroundColor Yellow
Install-Module -Name Microsoft.Graph.Authentication -Scope CurrentUser -Force
}
if (!(Get-InstalledModule -Name Microsoft.Graph.Identity.SignIns))
{
Write-Host 'Module Microsoft.Graph.Identity.SignIns is not installed. Installing for current user...' -ForegroundColor Yellow
Install-Module -Name Microsoft.Graph.Identity.SignIns -Scope CurrentUser -Force
}
}PowerShellReviewing and updating Conditional Access rules
The CheckAndUpdateCARules function first identifies all Entra roles that contain the word “Administrator” in their names.
It then identifies all rules that apply specifically to administrator roles and checks whether the assigned roles match the identified roles. If not, the rules are updated to include the missing administrator roles. If test mode is enabled, the script simply outputs which policy would be updated.
If no roles are missing, the script outputs a message to that effect and terminates.
function CheckAndUpdateCARules
{
if ($WhatIf)
{
Write-Output '==================================================' -ForegroundColor Yellow
Write-Output ' RUNNING IN WHAT-IF MODE (SIMULATION ON) ' -ForegroundColor Yellow
Write-Output ' No live changes will be made to your policies. ' -ForegroundColor Yellow
Write-Output '==================================================' -ForegroundColor Yellow
}
# Connect to Microsoft Graph
Write-Output 'Connecting to Microsoft Graph...' -ForegroundColor Yellow
if ($AuthenticationMode -eq 'Interactive'){Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess', 'RoleManagement.Read.Directory'}
if ($AuthenticationMode -eq 'Automated'){Connect-MgGraph -Identity}
# Retrieve all directory roles containing "Administrator" in their name
Write-Output 'Retrieving all directory roles with "Administrator" in the name...' -ForegroundColor Cyan
$allAdminRoles = Get-MgDirectoryRoleTemplate | Where-Object { $_.DisplayName -like "*Administrator*" }
if ($null -eq $allAdminRoles -or $allAdminRoles.Count -eq 0)
{
Write-Error "No directory roles found containing the word 'Administrator' in the name."
return
}
Write-Output "Total administrator roles found: $($allAdminRoles.Count)" -ForegroundColor Green
# Retrieve all Conditional Access policies
Write-Output "Retrieving all Conditional Access policies..." -ForegroundColor Cyan
$caPolicies = Get-MgIdentityConditionalAccessPolicy
ForEach ($policy in $caPolicies)
{
# Check if the policy targets specific roles
$includedRoles = $policy.Conditions.Users.IncludeRoles
if ($null -ne $includedRoles -and $includedRoles.Count -gt 0)
{
# Check if at least one of the included roles is an administrator role
$hasAdminRole = $false
foreach ($roleId in $includedRoles)
{
if ($roleId -in $allAdminRoles.Id)
{
$hasAdminRole = $true
break
}
}
# If the policy applies to at least one administrator role
if ($hasAdminRole)
{
Write-Output '--------------------------------------------------' -ForegroundColor Yellow
Write-Output "Policy matched: $($policy.DisplayName)" -ForegroundColor Yellow
# Identify missing administrator roles
$missingRoles = @()
foreach ($adminRole in $allAdminRoles)
{
if ($adminRole.Id -notin $includedRoles)
{
$missingRoles += $adminRole.Id
}
}
if ($missingRoles.Count -gt 0)
{
Write-Output "The following roles are missing in this policy: $($missingRoles.Count)" -ForegroundColor Magenta
# Create a new list of roles to include (Existing + Missing)
$updatedRoles = $includedRoles + $missingRoles
# Prepare the update object
$updateParams = @{
Conditions = @{
Users = @{
IncludeRoles = $updatedRoles
}
}
}
# Update or simulate the policy update
if ($WhatIf) {Write-Output "[WHAT-IF] Would update policy '$($policy.DisplayName)' to include all administrator roles." -ForegroundColor DarkYellow}
else {
try {
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -BodyParameter $updateParams
Write-Output "Policy '$($policy.DisplayName)' successfully updated." -ForegroundColor Green
}
catch {
Write-Error "Failed to update policy '$($policy.DisplayName)': $_"
}
}
}
else {
Write-Output "Policy '$($policy.DisplayName)' already contains all administrator roles." -ForegroundColor Green
}
}
}
}
Write-Output '--------------------------------------------------' -ForegroundColor Cyan
Write-Output 'Review and update process completed.' -ForegroundColor Cyan
}PowerShellExecute functions
Functions, as such, are merely a logical container for executing commands. However, they must be explicitly executed for an action to actually take place. Therefore, the functions are referenced at the end of the script and executed as a result.
The CheckModules function is executed only when the script is run interactively, since Azure Automation assumes that a suitable runtime environment has been configured.
# Execute functions
if ($ExecutionMode -eq 'Interactive'){CheckModules}
CheckAndUpdateCARulesPowerShell
Liked this article? Share it!

