From 43666001114d62dc7d055e0013db663c9a9cd7b3 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Mon, 24 Oct 2022 22:06:32 -0400 Subject: [PATCH 1/9] fix installed module verification --- ...Invoke-AsBuiltReport.Microsoft.Windows.ps1 | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 index 0645ed8..5bff960 100644 --- a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 +++ b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 @@ -27,16 +27,20 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PScriboMessage -IsWarning "Documentation: https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows" Write-PScriboMessage -IsWarning "Issues or bug reporting: https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues" - $InstalledVersion = Get-Module -ListAvailable -Name AsBuiltReport.Microsoft.Windows -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version + Try { + $InstalledVersion = Get-Module -ListAvailable -Name AsBuiltReport.Microsoft.Windows -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version - if ($InstalledVersion) { - Write-PScriboMessage -IsWarning "Installed AsBuiltReport.Microsoft.Windows Version: $($InstalledVersion.ToString())" - $MostCurrentVersion = Find-Module -Name AsBuiltReport.Microsoft.Windows -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version - if ($MostCurrentVersion -and ($MostCurrentVersion -gt $InstalledVersion)) { - Write-PScriboMessage -IsWarning "New Update: AsBuiltReport.Microsoft.Windows Version: $($MostCurrentVersion.ToString())" - Write-PScriboMessage -IsWarning "To Update run: Update-Module -Name AsBuiltReport.Microsoft.Windows -Force" + if ($InstalledVersion) { + Write-PScriboMessage -IsWarning "AsBuiltReport.Microsoft.Windows $($InstalledVersion.ToString()) is currently installed." + $LatestVersion = Find-Module -Name AsBuiltReport.Microsoft.Windows -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version + if ($LatestVersion -gt $InstalledVersion) { + Write-PScriboMessage -IsWarning "AsBuiltReport.Microsoft.Windows $($LatestVersion.ToString()) is available." + Write-PScriboMessage -IsWarning "Run 'Update-Module -Name AsBuiltReport.Microsoft.Windows -Force' to install the latest version." + } + } + } Catch { + Write-PscriboMessage -IsWarning $_.Exception.Message } - } # Import Report Configuration $Report = $ReportConfig.Report From db637352df591dce65a6b4a3b88f5a7e53e2ee4c Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Mon, 24 Oct 2022 22:12:07 -0400 Subject: [PATCH 2/9] updated changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e7b9a..d6c798a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # :arrows_counterclockwise: Microsoft Windows As Built Report Changelog +## [0.4.1] - 2022-10-XX + +### Fixed + +- Fixes [#8](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues/8) + ## [0.4.0] - 2022-10-20 ### Added From 520a3666aca25efd898f26ae09fc297435a739e9 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Mon, 31 Oct 2022 12:14:32 -0400 Subject: [PATCH 3/9] Fix #9 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81e0863..3abcfbf 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ The Microsoft Windows As Built Report utilises a JSON file to allow configuratio A Microsoft Windows report configuration file can be generated by executing the following command; ```powershell -New-AsBuiltReportConfig -Report AsBuiltReport.Microsoft.Windows -FolderPath -Filename +New-AsBuiltReportConfig -Report Microsoft.Windows -FolderPath -Filename ``` Executing this command will copy the default Microsoft Windows report JSON configuration to a user specified folder. From be9acfc1e77ec7e9860c1a462e69ce5ef3e2bcf4 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Sat, 17 Dec 2022 22:32:45 -0400 Subject: [PATCH 4/9] Removed PowerShell 7 support from documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3abcfbf..ad8f1ff 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ This report is compatible with the following PowerShell versions; | Windows PowerShell 5.1 | PowerShell 7 | |:----------------------:|:--------------------:| -| :white_check_mark: | :white_check_mark: | +| :white_check_mark: | :x: | ## :wrench: System Requirements From 844860abde2b85dcfa8d03e0214c1b9c9768197e Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Sun, 25 Dec 2022 19:09:47 -0400 Subject: [PATCH 5/9] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ad8f1ff..d0d9a71 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ This report is compatible with the following PowerShell versions; ## :wrench: System Requirements -PowerShell 5.1 or PowerShell 7, and the following PowerShell modules are required for generating a Microsoft Windows As Built report. +PowerShell 5.1 and the following PowerShell modules are required for generating a Microsoft Windows As Built report. - [AsBuiltReport.Microsoft.Windows Module](https://www.powershellgallery.com/packages/AsBuiltReport.Microsoft.Windows/) - [IISAdministration Module](https://docs.microsoft.com/en-us/powershell/module/iisadministration/?view=windowsserver2022-ps) @@ -74,7 +74,7 @@ PowerShell 5.1 or PowerShell 7, and the following PowerShell modules are require ### Linux & macOS -This report does not support Linux or Mac due to the fact that the Windows modules are dependent on the .NET Framework. Until Microsoft migrates these modules to native PowerShell Core, only PowerShell >= (5.x, 7) will be supported on Windows. +This report does not support Linux or Mac due to the fact that the Windows modules are dependent on the .NET Framework. Until Microsoft migrates these modules to native PowerShell Core, only PowerShell >= 5.1.x will be supported on Windows. ### :closed_lock_with_key: Required Privileges From 40723e65ee225a7726797484ed4801e16a7c860f Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Wed, 3 May 2023 17:10:46 -0400 Subject: [PATCH 6/9] Added code to detect if requirements are installed --- .vscode/launch.json | 13 ++++ README.md | 6 ++ Src/Private/Get-AbrWinHostStorageMPIO.ps1 | 2 +- Src/Private/Get-AbrWinOSRoleFeature.ps1 | 2 +- Src/Private/Get-RequiredFeature.ps1 | 62 +++++++++++++++++++ ...Invoke-AsBuiltReport.Microsoft.Windows.ps1 | 38 ++++++++++-- 6 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 Src/Private/Get-RequiredFeature.ps1 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..bd155eb --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "PowerShell: Interactive Session", + "type": "PowerShell", + "request": "launch" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 3abcfbf..f606ae1 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,9 @@ Install-WindowsFeature -Name Hyper-V-PowerShell Install-WindowsFeature -Name web-mgmt-console Install-WindowsFeature -Name Web-Scripting-Tools +#FailOver Cluster powershell modules +Install-WindowsFeature -Name RSAT-Clustering-PowerShell + ``` ### PowerShell v5.x running on Windows 10 client computer (JumpBox) @@ -111,6 +114,9 @@ Install-Module AsBuiltReport.Microsoft.Windows Add-WindowsCapability –online –Name 'Rsat.Dns.Tools~~~~0.0.1.0' Add-WindowsCapability -Online -Name 'Rsat.DHCP.Tools~~~~0.0.1.0' +#FailOver Cluster powershell modules +Add-WindowsCapability -Online -Name 'Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0' + # Hyper-V Server powershell modules Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell diff --git a/Src/Private/Get-AbrWinHostStorageMPIO.ps1 b/Src/Private/Get-AbrWinHostStorageMPIO.ps1 index ea982cb..15c0806 100644 --- a/Src/Private/Get-AbrWinHostStorageMPIO.ps1 +++ b/Src/Private/Get-AbrWinHostStorageMPIO.ps1 @@ -26,7 +26,7 @@ function Get-AbrWinHostStorageMPIO } process { - if ($InfoLevel.Storage -ge 1) { + if ($InfoLevel.Storage -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $MPIOInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "Multipath*" } } if ($MPIOInstalledCheck.InstallState -eq "Installed") { diff --git a/Src/Private/Get-AbrWinOSRoleFeature.ps1 b/Src/Private/Get-AbrWinOSRoleFeature.ps1 index bbe94dc..5850eb4 100644 --- a/Src/Private/Get-AbrWinOSRoleFeature.ps1 +++ b/Src/Private/Get-AbrWinOSRoleFeature.ps1 @@ -25,7 +25,7 @@ function Get-AbrWinOSRoleFeature { } process { - if ($InfoLevel.OperatingSystem -ge 1) { + if ($InfoLevel.OperatingSystem -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $HostRolesAndFeatures = Invoke-Command -Session $TempPssSession -ScriptBlock{ Get-WindowsFeature | Where-Object { $_.Installed -eq $True } } if ($HostRolesAndFeatures) { diff --git a/Src/Private/Get-RequiredFeature.ps1 b/Src/Private/Get-RequiredFeature.ps1 new file mode 100644 index 0000000..4a2f382 --- /dev/null +++ b/Src/Private/Get-RequiredFeature.ps1 @@ -0,0 +1,62 @@ +function Get-RequiredFeature { + <# + .SYNOPSIS + Function to check if the required version of windows feature is installed + .DESCRIPTION + Function to check if the required version of windows feature is installed + .NOTES + Version: 0.1.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + .PARAMETER Name + The name of the required windows feature + .PARAMETER Version + The version of the required windows feature + #> + + Param + ( + [CmdletBinding()] + [Parameter(Mandatory = $true, ValueFromPipeline = $false)] + [ValidateNotNullOrEmpty()] + [String] + $Name, + + [Parameter(Mandatory = $true, ValueFromPipeline = $false)] + [ValidateNotNullOrEmpty()] + [String] + $OSType, + + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] + [Bool] + $Feature = $False + ) + + process { + # Check if the required version of Module is installed + if ($OSType -eq 'WorkStation') { + if ($Feature) { + $RequiredFeature = Invoke-Command -Session $TempPssSession { Get-WindowsOptionalFeature -FeatureName $Using:Name -Online } + if ($RequiredFeature.State -ne "Enabled") { + throw "$Name is required to run the Microsoft AD As Built Report. Run 'Enable-WindowsOptionalFeature -Online -FeatureName '$($Name)'' to install the required modules. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + } + } else { + $RequiredFeature = Invoke-Command -Session $TempPssSession { Get-WindowsCapability -online -Name $Using:Name } + if ($RequiredFeature.State -ne "Installed") { + throw "$Name is required to run the Microsoft AD As Built Report. Run 'Add-WindowsCapability -online -Name '$($Name)'' to install the required modules. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + } + } + } + elseif ($OSType -eq 'Server' -or $OSType -eq 'DomainController') { + $RequiredFeature = Invoke-Command -Session $TempPssSession { Get-WindowsFeature -Name $Using:Name } + if ($RequiredFeature.InstallState -ne 'Installed') { + throw "$Name is required to run the Microsoft AD As Built Report. Run 'Install-WindowsFeature -Name '$($Name)'' to install the required modules. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + } + } + else { + throw "Unable to validate if $Name is installed. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + } + } + end {} +} \ No newline at end of file diff --git a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 index 5bff960..eafd1e8 100644 --- a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 +++ b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 @@ -42,6 +42,14 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PscriboMessage -IsWarning $_.Exception.Message } + $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) + + + if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + + throw "The requested operation requires elevation: Run PowerShell console as administrator" + } + # Import Report Configuration $Report = $ReportConfig.Report $InfoLevel = $ReportConfig.InfoLevel @@ -63,7 +71,27 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PScriboMessage -IsWarning "Unable to connect to $($System)" throw } + $script:HostInfo = Invoke-Command -Session $TempPssSession { Get-ComputerInfo } + + #Validate Required Modules and Features + $script:OSType = Invoke-Command -Session $TempPssSession { (Get-ComputerInfo).OsProductType } + if ($OSType.Value -eq 'WorkStation') { + Get-RequiredFeature -Name 'IIS-WebServerRole' -OSType $OSType.Value -Feature $True + Get-RequiredFeature -Name 'IIS-WebServerManagementTools' -OSType $OSType.Value -Feature $True + Get-RequiredFeature -Name 'IIS-ManagementScriptingTools' -OSType $OSType.Value -Feature $True + Get-RequiredFeature -Name 'Rsat.Dns.Tools~~~~0.0.1.0' -OSType $OSType.Value + Get-RequiredFeature -Name 'Rsat.DHCP.Tools~~~~0.0.1.0' -OSType $OSType.Value + + } + if ($OSType.Value -eq 'Server' -or $OSType.Value -eq 'DomainController') { + Get-RequiredFeature -Name web-mgmt-console -OSType $OSType.Value + Get-RequiredFeature -Name Web-Scripting-Tools -OSType $OSType.Value + Get-RequiredFeature -Name Hyper-V-PowerShell -OSType $OSType.Value + Get-RequiredFeature -Name RSAT-DNS-Server -OSType $OSType.Value + Get-RequiredFeature -Name RSAT-DHCP -OSType $OSType.Value + } + $script:HostCPU = Get-CimInstance -Class Win32_Processor -CimSession $TempCimSession $script:HostComputer = Get-CimInstance -Class Win32_ComputerSystem -CimSession $TempCimSession $script:HostBIOS = Get-CimInstance -Class Win32_Bios -CimSession $TempCimSession @@ -163,7 +191,7 @@ function Invoke-AsBuiltReport.Microsoft.Windows { } } #HyperV Configuration - if ($InfoLevel.HyperV -ge 1) { + if ($InfoLevel.HyperV -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $HyperVInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*Hyper-V*" } } if ($HyperVInstalledCheck.InstallState -eq "Installed") { @@ -188,7 +216,7 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PscriboMessage -IsWarning $_.Exception.Message } } - if ($InfoLevel.IIS -ge 1) { + if ($InfoLevel.IIS -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $IISInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*Web-Server*" } } if ($IISInstalledCheck.InstallState -eq "Installed") { @@ -212,7 +240,7 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PscriboMessage -IsWarning $_.Exception.Message } } - if ($InfoLevel.SMB -ge 1) { + if ($InfoLevel.SMB -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $SMBInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*FileAndStorage-Services*" } } if ($SMBInstalledCheck.InstallState -eq "Installed") { @@ -237,7 +265,7 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PscriboMessage -IsWarning $_.Exception.Message } } - if ($InfoLevel.DHCP -ge 1) { + if ($InfoLevel.DHCP -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $DHCPInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*DHCP*" } } if ($DHCPInstalledCheck.InstallState -eq "Installed") { @@ -264,7 +292,7 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Write-PscriboMessage -IsWarning $_.Exception.Message } } - if ($InfoLevel.DNS -ge 1) { + if ($InfoLevel.DNS -ge 1 -and $OSType.Value -ne 'WorkStation') { try { $DHCPInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*DNS*" } } if ($DHCPInstalledCheck.InstallState -eq "Installed") { From 0bcd1c7a688108bb07e88f6b6cf950268cfc7614 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 5 May 2023 22:45:01 -0400 Subject: [PATCH 7/9] Improved module requirements --- AsBuiltReport.Microsoft.Windows.json | 3 +- README.md | 5 +- Src/Private/Get-AbrWinOSService.ps1 | 2 +- Src/Private/Get-RequiredFeature.ps1 | 52 +++++- ...Invoke-AsBuiltReport.Microsoft.Windows.ps1 | 174 ++++++++++-------- 5 files changed, 148 insertions(+), 88 deletions(-) diff --git a/AsBuiltReport.Microsoft.Windows.json b/AsBuiltReport.Microsoft.Windows.json index 5b03593..bbbb9c8 100644 --- a/AsBuiltReport.Microsoft.Windows.json +++ b/AsBuiltReport.Microsoft.Windows.json @@ -23,7 +23,8 @@ "IIS": 1, "SMB": 1, "DHCP": 1, - "DNS": 1 + "DNS": 1, + "FailOverCluster": 1 }, "HealthCheck": { diff --git a/README.md b/README.md index 96bc3e0..59ae813 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ Install-WindowsFeature -Name RSAT-Clustering-PowerShell ``` -### PowerShell v5.x running on Windows 10 client computer (JumpBox) +### PowerShell v5.x running on Windows client computer ```powershell Install-Module AsBuiltReport.Microsoft.Windows @@ -230,5 +230,4 @@ PS C:\> New-AsBuiltReport -Report Microsoft.Windows -Target 'win-server-01v.cont ## :x: Known Issues - Issues with WinRM when using the IP address instead of the "Fully Qualified Domain Name". -- This project relies heavily on the remote connection function through WinRM. For this reason the use of a Windows 10 client is specifically used as a jumpbox. -- The report provides the ability to extract the configuration of the Hyper-V/IIS services. In order to obtain this information it is required that the servers running these services have powershell modules installed for each service. +- The report provides the ability to extract the configuration of the DNS/DHCP/Hyper-V/IIS/FailOver-Cluster services. In order to obtain this information it is required that the servers running these services have the corresponding powershell modules installed. diff --git a/Src/Private/Get-AbrWinOSService.ps1 b/Src/Private/Get-AbrWinOSService.ps1 index c7137a7..fffe50a 100644 --- a/Src/Private/Get-AbrWinOSService.ps1 +++ b/Src/Private/Get-AbrWinOSService.ps1 @@ -32,7 +32,7 @@ function Get-AbrWinOSService { Section -Style Heading3 'Services' { Paragraph 'The following table details status of important services' Blankline - $Services = @('DNS','DFS Replication','Intersite Messaging','Kerberos Key Distribution Center','Active Directory Domain Services','W32Time','ADWS','DHCPServer','Dnscache','gpsvc','HvHost','vmcompute','vmms','iphlpsvc','MSiSCSI','Netlogon','RasMan','SessionEnv','TermService','RpcSs','RpcEptMapper','SamSs','LanmanServer','Schedule','lmhosts','UsoSvc','mpssvc','W3SVC','MSSQLSERVER') + $Services = @('DNS','DFS Replication','Intersite Messaging','Kerberos Key Distribution Center','Active Directory Domain Services','W32Time','ADWS','DHCPServer','Dnscache','gpsvc','HvHost','vmcompute','vmms','iphlpsvc','MSiSCSI','Netlogon','RasMan','SessionEnv','TermService','RpcSs','RpcEptMapper','SamSs','LanmanServer','Schedule','lmhosts','UsoSvc','mpssvc','W3SVC','MSSQLSERVER','ClusSvc') $ServicesReport = @() Foreach ($Service in $Services) { try { diff --git a/Src/Private/Get-RequiredFeature.ps1 b/Src/Private/Get-RequiredFeature.ps1 index 4a2f382..6f74fd4 100644 --- a/Src/Private/Get-RequiredFeature.ps1 +++ b/Src/Private/Get-RequiredFeature.ps1 @@ -29,8 +29,17 @@ function Get-RequiredFeature { $OSType, [Parameter(Mandatory = $false, ValueFromPipeline = $false)] - [Bool] - $Feature = $False + [Switch] + $Feature = $False, + + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] + [Switch] + $Status = $False, + + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] + [ValidateNotNullOrEmpty()] + [String] + $Service ) process { @@ -38,20 +47,47 @@ function Get-RequiredFeature { if ($OSType -eq 'WorkStation') { if ($Feature) { $RequiredFeature = Invoke-Command -Session $TempPssSession { Get-WindowsOptionalFeature -FeatureName $Using:Name -Online } - if ($RequiredFeature.State -ne "Enabled") { - throw "$Name is required to run the Microsoft AD As Built Report. Run 'Enable-WindowsOptionalFeature -Online -FeatureName '$($Name)'' to install the required modules. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + if ($Status) { + if ($RequiredFeature.State -eq "Enabled") { + return $true + } else { + return $false + } + } + if (-Not $Status) { + if ($RequiredFeature.State -ne "Enabled") { + Write-PScriboMessage -IsWarning "$Name module is required to be installed on $System to be able to document $Service service. Run 'Enable-WindowsOptionalFeature -Online -FeatureName '$($Name)'' to install the required modules." + } } } else { $RequiredFeature = Invoke-Command -Session $TempPssSession { Get-WindowsCapability -online -Name $Using:Name } - if ($RequiredFeature.State -ne "Installed") { - throw "$Name is required to run the Microsoft AD As Built Report. Run 'Add-WindowsCapability -online -Name '$($Name)'' to install the required modules. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + if ($Status) { + if ($RequiredFeature.State -eq "Installed") { + return $true + } else { + return $false + } + } + if (-Not $Status) { + if ($RequiredFeature.State -ne "Installed") { + Write-PScriboMessage -IsWarning "$Name module is required to be installed on $System to be able to document $Service service. Run 'Add-WindowsCapability -online -Name '$($Name)'' to install the required modules." + } } } } elseif ($OSType -eq 'Server' -or $OSType -eq 'DomainController') { $RequiredFeature = Invoke-Command -Session $TempPssSession { Get-WindowsFeature -Name $Using:Name } - if ($RequiredFeature.InstallState -ne 'Installed') { - throw "$Name is required to run the Microsoft AD As Built Report. Run 'Install-WindowsFeature -Name '$($Name)'' to install the required modules. https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.AD" + if ($Status) { + if ($RequiredFeature.InstallState -eq 'Installed') { + return $true + } else { + return $false + } + } + if (-Not $Status) { + if ($RequiredFeature.InstallState -ne 'Installed') { + Write-PScriboMessage -IsWarning "$Name module is required to be installed on $System to be able to document $Service service. Run 'Install-WindowsFeature -Name '$($Name)'' to install the required modules." + } } } else { diff --git a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 index eafd1e8..5887d99 100644 --- a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 +++ b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 @@ -76,22 +76,6 @@ function Invoke-AsBuiltReport.Microsoft.Windows { #Validate Required Modules and Features $script:OSType = Invoke-Command -Session $TempPssSession { (Get-ComputerInfo).OsProductType } - if ($OSType.Value -eq 'WorkStation') { - Get-RequiredFeature -Name 'IIS-WebServerRole' -OSType $OSType.Value -Feature $True - Get-RequiredFeature -Name 'IIS-WebServerManagementTools' -OSType $OSType.Value -Feature $True - Get-RequiredFeature -Name 'IIS-ManagementScriptingTools' -OSType $OSType.Value -Feature $True - Get-RequiredFeature -Name 'Rsat.Dns.Tools~~~~0.0.1.0' -OSType $OSType.Value - Get-RequiredFeature -Name 'Rsat.DHCP.Tools~~~~0.0.1.0' -OSType $OSType.Value - - } - if ($OSType.Value -eq 'Server' -or $OSType.Value -eq 'DomainController') { - Get-RequiredFeature -Name web-mgmt-console -OSType $OSType.Value - Get-RequiredFeature -Name Web-Scripting-Tools -OSType $OSType.Value - Get-RequiredFeature -Name Hyper-V-PowerShell -OSType $OSType.Value - Get-RequiredFeature -Name RSAT-DNS-Server -OSType $OSType.Value - Get-RequiredFeature -Name RSAT-DHCP -OSType $OSType.Value - } - $script:HostCPU = Get-CimInstance -Class Win32_Processor -CimSession $TempCimSession $script:HostComputer = Get-CimInstance -Class Win32_ComputerSystem -CimSession $TempCimSession $script:HostBIOS = Get-CimInstance -Class Win32_Bios -CimSession $TempCimSession @@ -191,14 +175,13 @@ function Invoke-AsBuiltReport.Microsoft.Windows { } } #HyperV Configuration - if ($InfoLevel.HyperV -ge 1 -and $OSType.Value -ne 'WorkStation') { - try { - $HyperVInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*Hyper-V*" } } - if ($HyperVInstalledCheck.InstallState -eq "Installed") { - $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'vmms' -ErrorAction SilentlyContinue } - if ($Status.Status -eq "Running") { - Section -Style Heading2 "Hyper-V Configuration Settings" { - Paragraph 'The following table details the Hyper-V Server Settings' + if ($InfoLevel.HyperV -ge 1) { + $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'vmms' -ErrorAction SilentlyContinue } + if ($Status) { + try { + if (Get-RequiredFeature -Name Hyper-V-PowerShell -OSType $OSType.Value -Status) { + Section -Style Heading2 "Hyper-V Configuration" { + Paragraph 'The following table details the Hyper-V server settings' Blankline # Hyper-V Configuration Get-AbrWinHyperVSummary @@ -209,21 +192,24 @@ function Invoke-AsBuiltReport.Microsoft.Windows { # Hyper-V VM Information (Buggy as hell) #Get-AbrWinHyperVHostVM } + } else { + Get-RequiredFeature -Name Hyper-V-PowerShell -OSType $OSType.Value -Service "Hyper-V" } } - } - catch { - Write-PscriboMessage -IsWarning $_.Exception.Message + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } else { + Write-PScriboMessage "No HyperV service detected. Disabling HyperV server section" } } - if ($InfoLevel.IIS -ge 1 -and $OSType.Value -ne 'WorkStation') { - try { - $IISInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*Web-Server*" } } - if ($IISInstalledCheck.InstallState -eq "Installed") { - $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'W3SVC' -ErrorAction SilentlyContinue } - if ($Status.Status -eq "Running") { - Section -Style Heading2 "IIS Configuration Settings" { - Paragraph 'The following table details the IIS Server Settings' + if ($InfoLevel.IIS -ge 1) { + $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'W3SVC' -ErrorAction SilentlyContinue } + if ($Status) { + try { + if (((Get-RequiredFeature -Name web-mgmt-console -OSType $OSType.Value -Status) -and (Get-RequiredFeature -Name Web-Scripting-Tools -OSType $OSType.Value -Status)) -or ((Get-RequiredFeature -Name IIS-WebServerRole -OSType $OSType.Value -Status) -and (Get-RequiredFeature -Name WebServerManagementTools -OSType $OSType.Value -Status) -and (Get-RequiredFeature -Name IIS-ManagementScriptingTools -OSType $OSType.Value -Status))) { + Section -Style Heading2 "IIS Configuration" { + Paragraph 'The following table details the IIS server settings' Blankline # IIS Configuration Get-AbrWinIISSummary @@ -231,33 +217,38 @@ function Invoke-AsBuiltReport.Microsoft.Windows { Get-AbrWinIISWebAppPool # IIS Web Site Get-AbrWinIISWebSite - + } + } else { + If ($OSType -eq 'Server' -or $OSType -eq 'DomainController') { + Get-RequiredFeature -Name web-mgmt-console -OSType $OSType.Value -Service "IIS" + Get-RequiredFeature -Name Web-Scripting-Tools -OSType $OSType.Value -Service "IIS" + } else { + Get-RequiredFeature -Name IIS-WebServerRole -OSType $OSType.Value -Service "IIS" + Get-RequiredFeature -Name WebServerManagementTools -OSType $OSType.Value -Service "IIS" + Get-RequiredFeature -Name IIS-ManagementScriptingTools -OSType $OSType.Value -Service "IIS" } } } - } - catch { - Write-PscriboMessage -IsWarning $_.Exception.Message + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } else { + Write-PScriboMessage "No W3SVC service detected. Disabling IIS server section" } } - if ($InfoLevel.SMB -ge 1 -and $OSType.Value -ne 'WorkStation') { + if ($InfoLevel.SMB -ge 1) { try { - $SMBInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*FileAndStorage-Services*" } } - if ($SMBInstalledCheck.InstallState -eq "Installed") { - $Global:SMBShares = Invoke-Command -Session $TempPssSession { Get-SmbShare | Where-Object {$_.Special -like 'False'} } - if ($SMBShares) { - Section -Style Heading2 "File Server Configuration Settings" { - Paragraph 'The following table details the File Server Settings' - Blankline - # SMB Server Configuration - Get-AbrWinSMBSummary - # SMB Server Network Interface - Get-AbrWinSMBNetworkInterface - # SMB Shares - Get-AbrWinSMBShare - - - } + $Global:SMBShares = Invoke-Command -Session $TempPssSession { Get-SmbShare | Where-Object {$_.Special -like 'False'} } + if ($SMBShares) { + Section -Style Heading2 "File Server Configuration" { + Paragraph 'The following table details the File Server settings' + Blankline + # SMB Server Configuration + Get-AbrWinSMBSummary + # SMB Server Network Interface + Get-AbrWinSMBNetworkInterface + # SMB Shares + Get-AbrWinSMBShare } } } @@ -266,13 +257,12 @@ function Invoke-AsBuiltReport.Microsoft.Windows { } } if ($InfoLevel.DHCP -ge 1 -and $OSType.Value -ne 'WorkStation') { - try { - $DHCPInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*DHCP*" } } - if ($DHCPInstalledCheck.InstallState -eq "Installed") { - $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'DHCPServer' -ErrorAction SilentlyContinue } - if ($Status.Status -eq "Running") { - Section -Style Heading2 "DHCP Server Configuration Settings" { - Paragraph 'The following table details the DHCP Server Settings' + $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'DHCPServer' -ErrorAction SilentlyContinue } + if ($Status) { + try { + if (Get-RequiredFeature -Name RSAT-DHCP -OSType $OSType.Value -Status) { + Section -Style Heading2 "DHCP Server Configuration" { + Paragraph 'The following table details the DHCP server configurations' Blankline # DHCP Server Configuration Get-AbrWinDHCPInfrastructure @@ -285,34 +275,68 @@ function Invoke-AsBuiltReport.Microsoft.Windows { # DHCP Server Per Scope Info Get-AbrWinDHCPv4PerScopeSetting } + } else { + Get-RequiredFeature -Name RSAT-DHCP -OSType $OSType.Value -Service "DHCP Server" } } - } - catch { - Write-PscriboMessage -IsWarning $_.Exception.Message + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } else { + Write-PScriboMessage "No DHCPServer service detected. Disabling Dhcp server section" } } if ($InfoLevel.DNS -ge 1 -and $OSType.Value -ne 'WorkStation') { - try { - $DHCPInstalledCheck = Invoke-Command -Session $TempPssSession { Get-WindowsFeature | Where-Object { $_.Name -like "*DNS*" } } - if ($DHCPInstalledCheck.InstallState -eq "Installed") { - $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'DNS' -ErrorAction SilentlyContinue } - if ($Status.Status -eq "Running") { - Section -Style Heading2 "DNS Server Configuration Settings" { - Paragraph 'The following table details the DNS Server Settings' + $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'DNS' -ErrorAction SilentlyContinue } + if ($Status) { + try { + if (Get-RequiredFeature -Name RSAT-DNS-Server -OSType $OSType.Value -Status) { + Section -Style Heading2 "DNS Server Configuration" { + Paragraph 'The following table details the DNS server settings' Blankline # DNS Server Configuration Get-AbrWinDNSInfrastructure # DNS Zones Configuration Get-AbrWinDNSZone } + } else { + Get-RequiredFeature -Name RSAT-DNS-Server -OSType $OSType.Value -Service "DNS Server" } } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } else { + Write-PScriboMessage "No DNS Server service detected. Disabling DNS server section" } - catch { - Write-PscriboMessage -IsWarning $_.Exception.Message + } + + if ($InfoLevel.FailOverCluster -ge 1 -and $OSType.Value -ne 'WorkStation') { + $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'ClusSvc' -ErrorAction SilentlyContinue } + if ($Status.Status -eq "Running") { + try { + if (Get-RequiredFeature -Name RSAT-Clustering-PowerShell -OSType $OSType.Value -Status) { + Section -Style Heading2 "Failover Cluster Configuration" { + Paragraph 'The following table details the Failover Cluster Settings' + Blankline + # # DNS Server Configuration + # Get-AbrWinDNSInfrastructure + # # DNS Zones Configuration + # Get-AbrWinDNSZone + } + } + else { + Get-RequiredFeature -Name RSAT-Clustering-PowerShell -OSType $OSType.Value -Service "FailOver Cluster" + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } else { + Write-PScriboMessage "No FailOver Cluster service detected. Disabling FailOver Cluster section" } } + } Remove-PSSession $TempPssSession Remove-CimSession $TempCimSession From bf41f071fd938a537e9535e1a128c8d4100b2c3f Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Mon, 8 May 2023 16:22:12 -0400 Subject: [PATCH 8/9] Added FailOver Cluster Section --- AsBuiltReport.Microsoft.Windows.Style.ps1 | 40 +++++---- AsBuiltReport.Microsoft.Windows.json | 6 ++ AsBuiltReport.Microsoft.Windows.psd1 | 4 +- README.md | 1 + Src/Private/Get-AbrWinFOCluster.ps1 | 64 ++++++++++++++ .../Get-AbrWinFOClusterAvailableDisk.ps1 | 66 ++++++++++++++ .../Get-AbrWinFOClusterFaultDomain.ps1 | 68 ++++++++++++++ Src/Private/Get-AbrWinFOClusterNetwork.ps1 | 74 ++++++++++++++++ .../Get-AbrWinFOClusterNetworkInterface.ps1 | 72 +++++++++++++++ Src/Private/Get-AbrWinFOClusterNode.ps1 | 88 +++++++++++++++++++ Src/Private/Get-AbrWinFOClusterPermission.ps1 | 66 ++++++++++++++ Src/Private/Get-AbrWinFOClusterQuorum.ps1 | 66 ++++++++++++++ Src/Private/Get-AbrWinFOClusterResource.ps1 | 72 +++++++++++++++ .../Get-AbrWinFOClusterSharedVolume.ps1 | 74 ++++++++++++++++ .../Get-AbrWinFOClusterSharedVolumeState.ps1 | 68 ++++++++++++++ Src/Private/Get-AbrWinNetFirewall.ps1 | 4 +- Src/Private/SharedUtilsFunctions.ps1 | 60 ++++++------- ...Invoke-AsBuiltReport.Microsoft.Windows.ps1 | 26 ++++-- 18 files changed, 859 insertions(+), 60 deletions(-) create mode 100644 Src/Private/Get-AbrWinFOCluster.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterAvailableDisk.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterFaultDomain.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterNetwork.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterNetworkInterface.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterNode.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterPermission.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterQuorum.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterResource.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterSharedVolume.ps1 create mode 100644 Src/Private/Get-AbrWinFOClusterSharedVolumeState.ps1 diff --git a/AsBuiltReport.Microsoft.Windows.Style.ps1 b/AsBuiltReport.Microsoft.Windows.Style.ps1 index def6415..84b375d 100644 --- a/AsBuiltReport.Microsoft.Windows.Style.ps1 +++ b/AsBuiltReport.Microsoft.Windows.Style.ps1 @@ -1,28 +1,34 @@ # Microsoft Windows Default Document Style # Configure document options -DocumentOption -EnableSectionNumbering -PageSize A4 -DefaultFont 'Arial' -MarginLeftAndRight 71 -MarginTopAndBottom 71 -Orientation $Orientation +DocumentOption -EnableSectionNumbering -PageSize A4 -DefaultFont 'Segoe Ui' -MarginLeftAndRight 71 -MarginTopAndBottom 71 -Orientation $Orientation # Configure Heading and Font Styles -Style -Name 'Title' -Size 24 -Color '0076CE' -Align Center +Style -Name 'Title' -Size 24 -Color '0078D4' -Align Center Style -Name 'Title 2' -Size 18 -Color '00447C' -Align Center -Style -Name 'Title 3' -Size 12 -Color '00447C' -Align Left -Style -Name 'Heading 1' -Size 16 -Color '00447C' +Style -Name 'Title 3' -Size 12 -Color '1F6BCF' -Align Left +Style -Name 'Heading 1' -Size 16 -Color '0078D4' Style -Name 'Heading 2' -Size 14 -Color '00447C' -Style -Name 'Heading 3' -Size 12 -Color '00447C' -Style -Name 'Heading 4' -Size 11 -Color '00447C' -Style -Name 'Heading 5' -Size 10 -Color '00447C' +Style -Name 'Heading 3' -Size 13 -Color '0081FF' +Style -Name 'NO TOC Heading 3' -Size 13 -Color '0081FF' +Style -Name 'Heading 4' -Size 12 -Color '0077B7' +Style -Name 'NO TOC Heading 4' -Size 12 -Color '0077B7' +Style -Name 'Heading 5' -Size 11 -Color '1A9BA3' +Style -Name 'NO TOC Heading 5' -Size 11 -Color '1A9BA3' +Style -Name 'Heading 6' -Size 10 -Color '505050' +Style -Name 'NO TOC Heading 6' -Size 10 -Color '505050' +Style -Name 'NO TOC Heading 7' -Size 10 -Color '551A4C' -Italic Style -Name 'Normal' -Size 10 -Color '565656' -Default Style -Name 'Caption' -Size 10 -Color '565656' -Italic -Align Center Style -Name 'Header' -Size 10 -Color '565656' -Align Center Style -Name 'Footer' -Size 10 -Color '565656' -Align Center -Style -Name 'TOC' -Size 16 -Color '00447C' -Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAFAFA' -BackgroundColor '0076CE' +Style -Name 'TOC' -Size 16 -Color '1F6BCF' +Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAFAFA' -BackgroundColor '0078D4' Style -Name 'TableDefaultRow' -Size 10 -Color '565656' -Style -Name 'Critical' -Size 10 -BackgroundColor 'F5DBD9' -Style -Name 'Warning' -Size 10 -BackgroundColor 'FEF3B5' -Style -Name 'Info' -Size 10 -BackgroundColor 'E1F1F6' -Style -Name 'OK' -Size 10 -BackgroundColor 'DFF0D0' +Style -Name 'Critical' -Size 10 -BackgroundColor 'E81123' -Color 'FAFAFA' +Style -Name 'Warning' -Size 10 -BackgroundColor 'FCD116' +Style -Name 'Info' -Size 10 -BackgroundColor '0072C6' +Style -Name 'OK' -Size 10 -BackgroundColor '7FBA00' # Configure Table Styles $TableDefaultProperties = @{ @@ -67,13 +73,13 @@ if ($Orientation -eq 'Portrait') { $LineCount = 15 + $LineCount } -# Microsoft Logo Image +# Cover Page Image if ($ReportConfig.Report.ShowCoverPageImage) { Try { - Image -Text 'Microsoft Logo' -Align 'Center' -Percent 20 -Base64 "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" - BlankLine -Count 2 + Image -Text 'AsBuiltReport Logo' -Align 'Center' -Percent 45 -Base64 "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" + BlankLine -Count 1 } Catch { - Write-PScriboMessage -Message ".NET Core is required for cover page image support. Please install .NET Core or disable 'ShowCoverPageImage' in the report JSON configuration file." + Write-PScriboMessage -IsWarning "Unable to display cover page image. Please set 'ShowCoverPageImage' to 'false' in the report JSON configuration file to avoid this error." } } diff --git a/AsBuiltReport.Microsoft.Windows.json b/AsBuiltReport.Microsoft.Windows.json index bbbb9c8..00463b7 100644 --- a/AsBuiltReport.Microsoft.Windows.json +++ b/AsBuiltReport.Microsoft.Windows.json @@ -44,6 +44,12 @@ "Credential": true, "Statistics": true, "BP": true + }, + "FailOverCluster": { + "Nodes": true, + "Network": true, + "ClusterSharedVolume": true + } } } diff --git a/AsBuiltReport.Microsoft.Windows.psd1 b/AsBuiltReport.Microsoft.Windows.psd1 index c97649c..61756ce 100644 --- a/AsBuiltReport.Microsoft.Windows.psd1 +++ b/AsBuiltReport.Microsoft.Windows.psd1 @@ -12,7 +12,7 @@ RootModule = 'AsBuiltReport.Microsoft.Windows.psm1' # Version number of this module. -ModuleVersion = '0.4.0' +ModuleVersion = '0.5.0' # Supported PSEditions # CompatiblePSEditions = @() @@ -54,7 +54,7 @@ PowerShellVersion = '5.1' RequiredModules = @( @{ ModuleName = 'AsBuiltReport.Core'; - ModuleVersion = '1.2.0' + ModuleVersion = '1.3.0' } ) diff --git a/README.md b/README.md index 59ae813..d8effc8 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,7 @@ The table below outlines the default and maximum **InfoLevel** settings for each | HyperV | 1 | 1 | | DHCP | 1 | 2 | | DNS | 1 | 2 | +| FailOverCluster | 1 | 2 | ### Healthcheck diff --git a/Src/Private/Get-AbrWinFOCluster.ps1 b/Src/Private/Get-AbrWinFOCluster.ps1 new file mode 100644 index 0000000..d21bf3d --- /dev/null +++ b/Src/Private/Get-AbrWinFOCluster.ps1 @@ -0,0 +1,64 @@ +function Get-AbrWinFOCluster { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster configuration + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Server information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-Cluster -Name $using:Cluster | Select-Object -Property * } + if ($Settings) { + $OutObj = @() + try { + $inObj = [ordered] @{ + 'Name' = $Settings.Name + 'Domain' = $Settings.Domain + 'Shared Volumes Root' = $Settings.SharedVolumesRoot + 'Administrative Access Point' = $Settings.AdministrativeAccessPoint + 'Description' = ConvertTo-EmptyToFiller $Settings.Description + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + + $TableParams = @{ + Name = "FailOver Cluster Servers Settings - $($System.toUpper().split(".")[0])" + List = $true + ColumnWidths = 40, 60 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterAvailableDisk.ps1 b/Src/Private/Get-AbrWinFOClusterAvailableDisk.ps1 new file mode 100644 index 0000000..0581c4e --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterAvailableDisk.ps1 @@ -0,0 +1,66 @@ +function Get-AbrWinFOClusterAvailableDisk { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Available Disk + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Available Disk information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterAvailableDisk -Cluster $using:Cluster} | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Available Disk" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'Number' = $Setting.Number + 'Size' = ConvertTo-FileSizeString $Setting.Size + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + $TableParams = @{ + Name = "Available Disk - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 40, 30, 30 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterFaultDomain.ps1 b/Src/Private/Get-AbrWinFOClusterFaultDomain.ps1 new file mode 100644 index 0000000..587d729 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterFaultDomain.ps1 @@ -0,0 +1,68 @@ +function Get-AbrWinFOClusterFaultDomain { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Fault Domain + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Fault Domain information." + } + + process { + try { + $Settings = Get-ClusterFaultDomain -CimSession $TempCimSession | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Fault Domain" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'Type' = $Setting.Type + 'Parent Name' = $Setting.ParentName + 'Children Names' = $Setting.ChildrenNames + 'Location' = ConvertTo-EmptyToFiller $Setting.Location + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + $TableParams = @{ + Name = "Fault Domain - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 20, 20, 20, 20, 20 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterNetwork.ps1 b/Src/Private/Get-AbrWinFOClusterNetwork.ps1 new file mode 100644 index 0000000..b0aad85 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterNetwork.ps1 @@ -0,0 +1,74 @@ +function Get-AbrWinFOClusterNetwork { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Networks + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Networks information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterNetwork -Cluster $using:Cluster} | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Networks" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'State' = $Setting.State + 'Role' = $Setting.Role + 'Address' = "$($Setting.Address)/$($Setting.AddressMask)" + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + + if ($HealthCheck.FailOverCluster.Network) { + $OutObj | Where-Object { $_.'State' -ne 'UP'} | Set-Style -Style Warning -Property 'State' + } + + $TableParams = @{ + Name = "Networks - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 30, 15, 20, 35 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + # Cluster Network Interfaces + Get-AbrWinFOClusterNetworkInterface + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterNetworkInterface.ps1 b/Src/Private/Get-AbrWinFOClusterNetworkInterface.ps1 new file mode 100644 index 0000000..012563a --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterNetworkInterface.ps1 @@ -0,0 +1,72 @@ +function Get-AbrWinFOClusterNetworkInterface { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Network Interfaces + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Network Interface information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterNetworkInterface -Cluster $using:Cluster} | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Interfaces" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'Node' = $Setting.Node + 'Network' = $Setting.Network + 'State' = $Setting.State + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + + if ($HealthCheck.FailOverCluster.Network) { + $OutObj | Where-Object { $_.'State' -ne 'UP'} | Set-Style -Style Warning -Property 'State' + } + + $TableParams = @{ + Name = "Interfaces - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 30, 25, 30, 15 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterNode.ps1 b/Src/Private/Get-AbrWinFOClusterNode.ps1 new file mode 100644 index 0000000..056b534 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterNode.ps1 @@ -0,0 +1,88 @@ +function Get-AbrWinFOClusterNode { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Nodes + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.Infrastructure.FailOverCluster)." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterNode -Cluster $using:Cluster} | Sort-Object -Property Identity + if ($Settings) { + Write-PscriboMessage "Collecting Host FailOver Cluster Permissions Settings information." + Section -Style Heading3 'Nodes' { + $OutObj = @() + foreach ($Setting in $Settings) { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'State' = $Setting.State + 'Type' = $Setting.Type + 'Cluster' = $Setting.Cluster + 'Fault Domain' = $Setting.FaultDomain + 'Model' = $Setting.Model + 'Manufacturer' = $Setting.Manufacturer + 'Description' = ConvertTo-EmptyToFiller $Setting.Description + + } + $OutObj += [PSCustomObject]$InObj + } + + if ($HealthCheck.FailOverCluster.Nodes) { + $OutObj | Where-Object { $_.'State' -ne 'UP'} | Set-Style -Style Warning -Property 'State' + } + + if ($InfoLevel.FailOverCluster -ge 2) { + Paragraph "The following sections detail the configuration of the Failover Cluster Nodes." + foreach ($Setting in $OutObj) { + Section -ExcludeFromTOC -Style NOTOCHeading4 "$($Setting.Name)" { + $TableParams = @{ + Name = "Node - $($Setting.Name)" + List = $true + ColumnWidths = 50, 50 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $Setting | Table @TableParams + } + } + } else { + Paragraph "The following table summarizes the configuration of the Failover Cluster Nodes." + BlankLine + $TableParams = @{ + Name = "Nodes - $($Cluster.toUpper().split(".")[0])" + List = $false + Columns = 'Name', 'State', 'Type' + ColumnWidths = 40, 30, 30 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + } catch { + Write-PscriboMessage -IsWarning "FailOver Cluster Nodes Section: $($_.Exception.Message)" + } + } + + end {} +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterPermission.ps1 b/Src/Private/Get-AbrWinFOClusterPermission.ps1 new file mode 100644 index 0000000..837e1c5 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterPermission.ps1 @@ -0,0 +1,66 @@ +function Get-AbrWinFOClusterPermission { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Permissions + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Permissions Settings information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterAccess -Cluster $using:Cluster} | Sort-Object -Property Identity + if ($Settings) { + Section -Style Heading3 "Access Permissions" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Identity' = $Setting.IdentityReference + 'Access Control Type' = $Setting.AccessControlType + 'Rights' = $Setting.ClusterRights + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + $TableParams = @{ + Name = "Access Permission - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 60, 20, 20 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterQuorum.ps1 b/Src/Private/Get-AbrWinFOClusterQuorum.ps1 new file mode 100644 index 0000000..fc329c8 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterQuorum.ps1 @@ -0,0 +1,66 @@ +function Get-AbrWinFOClusterQuorum { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Quorum + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Quorum information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterQuorum -Cluster $using:Cluster | Select-Object -Property * } | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Quorum" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Cluster' = $Setting.Cluster + 'Quorum Resource' = $Setting.QuorumResource + 'Quorum Type' = $Setting.QuorumType + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + $TableParams = @{ + Name = "Quorum - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 33, 34, 33 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterResource.ps1 b/Src/Private/Get-AbrWinFOClusterResource.ps1 new file mode 100644 index 0000000..75171a3 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterResource.ps1 @@ -0,0 +1,72 @@ +function Get-AbrWinFOClusterResource { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Resource + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Resource information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterResource -Cluster $using:Cluster | Select-Object -Property * } | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Resource" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'Owner Group' = $Setting.OwnerGroup + 'Resource Type' = $Setting.ResourceType + 'State' = $Setting.State + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + + if ($HealthCheck.FailOverCluster.Network) { + $OutObj | Where-Object { $_.'State' -notlike 'Online'} | Set-Style -Style Warning -Property 'State' + } + + $TableParams = @{ + Name = "Resource - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 25, 25, 35, 15 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterSharedVolume.ps1 b/Src/Private/Get-AbrWinFOClusterSharedVolume.ps1 new file mode 100644 index 0000000..b1133b2 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterSharedVolume.ps1 @@ -0,0 +1,74 @@ +function Get-AbrWinFOClusterSharedVolume { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Shared Volume + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Shared Volume information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterSharedVolume -Cluster $using:Cluster | Select-Object -Property * } | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading3 "Cluster Shared Volume" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'Owner Node' = $Setting.OwnerNode + 'Shared Volume' = $Setting.SharedVolumeInfo.FriendlyVolumeName + 'State' = $Setting.State + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + + if ($HealthCheck.FailOverCluster.ClusterSharedVolume) { + $OutObj | Where-Object { $_.'State' -notlike 'Online'} | Set-Style -Style Warning -Property 'State' + } + + $TableParams = @{ + Name = "Cluster Shared Volume - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 25, 25, 35, 15 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + #Cluster Shared Volume State + Get-AbrWinFOClusterSharedVolumeState + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinFOClusterSharedVolumeState.ps1 b/Src/Private/Get-AbrWinFOClusterSharedVolumeState.ps1 new file mode 100644 index 0000000..052bb79 --- /dev/null +++ b/Src/Private/Get-AbrWinFOClusterSharedVolumeState.ps1 @@ -0,0 +1,68 @@ +function Get-AbrWinFOClusterSharedVolumeState { + <# + .SYNOPSIS + Used by As Built Report to retrieve Microsoft FailOver Cluster Shared Volume State + .DESCRIPTION + Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + Twitter: @jcolonfzenpr + Github: rebelinux + Credits: Iain Brighton (@iainbrighton) - PScribo module + + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows + #> + + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "FailOverCluster InfoLevel set at $($InfoLevel.FailOverCluster)." + Write-PscriboMessage "Collecting Host FailOver Cluster Shared Volume State information." + } + + process { + try { + $Settings = Invoke-Command -Session $TempPssSession { Get-ClusterSharedVolumeState -Cluster $using:Cluster | Select-Object -Property * } | Sort-Object -Property Name + if ($Settings) { + Section -Style Heading4 "Cluster Shared Volume State" { + $OutObj = @() + foreach ($Setting in $Settings) { + try { + $inObj = [ordered] @{ + 'Name' = $Setting.Name + 'Node' = $Setting.Node + 'State' = $Setting.StateInfo + 'Volume Name' = $Setting.VolumeFriendlyName + 'Volume Path' = $Setting.VolumeName + } + $OutObj += [pscustomobject]$inobj + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + $TableParams = @{ + Name = "Cluster Shared Volume State - $($Cluster.toUpper().split(".")[0])" + List = $false + ColumnWidths = 20, 20, 20, 20, 20 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutObj | Table @TableParams + } + } + } + catch { + Write-PscriboMessage -IsWarning $_.Exception.Message + } + } + + end {} + +} \ No newline at end of file diff --git a/Src/Private/Get-AbrWinNetFirewall.ps1 b/Src/Private/Get-AbrWinNetFirewall.ps1 index f13a694..bfd5309 100644 --- a/Src/Private/Get-AbrWinNetFirewall.ps1 +++ b/Src/Private/Get-AbrWinNetFirewall.ps1 @@ -5,7 +5,7 @@ function Get-AbrWinNetFirewall { .DESCRIPTION Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.3.0 + Version: 0.5.0 Author: Andrew Ramsay Editor: Jonathan Colon Twitter: @asbuiltreport @@ -49,7 +49,7 @@ function Get-AbrWinNetFirewall { } if ($HealthCheck.Networking.Firewall) { - $NetFirewallProfileReport | Where-Object { $_.'Profile Enabled' -notlike 'No'} | Set-Style -Style Warning -Property 'Profile Enabled' + $NetFirewallProfileReport | Where-Object { $_.'Profile Enabled' -notlike 'Yes'} | Set-Style -Style Warning -Property 'Profile Enabled' } $TableParams = @{ diff --git a/Src/Private/SharedUtilsFunctions.ps1 b/Src/Private/SharedUtilsFunctions.ps1 index b183ec8..618a91a 100644 --- a/Src/Private/SharedUtilsFunctions.ps1 +++ b/Src/Private/SharedUtilsFunctions.ps1 @@ -110,40 +110,32 @@ function Invoke-DcDiag { }# end function ConvertTo-EmptyToFiller { - <# - .SYNOPSIS - Used by As Built Report to convert empty culumns to "-". - .DESCRIPTION - - .NOTES - Version: 0.4.0 - Author: Jonathan Colon - - .EXAMPLE - - .LINK - - #> - [CmdletBinding()] - [OutputType([String])] - Param - ( - [Parameter ( - Position = 0, - Mandatory)] - [AllowEmptyString()] - [string] - $TEXT - ) - - switch ($TEXT) { - "" {"-"; break} - $Null {"-"; break} - "True" {"Yes"; break} - "False" {"No"; break} - default {$TEXT} - } - } # end + <# + .SYNOPSIS + Used by As Built Report to convert empty culumns to "-". + .DESCRIPTION + .NOTES + Version: 0.5.0 + Author: Jonathan Colon + .EXAMPLE + .LINK + #> + [CmdletBinding()] + [OutputType([String])] + Param + ( + [Parameter ( + Position = 0, + Mandatory)] + [AllowEmptyString()] + [string]$TEXT + ) + + switch ([string]::IsNullOrEmpty($TEXT)) { + $true {"--"; break} + default {$TEXT} + } +} function Convert-IpAddressToMaskLength { <# diff --git a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 index 5887d99..f4dcd40 100644 --- a/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 +++ b/Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1 @@ -315,14 +315,30 @@ function Invoke-AsBuiltReport.Microsoft.Windows { $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'ClusSvc' -ErrorAction SilentlyContinue } if ($Status.Status -eq "Running") { try { - if (Get-RequiredFeature -Name RSAT-Clustering-PowerShell -OSType $OSType.Value -Status) { + $script:Cluster = Invoke-Command -Session $TempPssSession -ScriptBlock { (Get-Cluster).Name } + if ((Get-RequiredFeature -Name RSAT-Clustering-PowerShell -OSType $OSType.Value -Status )-and $Cluster) { Section -Style Heading2 "Failover Cluster Configuration" { Paragraph 'The following table details the Failover Cluster Settings' Blankline - # # DNS Server Configuration - # Get-AbrWinDNSInfrastructure - # # DNS Zones Configuration - # Get-AbrWinDNSZone + # Failover Cluster Server Configuration + Get-AbrWinFOCluster + # Cluster Access Permission + Get-AbrWinFOClusterPermission + # Cluster Nodes + Get-AbrWinFOClusterNode + # Cluster Available Disks + Get-AbrWinFOClusterAvailableDisk + # Cluster Fault Domain + Get-AbrWinFOClusterFaultDomain + # Cluster Networks + Get-AbrWinFOClusterNetwork + # Cluser Quorum + Get-AbrWinFOClusterQuorum + #Cluster Resources + Get-AbrWinFOClusterResource + #Cluster Shared Volume + Get-AbrWinFOClusterSharedVolume + } } else { From 6a43a3298bd80ada1eb0af1cffd39d192bd38353 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Mon, 8 May 2023 16:36:42 -0400 Subject: [PATCH 9/9] Improved bug and feature request templates --- .github/ISSUE_TEMPLATE/bug_report.md | 35 -------- .github/ISSUE_TEMPLATE/bug_report.yml | 98 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/change_request.yml | 34 ++++++++ .github/ISSUE_TEMPLATE/config.yml | 1 + .github/ISSUE_TEMPLATE/feature_request.md | 17 ---- .vscode/launch.json | 13 --- CHANGELOG.md | 15 +++- 7 files changed, 147 insertions(+), 66 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/change_request.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 .vscode/launch.json diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index b735373..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..76cb579 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,98 @@ +name: Bug Report +description: File a bug report +labels: ["bug"] +assignees: + - rebelinux +body: + - type: textarea + id: bug-description + attributes: + label: Bug description + description: >- + Please provide a clear and concise description of the bug. + validations: + required: true + - type: input + id: command-line-input + attributes: + label: Command-line input + description: >- + Please provide the command line input you are using to run AsBuiltReport. Please ensure that you obscure any sensitive information. + placeholder: New-AsBuiltReport -Report Microsoft.Windows -Target xxxxxxx -Format Word,HTML -OutputFolderPath .\Documents\ -AsBuiltConfigFilePath .\AsBuiltReport\AsBuiltReport.json -ReportConfigFilePath .\AsBuiltReport\AsBuiltReport.Microsoft.Windows.json -EnableHealthCheck -Verbose + validations: + required: true + - type: textarea + id: steps-to-reproduce + attributes: + label: Steps to reproduce + description: >- + Please provide a detailed list of steps to reproduce the bug. + placeholder: |- + 1. .... + 2. .... + 3. .... + validations: + required: true + - type: textarea + id: expected-behaviour + attributes: + label: Expected behaviour + description: >- + Please provide a clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: >- + Please attach any screenshots to help explain the problem. Please ensure that you obscure any sensitive information. + placeholder: |- + Drag and drop screenshots here. + - type: textarea + id: operating-system + attributes: + label: Operating System + description: Please provide information about the operating system are you using. + placeholder: macOS Big Sur, Windows 10, Ubuntu 20.04 LTS + validations: + required: true + - type: textarea + id: powershell-version + attributes: + label: PowerShell Version + description: Please provide information about the PowerShell version you are using. Please provide the output from the following PowerShell command `$PSVersionTable`. + placeholder: $PSVersionTable + validations: + required: true + - type: textarea + id: powershell-modules + attributes: + label: PowerShell Modules + description: Please provide information about the PowerShell modules are you using. Please provide the output from the following PowerShell command `Get-Module -ListAvailable @("AsBuiltReport.Core";"AsBuiltReport.Microsoft.Windows";"PScribo") | Select Name, Version` + placeholder: Get-Module -ListAvailable @("AsBuiltReport.Core";"AsBuiltReport.Microsoft.Windows";"PScribo") | Select Name, Version + validations: + required: true + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: This field is optional. You may provide additional context for the bug you wish to report. You may wish to include links to any related [issues](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues) or other relevant information. + - type: checkboxes + id: checklist + attributes: + label: Before submitting + description: >- + Please ensure your bug report fulfills all of the following requirements. + If you are unsure of what a specific requirement means, please follow the links to learn about it and understand why it is necessary before submitting. + options: + - label: >- + I have read and followed the [bug reporting guidelines](https://www.asbuiltreport.com/about/contributing/#reporting-issues-and-bugs). + required: true + - label: >- + I have read [the documentation](https://www.asbuiltreport.com/user-guide/new-asbuiltconfig), + and referred to the [known issues](https://www.asbuiltreport.com/user-guide/known-issues/) before submitting this bug report. + required: true + - label: >- + I have checked for previously opened & closed [issues](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues) before submitting this bug report. + required: true diff --git a/.github/ISSUE_TEMPLATE/change_request.yml b/.github/ISSUE_TEMPLATE/change_request.yml new file mode 100644 index 0000000..2808ecd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/change_request.yml @@ -0,0 +1,34 @@ +name: Change Request +description: Request a new change or an improvement +labels: ["change request"] +assignees: + - rebelinux +body: + - type: textarea + id: description + attributes: + label: Description + description: >- + Please provide a detailed description of your idea so that the project maintainers and contributors can fully understand what change, feature, or improvement you are proposing. + validations: + required: true + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: This field is optional. You may provide additional context for the idea you wish to propose. You may wish to include links to any related [issues](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues) or other relevant information. + - type: checkboxes + id: checklist + attributes: + label: Before submitting + description: >- + Please ensure your change request fulfills all of the following requirements. + If you are unsure of what a specific requirement means, please follow the links to learn about it and understand why it is necessary before submitting. + options: + - label: >- + I have read [the documentation](https://www.asbuiltreport.com/user-guide/new-asbuiltconfig), + and referred to the [known issues](https://www.asbuiltreport.com/user-guide/known-issues/) before submitting this change request. + required: true + - label: >- + I have checked for previously opened & closed [issues](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues) before submitting this change request. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..ec4bb38 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 066b2d9..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index bd155eb..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "PowerShell: Interactive Session", - "type": "PowerShell", - "request": "launch" - } - ] -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d6c798a..72c863a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ # :arrows_counterclockwise: Microsoft Windows As Built Report Changelog -## [0.4.1] - 2022-10-XX +## [0.5.0] - 2023-05-08 + +### Added + +- Added FailOver Cluster section + +### Changed + +- Improved bug and feature request templates +- Changed default logo from Microsoft to the AsBuiltReport logo due to licensing requirements +- Changed default report style font to 'Segoe Ui' to align with Microsoft guidelines +- Changed Required Modules to AsBuiltReport.Core v1.3.0 + +## [0.4.1] - 2022-10-20 ### Fixed