Skip to main content

Exchange Reverse Permission audit Powershell Gui version 2 Exchange 2007

This script builds on a script I posted earlier in the year that produced a GUI that showed permissions and reverse permissions for Exchange Mailboxes (eg what other mailboxes a particular mailbox has access to). The previous version just looked at the Mailbox Rights and Send AS/Receive AS rights. This new version using Exchange Web Services looks at firstly the rights on the shared folders in a mailbox (eg Root,calendar,inbox,notes,task,journal) and also the Outlook Delegates and the rights assigned to the delegates such as Private Items access and Meeting recipients as well as all the other permissions it did previously. Sorry i haven't got the snapshot functionality done yet which i think i promised before but...

The cool thing is this script now lets us answer a bunch of new questions such as

Which users have given acess to paricular folders in their Mailbox to other people(including the default user which may mean the have unwillingly delegated access to everyone). And we can look at the reverse of this which is what mailboxes folders a particular mailbox has been given access to.

We can see all the Outlook delegations that have been configured and who will receive who's meeting request etc. And the reverse which is what delegate meeting request a particular mailbox will receive.

The big thing is that this script pulls together all the disparate permissions you have to consider when determining mailbox access and displays them in one location so any of the above type of questions become exceedingly easier to answer. Well that's the theory anyway.

This script uses the EWS Powershell library I've been building for a while to provide some eaiser to use functions when accessing Exchange Web Services from Powershell . The ability to access/set folder permissions was added in SP1 with Exchange Web Services. Folder permissions are a little tricky to deal with as I've talked about in the past, basically you have two different types of permission sets, calendarpermissions and normal folder permissions. So its important to detect and differentiate between them and there is also a problem with calendar permissions in that the Outlook Roles don't map to the CalendarPermissionLevelType in EWS. Fortunately i solved this one in the past with a few helper routines that will map the custom levels back to their correct Outlook roles so they make a bit more sense. The delegate code is pretty simple and just returns the outlook delegates as a genericlist.

To report on folder permissions and Delegates using Exchange Web Services you need to have rights on the mailboxes you are going to report on. There are a few ways of granting these rights firstly you can do this by granting those rights to a specific user using add-mailboxpermission as documented here. Or you can grant the rights via EWS impersonation by allowing impersonation on the server and mailStores your going to access see this. To allow for these varying degrees of rights allocations when you run the script its will first prompt you for the EWS authentication and Autodiscover settings. If you have autodiscover configured correctly the script should be able to query AD to find the correct EWS URL to use otherwise you can manually input the URL to your CAS which would look something like "https://casservername.domain.com/ews/exchange.asmx". Once you have made the EWS authentication choices the script will start querying active directory and the mailboxes for every users permissions and depending on the number of mailboxes and users you have hopefully eventually get back to you with a result.

To use this script you need to download the latest copy of the EWSUtil from here and put it in the c:\temp directory as this is where the script expect the dll eg

[void][Reflection.Assembly]::LoadFile("c:\temp\EWSUtil.dll")

I've put a download of the script here the new bits of the code look like.

if ($seAuthCheck.Checked -eq $false) {
$ewc = new-object EWSUtil.EWSConnection($mbMailboxEmail,$useImp, $unUserNameTextBox.Text, $unPasswordTextBox.Text, $unDomainTextBox.Text,$casUrl)
}
else{
$ewc = new-object EWSUtil.EWSConnection($mbMailboxEmail,$useImp, "", "", "",$casUrl)
}
$fldarry = new-object EWSUtil.EWS.BaseFolderIdType[] 6
for ($fcint=0;$fcint -lt 6;$fcint++){
$dTypeFld = new-object EWSUtil.EWS.DistinguishedFolderIdType

switch ($fcint){
0 {$dTypeFld.Id = [EWSUtil.EWS.DistinguishedFolderIdNameType]::inbox}
1 {$dTypeFld.Id = [EWSUtil.EWS.DistinguishedFolderIdNameType]::calendar}
2 {$dTypeFld.Id = [EWSUtil.EWS.DistinguishedFolderIdNameType]::contacts}
3 {$dTypeFld.Id = [EWSUtil.EWS.DistinguishedFolderIdNameType]::tasks}
4 {$dTypeFld.Id = [EWSUtil.EWS.DistinguishedFolderIdNameType]::journal}
5 {$dTypeFld.Id = [EWSUtil.EWS.DistinguishedFolderIdNameType]::msgfolderroot}
}
$mbMailbox = new-object EWSUtil.EWS.EmailAddressType
$mbMailbox.EmailAddress = $mbMailboxEmail
$dTypeFld.Mailbox = $mbMailbox
$fldarry[$fcint] = $dTypeFld
}
$Folders = $ewc.GetFolder($fldarry)
If ($Folders.Count -ne 0) {
ForEach ($Folder in $Folders) {
if ($Folder.GetType() -eq [EWSUtil.EWS.CalendarFolderType]){
ForEach ($Permissions in $Folder.PermissionSet.CalendarPermissions){
if ($Permissions.UserId.DistinguishedUserSpecified -eq $false){
$sidbind = "LDAP://sid="
$AceName = $ace.IdentityReference.Value
$aceuser = [ADSI]$sidbind
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),("FolderRight-" + $Folder.DisplayName),$aceuser.samaccountname.ToString(),$ewc.enumOutlookRole($Permissions),"Allow")
$fpCount++
if ($rvFolderPerms.Containskey($aceuser.samaccountname.ToString())){
$rvFolderPerms[$aceuser.samaccountname.ToString()] = [int]$rvFolderPerms[$aceuser.samaccountname.ToString()] +1
}
else {
$rvFolderPerms.add($aceuser.samaccountname.ToString(),1)
}
}
else{
if ($Permissions.UserId.DistinguishedUser -eq [EWSUtil.EWS.DistinguishedUserType]::Default){
if ($Permissions.CalendarPermissionLevel -ne [EWSUtil.EWS.CalendarPermissionLevelType]::None){
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),("FolderRight-" + $Folder.DisplayName),"Default",$ewc.enumOutlookRole($Permissions),"Allow")
$dfCount++
}
}
}
}


}
else {
ForEach ($Permissions in $Folder.PermissionSet.Permissions){
if ($Permissions.UserId.DistinguishedUserSpecified -eq $false){
$sidbind = "LDAP://sid="
$AceName = $ace.IdentityReference.Value
$aceuser = [ADSI]$sidbind
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),("FolderRight-" + $Folder.DisplayName),$aceuser.samaccountname.ToString(),$Permissions.PermissionLevel.ToString(),"Allow")
$fpCount++
if ($rvFolderPerms.Containskey($aceuser.samaccountname.ToString())){
$rvFolderPerms[$aceuser.samaccountname.ToString()] = [int]$rvFolderPerms[$aceuser.samaccountname.ToString()] +1
}
else {
$rvFolderPerms.add($aceuser.samaccountname.ToString(),1)
}
}
else{
if ($Permissions.UserId.DistinguishedUser -eq [EWSUtil.EWS.DistinguishedUserType]::Default){
if ($Permissions.PermissionLevel -ne [EWSUtil.EWS.PermissionLevelType]::None){
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),("FolderRight-" + $Folder.DisplayName),"Default",$Permissions.PermissionLevel.ToString(),"Allow")
$dfCount++
}
}
}
}
}
}
}
$delegates = $ewc.getdeletgates($mbMailboxEmail)
foreach ($delegate in $delegates){
$sidbind = "LDAP://sid="
$AceName = $ace.IdentityReference.Value
$aceuser = [ADSI]$sidbind
$dgCount++
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),"DelegateRight",$aceuser.samaccountname.ToString(),"Mailbox Delegated","Allow")
if ($delegate.DelegateUser.ReceiveCopiesOfMeetingMessagesSpecified -eq $true){
if ($delegate.DelegateUser.ReceiveCopiesOfMeetingMessages-eq $true){
$dgCount++
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),"DelegateRight",$aceuser.samaccountname.ToString(),"Recieve Meetings","Allow")
if ($rvDelegatePerms.Containskey($aceuser.samaccountname.ToString())){
$rvDelegatePerms[$aceuser.samaccountname.ToString()] = [int]$rvDelegatePerms[$aceuser.samaccountname.ToString()] +1
}
else {
$rvDelegatePerms.add($aceuser.samaccountname.ToString(),1)
}
}
}

if ($delegate.DelegateUser.ViewPrivateItemsSpecified -eq $true){
if ($delegate.DelegateUser.ViewPrivateItems-eq $true){
$dgCount++
[VOID]$rsTable.rows.add($uoUserobject.samaccountname.ToString(),"DelegateRight",$aceuser.samaccountname.ToString(),"View Private Items","Allow")
if ($rvDelegatePerms.Containskey($aceuser.samaccountname.ToString())){
$rvDelegatePerms[$aceuser.samaccountname.ToString()] = [int]$rvDelegatePerms[$aceuser.samaccountname.ToString()] +1
}
else {
$rvDelegatePerms.add($aceuser.samaccountname.ToString(),1)
}
}
}
if ($rvDelegatePerms.Containskey($aceuser.samaccountname.ToString())){
$rvDelegatePerms[$aceuser.samaccountname.ToString()] = [int]$rvDelegatePerms[$aceuser.samaccountname.ToString()] +1
}
else {
$rvDelegatePerms.add($aceuser.samaccountname.ToString(),1)
}

}

Popular posts from this blog

Using the MSAL (Microsoft Authentication Library) in EWS with Office365

Last July Microsoft announced here they would be disabling basic authentication in EWS on October 13 2020 which is now a little over a year away. Given the amount of time that has passed since the announcement any line of business applications or third party applications that you use that had been using Basic authentication should have been modified or upgraded to support using oAuth. If this isn't the case the time to take action is now. When you need to migrate a .NET app or script you have using EWS and basic Authentication you have two Authentication libraries you can choose from ADAL - Azure AD Authentication Library (uses the v1 Azure AD Endpoint) MSAL - Microsoft Authentication Library (uses the v2 Microsoft Identity Platform Endpoint) the most common library you will come across in use is the ADAL libraries because its been around the longest, has good support across a number of languages and allows complex authentications scenarios with support for SAML etc. The

How to test SMTP using Opportunistic TLS with Powershell and grab the public certificate a SMTP server is using

Most email services these day employ Opportunistic TLS when trying to send Messages which means that wherever possible the Messages will be encrypted rather then the plain text legacy of SMTP.  This method was defined in RFC 3207 "SMTP Service Extension for Secure SMTP over Transport Layer Security" and  there's a quite a good explanation of Opportunistic TLS on Wikipedia  https://en.wikipedia.org/wiki/Opportunistic_TLS .  This is used for both Server to Server (eg MTA to MTA) and Client to server (Eg a Message client like Outlook which acts as a MSA) the later being generally Authenticated. Basically it allows you to have a normal plain text SMTP conversation that is then upgraded to TLS using the STARTTLS verb. Not all servers will support this verb so if its not supported then a message is just sent as Plain text. TLS relies on PKI certificates and the administrative issue s that come around certificate management like expired certificates which is why I wrote th

A walk-though using the Graph API Mailbox reports in Powershell

Quite recently the Reporting side of the Graph API has moved in GA from beta, there are quite a number of reports that can be run across various Office365 surfaces but in this post I'm going to focus on the Mailbox related ones. Accessing Office365 Reports using Powershell is nothing new and has been available in the previous reporting endpoint  https://msdn.microsoft.com/en-us/library/office/jj984326.aspx however from the end of January many of these cmdlets are now being depreciated in favour of the Graph API  https://msdn.microsoft.com/en-us/library/office/dn387059.aspx . Prerequisites  In comparison to using the Remote PowerShell cmdlets where only the correct Office365 Admin permissions where needed, to use the new Graph API reports endpoint you need to use OAuth for authentication so this requires an Application Registration  https://developer.microsoft.com/en-us/graph/docs/concepts/auth_overview  that is then given the correct oAuth Grants to use the Reports EndPoin
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.