Src/Private/Get-AbrExoRecovery.ps1
|
function Get-AbrExoRecovery { <# .SYNOPSIS Documents Exchange Online backup and recovery capabilities: native recovery options, service-level recovery, deleted item retention periods, and third-party backup posture. .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Exchange Online Recovery/Backup configuration for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'Recovery' } process { Section -Style Heading2 'Backup, Recovery & Business Continuity' { Paragraph "The following section documents native Exchange Online recovery capabilities, data retention for recovery purposes, and the overall recovery posture for tenant $TenantId." BlankLine #region Native Recovery Capabilities Section -Style Heading3 'Native Recovery Capabilities' { Paragraph "Exchange Online does not provide traditional backup files. Microsoft provides the following native data recovery mechanisms:" BlankLine $NatRecObj = [System.Collections.ArrayList]::new() $natRows = @( [pscustomobject]@{ 'Recovery Method' = 'Deleted Items Folder' 'Retention Period' = 'Until user empties folder' 'Who Can Recover' = 'User (self-service via OWA/Outlook)' 'Data Covered' = 'Items deleted by the user (first-stage delete)' 'RPO' = 'Immediate (no data loss)' } [pscustomobject]@{ 'Recovery Method' = 'Recoverable Items (Soft Delete)' 'Retention Period' = '14 days default (configurable up to 30 days)' 'Who Can Recover' = 'User via Recover Deleted Items, or Admin via eDiscovery' 'Data Covered' = 'Items removed from Deleted Items, shift-deleted items' 'RPO' = 'Up to 14-30 days prior to hard delete' } [pscustomobject]@{ 'Recovery Method' = 'Single Item Recovery (SIR)' 'Retention Period' = '14 days default while enabled' 'Who Can Recover' = 'Admin via eDiscovery / Content Search' 'Data Covered' = 'Protects against purge of recoverable items' 'RPO' = 'Up to 14 days before purge' } [pscustomobject]@{ 'Recovery Method' = 'Litigation Hold' 'Retention Period' = 'Indefinite (while hold is active)' 'Who Can Recover' = 'Admin via eDiscovery / Content Search' 'Data Covered' = 'All mailbox content (including sent/calendar/tasks)' 'RPO' = 'Zero data loss from point of hold activation' } [pscustomobject]@{ 'Recovery Method' = 'In-Place Archive' 'Retention Period' = 'Unlimited (separate 100 GB+ archive mailbox)' 'Who Can Recover' = 'User (self-service) and Admin' 'Data Covered' = 'Archived email content' 'RPO' = 'Data retained in archive indefinitely' } [pscustomobject]@{ 'Recovery Method' = 'Microsoft 365 Service-Level Backup' 'Retention Period' = 'Microsoft internal (14+ day geo-redundant replication)' 'Who Can Recover' = 'Microsoft (via support request for catastrophic loss)' 'Data Covered' = 'Entire service data centre failure scenarios only' 'RPO' = 'Not a user-accessible backup; SLA-based recovery only' } ) foreach ($row in $natRows) { $NatRecObj.Add($row) | Out-Null } $NatTableParams = @{ Name = "Native Recovery Methods - $TenantId"; List = $false; ColumnWidths = 18, 18, 22, 24, 18 } if ($Report.ShowTableCaptions) { $NatTableParams['Caption'] = "- $($NatTableParams.Name)" } if ($NatRecObj.Count -gt 0) { $NatRecObj | Table @NatTableParams } } #endregion #region Tenant Recovery Configuration Summary try { Write-Host " - Retrieving tenant recovery configuration..." $AllMailboxes = Get-Mailbox -ResultSize Unlimited -ErrorAction Stop | Where-Object { $_.RecipientTypeDetails -in @('UserMailbox', 'SharedMailbox') } $SirEnabled = @($AllMailboxes | Where-Object { $_.SingleItemRecoveryEnabled -eq $true }).Count $LitHoldCount = @($AllMailboxes | Where-Object { $_.LitigationHoldEnabled -eq $true }).Count $ArchiveEnabled = @($AllMailboxes | Where-Object { $_.ArchiveStatus -ne 'None' }).Count $TotalMbx = @($AllMailboxes).Count # Most common deleted items retention $CommonRetention = $AllMailboxes | Group-Object -Property RetainDeletedItemsFor | Sort-Object Count -Descending | Select-Object -First 1 Section -Style Heading3 'Tenant Recovery Configuration' { Paragraph "The following summarises the recovery configuration across $TotalMbx mailbox(es) in tenant $TenantId." BlankLine $TrcObj = [System.Collections.ArrayList]::new() $trcInObj = [ordered] @{ 'Total Mailboxes' = $TotalMbx 'Single Item Recovery Enabled' = "$SirEnabled of $TotalMbx ($([math]::Round(($SirEnabled / [math]::Max($TotalMbx,1)) * 100, 0))%)" 'Litigation Hold Active' = "$LitHoldCount of $TotalMbx" 'Archive Mailbox Enabled' = "$ArchiveEnabled of $TotalMbx ($([math]::Round(($ArchiveEnabled / [math]::Max($TotalMbx,1)) * 100, 0))%)" 'Most Common Deleted Item Retention' = if ($CommonRetention) { "$($CommonRetention.Name) ($($CommonRetention.Count) mailboxes)" } else { 'Unknown' } } $TrcObj.Add([pscustomobject]$trcInObj) | Out-Null $TrcTableParams = @{ Name = "Recovery Configuration Summary - $TenantId"; List = $true; ColumnWidths = 45, 55 } if ($Report.ShowTableCaptions) { $TrcTableParams['Caption'] = "- $($TrcTableParams.Name)" } $TrcObj | Table @TrcTableParams } } catch { Write-ExoError 'Recovery' "Unable to retrieve recovery configuration: $($_.Exception.Message)" } #endregion #region RPO/RTO Summary Section -Style Heading3 'Recovery Objectives' { Paragraph "The following documents the native recovery objectives for Exchange Online in tenant $TenantId. NOTE: Third-party backup solutions may provide additional RPO/RTO capabilities." BlankLine $RpoObj = [System.Collections.ArrayList]::new() $rpoRows = @( [pscustomobject]@{ 'Scenario'='Accidental email deletion (user recovers)'; 'RPO'='0 (immediate)'; 'RTO'='Minutes (self-service)'; 'Method'='Recover Deleted Items in Outlook/OWA' } [pscustomobject]@{ 'Scenario'='Accidental purge from Recoverable Items'; 'RPO'='Up to 14 days'; 'RTO'='Hours (admin via eDisc)'; 'Method'='Content Search / eDiscovery export' } [pscustomobject]@{ 'Scenario'='Mailbox corruption / accidental bulk delete'; 'RPO'='Up to 14-30 days'; 'RTO'='Hours to days'; 'Method'='eDiscovery, Litigation Hold restore' } [pscustomobject]@{ 'Scenario'='Ransomware / malicious deletion'; 'RPO'='Point of Litigation Hold / archive'; 'RTO'='Days'; 'Method'='eDiscovery, Microsoft support, third-party backup' } [pscustomobject]@{ 'Scenario'='Microsoft datacentre failure'; 'RPO'='Near-zero (geo-redundant)'; 'RTO'='Per Microsoft SLA (99.9% uptime)'; 'Method'='Automatic failover (Microsoft managed)' } ) foreach ($row in $rpoRows) { $RpoObj.Add($row) | Out-Null } $RpoTableParams = @{ Name = "Recovery Objectives - $TenantId"; List = $false; ColumnWidths = 28, 14, 18, 40 } if ($Report.ShowTableCaptions) { $RpoTableParams['Caption'] = "- $($RpoTableParams.Name)" } if ($RpoObj.Count -gt 0) { $RpoObj | Table @RpoTableParams } } #endregion #region Third-Party Backup Note Section -Style Heading3 'Third-Party Backup Assessment' { Paragraph "Microsoft Exchange Online does not provide a traditional tape or snapshot backup. For organisations requiring point-in-time recovery beyond native capabilities (particularly for ransomware recovery, accidental bulk deletes, or regulatory requirements), a third-party backup solution is recommended." BlankLine Paragraph "Third-party backup solutions commonly used with Microsoft 365 include: Veeam Backup for Microsoft 365, Druva inSync, Acronis Cyber Cloud, Barracuda Cloud-to-Cloud Backup, and AvePoint Cloud Backup." BlankLine Paragraph "RECOMMENDATION: Review whether the organisation's backup and recovery strategy requirements are met by native Microsoft 365 capabilities alone, or whether a third-party backup solution should be implemented. Document the decision and review annually." } #endregion } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'Recovery' } } |