Delegating Reporting Access for Exchange Online
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 /en-us/Exchange/policy-and-compliance/non-owner-mailbox-access-reports?view=exchserver-2019.