Skip Ribbon Commands
Skip to main content

Quick Launch

Todd Klindt's home page > Todd Klindt's Office 365 Admin Blog > Posts > Copying Office 365 Group Permissions with PowerShell
December 18
Copying Office 365 Group Permissions with PowerShell

Office 365 Groups, or “Unified Groups” to their friends, have been a confusing Office 365 feature from an administrative perspective for as long as they’ve been around. Users can create them all willy-nilly (unless you disable that), the SharePoint sites they create don’t show up in the SharePoint Admin Center (until you use the new one), the list goes on and on. Another frustrating part of Groups is that you can’t do any nesting, of any kind. You can’t put a Unified Group in an Azure AD Security Group, or vice versa. You can’t put a SharePoint Group in a Unified Group either. Because of these limitations it’s very tough to reuse group membership. You can’t create an HR Azure AD Security Group and drop it into the HR Benefits Unified Group or the HR Hiring Unified Group. Now, the obvious question is, “If these two Unified Groups have the same membership why are they two groups instead of one?” Good question, fair reader. Sometimes it just works out that way. Sometimes the AD Security Group would only be a subset of the users in the Unified Group in question. Regardless, this question came up on a customer call and I was challenged to find a way to ease the administrative burden of manually adding the same users to multiple Unified Groups. What was my answer, “Of course I can do it, with PowerShell!” Sometimes I answer without thinking first.

I had used the PnP PowerShell in the past to get a list of all of the Unified Groups in a tenant, so I was pretty sure it could be done. I whipped out Get-Command and listed all the cmdlets that contained the noun “UnifiedGroup.”

Get-Command -Noun *unifiedgroup*

That exposed two cmdlets I’d need: Get-PnPUnifiedGroupOwners and Get-PnPUnifiedGroupMembers. That’s good. But there were no corresponding “Set” cmdlets. That’s bad. Normally this is where I’d panic. Instead, I took a deep breath and instead of panicking, I typed Get-Command -ParameterName members. Low and behold, Get-Command blessed me with New-PnPUnifiedGroup and Set-PnPUnifiedGroup. We retrieve the list of Members with Get-PnPUnifiedGroupMembers but we set them with Set-PnPUnifiedGroup –Members. Not totally consistent, but I can work with that.

From past experience I knew I had to be connected to the Microsoft Graph to use the Unified Group cmdlets, so  I authenticated against the Graph so I could start poking around.

Connect-PnPOnline –Graph

If you haven’t connected to the Graph before, hold onto your hats. It’s different than what you’re used to. You’ll be given a code to register with the Graph that allows the PnP to query it. It feels weird, but everything is working correctly.

Once I was connected to the Graph I ran Get-PnPUnifiedGroupMembers to see what the output looked like. It gave me back a collection of objects that corresponded to the users that were members of that Unified Group. Fair enough.


We can store them in a variable for use later. Now, how do we assign membership? help Set-PnPUnifiedGroup –Examples didn’t provide a lot of help. It only showed adding a single Owner. But it did show me that the cmdlet was expecting the parameter to be a string, and that string needed to be the UPN of the user I wanted to add. I can work with that too.

The mechanics of saving out the list of users and owners and assigning them to another group was a little tricky, but not bad. I walked through the output of Get- and wrote the UPNs of each object to a new collection that I would then pass on to Set-. It looks like this:

$members = Get-PnPUnifiedGroupMembers -Identity $source

$members | ForEach-Object -begin  {$memberlist  = @() } -process {$memberlist += $($_.UserPrincipalName) }

Set-PnPUnifiedGroup -Identity $destination -Members $memberlist -Owners $ownerlist

The only sticking point was that doing it that way would overwrite whatever Members or Owners the Destination Group already had. To handle that I created a boolean variable, $mergeusers, that I could set to $true or $false depending on whether I wanted to clobber the existing users or not. If I did not want to clobber them I used the following code to merge the current Members of Destination with the Members of Source:

$membersDest = Get-PnPUnifiedGroupMembers -Identity $destination

$members = $members + $membersDest

Then later when I write the users in $members to the Destination Group it has both sets of Members.

I added some very, very simple error handling so that another human has a chance of running it. This is what I ended up with:

# Set some values
# use Get-PnPUnifiedGroup to get Unified Group names
# Name of Unified Group whose owners and membership we want to copy
$source = "Regulations"

# Name of Unified Group whose owners and membership we want to populate
$destination = "Empty"

# Whether to overwrite Destination membership or merge them
$mergeusers = $false

# Check to see if PnP Module is loaded
$pnploaded = Get-Module SharePointPnPPowerShellOnline
if ($pnploaded -eq $false) {
    Write-Host "Please load the PnP PowerShell and run again"
    Write-Host "install-module SharePointPnPPowerShellOnline"
# PnP Module is loaded

# Check to see if user is connected to Microsoft Graph
    $owners = Get-PnPUnifiedGroupOwners -Identity $source
catch [System.InvalidOperationException]
    Write-Host "No connection to Microsoft Graph found"  -BackgroundColor Black -ForegroundColor Red
    Write-Host "No Azure AD connection, please connect first with Connect-PnPOnline -Graph" -BackgroundColor Black -ForegroundColor Red
catch [System.ArgumentNullException]
        Write-Host "Group not found"  -BackgroundColor Black -ForegroundColor Red
        Write-Host "Verify connection to Azure AD with Connect-PnPOnline -Graph" -BackgroundColor Black -ForegroundColor Red
        Write-Host "Use Get-PnPUnifiedGroup to get Unified Group names"  -BackgroundColor Black -ForegroundColor Red
    Write-Host "Some other error"   -BackgroundColor Black -ForegroundColor Red

$members = Get-PnPUnifiedGroupMembers -Identity $source

if ($mergeusers -eq $true) {
     # Get existing owners and members of Destination so that we can combine them
    $ownersDest = Get-PnPUnifiedGroupOwners -Identity $destination
    $membersDest = Get-PnPUnifiedGroupMembers -Identity $destination

    # Add the two lists together so we don't overwrite any existing owners or members in Destination
    $owners = $owners + $ownersDest
    $members = $members + $membersDest

# Set the owners and members of Destination
$owners | ForEach-Object -begin  {$ownerlist  = @() } -process {$ownerlist += $($_.UserPrincipalName) }
$members | ForEach-Object -begin  {$memberlist  = @() } -process {$memberlist += $($_.UserPrincipalName) }

Set-PnPUnifiedGroup -Identity $destination -Members $memberlist -Owners $ownerlist

Feel free to pick through that for any nuggets that might help you.

Happy copying.




There are no comments for this post.

Add Comment

Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.


Body *

Today's date *

Select a date from the calendar.
Please enter today's date so I know you are a real person


Want a message when I reply to your comment? Put your Twitter handle here.