From 6ad0bd321cf975981a5e54a4b331c0352076fe3e Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Wed, 31 May 2023 22:01:22 -0400 Subject: [PATCH] Add HealthCheck Recommendations #100 --- AsBuiltReport.Veeam.VBR.psd1 | 2 +- AsBuiltreport.Veeam.VBR.json | 4 +- CHANGELOG.md | 16 ++++++ Src/Private/Get-AbrVbrBackupRepository.ps1 | 6 ++ Src/Private/Get-AbrVbrBackupServerInfo.ps1 | 12 +++- Src/Private/Get-AbrVbrBackupjob.ps1 | 7 ++- Src/Private/Get-AbrVbrBackupjobHyperV.ps1 | 2 +- Src/Private/Get-AbrVbrBackupjobVMware.ps1 | 12 +++- .../Get-AbrVbrConfigurationBackupSetting.ps1 | 14 +++++ .../Get-AbrVbrEmailNotificationSetting.ps1 | 10 +++- .../Get-AbrVbrEnterpriseManagerInfo.ps1 | 8 +++ Src/Private/Get-AbrVbrObjectRepository.ps1 | 55 ++++++++++++------- Src/Private/Get-AbrVbrReplFailoverPlan.ps1 | 4 ++ Src/Private/Get-AbrVbrReplReplica.ps1 | 12 +++- Src/Private/Get-AbrVbrRepljobHyperV.ps1 | 2 +- Src/Private/Get-AbrVbrRepljobVMware.ps1 | 2 +- Src/Private/Get-AbrVbrScaleOutRepository.ps1 | 36 +++++++++--- Src/Public/Invoke-AsBuiltReport.Veeam.VBR.ps1 | 13 +++-- 18 files changed, 172 insertions(+), 45 deletions(-) diff --git a/AsBuiltReport.Veeam.VBR.psd1 b/AsBuiltReport.Veeam.VBR.psd1 index 90608e2..fdc76b3 100644 --- a/AsBuiltReport.Veeam.VBR.psd1 +++ b/AsBuiltReport.Veeam.VBR.psd1 @@ -12,7 +12,7 @@ RootModule = 'AsBuiltReport.Veeam.VBR.psm1' # Version number of this module. -ModuleVersion = '0.7.1' +ModuleVersion = '0.7.2' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/AsBuiltreport.Veeam.VBR.json b/AsBuiltreport.Veeam.VBR.json index a636c06..3d9ae14 100644 --- a/AsBuiltreport.Veeam.VBR.json +++ b/AsBuiltreport.Veeam.VBR.json @@ -91,7 +91,9 @@ "Tenants": true, "BackupStorage": true, "ReplicaResources": true + }, + "Jobs": { + "Status": true } - } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f8d700..41dd705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # :arrows_clockwise: Veeam VBR As Built Report Changelog +## [0.7.2] - 2023-05-30 + +### Added + +- Added HealthCheck recommendations +- Added Global Notification options + +### Changed + +- Visually improved the Backup Window Time Period table + +### Fixed + +- Fix [#99](https://github.com/AsBuiltReport/AsBuiltReport.Veeam.VBR/issues/99) +- Fix [#100](https://github.com/AsBuiltReport/AsBuiltReport.Veeam.VBR/issues/100) + ## [0.7.1] - 2023-03-07 ### Changed diff --git a/Src/Private/Get-AbrVbrBackupRepository.ps1 b/Src/Private/Get-AbrVbrBackupRepository.ps1 index 2eb1edc..2d3b076 100644 --- a/Src/Private/Get-AbrVbrBackupRepository.ps1 +++ b/Src/Private/Get-AbrVbrBackupRepository.ps1 @@ -166,6 +166,7 @@ function Get-AbrVbrBackupRepository { $OutObj += [pscustomobject]$inobj if ($HealthCheck.Infrastructure.BR) { + $OutObj | Where-Object { $_.'Immutability Supported' -eq 'Yes' } | Set-Style -Style OK -Property 'Immutability Supported' $OutObj | Where-Object { $_.'Immutability Supported' -eq 'Yes' -and $_.'Immutability Enabled' -eq 'No' } | Set-Style -Style Warning -Property 'Immutability Enabled' } @@ -178,6 +179,11 @@ function Get-AbrVbrBackupRepository { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + + if (($HealthCheck.Infrastructure.BestPractice) -and ($OutObj | Where-Object { $_.'Immutability Supported' -eq 'Yes' -and $_.'Immutability Enabled' -eq 'No' })) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Veeam recommend to implement Immutability where it is supported. It is done for increased security: immutability protects your data from loss as a result of attacks, malware activity or any other injurious actions." -Italic -Bold + } } } catch { diff --git a/Src/Private/Get-AbrVbrBackupServerInfo.ps1 b/Src/Private/Get-AbrVbrBackupServerInfo.ps1 index b3383aa..d086686 100644 --- a/Src/Private/Get-AbrVbrBackupServerInfo.ps1 +++ b/Src/Private/Get-AbrVbrBackupServerInfo.ps1 @@ -145,14 +145,14 @@ function Get-AbrVbrBackupServerInfo { 'BIOS Version' = $HWBIOS.Version 'Processor Manufacturer' = $HWCPU[0].Manufacturer 'Processor Model' = $HWCPU[0].Name - 'Number of CPU Cores' = $HWCPU[0].NumberOfCores - 'Number of Logical Cores' = $HWCPU[0].NumberOfLogicalProcessors + 'Number of CPU Cores' = ($HWCPU.NumberOfCores | Measure-Object -Sum).Sum + 'Number of Logical Cores' = ($HWCPU.NumberOfLogicalProcessors | Measure-Object -Sum).Sum 'Physical Memory (GB)' = ConvertTo-FileSizeString $HW.CsTotalPhysicalMemory } $OutObj += [pscustomobject]$inobj if ($HealthCheck.Infrastructure.Server) { - $OutObj | Where-Object { $_.'Number of CPU Cores' -lt 4} | Set-Style -Style Warning -Property 'Number of CPU Cores' + $OutObj | Where-Object { $_.'Number of CPU Cores' -lt 2} | Set-Style -Style Warning -Property 'Number of CPU Cores' if ([int]([regex]::Matches($OutObj.'Physical Memory (GB)', "\d+(?!.*\d+)").value) -lt 8) { $OutObj | Set-Style -Style Warning -Property 'Physical Memory (GB)' } } @@ -165,6 +165,12 @@ function Get-AbrVbrBackupServerInfo { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if ($HealthCheck.Infrastructure.BestPractice) { + if (([int]([regex]::Matches($OutObj.'Physical Memory (GB)', "\d+(?!.*\d+)").value) -lt 8) -or ($OutObj | Where-Object { $_.'Number of CPU Cores' -lt 2})) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Recommended Veeam Backup Server minimum configuration is two CPU cores and 8GB RAM." -Italic -Bold + } + } #---------------------------------------------------------------------------------------------# # Backup Server Local Disk Inventory Section # #---------------------------------------------------------------------------------------------# diff --git a/Src/Private/Get-AbrVbrBackupjob.ps1 b/Src/Private/Get-AbrVbrBackupjob.ps1 index 175a393..dbe8b44 100644 --- a/Src/Private/Get-AbrVbrBackupjob.ps1 +++ b/Src/Private/Get-AbrVbrBackupjob.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrBackupjob { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -53,6 +53,11 @@ function Get-AbrVbrBackupjob { } } + if ($HealthCheck.Jobs.Status) { + $OutObj | Where-Object { $_.'Latest Result' -eq 'Failed' } | Set-Style -Style Critical -Property 'Latest Result' + $OutObj | Where-Object { $_.'Latest Result' -eq 'Warning' } | Set-Style -Style Warning -Property 'Latest Result' + } + $TableParams = @{ Name = "Backup Jobs - $VeeamBackupServer" List = $false diff --git a/Src/Private/Get-AbrVbrBackupjobHyperV.ps1 b/Src/Private/Get-AbrVbrBackupjobHyperV.ps1 index d06bbce..32ec841 100644 --- a/Src/Private/Get-AbrVbrBackupjobHyperV.ps1 +++ b/Src/Private/Get-AbrVbrBackupjobHyperV.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrBackupjobHyperV { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux diff --git a/Src/Private/Get-AbrVbrBackupjobVMware.ps1 b/Src/Private/Get-AbrVbrBackupjobVMware.ps1 index 3ed758a..66a0f94 100644 --- a/Src/Private/Get-AbrVbrBackupjobVMware.ps1 +++ b/Src/Private/Get-AbrVbrBackupjobVMware.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrBackupjobVMware { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -405,6 +405,10 @@ function Get-AbrVbrBackupjobVMware { } $OutObj = [pscustomobject]$inobj + if ($HealthCheck.Jobs.BestPractice) { + $OutObj | Where-Object { $_.'Enabled Backup File Encryption' -eq 'No'} | Set-Style -Style Warning -Property 'Enabled Backup File Encryption' + } + $TableParams = @{ Name = "Advanced Settings (Storage) - $($Bkjob.Name)" List = $true @@ -414,6 +418,12 @@ function Get-AbrVbrBackupjobVMware { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if ($HealthCheck.Jobs.BestPractice) { + if ($OutObj | Where-Object { $_.'Enabled Backup File Encryption' -eq 'No'}) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Backup and replica data is a high potential source of vulnerability. To secure data stored in backups and replicas, use Veeam Backup & Replication inbuilt encryption to protect data in backups" -Italic -Bold + } + } } catch { Write-PscriboMessage -IsWarning $_.Exception.Message diff --git a/Src/Private/Get-AbrVbrConfigurationBackupSetting.ps1 b/Src/Private/Get-AbrVbrConfigurationBackupSetting.ps1 index d63d805..90fe379 100644 --- a/Src/Private/Get-AbrVbrConfigurationBackupSetting.ps1 +++ b/Src/Private/Get-AbrVbrConfigurationBackupSetting.ps1 @@ -80,6 +80,20 @@ function Get-AbrVbrConfigurationBackupSetting { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if ($HealthCheck.Infrastructure.BestPractice) { + if ($OutObj | Where-Object { $_.'Encryption Enabled' -like 'No' -or $_.'Run Job Automatically' -like 'No' -or $_.'Enabled' -like 'No' }) { + Paragraph "Health Check:" -Italic -Bold -Underline + if ($OutObj | Where-Object { $_.'Encryption Enabled' -like 'No'} ) { + Paragraph "Best Practice: Whenever possible, enable configuration backup encryption." -Italic -Bold + } + if ($OutObj | Where-Object { $_.'Run Job Automatically' -like 'No'}) { + Paragraph "Best Practice: It`s a recommended best practice to activate the 'Run job automatically' option of the Backup Configuration job." -Italic -Bold + } + if ($OutObj | Where-Object { $_.'Enabled' -like 'No'}) { + Paragraph "Best Practice: It`s a recommended best practice to enable the Backup Configuration j ob" -Italic -Bold + } + } + } } } } diff --git a/Src/Private/Get-AbrVbrEmailNotificationSetting.ps1 b/Src/Private/Get-AbrVbrEmailNotificationSetting.ps1 index 27c7a1d..5c7ba00 100644 --- a/Src/Private/Get-AbrVbrEmailNotificationSetting.ps1 +++ b/Src/Private/Get-AbrVbrEmailNotificationSetting.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrEmailNotificationSetting { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -26,10 +26,10 @@ function Get-AbrVbrEmailNotificationSetting { process { try { - if ((Get-VBRMailNotificationConfiguration).count -gt 0) { + $EmailSettings = Get-VBRMailNotificationConfiguration + if ($EmailSettings) { Section -Style Heading4 'Email Notification' { $OutObj = @() - $EmailSettings = Get-VBRMailNotificationConfiguration foreach ($EmailSetting in $EmailSettings) { $inObj = [ordered] @{ 'Email Recipient' = $EmailSetting.Recipient @@ -63,6 +63,10 @@ function Get-AbrVbrEmailNotificationSetting { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if ($HealthCheck.Infrastructure.BestPractice -and ($OutObj | Where-Object { $_.'Enabled' -eq 'No' })) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Veeam recommends configuring email notifications to be able to receive alerts with the results of jobs performed on the backup server." -Italic -Bold + } } } } diff --git a/Src/Private/Get-AbrVbrEnterpriseManagerInfo.ps1 b/Src/Private/Get-AbrVbrEnterpriseManagerInfo.ps1 index f170259..e6a142c 100644 --- a/Src/Private/Get-AbrVbrEnterpriseManagerInfo.ps1 +++ b/Src/Private/Get-AbrVbrEnterpriseManagerInfo.ps1 @@ -54,6 +54,10 @@ function Get-AbrVbrEnterpriseManagerInfo { if ($OutObj) { + if ($HealthCheck.Infrastructure.BackupServer) { + $OutObj | Where-Object { $_.'Skip License Push' -eq 'Yes' } | Set-Style -Style Warning -Property 'Skip License Push' + } + $TableParams = @{ Name = "Enterprise Manager - $($BackupServer.Name.Split(".")[0])" List = $true @@ -63,6 +67,10 @@ function Get-AbrVbrEnterpriseManagerInfo { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if ($HealthCheck.Infrastructure.BestPractice -and ($OutObj | Where-Object { $_.'Skip License Push' -eq 'Yes' })) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Veeam recommends centralized license management through Enterprise Manager." -Italic -Bold + } } } } diff --git a/Src/Private/Get-AbrVbrObjectRepository.ps1 b/Src/Private/Get-AbrVbrObjectRepository.ps1 index 57b4f62..0772170 100644 --- a/Src/Private/Get-AbrVbrObjectRepository.ps1 +++ b/Src/Private/Get-AbrVbrObjectRepository.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrObjectRepository { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -110,6 +110,7 @@ function Get-AbrVbrObjectRepository { 'Type' = ($ObjectRepo).Type 'Amazon S3 Folder' = ($ObjectRepo).AmazonS3Folder 'Immutability Period' = $ObjectRepo.ImmutabilityPeriod + 'Immutability Enabled'= ConvertTo-TextYN $ObjectRepo.BackupImmutabilityEnabled 'Size Limit Enabled' = ConvertTo-TextYN ($ObjectRepo).SizeLimitEnabled 'Size Limit' = ($ObjectRepo).SizeLimit @@ -138,6 +139,10 @@ function Get-AbrVbrObjectRepository { } $OutObj = [pscustomobject]$inobj + if ($HealthCheck.Infrastructure.BR) { + $OutObj | Where-Object { $_.'Immutability Enabled' -eq 'No' } | Set-Style -Style Warning -Property 'Immutability Enabled' + } + $TableParams = @{ Name = "Object Storage Repository - $($ObjectRepo.Name)" List = $true @@ -147,6 +152,10 @@ function Get-AbrVbrObjectRepository { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if (($HealthCheck.Infrastructure.BestPractice) -and ($OutObj | Where-Object { $_.'Immutability Enabled' -eq 'No' })) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Veeam recommend to implement Immutability where it is supported. It is done for increased security: immutability protects your data from loss as a result of attacks, malware activity or any other injurious actions." -Italic -Bold + } } } catch { @@ -182,33 +191,37 @@ function Get-AbrVbrObjectRepository { default {$ObjectRepoArchive.GatewayServer.Name.split(".")[0]} } 'Gateway Server Enabled' = ConvertTo-TextYN $ObjectRepoArchive.UseGatewayServer + 'Immutability Enabled' = ConvertTo-TextYN $ObjectRepoArchive.BackupImmutabilityEnabled 'Archive Type' = $ObjectRepoArchive.ArchiveType } if ($ObjectRepoArchive.ArchiveType -eq 'AmazonS3Glacier') { - $inObj.add('AWS Deep Archive', (ConvertTo-TextYN $ObjectRepoArchive.UseDeepArchive)) - $inObj.add('AWS Backup Immutability', (ConvertTo-TextYN ($ObjectRepoArchive.BackupImmutabilityEnabled))) - $inObj.add('AWS Proxy Instance Type', $ObjectRepoArchive.AmazonProxySpec.InstanceType) - $inObj.add('AWS Proxy Instance vCPU', $ObjectRepoArchive.AmazonProxySpec.InstanceType.vCPUs) - $inObj.add('AWS Proxy Instance Memory', ([Math]::Round($ObjectRepoArchive.AmazonProxySpec.InstanceType.Memory*1MB/1GB))) - $inObj.add('AWS Proxy Subnet', $ObjectRepoArchive.AmazonProxySpec.Subnet) - $inObj.add('AWS Proxy Security Group', $ObjectRepoArchive.AmazonProxySpec.SecurityGroup) - $inObj.add('AWS Proxy Availability Zone', $ObjectRepoArchive.AmazonProxySpec.Subnet.AvailabilityZone) + $inObj.add('Deep Archive', (ConvertTo-TextYN $ObjectRepoArchive.UseDeepArchive)) + $inObj.add('Proxy Instance Type', $ObjectRepoArchive.AmazonProxySpec.InstanceType) + $inObj.add('Proxy Instance vCPU', $ObjectRepoArchive.AmazonProxySpec.InstanceType.vCPUs) + $inObj.add('Proxy Instance Memory', ([Math]::Round($ObjectRepoArchive.AmazonProxySpec.InstanceType.Memory*1MB/1GB))) + $inObj.add('Proxy Subnet', $ObjectRepoArchive.AmazonProxySpec.Subnet) + $inObj.add('Proxy Security Group', $ObjectRepoArchive.AmazonProxySpec.SecurityGroup) + $inObj.add('Proxy Availability Zone', $ObjectRepoArchive.AmazonProxySpec.Subnet.AvailabilityZone) } elseif ($ObjectRepoArchive.ArchiveType -eq 'AzureArchive') { - $inObj.add('Azure Service Type', $ObjectRepoArchive.AzureBlobFolder.ServiceType) - $inObj.add('Azure Archive Container', $ObjectRepoArchive.AzureBlobFolder.Container) - $inObj.add('Azure Archive Folder', $ObjectRepoArchive.AzureBlobFolder.Name) - $inObj.add('Azure Proxy Resource Group', $ObjectRepoArchive.AzureProxySpec.ResourceGroup) - $inObj.add('Azure Proxy Network', $ObjectRepoArchive.AzureProxySpec.Network) - $inObj.add('Azure Proxy VM Size', $ObjectRepoArchive.AzureProxySpec.VMSize) - $inObj.add('Azure Proxy VM vCPU', $ObjectRepoArchive.AzureProxySpec.VMSize.Cores) - $inObj.add('Azure Proxy VM Memory', ([Math]::Round($ObjectRepoArchive.AzureProxySpec.VMSize.Memory*1MB/1GB))) - $inObj.add('Azure Proxy VM Max Disks', $ObjectRepoArchive.AzureProxySpec.VMSize.MaxDisks) - $inObj.add('Azure Proxy VM Location', $ObjectRepoArchive.AzureProxySpec.VMSize.Location) + $inObj.add('Service Type', $ObjectRepoArchive.AzureBlobFolder.ServiceType) + $inObj.add('Archive Container', $ObjectRepoArchive.AzureBlobFolder.Container) + $inObj.add('Archive Folder', $ObjectRepoArchive.AzureBlobFolder.Name) + $inObj.add('Proxy Resource Group', $ObjectRepoArchive.AzureProxySpec.ResourceGroup) + $inObj.add('Proxy Network', $ObjectRepoArchive.AzureProxySpec.Network) + $inObj.add('Proxy VM Size', $ObjectRepoArchive.AzureProxySpec.VMSize) + $inObj.add('Proxy VM vCPU', $ObjectRepoArchive.AzureProxySpec.VMSize.Cores) + $inObj.add('Proxy VM Memory', ([Math]::Round($ObjectRepoArchive.AzureProxySpec.VMSize.Memory*1MB/1GB))) + $inObj.add('Proxy VM Max Disks', $ObjectRepoArchive.AzureProxySpec.VMSize.MaxDisks) + $inObj.add('Proxy VM Location', $ObjectRepoArchive.AzureProxySpec.VMSize.Location) } $OutObj += [pscustomobject]$inobj + if ($HealthCheck.Infrastructure.BR) { + $OutObj | Where-Object { $_.'Immutability Enabled' -eq 'No' } | Set-Style -Style Warning -Property 'Immutability Enabled' + } + $TableParams = @{ Name = "Archive Object Storage Repository - $($ObjectRepoArchive.Name)" List = $true @@ -218,6 +231,10 @@ function Get-AbrVbrObjectRepository { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams + if (($HealthCheck.Infrastructure.BestPractice) -and ($OutObj | Where-Object { $_.'Immutability Enabled' -eq 'No'})) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Veeam recommend to implement Immutability where it is supported. It is done for increased security: immutability protects your data from loss as a result of attacks, malware activity or any other injurious actions." -Italic -Bold + } } } catch { diff --git a/Src/Private/Get-AbrVbrReplFailoverPlan.ps1 b/Src/Private/Get-AbrVbrReplFailoverPlan.ps1 index 4177f22..757ca6c 100644 --- a/Src/Private/Get-AbrVbrReplFailoverPlan.ps1 +++ b/Src/Private/Get-AbrVbrReplFailoverPlan.ps1 @@ -45,6 +45,10 @@ function Get-AbrVbrReplFailoverPlan { } $OutObj = [pscustomobject]$inobj + if ($HealthCheck.Replication.FailoverPlan) { + $OutObj | Where-Object { $_.'Status' -ne 'Ready' } | Set-Style -Style Warning -Property 'Status' + } + $TableParams = @{ Name = "Failover Plan - $($FailOverPlan.Name)" List = $true diff --git a/Src/Private/Get-AbrVbrReplReplica.ps1 b/Src/Private/Get-AbrVbrReplReplica.ps1 index 5d1d5a6..6f208ca 100644 --- a/Src/Private/Get-AbrVbrReplReplica.ps1 +++ b/Src/Private/Get-AbrVbrReplReplica.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrReplReplica { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -39,12 +39,16 @@ function Get-AbrVbrReplReplica { 'VM Name' = $VM.VmName 'Job Name' = $Replica.JobName 'Type' = $Replica.TypeToString - 'Restore Points' = ($VM | Get-VBRRestorePoint).count + 'State' = $VM.State } $OutObj += [pscustomobject]$inobj } } + if ($HealthCheck.Replication.Replica) { + $OutObj | Where-Object { $_.'State' -ne 'Ready' } | Set-Style -Style Warning -Property 'State' + } + $TableParams = @{ Name = "Replicas - $VeeamBackupServer" List = $false @@ -79,6 +83,10 @@ function Get-AbrVbrReplReplica { } $OutObj = [pscustomobject]$inobj + if ($HealthCheck.Replication.Replica) { + $OutObj | Where-Object { $_.'State' -ne 'Ready' } | Set-Style -Style Warning -Property 'State' + } + $TableParams = @{ Name = "$($Replica.JobName) - $($VM.VmName)" List = $true diff --git a/Src/Private/Get-AbrVbrRepljobHyperV.ps1 b/Src/Private/Get-AbrVbrRepljobHyperV.ps1 index 3eb9bd0..be8d0c4 100644 --- a/Src/Private/Get-AbrVbrRepljobHyperV.ps1 +++ b/Src/Private/Get-AbrVbrRepljobHyperV.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrRepljobHyperV { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux diff --git a/Src/Private/Get-AbrVbrRepljobVMware.ps1 b/Src/Private/Get-AbrVbrRepljobVMware.ps1 index 00ccd4f..6eadefb 100644 --- a/Src/Private/Get-AbrVbrRepljobVMware.ps1 +++ b/Src/Private/Get-AbrVbrRepljobVMware.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrRepljobVMware { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux diff --git a/Src/Private/Get-AbrVbrScaleOutRepository.ps1 b/Src/Private/Get-AbrVbrScaleOutRepository.ps1 index b75fb00..68433e6 100644 --- a/Src/Private/Get-AbrVbrScaleOutRepository.ps1 +++ b/Src/Private/Get-AbrVbrScaleOutRepository.ps1 @@ -6,7 +6,7 @@ function Get-AbrVbrScaleOutRepository { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -89,7 +89,7 @@ function Get-AbrVbrScaleOutRepository { 'Use Per VM Backup Files' = ConvertTo-TextYN $BackupRepo.UsePerVMBackupFiles 'Perform Full When Extent Offline' = ConvertTo-TextYN $BackupRepo.PerformFullWhenExtentOffline 'Use Capacity Tier' = ConvertTo-TextYN $BackupRepo.EnableCapacityTier - 'Encryption Enabled' = ConvertTo-TextYN $BackupRepo.EncryptionEnabled + 'Encrypt data uploaded to Object Storage' = ConvertTo-TextYN $BackupRepo.EncryptionEnabled 'Encryption Key' = Switch ($BackupRepo.EncryptionKey.Description) { $null {'Disabled'} default {$BackupRepo.EncryptionKey.Description} @@ -98,7 +98,7 @@ function Get-AbrVbrScaleOutRepository { 'Override Policy Enabled' = ConvertTo-TextYN $BackupRepo.OverridePolicyEnabled 'Override Space Threshold' = $BackupRepo.OverrideSpaceThreshold 'Use Archive GFS Tier' = ConvertTo-TextYN $BackupRepo.ArchiveTierEnabled - 'Archive GFS Backup older than' = $BackupRepo.ArchivePeriod + 'Archive GFS Backup older than' = "$($BackupRepo.ArchivePeriod) days" 'Store archived backup as standalone fulls' = ConvertTo-TextYN $BackupRepo.ArchiveFullBackupModeEnabled 'Cost Optimized Archive Enabled' = ConvertTo-TextYN $BackupRepo.CostOptimizedArchiveEnabled 'Description' = $BackupRepo.Description @@ -106,6 +106,10 @@ function Get-AbrVbrScaleOutRepository { $OutObj = [pscustomobject]$inobj + if ($HealthCheck.Infrastructure.Settings) { + $OutObj | Where-Object { $_.'Encrypt data uploaded to Object Storage' -like 'No'} | Set-Style -Style Warning -Property 'Encrypt data uploaded to Object Storage' + } + $TableParams = @{ Name = "General Settings - $($BackupRepo.Name)" List = $true @@ -117,6 +121,10 @@ function Get-AbrVbrScaleOutRepository { } $OutObj | Table @TableParams + if (($HealthCheck.Infrastructure.BestPractice) -and ($OutObj | Where-Object { $_.'Encrypt data uploaded to Object Storage' -like 'No'})) { + Paragraph "Health Check:" -Italic -Bold -Underline + Paragraph "Best Practice: Veeam Backup & Replication allows you to encrypt offloaded data. With the Encrypt data uploaded to object storage setting selected, the entire collection of blocks along with the metadata will be encrypted while being offloaded regardless of the jobs encryption settings. This helps you protect the data from an unauthorized access." -Italic -Bold + } } } catch { @@ -139,6 +147,11 @@ function Get-AbrVbrScaleOutRepository { 'Status' = $Extent.Status } $OutObj += [pscustomobject]$inobj + + if ($HealthCheck.Infrastructure.Settings) { + $OutObj | Where-Object { $_.'Status' -ne 'Normal'} | Set-Style -Style Warning -Property 'Status' + } + $TableParams = @{ Name = "Performance Tier - $($Extent.Name)" List = $true @@ -173,6 +186,7 @@ function Get-AbrVbrScaleOutRepository { default {($CapacityExtent.Repository).GatewayServer.Name} } 'Immutability Period' = $CapacityExtent.Repository.ImmutabilityPeriod + 'Immutability Enabled'= ConvertTo-TextYN $CapacityExtent.Repository.BackupImmutabilityEnabled 'Size Limit Enabled' = ConvertTo-TextYN ($CapacityExtent.Repository).SizeLimitEnabled 'Size Limit' = ($CapacityExtent.Repository).SizeLimit } @@ -183,12 +197,16 @@ function Get-AbrVbrScaleOutRepository { } elseif (($CapacityExtent.Repository).Type -eq 'AzureBlob') { $inObj.remove('Service Point') $inObj.remove('Amazon S3 Folder') - $inObj.remove('Immutability Period') $inObj.add('Azure Blob Name', ($CapacityExtent.Repository.AzureBlobFolder).Name) $inObj.add('Azure Blob Container', ($CapacityExtent.Repository.AzureBlobFolder).Container) } $OutObj += [pscustomobject]$inobj + + if ($HealthCheck.Infrastructure.SOBR) { + $OutObj | Where-Object { $_.'Immutability Enabled' -eq 'No' } | Set-Style -Style Warning -Property 'Immutability Enabled' + } + $TableParams = @{ Name = "Capacity Tier - $(($CapacityExtent.Repository).Name)" List = $true @@ -220,16 +238,20 @@ function Get-AbrVbrScaleOutRepository { 0 {"Auto"} default {($ArchiveExtent.Repository).GatewayServer.Name} } + 'Immutability Enabled' = ConvertTo-TextYN $ArchiveExtent.Repository.BackupImmutabilityEnabled } - if (($ArchiveExtent.Repository).ArchiveType -eq 'AmazonS3Glacier') { - $inObj.add('Backup Immutability Enabled', (ConvertTo-TextYN ($ArchiveExtent.Repository).BackupImmutabilityEnabled)) - } elseif (($ArchiveExtent.Repository).ArchiveType -eq 'AzureArchive') { + if (($ArchiveExtent.Repository).ArchiveType -eq 'AzureArchive') { $inObj.add('Azure Service Type', ($ArchiveExtent.Repository.AzureBlobFolder).ServiceType) $inObj.add('Azure Blob Name', ($ArchiveExtent.Repository.AzureBlobFolder).Name) $inObj.add('Azure Blob Container', ($ArchiveExtent.Repository.AzureBlobFolder).Container) } $OutObj += [pscustomobject]$inobj + + if ($HealthCheck.Infrastructure.SOBR) { + $OutObj | Where-Object { $_.'Immutability Enabled' -eq 'No' } | Set-Style -Style Warning -Property 'Immutability Enabled' + } + $TableParams = @{ Name = "Archive Tier - $(($ArchiveExtent.Repository).Name)" List = $true diff --git a/Src/Public/Invoke-AsBuiltReport.Veeam.VBR.ps1 b/Src/Public/Invoke-AsBuiltReport.Veeam.VBR.ps1 index 989cfac..5e7c768 100644 --- a/Src/Public/Invoke-AsBuiltReport.Veeam.VBR.ps1 +++ b/Src/Public/Invoke-AsBuiltReport.Veeam.VBR.ps1 @@ -5,7 +5,7 @@ function Invoke-AsBuiltReport.Veeam.VBR { .DESCRIPTION Documents the configuration of Veeam VBR in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.7.1 + Version: 0.7.2 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -65,9 +65,11 @@ function Invoke-AsBuiltReport.Veeam.VBR { Section -Style Heading2 'Backup Infrastructure' { Paragraph "The following section details configuration information about the Backup Server: $($VeeamBackupServer)" BlankLine - Get-AbrVbrInfrastructureSummary - Get-AbrVbrBackupServerInfo - Get-AbrVbrEnterpriseManagerInfo + if ($InfoLevel.Infrastructure.BackupServer -ge 1) { + Get-AbrVbrInfrastructureSummary + Get-AbrVbrBackupServerInfo + Get-AbrVbrEnterpriseManagerInfo + } Write-PScriboMessage "Infrastructure Licenses InfoLevel set at $($InfoLevel.Infrastructure.Licenses)." if ($InfoLevel.Infrastructure.Licenses -ge 1) { Get-AbrVbrInstalledLicense @@ -79,15 +81,18 @@ function Invoke-AsBuiltReport.Veeam.VBR { BlankLine Get-AbrVbrConfigurationBackupSetting Get-AbrVbrEmailNotificationSetting + Get-AbrVbrGlobalNotificationSetting Get-AbrVbrIOControlSetting Get-AbrVbrBackupServerCertificate Get-AbrVbrNetworkTrafficRule } } + Get-AbrVbrUserRoleAssignment Get-AbrVbrCredential Get-AbrVbrLocation Get-AbrVbrManagedServer + Write-PScriboMessage "Infrastructure Backup Proxy InfoLevel set at $($InfoLevel.Infrastructure.Proxy)." if ($InfoLevel.Infrastructure.Proxy -ge 1) { Get-AbrVbrBackupProxy