Earlier this week, I had a request for assistance with delegating reporting features in Exchange Online to non-administrative users. This is a frequent topic of discussion when it comes to compliance and security officers validating that systems are not being misused by unauthorized persons.
Let’s say we want to allow Adele, our compliance officer, the ability to view the mailbox access reports. Fortunately, this is a pretty easy task that can be accomplished with just a little PowerShell (or a little UI work). I’ll show both ways.
User Interface
- Launch a browser and navigate to https://outlook.office365.com/ecp/UsersGroups/AdminRoleGroups.slab. Select Records Management and click the pencil/edit icon.
- Under Members, select + (Add).
- Select the user(s) from the GAL and click Add. Click OK when finished.
PowerShell
And then, the PowerShell Way. Copy, save to a .ps1, and run with the appropriate parameters. This will enable the organization configuration and update all of the mailboxes with the appropriate parameters (settings that aren’t available in the UI).
<# .SYNOPSIS Enable audit logging and reporting capability for non-administrative users. .PARAMETER Credential Office 365 global admin credential. .PARAMETER Logfile Specify log file for operations. .PARAMETER Members Users to add to RecordsManagement role. .PARAMETER UpdateAllMailboxes Update all mailboxes in tenant with either AuditBypassDisabled $false (if Set-OrganizationConfig supports AuditDisabled parameter) or AuditEnabled $true (if AuditDisabled Set-OrganizationConfig parameter is not available). .PARAMETER UseExistingSession Use existing Office 365 session instead of connecting to a new session. #> param ( $Credential, [switch]$Debug, [array]$Members, $Logfile = ".\MailboxAuditLogConfiguration.txt", [switch]$UpdateAllMailboxes, [switch]$UseExistingSession ) # Need a global admin credential If (!($UseExistingSession)) { If (!($Credential)) { $Credential = Get-Credential } # Connect to Office 365 $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection Import-PSSession $Session $ComplianceSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $Credential -Authentication Basic -AllowRedirection Import-PSSession $ComplianceSession -AllowClobber -DisableNameChecking } function Write-Log([string[]]$Message, [string]$LogFile = $Script:LogFile, [switch]$ConsoleOutput, [ValidateSet("SUCCESS", "INFO", "WARN", "ERROR", "DEBUG")][string]$LogLevel) { $Message = $Message + $Input If (!$LogLevel) { $LogLevel = "INFO" } switch ($LogLevel) { SUCCESS { $Color = "Green" } INFO { $Color = "White" } WARN { $Color = "Yellow" } ERROR { $Color = "Red" } DEBUG { $Color = "Gray" } } if ($Message -ne $null -and $Message.Length -gt 0) { $TimeStamp = [System.DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss") if ($LogFile -ne $null -and $LogFile -ne [System.String]::Empty) { Out-File -Append -FilePath $LogFile -InputObject "[$TimeStamp] [$LogLevel] $Message" } if ($ConsoleOutput -eq $true) { Write-Host "[$TimeStamp] [$LogLevel] :: $Message" -ForegroundColor $Color } } } $Error.Clear() # Configure environment for auditing Try { Enable-OrganizationCustomization -ea Stop | Out-Null } Catch { $Response = $Error.Exception If ($Response -like "*This operation is not required.*") { Write-Log -LogFile $Logfile -Message "$($Response)" -LogLevel INFO } Else { Write-Log -LogFile $Logfile -Message "$($Response)" -ConsoleOutput -LogLevel ERROR } } # Enable Audit Logging organization-wide Try { Write-Log -Message "Enabling Unified Audit Log Ingestion." -LogFile INFO -ConsoleOutput -LogLevel INFO Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true } Catch { Write-Log -Message "Error encountered attempting to update Unified Audit Log setting." -LogFile $Logfile -LogLevel ERROR -ConsoleOutput } # Set-OrganizationConfig -AuditDisabled is a new feature that is rolling out. If the AuditDisabled feature isn't available, # mailbox auditing must be enabled on every mailbox. $Error.Clear() Write-Log -LogFile $Logfile -Message "Gathering list of mailboxes." -LogLevel INFO -ConsoleOutput If ($UpdateAllMailboxes) { $Mailboxes = Get-Mailbox -ResultSize Unlimited } $Error.Clear() Try { Write-Log -LogFile $Logfile -Message "Checking for Set-OrganizationConfig AuditDisabled parameter." -LogLevel DEBUG Get-Command Set-OrganizationConfig -ParameterName AuditDisabled -ea Stop | Out-Null If (!($Error)) { Write-Log -LogFile $Logfile -Message "Parameter AuditDisabled available. Setting AuditDisabled parameter to FALSE." -LogLevel INFO -ConsoleOutput Set-OrganizationConfig -AuditDisabled $False If ($UpdateAllMailboxes) { Write-Log -LogFile $Logfile -Message "Resetting any mailbox auditing bypass settings to default." -LogLevel SUCCESS -ConsoleOutput $i = 1 foreach ($Mailbox in $Mailboxes) { Write-Progress -Activity "Resetting AuditBypassEnabled for mailbox $($Mailbox.DisplayName)" -Status "[$($i)/$($Mailboxes.Count)]" -PercentComplete ($i/$Mailboxes.Count * 100) If ($Debug) { Write-Log -LogFile $Logfile -Message "Resetting AuditBypassEnabled for $($Mailbox.DisplayName) - ($($Mailbox.PrimarySmtpAddress))" -LogLevel DEBUG } Set-MailboxAuditBypassAssociation -Identity $Mailbox.Identity -AuditBypassEnabled $False -Confirm:$False -wa SilentlyContinue $i++ } } } } Catch { Write-Log -LogFile $Logfile -Message "Parameter AuditBypassEnabled not available." If ($UpdateAllMailboxes) { Write-Log -LogFile $Logfile -Message "UpdateAllMailboxes set. Updating Mailbox Audit parameters for all mailboxes." $i = 1 Foreach ($Mailbox in $Mailboxes) { Write-Progress -Activity "Enabling Mailbox Audit setting for mailbox $($Mailbox.DisplayName)" -Status "[$($i)/$($Mailboxes.Count)]" -PercentComplete ($i/$Mailboxes.Count * 100) If ($Debug) { Write-Log -LogFile $Logfile -Message "Enabling Mailbox Audit setting for $($Mailbox.DisplayName) - ($($Mailbox.PrimarySmtpAddress))" -LogLevel DEBUG } Set-Mailbox -Identity $Mailbox.Identity -AuditEnabled $True -wa SilentlyContinue } } } # Update Role Group Memberships If ($Members) { Write-Log -LogFile $Logfile -LogLevel INFO -Message "Adding members to RecordsManagement role." -ConsoleOutput Foreach ($Member in $Members) { $Error.Clear() Try { Add-RoleGroupMember -Member $Member -Identity RecordsManagement -ea Stop | Out-Null } Catch { $Value = $Error.Exception If ($Value -match "already a member") { Write-Log -LogFile $Logfile -Message $Value -LogLevel INFO } Else { Write-Log -LogFile $Logfile -Message $Value -ConsoleOutput -LogLevel ERROR } } } } Write-Log -Message "Complete." -LogFile $Logfile -ConsoleOutput -LogLevel INFO
Once the role permissions have been assigned, log back in with a newly added Records Management member, and then a user can navigate directly to https://outlook.office365.com/ecp/Reporting/AuditReports.slab. For more information on viewing the reports, check out https://docs.microsoft.com/en-us/Exchange/policy-and-compliance/non-owner-mailbox-access-reports?view=exchserver-2019.
One Reply to “Delegating Reporting Access for Exchange Online”
Comments are closed.