All scripts
Governance 503

Create an Entra Administrative Unit With a Scoped Admin Role

Creates a new Microsoft Entra administrative unit, adds members to it, and assigns a directory role scoped to just that unit instead of the whole tenant.

New-EntraAdministrativeUnit.ps1
<#
.SYNOPSIS
Creates a Microsoft Entra administrative unit and assigns a user a scoped admin role over it.

.DESCRIPTION
Administrative units let you delegate admin rights over one slice of your tenant, like one department or one location, instead of handing out tenant wide roles. This script creates a new administrative unit, adds a list of users to it as members, and assigns a chosen directory role to an admin scoped to just that unit. Requires the Microsoft Graph PowerShell SDK and an account with Privileged Role Administrator rights.

.PARAMETER Name
Display name for the new administrative unit.

.PARAMETER Description
Optional description for the administrative unit.

.PARAMETER MemberUserPrincipalNames
One or more user principal names to add as members of the administrative unit.

.PARAMETER ScopedAdminUserPrincipalName
User principal name of the person who should get a scoped admin role over this unit.

.PARAMETER RoleDisplayName
Display name of the directory role to assign, for example "User Administrator" or "Helpdesk Administrator".

.EXAMPLE
.\New-EntraAdministrativeUnit.ps1 -Name "Sales Department" -MemberUserPrincipalNames "alice@contoso.com","bob@contoso.com" -ScopedAdminUserPrincipalName "carol@contoso.com" -RoleDisplayName "User Administrator"

.AUTHOR
Shehryar Hassan
#>

[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)]
    [string]$Name,

    [Parameter(Mandatory = $false)]
    [string]$Description = "",

    [Parameter(Mandatory = $false)]
    [string[]]$MemberUserPrincipalNames = @(),

    [Parameter(Mandatory = $true)]
    [string]$ScopedAdminUserPrincipalName,

    [Parameter(Mandatory = $true)]
    [string]$RoleDisplayName
)

$requiredModules = @("Microsoft.Graph.Identity.DirectoryManagement", "Microsoft.Graph.Identity.Governance")
foreach ($module in $requiredModules) {
    if (-not (Get-Module -ListAvailable -Name $module)) {
        Write-Host "Installing $module ..."
        Install-Module -Name $module -Scope CurrentUser -Force
    }
}

Connect-MgGraph -Scopes "AdministrativeUnit.ReadWrite.All", "RoleManagement.ReadWrite.Directory", "User.Read.All"

Write-Host "Creating administrative unit '$Name' ..."
$au = New-MgDirectoryAdministrativeUnit -DisplayName $Name -Description $Description
Write-Host "Administrative unit created with ID $($au.Id)"

foreach ($upn in $MemberUserPrincipalNames) {
    $user = Get-MgUser -UserId $upn -ErrorAction SilentlyContinue
    if ($null -eq $user) {
        Write-Warning "User $upn not found, skipping."
        continue
    }
    $memberRef = @{
        "@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($user.Id)"
    }
    New-MgDirectoryAdministrativeUnitMemberByRef -AdministrativeUnitId $au.Id -BodyParameter $memberRef
    Write-Host "Added $upn as a member of the administrative unit."
}

$role = Get-MgDirectoryRole -Filter "DisplayName eq '$RoleDisplayName'"
if ($null -eq $role) {
    $roleTemplate = Get-MgDirectoryRoleTemplate -Filter "DisplayName eq '$RoleDisplayName'"
    if ($null -eq $roleTemplate) {
        throw "Could not find a role or role template named '$RoleDisplayName'."
    }
    $role = New-MgDirectoryRole -RoleTemplateId $roleTemplate.Id
}

$scopedAdmin = Get-MgUser -UserId $ScopedAdminUserPrincipalName -ErrorAction Stop

New-MgDirectoryAdministrativeUnitScopedRoleMember -AdministrativeUnitId $au.Id -RoleId $role.Id -BodyParameter @{
    RoleMemberInfo = @{
        Id = $scopedAdmin.Id
    }
}

Write-Host "Assigned $ScopedAdminUserPrincipalName the '$RoleDisplayName' role, scoped to the '$Name' administrative unit."
Write-Host "They can manage the users inside this unit without any rights over the rest of the tenant."

Read it before you run it, and test in a safe tenant first.