Scripts/Get-AuditLogSettings.ps1
function Get-MailboxAuditStatus { <# .SYNOPSIS Retrieves audit status and settings for all mailboxes in Microsoft 365. .DESCRIPTION Retrieves detailed information about mailbox audit settings, including audit status, bypass settings, and configured audit actions for owners, delegates, and administrators. .PARAMETER OutputDir Specifies the output directory for the audit status report. Default: Output\Audit Status .PARAMETER Encoding Specifies the encoding of the CSV output file. Default: UTF8 .PARAMETER UserIds UserIds is the UserIds parameter filtering the log entries by the account of the user who performed the actions. .PARAMETER LogLevel Specifies the level of logging: None: No logging Minimal: Critical errors only Standard: Normal operational logging Debug: Verbose logging for debugging purposes Default: Standard .EXAMPLE Get-MailboxAuditStatus Retrieves audit status for all mailboxes and exports to a CSV file in the default directory. .EXAMPLE Get-MailboxAuditStatus -OutputDir C:\Temp -Encoding UTF32 Retrieves audit status and saves the output to C:\Temp with UTF-32 encoding. #> [CmdletBinding()] param ( [string]$OutputDir = "Output\Audit Status", [string]$Encoding = "UTF8", [ValidateSet('None', 'Minimal', 'Standard', 'Debug')] [string]$LogLevel = 'Standard', [string[]]$UserIds ) Set-LogLevel -Level ([LogLevel]::$LogLevel) $isDebugEnabled = $script:LogLevel -eq [LogLevel]::Debug if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Input parameters:" -Level Debug Write-LogFile -Message "[DEBUG] OutputDir: $OutputDir" -Level Debug Write-LogFile -Message "[DEBUG] Encoding: $Encoding" -Level Debug Write-LogFile -Message "[DEBUG] LogLevel: $LogLevel" -Level Debug Write-LogFile -Message "[DEBUG] UserIds: $UserIds" -Level Debug Write-LogFile -Message "[DEBUG] PowerShell Version: $($PSVersionTable.PSVersion)" -Level Debug $exchangeModule = Get-Module -Name ExchangeOnlineManagement -ErrorAction SilentlyContinue if ($exchangeModule) { Write-LogFile -Message "[DEBUG] ExchangeOnlineManagement Module Version: $($exchangeModule.Version)" -Level Debug } else { Write-LogFile -Message "[DEBUG] ExchangeOnlineManagement Module not loaded" -Level Debug } } $summary = @{ TotalMailboxes = 0 AuditEnabled = 0 AuditDisabled = 0 AuditBypass = 0 OwnerActionsConfigured = 0 DelegateActionsConfigured = 0 AdminActionsConfigured = 0 ProcessedMailboxes = 0 StartTime = Get-Date ProcessingTime = $null OrgWideAuditingEnabled = $false } Write-LogFile -Message "=== Starting Mailbox Audit Status Collection ===" -Color "Cyan" -Level Standard if (!(Test-Path $OutputDir)) { New-Item -ItemType Directory -Force -Path $OutputDir > $null } else { if (!(Test-Path -Path $OutputDir)) { Write-LogFile -Message "[ERROR] Custom directory invalid: $OutputDir" -Level Minimal -Color "Red" return } } $date = Get-Date -Format "yyyyMMddHHmm" $outputFile = "$date-MailboxAuditStatus.csv" $outputDirectory = Join-Path $OutputDir $outputFile if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Output file configuration:" -Level Debug Write-LogFile -Message "[DEBUG] Date stamp: $date" -Level Debug Write-LogFile -Message "[DEBUG] File name: $outputFile" -Level Debug Write-LogFile -Message "[DEBUG] Full path: $outputDirectory" -Level Debug Write-LogFile -Message "[DEBUG] Encoding: $Encoding" -Level Debug } try { $orgConfig = Get-OrganizationConfig | Select-Object -ExpandProperty AuditDisabled $summary.OrgWideAuditingEnabled = -not $orgConfig if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Organization audit configuration:" -Level Debug Write-LogFile -Message "[DEBUG] AuditDisabled property: $orgConfig" -Level Debug Write-LogFile -Message "[DEBUG] Organization-wide auditing enabled: $($summary.OrgWideAuditingEnabled)" -Level Debug } if ($orgConfig) { Write-LogFile -Message "[WARNING] Organization-wide auditing is disabled!" -Level Minimal -Color "Red" } else { Write-LogFile -Message "[INFO] Organization-wide auditing is enabled - This overrides individual mailbox settings" -Level Standard -Color "Green" } } catch { Write-LogFile -Message "[INFO] Ensure you are connected to M365 by running the Connect-ExchangeOnline or Connect-M365 command before executing this script" -Level Minimal -Color "Yellow" Write-LogFile -Message "[ERROR] An error occurred: $($_.Exception.Message)" -Level Minimal -Color "Red" if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Organization config retrieval failed:" -Level Debug Write-LogFile -Message "[DEBUG] Exception type: $($_.Exception.GetType().Name)" -Level Debug Write-LogFile -Message "[DEBUG] Exception message: $($_.Exception.Message)" -Level Debug Write-LogFile -Message "[DEBUG] Stack trace: $($_.ScriptStackTrace)" -Level Debug } throw } Write-LogFile -Message "[INFO] Retrieving mailbox list..." -Level Standard if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Executing Get-EXOMailbox command..." -Level Debug Write-LogFile -Message "[DEBUG] Parameters: -ResultSize unlimited -PropertySets All" -Level Debug $mailboxRetrievalStart = Get-Date } try { $mailboxes = Get-EXOMailbox -ResultSize unlimited -PropertySets All $summary.TotalMailboxes = $mailboxes.Count Write-LogFile -Message "[INFO] Found $($mailboxes.Count) mailboxes to process" -Level Standard if ($isDebugEnabled) { $mailboxRetrievalTime = (Get-Date) - $mailboxRetrievalStart Write-LogFile -Message "[DEBUG] Mailbox retrieval completed:" -Level Debug Write-LogFile -Message "[DEBUG] Total mailboxes: $($mailboxes.Count)" -Level Debug Write-LogFile -Message "[DEBUG] Retrieval time: $($mailboxRetrievalTime.TotalSeconds) seconds" -Level Debug } } catch { Write-LogFile -Message "[ERROR] Failed to retrieve mailboxes: $($_.Exception.Message)" -Level Minimal -Color "Red" if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Mailbox retrieval error:" -Level Debug Write-LogFile -Message "[DEBUG] Exception: $($_.Exception.Message)" -Level Debug Write-LogFile -Message "[DEBUG] Stack trace: $($_.ScriptStackTrace)" -Level Debug } throw } Write-LogFile -Message "[INFO] Retrieving audit bypass associations..." -Level Standard $bypassLookup = @{} foreach ($mailbox in $mailboxes) { $bypassLookup[$mailbox.UserPrincipalName] = $false } if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Bypass lookup initialized with $($bypassLookup.Count) entries (all set to false)" -Level Debug } try { Write-LogFile -Message "[INFO] Attempting bulk retrieval of audit bypass associations..." -Level Standard $bypassAssociations = Get-MailboxAuditBypassAssociation -ResultSize Unlimited -WarningAction SilentlyContinue | Select-Object Identity, AuditBypassEnabled | Where-Object { $_.AuditBypassEnabled -eq $true } if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Bulk bypass retrieval completed:" -Level Debug Write-LogFile -Message "[DEBUG] Bypass associations found: $($bypassAssociations.Count)" -Level Debug } foreach ($bypass in $bypassAssociations) { if ($null -ne $bypass.Identity) { $bypassLookup[$bypass.Identity] = $True if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Set bypass = true for: $($bypass.Identity)" -Level Debug } } } if ($isDebugEnabled) { $bypassCount = ($bypassLookup.Values | Where-Object { $_ -eq $true }).Count Write-LogFile -Message "[DEBUG] Bypass lookup updated: $bypassCount mailboxes with bypass enabled" -Level Debug } } catch { Write-LogFile -Message "[WARNING] Bulk retrieval failed, likely due to too many mailboxes. This will timeout the cmdlet. Processing mailboxes individually..." -Level Standard -Color "Yellow" Write-LogFile -Message "[WARNING] This may take some time..." -Level Standard -Color "Yellow" if ($isDebugEnabled) { Write-LogFile -Message "[DEBUG] Bulk bypass retrieval failed, switching to individual processing:" -Level Debug Write-LogFile -Message "[DEBUG] Exception: $($_.Exception.Message)" -Level Debug } $batchSize = 10 for ($i = 0; $i -lt $mailboxes.Count; $i += $batchSize) { $batch = $mailboxes | Select-Object -Skip $i -First $batchSize if ($isDebugEnabled) { $batchNumber = [Math]::Floor($i / $batchSize) + 1 Write-LogFile -Message "[DEBUG] Processing batch $batchNumber (mailboxes $($i + 1) to $([Math]::Min($i + $batchSize, $mailboxes.Count)))" -Level Debug } foreach ($mbx in $batch) { try { $bypass = Get-MailboxAuditBypassAssociation -Identity $mbx.UserPrincipalName -WarningAction SilentlyContinue | Select-Object Identity, AuditBypassEnabled if ($bypass -and $bypass.Identity) { $bypassLookup[$bypass.Identity] = [bool]$bypass.AuditBypassEnabled } if ($isDebugEnabled -and $bypass.AuditBypassEnabled) { Write-LogFile -Message "[DEBUG] Individual bypass found: $($mbx.UserPrincipalName)" -Level Debug } else { $bypassLookup[$mbx.UserPrincipalName] = $false } } catch { $bypassLookup[$mbx.UserPrincipalName] = $false continue } } $processed = [Math]::Min($i + $batchSize, $mailboxes.Count) $percentage = [math]::Round(($processed / $mailboxes.Count) * 100, 2) Write-LogFile -Message "[INFO] Processed bypass status: $processed/$($mailboxes.Count) mailboxes ($percentage%)" -Level Standard Start-Sleep -Seconds 5 # Otherwise it might still timeout. } } $results = @() foreach ($mailbox in $mailboxes) { $summary.ProcessedMailboxes++ $bypassStatus = $bypassLookup[$mailbox.UserPrincipalName] if ($mailbox.AuditEnabled) { $summary.AuditEnabled++ } else { $summary.AuditDisabled++ } if ($bypassStatus) { $summary.AuditBypass++ } if ($mailbox.AuditOwner) { $summary.OwnerActionsConfigured++ } if ($mailbox.AuditDelegate) { $summary.DelegateActionsConfigured++ } if ($mailbox.AuditAdmin) { $summary.AdminActionsConfigured++ } if ($isDebugEnabled -and ($summary.ProcessedMailboxes % 100 -eq 0 -or $summary.ProcessedMailboxes -le 10)) { Write-LogFile -Message "[DEBUG] Processing mailbox $($summary.ProcessedMailboxes)/$($summary.TotalMailboxes): $($mailbox.UserPrincipalName)" -Level Debug Write-LogFile -Message "[DEBUG] AuditEnabled: $($mailbox.AuditEnabled), Bypass: $bypassStatus" -Level Debug Write-LogFile -Message "[DEBUG] Owner actions: $($mailbox.AuditOwner.Count), Delegate: $($mailbox.AuditDelegate.Count), Admin: $($mailbox.AuditAdmin.Count)" -Level Debug } # Sort the audit actions for each category $ownerActions = if ($mailbox.AuditOwner) { ($mailbox.AuditOwner | Sort-Object) -join ', ' } else { '' } $delegateActions = if ($mailbox.AuditDelegate) { ($mailbox.AuditDelegate | Sort-Object) -join ', ' } else { '' } $adminActions = if ($mailbox.AuditAdmin) { ($mailbox.AuditAdmin | Sort-Object) -join ', ' } else { '' } $defaultAuditSet = if ($mailbox.DefaultAuditSet) { ($mailbox.DefaultAuditSet | Sort-Object) -join ', ' } else { '' } $results += [PSCustomObject]@{ UserPrincipalName = $mailbox.UserPrincipalName DisplayName = $mailbox.DisplayName RecipientTypeDetails = $mailbox.RecipientTypeDetails AuditEnabled = $mailbox.AuditEnabled AuditBypassEnabled = $bypassStatus DefaultAuditSet = $defaultAuditSet OwnerAuditActions = $ownerActions OwnerAuditActionsCount = if ($mailbox.AuditOwner) { $mailbox.AuditOwner.Count } else { 0 } DelegateAuditActions = $delegateActions DelegateAuditActionsCount = if ($mailbox.AuditDelegate) { $mailbox.AuditDelegate.Count } else { 0 } AdminAuditActions = $adminActions AdminAuditActionsCount = if ($mailbox.AuditAdmin) { $mailbox.AuditAdmin.Count } else { 0 } EffectiveAuditState = if ($summary.OrgWideAuditingEnabled -and -not $bypassStatus) { "Enabled (Organization Policy)" } elseif ($bypassStatus) { "Bypassed" } else { "Disabled" } } } $results | Export-Csv -Path $outputDirectory -NoTypeInformation -Encoding $Encoding $summary.ProcessingTime = (Get-Date) - $summary.StartTime Write-LogFile -Message "`nOrganization Configuration:" -Level Standard -Color "Cyan" Write-LogFile -Message " Organization-wide Auditing: $(if ($summary.OrgWideAuditingEnabled) { 'Enabled' } else { 'Disabled' })" -Level Standard if ($summary.OrgWideAuditingEnabled) { Write-LogFile -Message " [!] Organization-wide auditing overrides individual mailbox settings" -Level Standard Write-LogFile -Message " [!] Default actions are automatically logged for all non-bypassed mailboxes" -Level Standard } Write-LogFile -Message "`nMailbox Statistics:" -Level Standard -Color "Cyan" Write-LogFile -Message " Total Mailboxes: $($summary.TotalMailboxes)" -Level Standard Write-LogFile -Message " Audit Enabled: $($summary.AuditEnabled)" -Level Standard Write-LogFile -Message " Audit Disabled: $($summary.AuditDisabled)" -Level Standard Write-LogFile -Message " Audit Bypass Enabled: $($summary.AuditBypass)" -Level Standard Write-LogFile -Message "`nAudit Actions Configured:" -Level Standard -Color "Cyan" Write-LogFile -Message " Owner Actions: $($summary.OwnerActionsConfigured)" -Level Standard Write-LogFile -Message " Delegate Actions: $($summary.DelegateActionsConfigured)" -Level Standard Write-LogFile -Message " Admin Actions: $($summary.AdminActionsConfigured)" -Level Standard Write-LogFile -Message "`nOutput Details:" -Level Standard -Color "Cyan" Write-LogFile -Message " Output File: $outputDirectory" -Level Standard Write-LogFile -Message " Processing Time: $($summary.ProcessingTime.ToString('mm\:ss'))" -Level Standard Write-LogFile -Message "===================================" -Color "Cyan" -Level Standard } |