Private/Backup/Find-BackupFile.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Discovers and inventories ACL backup files with comprehensive filtering and metadata extraction .DESCRIPTION This module provides specialized functionality for discovering backup files in enterprise environments with advanced filtering capabilities, comprehensive metadata extraction, and performance optimization for large backup repositories. Designed for backup lifecycle management and disaster recovery planning. BUSINESS VALUE: - Enables comprehensive backup inventory and lifecycle management - Supports automated backup retention and cleanup policies - Facilitates disaster recovery planning with intelligent backup discovery - Provides detailed backup analytics for governance and compliance ENTERPRISE FEATURES: - High-performance recursive directory searching - Advanced filtering by object DN patterns and date ranges - Comprehensive metadata extraction with integrity validation - Performance optimization for large backup repositories - Integration with enterprise monitoring and reporting systems .NOTES Author: Jeffrey Stuhr Blog: https://www.techbyjeff.net LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/ DEPENDENCIES: - Requires PowerShell 5.1 or later - Depends on Get-BackupFileMetadata for metadata extraction - Integrates with Write-StructuredLog for audit logging SECURITY CONSIDERATIONS: - Validates directory paths to prevent unauthorized access - Implements comprehensive input validation and sanitization - Provides secure file system traversal with error recovery - Tracks correlation IDs for complete audit trails PERFORMANCE CHARACTERISTICS: - Directory Scanning: Optimized for large repositories (10,000+ files) - Filtering Operations: Efficient pattern matching and date range filtering - Memory Usage: Stream-based processing to minimize memory footprint - Parallel Processing: Designed for scalability in enterprise environments TROUBLESHOOTING: - For performance issues: .\Troubleshooting\Performance\Backup-Optimization.md - For search problems: .\Troubleshooting\Common\Backup-Issues.md - For file access issues: .\Troubleshooting\Security\File-Access-Issues.md #> function Find-BackupFile { <# .SYNOPSIS Discovers and inventories backup files in specified directories .DESCRIPTION Searches for backup files matching specified criteria and provides comprehensive inventory information including metadata extraction, integrity status, and organization by object or date. This function is optimized for enterprise environments with large backup repositories. Features comprehensive filtering capabilities including object DN pattern matching, date range filtering, and metadata validation to support backup lifecycle management and disaster recovery planning. .PARAMETER BackupPath The directory path to search for backup files. Must be a valid directory path accessible to the current user context. .PARAMETER ObjectDN Optional filter to find backups for specific objects using wildcard patterns. Supports standard PowerShell wildcard syntax (* and ?). .PARAMETER DateRange Optional hashtable containing StartDate and/or EndDate properties to filter backups by creation date range. Dates should be DateTime objects. .PARAMETER CorrelationId Unique identifier for tracking this operation across distributed systems and audit logs. Auto-generated if not provided. .EXAMPLE PS> Find-BackupFile -BackupPath "C:\Backups" DESCRIPTION: Discovers all backup files in the specified directory OUTPUT: Comprehensive inventory of all backup files with metadata USE CASE: Complete backup repository inventory .EXAMPLE PS> Find-BackupFile -BackupPath "C:\Backups" -ObjectDN "*OU=Sales*" DESCRIPTION: Finds all backup files for Sales organizational unit objects OUTPUT: Comprehensive inventory of matching backup files with metadata USE CASE: Backup management and disaster recovery planning .EXAMPLE PS> $dateRange = @{ StartDate = (Get-Date).AddDays(-30); EndDate = Get-Date } PS> Find-BackupFile -BackupPath "C:\Backups" -DateRange $dateRange DESCRIPTION: Finds backups created within the last 30 days OUTPUT: Recent backup files for retention policy analysis USE CASE: Backup lifecycle management and cleanup operations .OUTPUTS [PSCustomObject[]] Array of backup file information objects containing: - Complete metadata from Get-BackupFileMetadata - File system information and accessibility status - Integrity validation results - Discovery context and correlation tracking .NOTES Author: Jeffrey Stuhr Blog: https://www.techbyjeff.net LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/ DISCOVERY FEATURES: - Recursive directory searching with performance optimization - Pattern-based filtering for object DN matching - Date range filtering for backup lifecycle management - Metadata extraction with integrity validation - Error recovery for corrupted or inaccessible backup files FILTERING CAPABILITIES: - ObjectDN: Supports PowerShell wildcard patterns (* and ?) - DateRange: Flexible date filtering with StartDate and EndDate - File Validation: Automatic filtering of invalid or corrupted backups - Performance Optimization: Early filtering to minimize processing overhead ERROR HANDLING: - Graceful handling of inaccessible or corrupted backup files - Comprehensive error logging with correlation tracking - Continues processing when individual files cannot be processed - Provides detailed error context for troubleshooting PERFORMANCE CONSIDERATIONS: - Optimized for large backup repositories (10,000+ files) - Stream-based processing to minimize memory usage - Early filtering to reduce processing overhead - Efficient file system traversal with error recovery TROUBLESHOOTING: - For performance issues: .\Troubleshooting\Performance\Backup-Optimization.md - For search problems: .\Troubleshooting\Common\Backup-Issues.md - For filtering issues: .\Troubleshooting\Common\Search-Filter-Issues.md #> [CmdletBinding()] [OutputType('BackupInventoryResult')] param( [Parameter(ValueFromPipeline)] [string]$BackupPath, [Parameter()] [string]$ObjectDN, [Parameter()] [hashtable]$DateRange, [Parameter()] [string]$CorrelationId = [System.Guid]::NewGuid().ToString() ) begin { Write-StructuredLog "Starting backup file discovery operation" -Level Debug -CorrelationId $CorrelationId } process { try { # Validate input parameters if (-not $BackupPath -or -not $BackupPath.Trim()) { Write-Error "BackupPath cannot be empty or whitespace" -ErrorAction Stop return } # Validate DateRange format if provided (do this before path validation) if ($DateRange) { if ($DateRange.StartDate -and $DateRange.StartDate -isnot [DateTime]) { Write-Error "DateRange.StartDate must be a DateTime object" -ErrorAction Stop return } if ($DateRange.EndDate -and $DateRange.EndDate -isnot [DateTime]) { Write-Error "DateRange.EndDate must be a DateTime object" -ErrorAction Stop return } if ($DateRange.StartDate -and $DateRange.EndDate -and $DateRange.StartDate -gt $DateRange.EndDate) { Write-Error "DateRange.StartDate cannot be later than DateRange.EndDate" -ErrorAction Stop return } } $sanitizedPath = $BackupPath.Trim() Write-StructuredLog "Starting backup file discovery in: $sanitizedPath" -Level Debug -CorrelationId $CorrelationId # Validate directory existence and accessibility try { if (-not (Test-Path $sanitizedPath -PathType Container)) { $errorMessage = "Backup directory not found or inaccessible: $sanitizedPath" Write-StructuredLog $errorMessage -Level Error -CorrelationId $CorrelationId Write-Error $errorMessage -ErrorAction Stop return } } catch { # Handle path traversal and other path validation errors $errorMessage = "Backup directory not found or inaccessible: $sanitizedPath" Write-StructuredLog $errorMessage -Level Error -CorrelationId $CorrelationId Write-Error $errorMessage -ErrorAction Stop return } # Discover XML backup files with performance optimization Write-StructuredLog "Scanning directory for XML backup files: $sanitizedPath" -Level Verbose -CorrelationId $CorrelationId try { $backupFiles = Get-ChildItem -Path $sanitizedPath -Filter "*.xml" -Recurse -File -ErrorAction Stop } catch { $errorMessage = "Failed to scan backup directory $sanitizedPath : $($_.Exception.Message)" Write-StructuredLog $errorMessage -Level Error -CorrelationId $CorrelationId Write-Error $errorMessage -ErrorAction Stop return } Write-StructuredLog "Found $($backupFiles.Count) XML files for analysis" -Level Verbose -CorrelationId $CorrelationId # Process backup files with error recovery $results = @() $processedCount = 0 $errorCount = 0 foreach ($file in $backupFiles) { try { $processedCount++ Write-Progress -Activity "Processing backup files" -Status "Processing file $processedCount of $($backupFiles.Count)" -PercentComplete (($processedCount / $backupFiles.Count) * 100) # Extract metadata using the dedicated function $metadata = Get-BackupFileMetadata -BackupFilePath $file.FullName -CorrelationId $CorrelationId # Apply ObjectDN filter if specified if ($ObjectDN -and $metadata.ObjectDN -notlike $ObjectDN) { Write-Verbose "Skipping backup $($file.Name) - ObjectDN '$($metadata.ObjectDN)' does not match filter '$ObjectDN'" continue } # Apply date range filter if specified if ($DateRange) { try { $backupDate = [DateTime]::Parse($metadata.BackupDate) if ($DateRange.StartDate -and $backupDate -lt $DateRange.StartDate) { Write-Verbose "Skipping backup $($file.Name) - BackupDate '$backupDate' is before StartDate '$($DateRange.StartDate)'" continue } if ($DateRange.EndDate -and $backupDate -gt $DateRange.EndDate) { Write-Verbose "Skipping backup $($file.Name) - BackupDate '$backupDate' is after EndDate '$($DateRange.EndDate)'" continue } } catch { Write-StructuredLog "Failed to parse backup date for $($file.FullName): $($_.Exception.Message)" -Level Warning -CorrelationId $CorrelationId continue } } # Add discovery context to metadata $enrichedMetadata = [PSCustomObject]@{} # Copy all metadata properties $metadata.PSObject.Properties | ForEach-Object { $enrichedMetadata | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value } # Add discovery-specific properties $enrichedMetadata | Add-Member -NotePropertyName 'DiscoveryCorrelationId' -NotePropertyValue $CorrelationId $enrichedMetadata | Add-Member -NotePropertyName 'DiscoveryTime' -NotePropertyValue (Get-Date -Format 'yyyy-MM-ddTHH:mm:ss.fffZ') $enrichedMetadata | Add-Member -NotePropertyName 'FilteredByObjectDN' -NotePropertyValue ([bool]$ObjectDN) $enrichedMetadata | Add-Member -NotePropertyName 'FilteredByDateRange' -NotePropertyValue ([bool]$DateRange) # Set the PSTypeName properly $enrichedMetadata.PSObject.TypeNames.Insert(0, 'BackupInventoryResult') $results += $enrichedMetadata } catch { $errorCount++ Write-StructuredLog "Failed to process backup file $($file.FullName): $($_.Exception.Message)" -Level Warning -CorrelationId $CorrelationId continue } } Write-Progress -Activity "Processing backup files" -Completed $discoveryResults = @{ TotalFilesScanned = $backupFiles.Count ValidBackupsFound = $results.Count ProcessingErrors = $errorCount FilterApplied = [bool]($ObjectDN -or $DateRange) ObjectDNFilter = $ObjectDN DateRangeFilter = $DateRange } Write-StructuredLog "Backup discovery completed" -Level Verbose -Data $discoveryResults -CorrelationId $CorrelationId return ,$results } catch { $errorDetails = @{ Message = $_.Exception.Message Category = $_.CategoryInfo.Category TargetObject = $_.TargetObject CorrelationId = $CorrelationId Function = $MyInvocation.MyCommand.Name Line = $_.InvocationInfo.ScriptLineNumber BackupPath = $BackupPath ObjectDNFilter = $ObjectDN DateRangeFilter = $DateRange } Write-StructuredLog "Error during backup file discovery" -Level Error -Data $errorDetails -CorrelationId $CorrelationId Write-Error "Failed to discover backup files: $($_.Exception.Message)" -ErrorAction Stop } } end { Write-StructuredLog "Backup file discovery operation completed" -Level Debug -CorrelationId $CorrelationId } } |