Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ powershell -ExecutionPolicy Bypass -File Tests\pssa-check.ps1

## Pull Request Checklist

- [ ] All 5,025 tests pass (`Run-Tests.ps1` exits with code 0)
- [ ] All 5,032 tests pass (`Run-Tests.ps1` exits with code 0)
- [ ] PSScriptAnalyzer reports 0 errors (`pssa-check.ps1`)
- [ ] Monolithic synced (`sync-to-monolithic.ps1` shows 0 parse errors)
- [ ] New functions follow PowerShell verb-noun naming (`Get-`, `Set-`, `Test-`, `Show-`)
Expand Down
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v1.109.0

VHDX encryption-at-rest verification — added to **BitLocker Management** (`[7] VHDX Encryption-at-Rest Audit`) and via the `VHDXEncryptionAudit` CLI action. A **read-only** check that reports whether each Hyper-V VM's virtual disk (VHD/VHDX) sits on a BitLocker-protected volume — so you can confirm VM storage is encrypted at rest.

It enumerates the virtual disks attached to the host's VMs, resolves the volume each one lives on, and reports **encrypted / unencrypted / unknown** per disk plus a summary count. Volumes that BitLocker can't enumerate (Cluster Shared Volumes, UNC, remote storage) are reported as "unknown" rather than guessed. `-Action VHDXEncryptionAudit -OutputFormat JSON` emits the per-disk result for fleet auditing. Makes no changes.

## v1.108.0

Windows Admin Center — new module (77-WindowsAdminCenter.ps1), reachable from **Roles & Features → [13] Windows Admin Center (WAC)** and via the `WACSetup` / `WACStatus` CLI actions. Installs and configures the WAC gateway on this host.
Expand Down
4 changes: 2 additions & 2 deletions Header.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
7h3 4b1d3r

.VERSION
1.108.0
1.109.0

.LAST UPDATED
05/23/2026
Expand Down Expand Up @@ -1391,7 +1391,7 @@
param(
# CLI headless mode: run a specific action without interactive menus
# Usage: RackStack.exe -Action Cleanup [-Tier Standard] [-Silent] [-OutputFormat JSON]
[ValidateSet('Cleanup', 'Debloat', 'HealthCheck', 'Batch', 'QuickScan', 'Inventory', 'DriftCheck', 'Snapshot', 'Compliance', 'Harden', 'Remediate', 'Aggregate', 'Compare', 'Export', 'Trend', 'CertCheck', 'ReportHTML', 'ListeningPorts', 'SoftwareList', 'Uptime', 'ServiceAudit', 'EventAudit', 'NetInfo', 'ScheduledExport', 'ValidateConfig', 'Watch', 'Query', 'Diff', 'Baseline', 'Alert', 'FleetScan', 'PatchStatus', 'UserAudit', 'FirewallAudit', 'TaskAudit', 'DiskAudit', 'TLSAudit', 'SMBAudit', 'DriverAudit', 'TimeAudit', 'BootAudit', 'GPOAudit', 'MemoryAudit', 'ProcessAudit', 'BackupAudit', 'ShareAudit', 'DNSAudit', 'PowerAudit', 'RegistryAudit', 'ProfileAudit', 'HyperVAudit', 'NetworkAudit', 'StorageAudit', 'FeatureAudit', 'AutoStartAudit', 'BIOSAudit', 'ClusterAudit', 'AuditPolicyAudit', 'EnvAudit', 'CrashAudit', 'LocalGroupAudit', 'WMIAudit', 'TempAudit', 'UpdatePolicyAudit', 'IISAudit', 'SSHAudit', 'BitLockerAudit', 'PrintAudit', 'CredGuardAudit', 'PortAudit', 'AntivirusAudit', 'DotNetAudit', 'RDPAudit', 'VPNAudit', 'HostsFileAudit', 'NetStatAudit', 'LicenseAudit', 'USBDeviceAudit', 'AppLockerAudit', 'EventSubAudit', 'HotfixAudit', 'SysInfoAudit', 'LogonAudit', 'ACLAudit', 'RecoveryAudit', 'ServiceAccountAudit', 'ProxyAudit', 'PendingRebootAudit', 'PageFileAudit', 'CPUAudit', 'DefenderExclusionAudit', 'KerberosAudit', 'DHCPAudit', 'NUMAAudit', 'SymlinkAudit', 'StartupScriptAudit', 'SecureChannelAudit', 'ComObjectAudit', 'FirewallLogAudit', 'ScheduledRebootAudit', 'PowerShellAudit', 'RouteTableAudit', 'TokenPrivilegeAudit', 'WindowsCapabilityAudit', 'ARPTableAudit', 'LocaleAudit', 'TaskHistoryAudit', 'NTFSAudit', 'Win11Cleanup', 'DarkMode', 'LightMode', 'iSCSIAudit', 'NICTeamAudit', 'SMBSessionAudit', 'WindowsUpdateAudit', 'ClusterQuorumAudit', 'S2DAudit', 'VirtualSwitchAudit', 'MPIOPathAudit', 'ServiceRecoveryAudit', 'VMOvercommitAudit', 'DedupAudit', 'ClusterNetworkAudit', 'ReplicaLagAudit', 'HandleLeakAudit', 'ShadowCopyAudit', 'QoSPolicyAudit', 'LiveMigrationAudit', 'DomainTrustAudit', 'DiskLatencyAudit', 'NICOffloadAudit', 'StorageTimeoutAudit', 'EventLogCapacityAudit', 'TcpSettingsAudit', 'WinRMAudit', 'ClusterHealthScore', 'VMInventoryExport', 'VMSnapshotAudit', 'StorageHealthScore', 'CSVSpaceAudit', 'SMBConnectionAudit', 'VolumeLabelAudit', 'NICErrorAudit', 'VMResourceWaste', 'HealthDashboard', 'SCCMClientAudit', 'SCOMAgentAudit', 'WACConnectivityAudit', 'AzureADAudit', 'ServerScore', 'FleetReport', 'PasswordPolicy', 'FirewallRuleAudit', 'GPResultAudit', 'DNSCacheAudit', 'TPMAudit', 'SecureBootAudit', 'TimeSkewAudit', 'NetworkProfileAudit', 'InsecureServiceAudit', 'SelfTest', 'CheckForUpdate', 'ExportLogs', 'UpdateSelf', 'Rollback', 'ScheduleUpdateCheck', 'Dashboard', 'History', 'Replay', 'AzureArcEnroll', 'DefenderEndpointOnboard', 'WSUSSetup', 'ADCSSetup', 'StorageMigrationSetup', 'GPOBackup', 'GPODrift', 'JEAList', 'NPSSetup', 'AlwaysOnVPNSetup', 'CISScan', 'SIEMSetup', 'SIEMStatus', 'WACSetup', 'WACStatus')]
[ValidateSet('Cleanup', 'Debloat', 'HealthCheck', 'Batch', 'QuickScan', 'Inventory', 'DriftCheck', 'Snapshot', 'Compliance', 'Harden', 'Remediate', 'Aggregate', 'Compare', 'Export', 'Trend', 'CertCheck', 'ReportHTML', 'ListeningPorts', 'SoftwareList', 'Uptime', 'ServiceAudit', 'EventAudit', 'NetInfo', 'ScheduledExport', 'ValidateConfig', 'Watch', 'Query', 'Diff', 'Baseline', 'Alert', 'FleetScan', 'PatchStatus', 'UserAudit', 'FirewallAudit', 'TaskAudit', 'DiskAudit', 'TLSAudit', 'SMBAudit', 'DriverAudit', 'TimeAudit', 'BootAudit', 'GPOAudit', 'MemoryAudit', 'ProcessAudit', 'BackupAudit', 'ShareAudit', 'DNSAudit', 'PowerAudit', 'RegistryAudit', 'ProfileAudit', 'HyperVAudit', 'NetworkAudit', 'StorageAudit', 'FeatureAudit', 'AutoStartAudit', 'BIOSAudit', 'ClusterAudit', 'AuditPolicyAudit', 'EnvAudit', 'CrashAudit', 'LocalGroupAudit', 'WMIAudit', 'TempAudit', 'UpdatePolicyAudit', 'IISAudit', 'SSHAudit', 'BitLockerAudit', 'PrintAudit', 'CredGuardAudit', 'PortAudit', 'AntivirusAudit', 'DotNetAudit', 'RDPAudit', 'VPNAudit', 'HostsFileAudit', 'NetStatAudit', 'LicenseAudit', 'USBDeviceAudit', 'AppLockerAudit', 'EventSubAudit', 'HotfixAudit', 'SysInfoAudit', 'LogonAudit', 'ACLAudit', 'RecoveryAudit', 'ServiceAccountAudit', 'ProxyAudit', 'PendingRebootAudit', 'PageFileAudit', 'CPUAudit', 'DefenderExclusionAudit', 'KerberosAudit', 'DHCPAudit', 'NUMAAudit', 'SymlinkAudit', 'StartupScriptAudit', 'SecureChannelAudit', 'ComObjectAudit', 'FirewallLogAudit', 'ScheduledRebootAudit', 'PowerShellAudit', 'RouteTableAudit', 'TokenPrivilegeAudit', 'WindowsCapabilityAudit', 'ARPTableAudit', 'LocaleAudit', 'TaskHistoryAudit', 'NTFSAudit', 'Win11Cleanup', 'DarkMode', 'LightMode', 'iSCSIAudit', 'NICTeamAudit', 'SMBSessionAudit', 'WindowsUpdateAudit', 'ClusterQuorumAudit', 'S2DAudit', 'VirtualSwitchAudit', 'MPIOPathAudit', 'ServiceRecoveryAudit', 'VMOvercommitAudit', 'DedupAudit', 'ClusterNetworkAudit', 'ReplicaLagAudit', 'HandleLeakAudit', 'ShadowCopyAudit', 'QoSPolicyAudit', 'LiveMigrationAudit', 'DomainTrustAudit', 'DiskLatencyAudit', 'NICOffloadAudit', 'StorageTimeoutAudit', 'EventLogCapacityAudit', 'TcpSettingsAudit', 'WinRMAudit', 'ClusterHealthScore', 'VMInventoryExport', 'VMSnapshotAudit', 'StorageHealthScore', 'CSVSpaceAudit', 'SMBConnectionAudit', 'VolumeLabelAudit', 'NICErrorAudit', 'VMResourceWaste', 'HealthDashboard', 'SCCMClientAudit', 'SCOMAgentAudit', 'WACConnectivityAudit', 'AzureADAudit', 'ServerScore', 'FleetReport', 'PasswordPolicy', 'FirewallRuleAudit', 'GPResultAudit', 'DNSCacheAudit', 'TPMAudit', 'SecureBootAudit', 'TimeSkewAudit', 'NetworkProfileAudit', 'InsecureServiceAudit', 'SelfTest', 'CheckForUpdate', 'ExportLogs', 'UpdateSelf', 'Rollback', 'ScheduleUpdateCheck', 'Dashboard', 'History', 'Replay', 'AzureArcEnroll', 'DefenderEndpointOnboard', 'WSUSSetup', 'ADCSSetup', 'StorageMigrationSetup', 'GPOBackup', 'GPODrift', 'JEAList', 'NPSSetup', 'AlwaysOnVPNSetup', 'CISScan', 'SIEMSetup', 'SIEMStatus', 'WACSetup', 'WACStatus', 'VHDXEncryptionAudit')]
[string]$Action,

[ValidateSet('Light', 'Standard', 'Aggressive')]
Expand Down
2 changes: 1 addition & 1 deletion Modules/00-Initialization.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ if (-not $PSCommandPath -and $script:ScriptPath) {
if (-not $script:ModuleRoot -and $script:ScriptPath) {
$script:ModuleRoot = [System.IO.Path]::GetDirectoryName($script:ScriptPath)
}
$script:ScriptVersion = "1.108.0"
$script:ScriptVersion = "1.109.0"
$script:ScriptStartTime = Get-Date

# Post-update cleanup: UpdateSelf / Rollback leave a `.pending-delete` sibling next to RackStack.exe.
Expand Down
73 changes: 72 additions & 1 deletion Modules/31-BitLocker.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ function Show-BitLockerManagement {
Write-MenuItem -Text "[4] Show Recovery Key"
Write-MenuItem -Text "[5] Check Encryption Progress"
Write-MenuItem -Text "[6] Verify Recovery Key Backup"
Write-MenuItem -Text "[7] VHDX Encryption-at-Rest Audit"
Write-OutputColor " └────────────────────────────────────────────────────────────────────────┘" -color "Info"
Write-OutputColor "" -color "Info"
Write-OutputColor " [B] ◄ Back" -color "Info"
Expand Down Expand Up @@ -492,11 +493,81 @@ function Show-BitLockerManagement {
Write-OutputColor "" -color "Info"
Test-BitLockerRecoveryBackup
}
"7" { Show-VHDXEncryptionAudit }
{ $_ -eq "b" -or $_ -eq "B" } { return }
default { Write-OutputColor " Invalid choice. Enter 1-6 or B." -color "Error"; Start-Sleep -Seconds 1 }
default { Write-OutputColor " Invalid choice. Enter 1-7 or B." -color "Error"; Start-Sleep -Seconds 1 }
}

Write-PressEnter
}
}

# Read-only encryption-at-rest verification: report whether each VHD/VHDX
# backing a Hyper-V VM sits on a BitLocker-protected volume. No changes made.
function Get-VHDXEncryptionStatus {
$paths = New-Object System.Collections.Generic.List[string]
try {
if (Get-Command -Name Get-VM -ErrorAction SilentlyContinue) {
foreach ($d in (Get-VM -ErrorAction SilentlyContinue | Get-VMHardDiskDrive -ErrorAction SilentlyContinue)) {
if (-not [string]::IsNullOrWhiteSpace($d.Path)) { $paths.Add($d.Path) }
}
}
}
catch { }
$unique = @($paths | Sort-Object -Unique)
# Cache volume -> protection status from BitLocker once.
$blByMount = @{}
try { foreach ($v in (Get-BitLockerVolume -ErrorAction SilentlyContinue)) { $blByMount["$($v.MountPoint)"] = "$($v.ProtectionStatus)" } } catch { }
$results = @()
foreach ($p in $unique) {
$root = $null
try { $root = ([System.IO.Path]::GetPathRoot($p)).TrimEnd('\') } catch { }
$prot = if ($root -and $blByMount.ContainsKey($root)) { $blByMount[$root] } else { "Unknown" }
$results += [PSCustomObject]@{
Path = $p; Volume = $root; Protection = $prot; Encrypted = ($prot -eq 'On')
}
}
return $results
}

# Interactive display of the VHDX encryption-at-rest audit.
function Show-VHDXEncryptionAudit {
Clear-Host
Write-CenteredOutput "VHDX Encryption-at-Rest Audit" -color "Info"
if ($null -eq (Get-Command -Name Get-BitLockerVolume -ErrorAction SilentlyContinue)) {
Write-OutputColor " BitLocker is not available on this system." -color "Warning"; return
}
$r = @(Get-VHDXEncryptionStatus)
if ($r.Count -eq 0) {
Write-OutputColor " No VHD/VHDX virtual disks found (no Hyper-V VMs, or none attached)." -color "Info"; return
}
Write-OutputColor "" -color "Info"
foreach ($item in $r) {
$label = if ($item.Encrypted) { "ENCRYPTED" } elseif ($item.Protection -eq 'Off') { "UNENCRYPTED" } else { "UNKNOWN" }
$c = if ($item.Encrypted) { "Success" } elseif ($item.Protection -eq 'Off') { "Error" } else { "Warning" }
Write-OutputColor (" [{0}] {1}" -f $label, $item.Path) -color $c
Write-OutputColor (" volume: $(if ($item.Volume) { $item.Volume } else { 'unresolved (CSV/UNC/remote)' })") -color "Debug"
}
$enc = @($r | Where-Object { $_.Encrypted }).Count
Write-OutputColor "" -color "Info"
Write-OutputColor " $enc of $($r.Count) virtual disk(s) sit on BitLocker-protected volumes." -color "Info"
Write-OutputColor " 'Unknown' volumes (CSV / UNC / remote storage) are not enumerable by Get-BitLockerVolume." -color "Debug"
}

# CLI entry: VHDXEncryptionAudit — read-only, JSON-aware.
function Start-VHDXEncryptionAudit {
$r = @(Get-VHDXEncryptionStatus)
if ($script:CLIOutputFormat -eq 'JSON') {
Write-Output (@{
Tool = $script:ToolFullName; Version = $script:ScriptVersion; Action = 'VHDXEncryptionAudit'
Timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss"); Hostname = $env:COMPUTERNAME
TotalDisks = $r.Count; EncryptedDisks = @($r | Where-Object { $_.Encrypted }).Count
Disks = @($r | ForEach-Object { @{ Path = $_.Path; Volume = $_.Volume; Protection = $_.Protection; Encrypted = $_.Encrypted } })
} | ConvertTo-Json -Depth 5)
}
else {
Show-VHDXEncryptionAudit
}
return $true
}
#endregion
2 changes: 1 addition & 1 deletion Modules/34-Help.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ function Search-HelpTopics {
@{ Title = "Performance"; Keywords = @("performance", "cpu", "memory", "disk", "io", "bandwidth", "dashboard", "process"); Description = "Live performance dashboard with CPU, memory, disk I/O, and network bandwidth monitoring" }
@{ Title = "Licensing & NTP"; Keywords = @("license", "activation", "kms", "avma", "ntp", "time", "timezone", "clock"); Description = "Windows licensing status (KMS/AVMA/Retail), NTP configuration, time sync, and timezone setup" }
@{ Title = "VM Management"; Keywords = @("checkpoint", "snapshot", "export", "import", "migration", "vhd", "iso"); Description = "VM checkpoints, export/import, migration readiness, VHD health, and ISO inventory" }
@{ Title = "CLI Actions"; Keywords = @("cli", "action", "headless", "automation", "fleet", "json", "audit", "scan", "score", "dashboard", "monitor", "policy", "sla", "netmap", "validate"); Description = "191 CLI actions for headless automation. Run -ListActions to see all. JSON output via -OutputFormat JSON. Key: ServerScore, HealthDashboard, FleetReport, CISScan, NPSSetup, AlwaysOnVPNSetup, SIEMStatus." }
@{ Title = "CLI Actions"; Keywords = @("cli", "action", "headless", "automation", "fleet", "json", "audit", "scan", "score", "dashboard", "monitor", "policy", "sla", "netmap", "validate"); Description = "192 CLI actions for headless automation. Run -ListActions to see all. JSON output via -OutputFormat JSON. Key: ServerScore, HealthDashboard, FleetReport, CISScan, NPSSetup, AlwaysOnVPNSetup, SIEMStatus." }
@{ Title = "SelfTest Action"; Keywords = @("selftest", "self-test", "diagnose", "diagnostic", "verify", "healthcheck", "sanity"); Description = "Internal diagnostic. -Action SelfTest checks PS version, elevation, module count, version consistency, defaults.json validity, temp path writability, FileServer reachability, and agent installer config. Exit 1 on any failure. Use -OutputFormat JSON for structured output." }
@{ Title = "Security Audits"; Keywords = @("security", "audit", "hardening", "compliance", "tls", "smb", "kerberos", "credguard", "applocker", "bitlockeraudit", "defenderexclusionaudit", "audit-policy", "secureboot", "tpm"); Description = "Security-focused CLI audits: TLSAudit, SMBAudit, KerberosAudit, CredGuardAudit, AppLockerAudit, BitLockerAudit, DefenderExclusionAudit, AuditPolicyAudit, SecureBootAudit, TPMAudit, UserAudit, LogonAudit, InsecureServiceAudit, RegistryAudit. All support -OutputFormat JSON." }
@{ Title = "Network Audits"; Keywords = @("netaudit", "dns", "firewall-audit", "firewalllog", "arp", "route", "tcp", "netstat", "dhcp", "netprofile", "winrm", "qos", "nicoffload"); Description = "Network audits: DNSAudit, DNSCacheAudit, FirewallAudit, FirewallRuleAudit, FirewallLogAudit, ARPTableAudit, RouteTableAudit, TcpSettingsAudit, NetStatAudit, DHCPAudit, NetworkProfileAudit, WinRMAudit, QoSPolicyAudit, NICOffloadAudit, NICErrorAudit, HostsFileAudit, VPNAudit, ProxyAudit." }
Expand Down
6 changes: 6 additions & 0 deletions Modules/50-EntryPoint.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ function Assert-Elevation {
@{ Action = 'SIEMStatus'; Description = 'Show SIEM log-forwarder readiness (WEF / WinRM / agents / Arc)' }
@{ Action = 'WACSetup'; Description = 'Install + configure the Windows Admin Center gateway (verified MSI, port, certificate)' }
@{ Action = 'WACStatus'; Description = 'Show Windows Admin Center gateway status (service, port, listening)' }
@{ Action = 'VHDXEncryptionAudit'; Description = 'Read-only: report whether each VM virtual disk sits on a BitLocker-protected volume' }
@{ Action = 'Batch'; Description = 'JSON-driven full configuration' }
)
if ($script:CLIOutputFormat -eq 'JSON') {
Expand Down Expand Up @@ -2041,6 +2042,11 @@ footer{text-align:center;color:#999;font-size:12px;padding:16px}
$wacOk = Start-WACSetup
[Environment]::Exit([int](-not $wacOk))
}
'VHDXEncryptionAudit' {
# Read-only: which VM virtual disks sit on BitLocker-protected volumes (JSON-aware).
$vhdxOk = Start-VHDXEncryptionAudit
[Environment]::Exit([int](-not $vhdxOk))
}
'Batch' {
if (-not $script:CLIConfig) {
Write-OutputColor " ERROR: -Action Batch requires -Config <path>" -color "Error"
Expand Down
Loading
Loading