Free/Busy Time Segmentation in Exchange Online

By default, all users in the same Exchange Online environment can view each other’s free/busy time. Using the Organization–Sharing settings you can share more information, but not less.

Exchange Online Sharing Rule
Unchecking the ‘Share your calendar folder’ box does not turn off calendar sharing. Counterintuitive!

Individuals can adjust their own free/busy time sharing in Outlook or Outlook Web App (OWA). But what if you have less-privileged users who should not be able to view another user’s free/busy time, for example, temporary employees or contract workers? Can they be restricted from viewing calendar information for other users?

It can be done, but it’s not simple.

My 3-part approach, summarized:

  1. Change each user’s sharing settings for the Default user to None via PowerShell
  2. Create a mail-enabled universal security group containing all privileged users. (Fortunately, this group already existed within my organization.)
  3. Change each user’s sharing settings for the security group created above to AvailabilityOnly via PowerShell (to allow just Free/Busy visibility)

I found Add Calendar Permissions in Office 365 via Powershell, which was a tremendous help in discovering the format of the calendar folder. For example, to adjust the Default user’s access to chris@example.com’s calendar to None, use the following PowerShell command:
Set-MailboxFolderPermission -Identity chris@example.com:\calendar -user Default -AccessRights None

Then I tried to add permissions for the security group:
$mycal = 'chris@example.com:\calendar'
Set-MailboxFolderPermission -Identity $mycal -User privileged-users-security-group@example.com -AccessRights AvailabilityOnly

Error:
There is no existing permission entry found for user: privileged-users-security-group.
+ CategoryInfo : NotSpecified: (:) [Set-MailboxFolderPermission], UserNotFoundInPermissionEntryException
+ FullyQualifiedErrorId : [Server=BLUPR0101MB1603,RequestId=d057882d-5663-417d-a614-ce73e5ab0565,TimeStamp=3/15/20
16 3:41:20 PM] [FailureCategory=Cmdlet-UserNotFoundInPermissionEntryException] B65CA2A0,Microsoft.Exchange.Managem
ent.StoreTasks.SetMailboxFolderPermission
+ PSComputerName : ps.outlook.com

Thanks to Setup secretary permissions to manage Calendar in Office 365, I discovered that the above error occurred because the security group had no current settings for the specified calendar. In that case, the Add-MailboxFolderPermission is the appropriate command:

Add-MailboxFolderPermission -Identity $mycal -User privileged-users-security-group@example.com -AccessRights AvailabilityOnly

Before running this across all of our users, I wanted to find out which users had customized their free/busy sharing settings. If they had customized them, I wanted to preserve their settings. For example, I decided to get the Default user sharing settings for the sales department users’ calendars:

$DeptMailboxes = Get-Mailbox -Filter {CustomAttribute2 -eq 'sales'}
ForEach ($Mailbox In $DeptMailboxes) { $Calendar = $Mailbox.UserPrincipalName + ":\calendar"; Get-MailboxFolderPermission -Identity $Calendar -User Default}

Unfortunately, the above did not return all of the properties needed to identify the calendars in question:
Calendar Default {AvailabilityOnly}
Calendar Default {LimitedDetails}
Calendar Default {AvailabilityOnly}
Calendar Default {AvailabilityOnly}

I specified a list of properties that was more useful:
ForEach ($Mailbox In $DeptMailboxes) { $Calendar = $Mailbox.UserPrincipalName + ":\calendar"; Get-MailboxFolderPermission -Identity $Calendar -User Default | Select Identity,FolderName,User,AccessRights }

Fortunately, only a handful of the users in my organization had customized their sharing settings, so I simply noted their settings and re-applied them after running these settings across all users in the organization:

$AllMailboxes = Get-Mailbox
ForEach ($Mailbox In $AllMailboxes) { $Calendar = $Mailbox.UserPrincipalName + ":\calendar"; Set-MailboxFolderPermission -Identity $Calendar -User Default -AccessRights None; Add-MailboxFolderPermission -Identity $Calendar -User privileged-users-security-group@example.com -AccessRights AvailabilityOnly }

This achieved the desired free/busy time segmentation. However, there’s one snag: what happens when new users are added? They will have the default sharing settings. That means that every time a new user is added, these steps will need to be run for that new user. I created the following PowerShell script — I can pipe the results of Get-Mailbox to this script to apply the customizations described above:

param(  
    [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)
    ]
    [Object[]]$Mailbox
)

Process {
    $Calendar = $Mailbox.UserPrincipalName + ":\calendar"
    Set-MailboxFolderPermission -Identity $Calendar -User Default -AccessRights None
    Add-MailboxFolderPermission -Identity $Calendar -User 'privileged-users-security-group@example.com' -AccessRights AvailabilityOnly
}

To run the script (assuming it is named Set-CustomFreeBusySharing.ps1):
Get-Mailbox -Identity bob@example.com | ./Set-CustomFreeBusySharing.ps1

Fully integrating that into my account creation process is a job for another day.

One other thing to note: users can still choose to modify their free/busy sharing with the Default user, in case they do want/need to share their availability with all users in the organization.

Other sites that had useful information while I researched this issue: