Sunday, September 5, 2021

Set User Department Based on OU

When you create dynamic distribution groups on-premises, you have the option to create them based on organizational unit. In Exchange Online (EXO), you don't have this option because Azure AD doesn't have the OUs for your tenant.

There are many attributes available for creating dynamic distribution groups in EXO and one available through the web interface is department. So, to simulate OU-based groups, we can set the department attribute.

To do this, I created a script on a DC that runs once per hour and sets the Department attribute based on the OU. When you run a script as SYSTEM on a DC, it has the ability to modify Active Directory. The function below is the core of the script.

#Function requires the OU as a distinguished name
Function Set-UserDepartment {
        [parameter(Mandatory=$true)] $OU,
        [parameter(Mandatory=$true)] $Department

    Write-Host ""
    Write-Host "Setting department attribute as $Department for users in $OU"
    #Find null values
    $nullusers = Get-ADUser -Filter {Department -notlike "*"} -Properties Department -SearchBase $OU
    #Find wrong value
    $wrongvalue = Get-ADUser -Filter {Department -ne $Department} -Properties Department -SearchBase $OU

    #Create one array of all users to fix
    $users = $nullusers + $wrongvalue

    Write-Host "null value: " $nullusers.count
    Write-Host "wrong value: " $wrongvalue.count

    #Set department
    Foreach ($u in $users) {
        Set-ADUser $u.DistinguishedName -Department $Department # -WhatIf

This function:

  • Expects the OU to be passed as a distinguished name
  • Finds users in the OU (and sub-OUs) with the department set to $null
  • Finds users in the OU (and sub-OUs) with the incorrect department
  • Sets the Department value as specified when you call the function for all users identified

Querying the users that don't have department set correctly and calling Set-ADUser for only those users is much faster than setting all users each time.

The count for null value or wrong value is incorrect when there is a single item because a single item is not an array. You can improve this by forcing them to be an array before populating them. Or, checking whether it's single item first, but for my purposes, this was sufficient.

Within the script, you can call the function as many times as required to set the attributes. You just pass the OU and the department value to the function like below.

#Call function to set department for Marketing
Set-UserDepartment -OU "OU=Marketing,DC=Contoso,dc=com" -Department Marketing