Office 365 Permission Inventory: Calendar permissions

It’s time for another article in the “permissions inventory” series. This time, we will take a look at Calendar permissions, more specifically the permissions on the default Calendar folder in users’ mailboxes. This kind of report is useful for keeping an eye on collaboration between your users (including external sharing), troubleshooting delegate issues and issues with the default permissions levels.

Getting the permissions is a rather trivial task, as all one has to do is to run the Get-MailboxFolderPermission cmdlet. When you run this cmdlet against hundreds or thousands of mailboxes though, handling the output can get a bit tricky. Especially when you have to take into account things such as the folder name localization in Exchange. Here’s a quick example:

As you can see from the above output, if you try to use the default “Calendar” name, the cmdlet will fail. Now, if you have run into this issue previously, you are probably aware that the folder might simply be renamed to match the language selected by the user, in this case German. One way to get around this issue is to hardcode all the known values for the name of the Calendar folder in different languages supported by Exchange Online, but this can get ugly.

Instead, one can utilize the Get-MailboxFolderStatistics cmdlet to get the correct folder. Unfortunately, this means running yet another cmdlet for every mailbox you are interested on reporting on, thus increasing the overall script run time. We can however speed things up a bit by reducing the output of the Get-MailboxFolderStatistics by using a combination of server-side and client-side filters, as shown below:

So far so good. However, we need to transform the Identity value in order to make sure the “:” symbol is added to it and also handle any folder names that have the “/” character in their name. Not a hard task, but something you need to keep in mind when dealing with folder level permissions.

Once all this is done, you need to take care of the actual output. As seen from the first screenshot above, multiple entries will be returned for each user, including the Default and Anonymous levels. In general, you might not be interested in those, but they can be useful in troubleshooting the “why can I not see availability info for user XXX” type of issues, or the opposite “how come user XXX can see my Calendar” complaints.

Apart from that, there are three kinds of permissions entries we will be looking into. First, we will of course cover internal sharing scenarios, where user X has granted permissions to user Y. Similarly, if sharing externally is allowed for the organization, we would be interested in reporting on those instances. Lastly, reporting on the “orphaned” entries might be useful in some cases, as in entries for which the corresponding user Y is no longer a valid recipient (left the company, doesn’t have a mailbox anymore, etc).

And once we have gathered all these permission entries, we need to decide what to do with the output. One way to handle it is to write each permission entry on a new line in the CSV file, similar to what the output of the Get-MailboxFolderPermission cmdlet looks like. This of course will result in multiple entries per user/mailbox, but makes it easier to filter. Another type of output can be generated by cramming everything into a single line per mailbox, thus reducing the number of entries. While the exact same information is contained in the resulting CSV file, working with the output will be a bit trickier and you will have to use advanced filters or the “text to columns” functionality in Excel.

The actual script can be found on my GitHub repo: https://github.com/michevnew/PowerShell/blob/master/Calendar_Permissions_inventory.ps1

Similar to the other scripts in the series, we make use of the PowerShell splatting concept to pass parameters when invoking the script. The first set of parameters controls which types of mailboxes will be included in the output, the default being only User mailboxes (used when you run the script without parameters or provide the –IncludeUserMailboxes parameter). Other supported types include Shared mailboxes as well as Room/Equipment mailboxes (-IncludeSharedMailboxes and –IncludeRoomMailboxes respectively). If you want to include all supported mailbox types, use the –IncludeAll parameter.

While technically we can also report on Group mailboxes, there is no method at present that actually allows you to grant folder level permissions to a Group (Calendar) folder, thus only the default entries will be returned. Feel free to edit the script and add Groups support if you wish, just remember to make use of the –GroupMailbox switch when running the Get-MailboxFolderPermission cmdlet. Similarly, Team and Discovery mailboxes are not included in the report.

Apart from the switches that control which mailbox types to include, one additional switch is made available to control the output type, namely the –CondensedOutput switch. Using it will return the “one line per mailbox” style of output, as detailed above. If you don’t specify the switch, the default one line per permission entry will be used instead. Do let us know which type of output you prefer 🙂

As with other scripts in the series, no “connect to Exchange Online” code is included, only a simple check for existing session. While care is taken to make sure the script runs as smooth as possible, running it against large number of objects can result in getting throttled or broken PowerShell sessions. You can uncomment line 71 to add some delay between the cmdlets, and lines 115 and 140 to make sure the output is written to a CSV file after each iteration. If you don’t want to include the default permissions entries in the output, remove the comment mark from line 82.

That’s pretty much it. For our next challenge, we will cover the permissions for all mailbox folders, not just the Calendar.

This entry was posted in Exchange Online, Microsoft 365, Office 365, PowerShell. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.