Script Repository


Update group membership of a user in Microsoft 365 based on Business Unit membership

July 07, 2020
5259

The scripts add/remove users from Microsoft 365 (Office 365) distribution, security and unified groups based on the Business Units the users are members of. To run the script, create a Scheduled Task configured for the Domain-DNS object type and add a managed domain to the Activity Scope of the task.

Parameter:

  • $unitDNsToGroupNames - Maps distinguished names (DNs) of the Business Units a user needs to be a member of to be added to Microsoft 365 (Office 365) distribution/security/unified groups with names of the groups that correspond to each Business Unit. A Business Unit can have one or more associated Microsoft 365 (Office 365) groups. For information on how to get DN of a directory object, see Get the DN of an Active Directory Object.

Distribution and mail-enabled Security Groups

Edit Remove
PowerShell
$unitDNsToGroupNames = @{
    "CN=My Unit1,CN=Business Units,CN=Configuration Objects,CN=Adaxes Configuration,CN=Adaxes" = @("MyGroup1", "MyGroup2");
    "CN=My Unit2,CN=Business Units,CN=Configuration Objects,CN=Adaxes Configuration,CN=Adaxes" = @("MyGroup3");
} # TODO: modify me

function UpdateGroupMembership($groupName, $memberIDs, $operation)
{
    foreach ($memberID in $memberIDs)
    {
        switch ($operation)
        {
            "Add"
            {
                try
                {
                    Add-DistributionGroupMember $groupName -Member $memberID -BypassSecurityGroupManagerCheck -ErrorAction Stop
                }
                catch
                {
                    $Context.LogMessage("An error occurred when adding the user to $groupName group. Error: " + $_.Exception.Message, "Warning")
                }
            }
            "Remove"
            {
                try
                {
                    Remove-DistributionGroupMember $groupName -Member $memberID -ErrorAction Stop -BypassSecurityGroupManagerCheck -Confirm:$False
                }
                catch
                {
                    $Context.LogMessage("An error occurred when removing the user from $groupName group. Error: " + $_.Exception.Message, "Warning")
                }
            }
        }
    }
}

$groupNamesToUserIDs = @{}
foreach ($dn in $unitDNsToGroupNames.Keys)
{
    $unit = $Context.BindToObjectByDN($dn)
    $members = $unit.Members()
    
    $groupNames = $unitDNsToGroupNames[$dn]
    foreach ($groupName in $groupNames)
    {
        if ($groupNamesToUserIDs.ContainsKey($groupName))
        {
            continue
        }
        
        $groupNamesToUserIDs.Add($groupName, (New-Object System.Collections.Generic.HashSet[System.String]))
    }
    for ($i = 0; $i -lt $members.Count; $i++)
    {
        $member = $members.GetObject($i)
        try
        {
            $objectId = ([Guid]$member.Get("adm-O365ObjectId")).ToString()
        }
        catch
        {
            continue
        }
        
        $groupNames | %%{ [void]$groupNamesToUserIDs[$_].Add($objectId) }
    }
}

try
{
    # Connect to Exchange Online
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $Context.GetOffice365Credential() -Authentication Basic -AllowRedirection
    Import-PSSession $session -AllowClobber -DisableNameChecking -CommandName "Get-DistributionGroupMember", "Add-DistributionGroupMember", "Remove-DistributionGroupMember"
    
    foreach ($groupName in $groupNamesToUserIDs.Keys)
    {
        # Get current members
        $members = Get-DistributionGroupMember $groupName
        $currentMembers = New-Object System.Collections.Generic.HashSet[System.String]
        $members | %%{[void]$currentMembers.Add($_.ExternalDirectoryObjectId)}
        
        # Get users to Add
        $membersToAdd = $groupNamesToUserIDs[$groupName]
        
        # Get users to Remove
        $membersToRemove = New-Object System.Collections.Generic.HashSet[System.String]
        $members | %%{ [void]$membersToRemove.Add($_.ExternalDirectoryObjectId) }
        $membersToRemove.ExceptWith($membersToAdd)
        
        # Exclude members already added to group
        $membersToAdd.ExceptWith($currentMembers)
        
        # Add users to group
        UpdateGroupMembership $groupName $membersToAdd "Add"
        
        # Remove users from group
        UpdateGroupMembership $groupName $membersToRemove "Remove"
    }
}
finally
{
    # Release resources
    if ($session) { Remove-PSSession $session }
}

Unified Groups

Edit Remove
PowerShell
$unitDNsToGroupNames = @{
    "CN=My Unit1,CN=Business Units,CN=Configuration Objects,CN=Adaxes Configuration,CN=Adaxes" = @("MyGroup1", "MyGroup2");
    "CN=My Unit2,CN=Business Units,CN=Configuration Objects,CN=Adaxes Configuration,CN=Adaxes" = @("MyGroup3");
} # TODO: modify me

function UpdateGroupMembership($groupName, $memberIDs, $operation)
{
    foreach ($memberID in $memberIDs)
    {
        switch ($operation)
        {
            "Add"
            {
                try
                {
                    Add-UnifiedGroupLinks -Identity $groupName -LinkType Members -Links $memberID -ErrorAction Stop
                }
                catch
                {
                    $Context.LogMessage("An error occurred when adding the user to $groupName group. Error: " + $_.Exception.Message, "Warning")
                }
            }
            "Remove"
            {
                try
                {
                    Remove-UnifiedGroupLinks -Identity $groupName -LinkType Members -Links $memberIDs -Confirm:$False -ErrorAction Stop
                }
                catch
                {
                    $Context.LogMessage("An error occurred when removing the user from $groupName group. Error: " + $_.Exception.Message, "Warning")
                }
            }
        }
    }
}

$groupNamesToUserIDs = @{}
foreach ($dn in $unitDNsToGroupNames.Keys)
{
    $unit = $Context.BindToObjectByDN($dn)
    $members = $unit.Members()
    
    $groupNames = $unitDNsToGroupNames[$dn]
    foreach ($groupName in $groupNames)
    {
        if ($groupNamesToUserIDs.ContainsKey($groupName))
        {
            continue
        }
        
        $groupNamesToUserIDs.Add($groupName, (New-Object System.Collections.Generic.HashSet[System.String]))
    }
    for ($i = 0; $i -lt $members.Count; $i++)
    {
        $member = $members.GetObject($i)
        try
        {
            $objectId = ([Guid]$member.Get("adm-O365ObjectId")).ToString()
        }
        catch
        {
            continue
        }
        
        $groupNames | %%{ [void]$groupNamesToUserIDs[$_].Add($objectId) }
    }
}

try
{
    # Connect to Exchange Online
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $Context.GetOffice365Credential() -Authentication Basic -AllowRedirection
    Import-PSSession $session -AllowClobber -DisableNameChecking -CommandName "Add-UnifiedGroupLinks", "Remove-UnifiedGroupLinks", "Get-UnifiedGroupLinks"
    
    foreach ($groupName in $groupNamesToUserIDs.Keys)
    {
        # Get current members
        $members = Get-UnifiedGroupLinks -Identity $groupName -LinkType Members
        $currentMembers = New-Object System.Collections.Generic.HashSet[System.String]
        $members | %%{[void]$currentMembers.Add($_.ExternalDirectoryObjectId)}
        
        # Get users to Add
        $membersToAdd = $groupNamesToUserIDs[$groupName]
        
        # Get users to Remove
        $membersToRemove = New-Object System.Collections.Generic.HashSet[System.String]
        $members | %%{ [void]$membersToRemove.Add($_.ExternalDirectoryObjectId) }
        $membersToRemove.ExceptWith($membersToAdd)
        
        # Exclude members already added to group
        $membersToAdd.ExceptWith($currentMembers)
        
        # Add users to group
        UpdateGroupMembership $groupName $membersToAdd "Add"
        
        # Remove users from group
        UpdateGroupMembership $groupName $membersToRemove "Remove"
    }
}
finally
{
    if ($session) { Remove-PSSession $session }
}

Security Groups that are not mail-enabled

To use the script, install the AzureAD module on the computer where Adaxes service is running.

Edit Remove
PowerShell
Import-Module AzureAD

$unitDNsToGroupNames = @{
    "CN=My Unit1,CN=Business Units,CN=Configuration Objects,CN=Adaxes Configuration,CN=Adaxes" = @("MyGroup1", "MyGroup2");
    "CN=My Unit2,CN=Business Units,CN=Configuration Objects,CN=Adaxes Configuration,CN=Adaxes" = @("MyGroup3");
} # TODO: modify me

function UpdateGroupMembership($groupID, $memberIDs, $operation)
{
    foreach ($memberID in $memberIDs)
    {
        switch ($operation)
        {
            "Add"
            {
                try
                {
                    Add-AzureADGroupMember -ObjectId $groupID -RefObjectId $memberID -ErrorAction Stop
                }
                catch
                {
                    $Context.LogMessage("An error occurred when adding the user to $groupName group. Error: " + $_.Exception.Message, "Warning")
                }
            }
            "Remove"
            {
                try
                {
                    Remove-AzureADGroupMember -ObjectId $groupID -MemberId $memberID -ErrorAction Stop
                }
                catch
                {
                    $Context.LogMessage("An error occurred when removing the user from $groupName group. Error: " + $_.Exception.Message, "Warning")
                }
            }
        }
    }
}

$groupNamesToUserIDs = @{}
foreach ($dn in $unitDNsToGroupNames.Keys)
{
    $unit = $Context.BindToObjectByDN($dn)
    $members = $unit.Members()
    
    $groupNames = $unitDNsToGroupNames[$dn]
    foreach ($groupName in $groupNames)
    {
        if ($groupNamesToUserIDs.ContainsKey($groupName))
        {
            continue
        }
        
        $groupNamesToUserIDs.Add($groupName, (New-Object System.Collections.Generic.HashSet[System.String]))
    }
    for ($i = 0; $i -lt $members.Count; $i++)
    {
        $member = $members.GetObject($i)
        try
        {
            $objectId = ([Guid]$member.Get("adm-O365ObjectId")).ToString()
        }
        catch
        {
            continue
        }
        
        $groupNames | %%{ [void]$groupNamesToUserIDs[$_].Add($objectId) }
    }
}

Connect-AzureAD -Credential $Context.GetOffice365Credential()

foreach ($groupName in $groupNamesToUserIDs.Keys)
{
    $group = Get-AzureADGroup -SearchString $groupName
    if ($group -eq $NULL)
    {
        $Context.LogMessage("$groupName group not found.", "Warning")
    }  
    
    # Get current members
    $members = Get-AzureADGroupMember -ObjectId $group.ObjectId
    $currentMembers = New-Object System.Collections.Generic.HashSet[System.String]
    $members | %%{[void]$currentMembers.Add($_.ObjectId)}
    
    # Get users to Add
    $membersToAdd = $groupNamesToUserIDs[$groupName]
    
    # Get users to Remove
    $membersToRemove = New-Object System.Collections.Generic.HashSet[System.String]
    $members | %%{ [void]$membersToRemove.Add($_.ObjectId) }
    $membersToRemove.ExceptWith($membersToAdd)
    
    # Exclude members already added to group
    $membersToAdd.ExceptWith($currentMembers)
    
    # Add users to group
    UpdateGroupMembership $group.ObjectId $membersToAdd "Add"
    
    # Remove users from group
    UpdateGroupMembership $group.ObjectId $membersToRemove "Remove"
}

Comments ( 2 )
avatar
Nils Mull
April 03, 2020

Hi Adaxes Team,
unfortunately the script doesn't work for me. In the logs it says:
"Cannot process argument transformation on parameter 'Credential'. A command that prompts the user failed because the host program or the command type does not support user interaction. The host was attempting to request confirmation with the following message: Enter your credentials. Stack trace: at <ScriptBlock>, <No file>: line 73"
best regards

avatar
Support
April 03, 2020

Hello Nils,

The error occurs because the account whose credentials were used to register your Office 365 tenant in Adaxes has MFA or conditional access enabled in Office 365. You need to disable both. To check the account:

  1. Launch Adaxes Administration Console.
  2. In the Console Tree, expand your service node.
  3. Navigate to Configuration\Cloud Services and select Office 365.
  4. In the Result Pane on the right, right-click your Office 365 tenant and then click Edit.
  5. The username of the account that was used to register the tenant will be displayed in the corresponding field.

Leave a comment

Related Scripts