Src/Private/Get-AbrExoRetentionPolicies.ps1
|
function Get-AbrExoRetentionPolicies { <# .SYNOPSIS Documents Exchange Online retention policies, retention tags, and journal rules. Covers MRM (Messaging Records Management) retention policies, journal rules, and litigation hold / in-place hold overview. .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Exchange Online Retention and Journaling configuration for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'RetentionPolicies' } process { Section -Style Heading2 'MRM Policies & Journaling' { Paragraph "The following section documents MRM retention policies, journal rules, and litigation hold configuration for tenant $TenantId." BlankLine #region MRM Retention Policies try { Write-Host " - Retrieving retention policies (MRM)..." $RetentionPolicies = Get-RetentionPolicy -ErrorAction Stop | Sort-Object Name if ($RetentionPolicies -and @($RetentionPolicies).Count -gt 0) { Section -Style Heading3 'MRM Retention Policies' { Paragraph "The following $(@($RetentionPolicies).Count) MRM retention policy/policies are configured in tenant $TenantId." BlankLine $RetObj = [System.Collections.ArrayList]::new() foreach ($Policy in $RetentionPolicies) { $TagCount = if ($Policy.RetentionPolicyTagLinks) { @($Policy.RetentionPolicyTagLinks).Count } else { 0 } $retInObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Default Policy' = $Policy.IsDefault 'Tag Count' = $TagCount 'GUID' = $Policy.Guid } $RetObj.Add([pscustomobject](ConvertTo-HashToYN $retInObj)) | Out-Null } $RetTableParams = @{ Name = "MRM Retention Policies - $TenantId"; List = $false; ColumnWidths = 40, 15, 10, 35 } if ($Report.ShowTableCaptions) { $RetTableParams['Caption'] = "- $($RetTableParams.Name)" } if ($RetObj.Count -gt 0) { $RetObj | Table @RetTableParams } $script:ExcelSheets['Retention Policies'] = $RetObj } #region Retention Tags (InfoLevel 2) if ($InfoLevel.RetentionPolicies -ge 2) { try { $RetentionTags = Get-RetentionPolicyTag -ErrorAction Stop | Sort-Object Name if ($RetentionTags -and @($RetentionTags).Count -gt 0) { Section -Style Heading3 'MRM Retention Tags' { Paragraph "The following $(@($RetentionTags).Count) retention tag(s) are configured in tenant $TenantId." BlankLine $TagObj = [System.Collections.ArrayList]::new() foreach ($Tag in $RetentionTags) { $tagInObj = [ordered] @{ 'Tag Name' = $Tag.Name 'Tag Type' = $Tag.Type 'Retention Action' = $Tag.RetentionAction 'Retention Days' = if ($Tag.RetentionEnabled -and $Tag.AgeLimitForRetention) { [int]$Tag.AgeLimitForRetention.TotalDays } else { 'Not Set' } 'Retention Enabled' = $Tag.RetentionEnabled 'System Tag' = $Tag.IsDefaultModeratedRecipientTag -or $Tag.MustDisplayCommentEnabled } $TagObj.Add([pscustomobject](ConvertTo-HashToYN $tagInObj)) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AuditLogging) { $null = ($TagObj | Where-Object { $_.'Retention Enabled' -eq 'No' } | Set-Style -Style Warning | Out-Null) } }) $TagTableParams = @{ Name = "Retention Tags - $TenantId"; List = $false; ColumnWidths = 28, 16, 16, 14, 14, 12 } if ($Report.ShowTableCaptions) { $TagTableParams['Caption'] = "- $($TagTableParams.Name)" } if ($TagObj.Count -gt 0) { $TagObj | Table @TagTableParams } $script:ExcelSheets['Retention Tags'] = $TagObj } } } catch { Write-ExoError 'RetentionPolicies' "Unable to retrieve retention tags: $($_.Exception.Message)" } } #endregion } else { Paragraph "No MRM retention policies are configured in tenant $TenantId. Microsoft 365 compliance retention labels (Purview) may be in use instead." } } catch { Write-ExoError 'RetentionPolicies' "Unable to retrieve retention policies: $($_.Exception.Message)" Paragraph "Unable to retrieve MRM retention policy data: $($_.Exception.Message)" } #endregion #region Journal Rules try { Write-Host " - Retrieving journal rules..." $JournalRules = Get-JournalRule -ErrorAction Stop | Sort-Object Name Section -Style Heading3 'Journal Rules' { if ($JournalRules -and @($JournalRules).Count -gt 0) { Paragraph "The following $(@($JournalRules).Count) journal rule(s) are configured in tenant $TenantId. Journal rules capture copies of email messages for compliance and archiving purposes." BlankLine $JrnObj = [System.Collections.ArrayList]::new() foreach ($Rule in $JournalRules) { $jrnInObj = [ordered] @{ 'Rule Name' = $Rule.Name 'Enabled' = $Rule.Enabled 'Journal Email' = $Rule.JournalEmailAddress 'Scope' = $Rule.Scope 'Recipient' = if ($Rule.Recipient) { $Rule.Recipient } else { 'All Messages' } } $JrnObj.Add([pscustomobject](ConvertTo-HashToYN $jrnInObj)) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AuditLogging) { $null = ($JrnObj | Where-Object { $_.Enabled -eq 'No' } | Set-Style -Style Warning | Out-Null) } }) $JrnTableParams = @{ Name = "Journal Rules - $TenantId"; List = $false; ColumnWidths = 25, 8, 30, 12, 25 } if ($Report.ShowTableCaptions) { $JrnTableParams['Caption'] = "- $($JrnTableParams.Name)" } if ($JrnObj.Count -gt 0) { $JrnObj | Table @JrnTableParams } $script:ExcelSheets['Journal Rules'] = $JrnObj } else { Paragraph "No journal rules are configured in tenant $TenantId." } } } catch { Write-ExoError 'RetentionPolicies' "Unable to retrieve journal rules: $($_.Exception.Message)" Paragraph "Unable to retrieve journal rules: $($_.Exception.Message)" } #endregion #region Litigation Hold Summary try { Write-Host " - Retrieving litigation hold summary..." $LitigationHoldMailboxes = Get-Mailbox -ResultSize Unlimited -Filter { LitigationHoldEnabled -eq $true } -ErrorAction Stop $LitigHoldCount = @($LitigationHoldMailboxes).Count Section -Style Heading3 'Litigation Hold Summary' { Paragraph "Litigation hold preserves all mailbox content for legal and compliance purposes." BlankLine $LitObj = [System.Collections.ArrayList]::new() $litInObj = [ordered] @{ 'Mailboxes on Litigation Hold' = $LitigHoldCount 'Total Mailboxes' = @(Get-Mailbox -ResultSize Unlimited -ErrorAction SilentlyContinue).Count } $LitObj.Add([pscustomobject]$litInObj) | Out-Null $LitTableParams = @{ Name = "Litigation Hold Summary - $TenantId"; List = $true; ColumnWidths = 50, 50 } if ($Report.ShowTableCaptions) { $LitTableParams['Caption'] = "- $($LitTableParams.Name)" } $LitObj | Table @LitTableParams if ($InfoLevel.RetentionPolicies -ge 2 -and $LitigHoldCount -gt 0) { BlankLine $LitDetailObj = [System.Collections.ArrayList]::new() foreach ($Mbx in ($LitigationHoldMailboxes | Sort-Object DisplayName)) { $litDetailInObj = [ordered] @{ 'Display Name' = $Mbx.DisplayName 'UPN' = $Mbx.UserPrincipalName 'Hold Duration (days)' = if ($Mbx.LitigationHoldDuration -and "$($Mbx.LitigationHoldDuration)" -match '^\d') { try { [int]([timespan]::Parse($Mbx.LitigationHoldDuration)).TotalDays } catch { $Mbx.LitigationHoldDuration } } else { 'Indefinite' } 'Hold Owner' = if ($Mbx.LitigationHoldOwner) { $Mbx.LitigationHoldOwner } else { 'Not Set' } 'Hold Date' = if ($Mbx.LitigationHoldDate) { $Mbx.LitigationHoldDate.ToString('yyyy-MM-dd') } else { 'Not Set' } } $LitDetailObj.Add([pscustomobject]$litDetailInObj) | Out-Null } $LitDetailTableParams = @{ Name = "Mailboxes on Litigation Hold - $TenantId"; List = $false; ColumnWidths = 22, 30, 16, 20, 12 } if ($Report.ShowTableCaptions) { $LitDetailTableParams['Caption'] = "- $($LitDetailTableParams.Name)" } if ($LitDetailObj.Count -gt 0) { $LitDetailObj | Table @LitDetailTableParams } $script:ExcelSheets['Litigation Hold'] = $LitDetailObj } } } catch { Write-ExoError 'RetentionPolicies' "Unable to retrieve litigation hold data: $($_.Exception.Message)" Paragraph "Unable to retrieve litigation hold data: $($_.Exception.Message)" } #endregion } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'RetentionPolicies' } } |