Convert security groups to mail-enabled and universal for Office 365 with PowerShell

by Thomas Verwer, Technical Consultant @ Rapid Circle When carrying out projects for Enterprise clients I commonly face challenges with companies not meeting the system requirements for Office 365. One of the most commonly seen missing requirements are on the Identity and Access Management part of Office 365.

When migrating legacy Identity and Acces Management infrastructures to Office 365 you quickly bump in to Microsoft’s Active Directory Services (ADS). To migrate this service to Windows Azure Active Directory – which is part of every Office 365 license – you can use the Windows Azure Active Directory Sync tool. Or as most IT Professionals know it “DirSync”, this is a special edition in the history of FIM.

Now back to businness. To migrate legacy security groups to Windows Azure Active Directory, for products such as Exchange Online it is a requirement to have a GroupScope of Universal.(see image below)


Since most companies still use Global security groups these need to be converted. Therefore I use a PowerShell script which automates this proces. For this script to work, import the ActiveDirectory module in PowerShell or run the script with Active Directory Module for Windows PowerShell.


if((Get-Module | where {$_.Name -eq “ActiveDirectory”}) -eq $null){ Import-Module ActiveDirectory } $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition Set-Location $scriptPath Write-Output “Output will be stored in ” (Get-Location)

$SeaBase = “DC=corp,DC=local” $SeaVal = “CN=Mailbox_*” $SeaScope = “Subtree” $GrpList = “ADSecGrp.csv” $UniGrpList = “Uni_ADSecGrp.csv” $strLogFile = “ErrorLog.txt” $DomainAdmin = Get-Credential

#Search for all Groups that are of type Security and scope is Global and starts with “Mailbox_” $SecGrps = Get-ADGroup -SearchScope $SeaScope -SearchBase $SeaBase -Filter {GroupCategory -eq “Security” -and GroupScope -eq “Global”}

foreach ($secGrp in $SecGrps) { try { $DN = $secGrp | Where-Object {$_.DistinguishedName -like $SeaVal} $DN | Export-Csv $GrpList -Append } catch { throw Break } }

(Get-Content $GrpList | Select-Object -Skip 1) | Set-Content $GrpList

Write-Output “Check $GrpList to verify all exported security Groups are of type Global” Write-Output “Press Y to continue” $selection = read-host if ($selection -eq “y” -or $selection -eq “Y”){ Write-Output “$GrpList CSV File Checked….” foreach($G in Import-Csv $GrpList){ try { $D = $G.DistinguishedName Get-ADGroup -Identity $G.SID Set-ADGroup -Identity $G.SID -GroupScope Universal -Credential $DomainAdmin } catch { $ErrorMessage = $_.Exception.Message Write-Output “Error converting for $D ..`n Error Message : $ErrorMessage” | Add-Content $strLogFile Throw Break } $DN = Get-ADGroup -Identity $G.SID $DN | Export-Csv $UniGrpList -Append } (Get-Content $UniGrpList | Select-Object -Skip 1) | Set-Content $UniGrpList Write-Output “Check $UniGrpList to verify all modified security Groups are of type Universal” }else{ Write-Output “Script Stopped by User” | Add-Content $strLogFile Break }

As you can see the script contains several variables. With these you can define the scope of OU’s or name convention for existing security groups. When running the PowerShell script it builds up a CSV-file called Uni_ADSecGrp.csv. When paused you can open and check the file to see if it contains the groups which you wish to convert. If so, you can insert “Y” to the script and it proceeds running.

After we have succesfully changed the GroupScopes to Universal we can carry on and use the second PowerShell script which mail-enables the security groups so they meet the requirements for Exchange Online. Besides the conversion to mail-enabled it also hides the groups from the Global Address List.

Run this script on one of the legacy Exchange servers with the use of the  Exchange Management Shell.


#if((Get-Module | where {$_.Name -eq “ActiveDirectory”}) -eq $null){ # Import-Module ActiveDirectory #}

#Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 # $env:ExchangeInstallPathbinRemoteExchange.ps1 #Connect-ExchangeServer -auto

Write-Output “Output will be stored in ” (Get-Location)

$GrpList = “Final_ADSecGrp.csv” $strLogFile = “enableErrorLog.txt” $log = “AfterLog.txt” $ErrorLog = “ErrorLog.txt”

foreach($G in Import-Csv “Uni_ADSecGrp.csv”){

try { Get-ADGroup -Identity $G.SID

Enable-DistributionGroup -Identity $G.DistinguishedName -Alias $G.Name Set-DistributionGroup -Identity $G.DistinguishedName -HiddenFromAddressListsEnabled $true Get-DistributionGroup -Identity $G.DistinguishedName | Add-Content $Log $x = Get-DistributionGroup -Identity $G.DistinguishedName if($x -ne $Null){ Write-Output $G.DistinguishedName }else{ Write-Output $G.DistinguishedName | Add-Content $ErrorLog } } catch { $ErrorMessage = $_.Exception.Message Write-Output “Error Enabl-DistributionGroup for $G.DistinguishedName …..`nError Message : $ErrorMessage” | Add-Content $strLogFile throw Break }


Once you have succesfully executed the second script you can add these objects to your Windows Azure Directory Sync cycle. Please be aware that when you convert the groups, the groups may not contain unsupported characters such as namespaces or & characters.

Best of luck to you all with carrying out succesfull Office 365 deployments. Before I publish the post, I have to share my respect to my colleague and teammate Dev Chaudhari for working on the scripting!

Original blog on: