Exchange Online: Dynamically add mailbox permissions through groups

Managing shared and resource mailbox permissions can be more or less a pain depending on how you do it. Adding users directly as delegates to the shared mailboxes gives you a bit more administrative overhead, but makes it possible to utilize the AutoMapping feature that automatically adds the additional mailboxes to the end users Outlook client. If you instead add mail-enabled security groups to the delegate list, you get less administrative overhead, but not the AutoMapping feature.

Even though this is a really “old” problem, I get questions around it almost every week. Therefore I wanted to share a solution with you that gives you an example on how to solve it still using groups. A script that will use Mail-Enabled Security Groups/Distribution Groups to dynamically populate the delegate list of a shared mailbox.

GETTING STARTED
In order to get started, you need to create one “Shadow Group” per mailbox who’s delegation properties you want to manage automatically. To make it as easy as possible, I’m using a prefix to identify the groups with the mailboxes, like Prefix-MailboxName. In my example below, the prefix is SM-. See the screenshot below for the correlation between them.
2014-11-16 11-39-45
It could of course be possible to use another attribute on the groups to store the mailbox name, but I thought this was an easier approach.

RUNNING THE SCRIPT
After editing the credentials in the Connect-ExchangeOnline function, you simply run the script as below:

.\SharedMailboxViaGroups.ps1 -Prefix 'SM-'

2014-11-16 12-10-56
As seen in the screenshot above it will process adds and removals of permissions for all mailboxes/groups in scope. Please note that both FullAccess and SendAs-permissions are added for each delegate.
SharedMailboxViaGroups.ps1

<#
.SYNOPSIS
    The script will automatically assign mailbox and recipient permissions on shared mailboxes based on groups.
.EXAMPLE
   .\SharedMailboxViaGroups.ps1 -Prefix 'SM-'
.PARAMETER Prefix
    Prefix of the groups that will manage permissions on the shared mailboxes.
.NOTES
    File Name: SharedMailboxViaGroups.ps1
    Author   : Johan Dahlbom, johan[at]dahlbom.eu
    Blog     : 365lab.net
    The script are provided “AS IS” with no guarantees, no warranties, and they confer no rights.
    Requires PowerShell Version 3.0!
#>
param (
  [string]$Prefix = 'SM-'
)

function Connect-ExchangeOnline {
  param(
    [string]$Username = 'admin@tenant.onmicrosoft.com',
    [string]$Password = 'password'
  )
  #Clean up existing PowerShell Sessions
  Get-PSSession | Remove-PSSession
  $CloudCred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $Username, (ConvertTo-SecureString $Password -AsPlainText -Force)
 
  #Connect to Exchange Online
  $Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $CloudCred -Authentication Basic -AllowRedirection
  $Commands = @("Add-MailboxPermission","Add-RecipientPermission","Remove-RecipientPermission","Remove-MailboxPermission","Get-MailboxPermission","Get-User","Get-DistributionGroupMember","Get-DistributionGroup","Get-Mailbox")
  Import-PSSession -Session $Session -Prefix "Cloud" -DisableNameChecking:$true -AllowClobber:$true -CommandName $Commands | Out-Null
}
function Add-JDMailboxPermission {
  param(
    [string]$Identity,
    [string]$SharedMailboxName
  )
  try {
    Add-CloudMailboxPermission -Identity $SharedMailboxName -User $Identity -AccessRights FullAccess -ErrorAction stop | Out-Null
    Add-CloudRecipientPermission -Identity $SharedMailboxName -Trustee $Identity -AccessRights SendAs -Confirm:$False -ErrorAction stop | Out-Null
    Write-Output "INFO: Successfully added $Identity to $SharedMailboxName"
  } catch {
    Write-Warning "Cannot add $Identity to $SharedMailboxName`r`n$_"
  }
}
function Remove-JDMailboxPermission {
  param(
    [string]$Identity,
    [string]$SharedMailboxName
  )
  try {
    Remove-CloudMailboxPermission -Identity $SharedMailboxName -User $Identity -AccessRights FullAccess -Confirm:$False -ErrorAction stop -WarningAction ignore | Out-Null
    Remove-CloudRecipientPermission -Identity $SharedMailboxName -Trustee $Identity -AccessRights SendAs -Confirm:$False -ErrorAction stop -WarningAction ignore  | Out-Null
    Write-Output "INFO: Successfully removed $Identity from $SharedMailboxName"
  } catch {
    Write-Warning "Cannot remove $Identity from $SharedMailboxName`r`n$_"
  }
}
function Sync-EXOResourceGroup {
  [CmdletBinding(SupportsShouldProcess=$true)]
  param(
    [string]$Prefix = 'SM-'
  )
  #Get All groups to process mailboxes for
  $MasterGroups = Get-CloudDistributionGroup -ResultSize Unlimited -Identity "$Prefix*"
  foreach ($Group in $MasterGroups) {
    #Remove prefix to get the mailbox name
    $MbxName = $Group.Name.Replace("$Prefix",'')
    $SharedMailboxName =  (Get-CloudMailbox -Identity $MbxName -ErrorAction ignore -WarningAction ignore).WindowsLiveID
    if ($SharedMailboxName) { 
      Write-Verbose -Message "Processing group $($Group.Name) and mailbox $SharedMailboxName"
      #Get all users with explicit permissions on the mailbox
      $SharedMailboxDelegates = Get-CloudMailboxPermission -Identity $SharedMailboxName -ErrorAction Stop -ResultSize Unlimited | Where-Object {$_.IsInherited -eq $false -and $_.User -ne "NT AUTHORITY\SELF" -and $_.User -notmatch 'S-\d-\d-\d+-\d+-\d+-\d+-\w+' -and $_.User -notlike "$Prefix*"} |  Select-Object @{Name="User";Expression={(Get-CloudUser -identity $_.User).WindowsLiveID }}
      #Get all group members
      $SharedMailboxMembers = Get-CloudDistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited
      #Remove users if group is empty
      if (-not($SharedMailboxMembers) -and $SharedMailboxDelegates) {
        Write-Warning "The group $Group is empty, will remove explicit permissions from $SharedMailboxName"
        foreach ($user in $SharedMailboxDelegates.User) {
          Remove-JDMailboxPermission -Identity $user -SharedMailboxName $SharedMailboxName
        }
        #Add users if no permissions are present
      } elseif (-not($SharedMailboxDelegates)) {
        foreach ($user in $SharedMailboxMembers.WindowsLiveID) {
          Add-JDMailboxPermission -Identity $user -SharedMailboxName $SharedMailboxName
        }
        #Process removals and adds
      } else {
        #Compare the group with the users that have actual access
        $Users = Compare-Object -ReferenceObject $SharedMailboxDelegates.User -DifferenceObject $SharedMailboxMembers.WindowsLiveID 
         
        #Add users that are members of the group but do not have access to the shared mailbox
        foreach ($user in ($users | Where-Object {$_.SideIndicator -eq "=>"})) {
          Add-JDMailboxPermission -Identity $user.InputObject -SharedMailboxName $SharedMailboxName
        }
        #Remove users that have access to the shared mailbox but are not members of the group
        foreach ($user in ($users | Where-Object {$_.SideIndicator -eq "<="})) {
          Remove-JDMailboxPermission -Identity $user.InputObject -SharedMailboxName $SharedMailboxName
        }
      }
    } else {
      Write-Warning "Could not find the mailbox $MbxName"
    }
  }
}
#Connect to Exchange Online
Connect-ExchangeOnline
#Start Processing groups and mailboxes
Sync-EXOResourceGroup -Prefix $Prefix -Verbose

SUMMARY
A pretty simple solution on a very common problem in most environments where you have shared mailboxes. Let me know if you have feature requests or if something is not working as intended!

Enjoy!

/Johan

Advertisement

2 thoughts on “Exchange Online: Dynamically add mailbox permissions through groups

  1. Pingback: Get rid of your Office 365 Scheduled tasks with Azure Automation! | Tailspintoys – 365lab.net

  2. stoeps

    Hey, seems, that the sendas permissions not working in your script. Can you confirm that? regards steffen

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s