-
Notifications
You must be signed in to change notification settings - Fork 0
/
Get-MailboxPermissionsAudit.ps1
278 lines (239 loc) · 12.1 KB
/
Get-MailboxPermissionsAudit.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<#==============================================================================
Exchange Mailbox Permission Dump Script
================================================================================
Programmed By: Joshua Loos ([email protected])
Programmed Date: 09/20/2016
Last Modified: 07/10/2019 [[email protected]]
------------------------------------------------------------------------
DISCLAIMER: Use this powershell script at your own risk and willingness.
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK
OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
.SYNOPSIS
This Powershell script is intended to dump permissions for users in a list or
queried from AD
.DESCRIPTION
Pulls Send-As, Send on Behalf, and folder level access permissions for a given
set of users
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE
RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
.NOTES
Version 3.0 November 29, 2016
Revsions:
1.0 Initial script created by customer.
2.0 Updated functionality to pull additional data and formulate reports.
3.0 Fixed some minor bugs, added functionality updated to pull additional
data, added comments.
4.0 Customer-specific changes, minor bug fixes
5.0 Cleaned up script with new functions and more comments
6.0 Improved error handling, purged customer-specific logic
7.0 Added checks for full mailbox permissions and quick output of unique relationships
8.0 Rehauled script - trimmed down to just delegate, full mailbox and sendas with no folder level checks
.PARAMETER OU
Optional. Specify a OU from which to query users. Do not use this parameter
when using ImportList or AnalyzeBatches
.PARAMETER ImportList
Optional. Specify the location of a CSV file that contains a list of primary
SMTP addresses under the column, "PrimarySMTPAddress". Do not use this parameter
when specifying an OU
.EXAMPLE
'.\Get-MailboxPermissionAudit.ps1' -ImportList "EarlyAdopters.csv"
.EXAMPLE
'.\Get-MailboxPermissionAudit.ps1' -OU "OU=Contractors,CN=Users,DC=contoso,DC=com"
#>
#region Parameters
Param(
[string]$OU,
[string]$ImportList
)
#endregion
#region Script Variables
# These variables are ok to change
$CustomerName = "Contoso by Microsoft"
$Domain = "contoso.local" # Domain only affects the default OU location if no OU is specified
#endregion
#region Script Setup
# Do not change these variables
[array]$Script:UserList = @()
[System.Collections.ArrayList]$Script:Permissions = New-Object System.Collections.ArrayList($null)
#[array]$Script:Permissions = @()
[array]$Script:MigrationBatches = @()
# Default path if no OU is specified
$SplitDomain = $Domain.split(".")
If (-not $OU -and -not $AnalyzeBatches) { $OU = "CN=Users,DC=$($SplitDomain[0]),DC=$($SplitDomain[1])" }
# The following few lines are used later to pull Send As permissions
$DSE = [ADSI]"LDAP://Rootdse"
$EXT = [ADSI]("LDAP://CN=Extended-Rights," + $DSE.ConfigurationNamingContext)
$Right = $EXT.psbase.Children | Where-Object { $_.DisplayName -eq "Send As" }
# Determining the output name of the report
$RunTime = $(Get-Date -Format "yyyyMMddTHHmmss")
$OutputLocation = "Permissions-$Runtime.csv"
# Build error report filename
$ErrorLogPath = "Permissions-ErrorLog-$Runtime.txt"
# Import commands to query AD
If (-not (Get-Module -Name ActiveDirectory)) {
Import-Module ActiveDirectory
}
#endregion
#regions Functions
Function Start-DrawBanner {
Write-Host "`n############################################################"
Write-Host "# " -NoNewline
Write-Host "Exchange Permissions Dump" -ForegroundColor Cyan -NoNewline
Write-Host " #"
Write-Host "# " -NoNewLine
Write-Host "Designed for:" -ForegroundColor Yellow -NoNewline
Write-Host " $CustomerName #"
Write-Host "# " -NoNewLine
Write-Host "Author:" -ForegroundColor Yellow -NoNewline
Write-Host " Joshua Loos -- [email protected] #"
Write-Host "############################################################`n"
}
Function Start-DrawRunSettings {
If ($OU) { Write-Host " Run Mode:`t`tPermission Dump" }
Write-Host " Domain:`t`t$Domain"
If (-not $ImportList) { Write-Host " OU:`t`t`t$OU" } Else { Write-Host " OU:`t`t`tFalse" }
If ($ImportList) { Write-Host " ImportList:`t`t$ImportList"} Else { Write-Host " ImportList:`t`tFalse" }
}
Function Write-Action ($Message) {
$TimeStamp = Get-Date -Format "HH:mm:ss"
Write-Host "[$TimeStamp] $Message"
}
Function Write-ErrorLog ($ErrorMessage) {
$TimeStamp = Get-Date -Format "HH:mm:ss"
$Output = "[$TimeStamp] [ERROR] $ErrorMessage"
$Output | Out-File $ErrorLogPath -Encoding ascii -Append
}
Function Get-UserList {
If ($ImportList) { # Use a list to import users
$ImportList = Import-Csv $ImportList
Foreach ($Row in $ImportList) {
$ImportUser = $($Row.PrimarySMTPAddress)
try { $Recipients = Get-Recipient $ImportUser.Trim() -ErrorAction Stop | Select-Object SamAccountName,RecipientTypeDetails,PrimarySMTPAddress }
catch { Write-ErrorLog "Unable to import user $ImportUser, Get-Recipient command failed. Error Message: $($_.ToString())" }
Foreach ($Recipient in $Recipients) {
If ($Recipient.RecipientTypeDetails -match "Mailbox" -and $Recipient.RecipientTypeDetails -notlike "*Remote*") {
try {
$UserObject = Get-ADUser $($Recipient.SamAccountName) -Properties msExchDelegateListLink,PublicDelegates,PublicDelegatesBL,GivenName,Surname,DistinguishedName,UserPrincipalName,mail,name,msExchRecipientTypeDetails | Select-Object msExchDelegateListLink,PublicDelegates,PublicDelegatesBL,GivenName,Surname,DistinguishedName,UserPrincipalName,mail,name,msExchRecipientTypeDetails
If ($UserObject.count -gt 1) {
Write-ErrorLog "Unable to import user. Duplicate users found for $ImportUser (SAM: $($Recipient.SamAccountName))."
} Else {
$Script:UserList += $UserObject
}
}
catch {Write-ErrorLog "Unable to import user $ImportUser, Get-ADUser command failed. Error Message: $($_.ToString())"}
} Else {
Write-ErrorLog "Unable to import user $ImportUser. User is not a User-, Shared-, or ResourceMailbox ($($Recipient.RecipientTypeDetails))."
}
}
}
}
Else { # Used when the OU parameter is specified, imports all users from that particular OU
try {
If ([ADSI]::Exists("LDAP://$OU")) {
$Script:UserList = Get-ADUser -SearchScope Subtree -SearchBase $OU -ResultSetSize $null -Filter {(objectCategory -eq "person") -and (objectClass -eq "user") -and (msExchRecipientTypeDetails -like "*")} -Properties msExchDelegateListLink,PublicDelegates,PublicDelegatesBL,GivenName,Surname,DistinguishedName,UserPrincipalName,mail,name,msExchRecipientTypeDetails | Select-Object msExchDelegateListLink,PublicDelegates,PublicDelegatesBL,GivenName,Surname,DistinguishedName,UserPrincipalName,mail,name,msExchRecipientTypeDetails
} Else {
Write-ErrorLog "Unable to get users, the OU that was specified does not exist."
}
} catch [System.Management.Automation.RuntimeException] {
Write-ErrorLog "Unable to get users. If you specified an OU, verify the path, otherwise, verify that the domain variable is accurate. Error Message: $($_.ToString())"
} catch {
Write-ErrorLog "Unable to get users, Get-ADUser command failed. Error Message: $($_.ToString())"
}
}
}
Function Get-Permissions { # Iterate through each user and grab Send-As permissions, Full Mailbox Access and Delegate Access
$i=0
ForEach ($User in $Script:UserList) {
$i++
Write-Progress -Activity "Grabbing permissions.." -Status "Processing user $($User.mail) ($i of $($Script:UserList.count))" -PercentComplete $($i/$($Script:UserList.count)*100)
# User data from Get-ADUser object
$EmailAddress = $User.mail
$FirstName = $User.givenname
$LastName = $User.surname
$DisplayName= $User.name
$UPN = $User.UserPrincipalName
$DistinguishedName= $User.DistinguishedName
$RecipientType= Switch ($User.msExchRecipientTypeDetails) {
1 {"User Mailbox"}
4 {"Shared Mailbox"}
16 {"Room Mailbox"}
32 {"Equipment Mailbox"}
64 {"Mail Contact"}
128 {"Mail User"}
256 {"Distribution Group"}
1024 {"Security Group"}
2048 {"Dynamic Group"}
2147483648 {"Remote Mailbox"}
Default {$user.msExchRecipientTypeDetails}
}
# Send-as permissions
$UserDN = [ADSI]("LDAP://$($User.DistinguishedName)")
$SAPermissions = New-Object -TypeName System.Collections.ArrayList
# Do not include inherited permissions. Only explicit permissions are migrated https://technet.microsoft.com/en-us/library/jj200581(v=exchg.150).aspx
$UserDN.psbase.ObjectSecurity.Access | Where-Object { ($_.ObjectType -eq [GUID]$Right.RightsGuid.Value) -and ($_.IsInherited -eq $false) } | Select-Object -ExpandProperty IdentityReference | ForEach-Object{
If($_ -notlike "NT AUTHORITY\SELF" -and $_ -notlike "*S-1-5-21*") { [void]$SAPermissions.Add($_) }
}
If ($SAPermissions) {
ForEach ($Perm in $SAPermissions) {
$DelegateName = $Perm.ToString().Replace("NT User:","")
$SendAsRow = [ordered]@{
'First Name' = $FirstName
'Last Name' = $LastName
'Primary SMTP' = $EmailAddress
'Display Name' = $DisplayName
UPN = $UPN
'DistringuishedName' = $DistinguishedName
'Recipient Type' = $RecipientType
'Delegate Name' = $DelegateName
'Delegate Right' = "SendAs"
}
$null = $Script:Permissions.Add((New-Object PSobject -property $SendAsRow))
}
}
# End of send-as permissions
# Full Mailbox Permissions added by austinmc
# this attribute lists all the other mailboxes your mailbox has FullAccess to, unless AutoMapping was set to $false when assigning the permission
If ($User.msExchDelegateListLink) {
ForEach ($DelegateLink in $User.msExchDelegateListLink) {
$DelegateName = $DelegateLink
$FullMbxRow = [ordered]@{
'First Name' = $FirstName
'Last Name' = $LastName
'Primary SMTP' = $EmailAddress
'Display Name' = $DisplayName
UPN = $UPN
'DistringuishedName' = $DistinguishedName
'Recipient Type' = $RecipientType
'Delegate Name' = $DelegateName
'Delegate Right' = "Full Mailbox"
}
$null = $Script:Permissions.Add((New-Object PSobject -property $FullMbxRow))
}
}
}
}
Function Export-Permissions # Export the permissions to a CSV file.
{
$Script:Permissions | Export-CSV -path ".\$OutputLocation" -NoTypeInformation
}
#endregion
#region Main
Measure-Command {
Clear-Host
Start-DrawBanner
Start-DrawRunSettings
Set-ADServerSettings -ViewEntireForest:$true
Write-Action "Getting list of users..."
Get-UserList
Write-Action "Found $(($Script:UserList | Measure-Object).Count) recipients."
Write-Action "Getting permissions..."
Get-Permissions
$PermCount = $($Script:Permissions | Measure-Object).Count
Write-Action "Found $PermCount delegation type permissions on those recipients."
If ($PermCount -gt 0) {
Write-Action "Exporting permissions to file..."
Export-Permissions
}
Write-Action "Script complete!"
}
#endregion