By default, Exchange Online (like on-premises Exchange before it) allows all users in an organization to view only the free/busy status (blue bars) on other users' calendar appointments. Some organizations require that the appointment summary or all calendar details be visible by all users. This is fairly simple for a single user to change on their own, but enforcing it across the organization takes a bit more effort. PowerShell comes in handy here! And there are plenty of articles out there on how to do that. But if you want to continuously enforce this configuration for all new mailboxes, or fix permissions when users change it, we need to schedule a recurring task. Azure Automation works well for this purpose in the Office 365 / Azure Cloud universe.
Start by creating a "service account" that is an Exchange Organization administrator. This can just be a standard Azure Active Directory account. It doesn't need to have an Office 365 license assigned to it. If you enforce MFA, make sure to generate an application password to use later on.
Go to the Exchange Administrator from the Office 365 admin panel. Then select Permissions and then Admin Roles.
Edit the Organization Management role and add the user you created in Azure AD.
In the Azure admin portal, create an Azure Automation Account (or user an existing one).
Go to the Credentials section of the automation and add the username and password of the Azure AD credentials you created. Note: if you have MFA enabled, the password must be the application password.
Go to the Runbooks section. Create a new runbook. Edit the runbook.
Exchange Online PowerShell cmdlets are available as a remote session. You use the stored credentials to establish the session, then import it into the running session. The number of cmdlets are large. You should filter which cmdlets you want to import. This saves a lot of time and prevents the odd crashes (the automation runspaces have a pretty limited amount of resources to work with).
$cred = Get-AutomationPSCredential -Name 'ExchangeOnlineAutomation'
$session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection -ThrottleLimit 1
$commands = @("Get-MailboxFolderPermission","Set-MailboxFolderPermission","Get-Mailbox")
$null = Import-PSSession -Session $session -DisableNameChecking:$true -CommandName $commands -AllowClobber:$true
Note: Azure Automation doesn't support piping to Out-Null, so the $null= is a trick to eat the output of a command you don't want to show up in the final script output.
From here, the rest is pretty simple, we just loop through every mailbox, look at the calendar's default ACE, and adjust it if necessary.
$mailboxes = Get-Mailbox -ResultSize Unlimited
$mailboxes | % {
$mb = $_
$calendarDefaultACE = Get-MailboxFolderPermission "$($mb.PrimarySmtpAddress):\Calendar" -User Default
if ($calendarDefaultACE -and $calendarDefaultACE.AccessRights -inotcontains "reviewer") {
Set-MailboxFolderPermission "$($mb.PrimarySmtpAddress):\Calendar" -User Default -AccessRights Reviewer
}
}
The above is assigning the ability of all users to see full calendar appointment details. If you just want to assign the ability to see the appointment summary, use LimitedDetails instead of Reviewer.
We don't want to leave any sessions dangling as you only get three to work with for Exchange Online PowerShell. So we should wrap all the above code in try..catch..finally and close the session at the end. Add some logging and we have the following.
$cred = Get-AutomationPSCredential -Name 'ExchangeOnlineAutomation'
try {
# Import an Exchange Online session
Write-Output "Connecting to Exchange Online."
$session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection -ThrottleLimit 1
$commands = @("Get-MailboxFolderPermission","Set-MailboxFolderPermission","Get-Mailbox")
$null = Import-PSSession -Session $session -DisableNameChecking:$true -CommandName $commands -AllowClobber:$true
$mailboxes = Get-Mailbox -ResultSize Unlimited
Write-Output "Found $(@($mailboxes.count)) mailboxes."
Write-Output "`r`nAssigning default permissions for calendar to REVIEWER."
$mailboxes | % {
$mb = $_
try {
$calendarDefaultACE = Get-MailboxFolderPermission "$($mb.PrimarySmtpAddress):\Calendar" -User Default
if ($calendarDefaultACE -and $calendarDefaultACE.AccessRights -inotcontains "reviewer") {
Set-MailboxFolderPermission "$($mb.PrimarySmtpAddress):\Calendar" -User Default -AccessRights Reviewer
Write-Output "$($mb.PrimarySmtpAddress): Setting permissions."
}
} catch {
Write-Output "$($mb.PrimarySmtpAddress): ERROR - $($_.Message)"
}
}
} finally {
# Close all open Exchange sessions
Get-PSSession | Remove-PSSession
Write-Output "`r`nExchange Online session closed."
}
You can test your runbook now. If it works as expected, publish it.
Now exit out of the editor and set a schedule. Every run costs a few cents, but really you probably only need to run this once per day so the cost should be extremely small.