diff --git a/Changelog.md b/Changelog.md index 0108d80..670dae9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,14 @@ # Changelog +## v1.113.0 + +SMB signing + encryption enforcement — two new CLI actions plus an Operations-menu item for hardening the SMB server on this host. + +- **`SmbSecurityCheck`** (read-only) — reports the current SMB server posture: required/enabled signing, `EncryptData`, `RejectUnencryptedAccess`, and whether SMBv1 is still enabled. `-OutputFormat JSON` emits the posture for fleet auditing; no changes are made. +- **`SmbEnforce`** (reversible) — requires SMB signing **and** encryption for every share served by this host (`Set-SmbServerConfiguration -RequireSecuritySignature $true -EncryptData $true`). The prior signing/encryption state is captured first and registered as a session undo action, and the change is fully Dry-Run aware (queued with an `Undo` closure that restores the prior values). + +Operations Menu gains **[35] SMB Signing & Encryption Enforcement** (interactive, with a confirmation prompt and a heads-up that very old clients that cannot sign/encrypt SMB may lose access). Addition to 56-OperationsMenu (no new module). CLI actions: 194 → 196. + ## v1.112.0 Richer VM inventory — the existing `VMInventoryExport` action now captures more per-VM detail for fleet auditing: diff --git a/Header.ps1 b/Header.ps1 index 92a0a30..28bc95d 100644 --- a/Header.ps1 +++ b/Header.ps1 @@ -30,7 +30,7 @@ 7h3 4b1d3r .VERSION - 1.112.0 + 1.113.0 .LAST UPDATED 05/23/2026 @@ -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', 'VHDXEncryptionAudit', 'ADRecycleBin', 'ClusterValidationReport')] + [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', 'ADRecycleBin', 'ClusterValidationReport', 'SmbEnforce', 'SmbSecurityCheck')] [string]$Action, [ValidateSet('Light', 'Standard', 'Aggressive')] diff --git a/Modules/00-Initialization.ps1 b/Modules/00-Initialization.ps1 index 5246ba4..98efad3 100644 --- a/Modules/00-Initialization.ps1 +++ b/Modules/00-Initialization.ps1 @@ -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.112.0" +$script:ScriptVersion = "1.113.0" $script:ScriptStartTime = Get-Date # Post-update cleanup: UpdateSelf / Rollback leave a `.pending-delete` sibling next to RackStack.exe. diff --git a/Modules/34-Help.ps1 b/Modules/34-Help.ps1 index b4a3d7b..37afd6f 100644 --- a/Modules/34-Help.ps1 +++ b/Modules/34-Help.ps1 @@ -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 = "194 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 = "196 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." } diff --git a/Modules/50-EntryPoint.ps1 b/Modules/50-EntryPoint.ps1 index 50649ef..688ce67 100644 --- a/Modules/50-EntryPoint.ps1 +++ b/Modules/50-EntryPoint.ps1 @@ -412,6 +412,8 @@ function Assert-Elevation { @{ Action = 'VHDXEncryptionAudit'; Description = 'Read-only: report whether each VM virtual disk sits on a BitLocker-protected volume' } @{ Action = 'ADRecycleBin'; Description = 'Show AD Recycle Bin status (JSON) or enable it interactively (irreversible)' } @{ Action = 'ClusterValidationReport'; Description = 'Run a non-disruptive failover-cluster validation and archive the HTML report (JSON-aware)' } + @{ Action = 'SmbSecurityCheck'; Description = 'Read-only: report SMB server signing/encryption posture (JSON-aware)' } + @{ Action = 'SmbEnforce'; Description = 'Enforce SMB server signing + encryption (reversible)' } @{ Action = 'Batch'; Description = 'JSON-driven full configuration' } ) if ($script:CLIOutputFormat -eq 'JSON') { @@ -2059,6 +2061,16 @@ footer{text-align:center;color:#999;font-size:12px;padding:16px} $cvrOk = Start-ClusterValidationReport [Environment]::Exit([int](-not $cvrOk)) } + 'SmbSecurityCheck' { + # Read-only SMB signing/encryption posture (JSON-aware). + $smbChkOk = Start-SmbSecurityCheck + [Environment]::Exit([int](-not $smbChkOk)) + } + 'SmbEnforce' { + # Enforce SMB signing + encryption (reversible; headless applies, console interactive). + $smbEnfOk = Start-SmbEnforce + [Environment]::Exit([int](-not $smbEnfOk)) + } 'Batch' { if (-not $script:CLIConfig) { Write-OutputColor " ERROR: -Action Batch requires -Config " -color "Error" diff --git a/Modules/56-OperationsMenu.ps1 b/Modules/56-OperationsMenu.ps1 index 4f987bf..80b19ee 100644 --- a/Modules/56-OperationsMenu.ps1 +++ b/Modules/56-OperationsMenu.ps1 @@ -70,6 +70,7 @@ function Show-OperationsMenu { Write-MenuItem "[29] Reboot Pending Details" Write-MenuItem "[30] Memory Pressure Diagnostics" Write-MenuItem "[34] CIS Compliance Scan (CIS L1)" + Write-MenuItem "[35] SMB Signing & Encryption Enforcement" Write-OutputColor " └────────────────────────────────────────────────────────────────────────┘" -color "Info" Write-OutputColor "" -color "Info" @@ -103,6 +104,7 @@ function Show-OperationsMenu { @{Num="29"; Name="Reboot Pending Details"}; @{Num="30"; Name="Memory Pressure Diagnostics"} @{Num="31"; Name="Batch VM Cleanup"}; @{Num="32"; Name="VM Migration Pre-Flight"} @{Num="33"; Name="Logged-On Users"}; @{Num="34"; Name="CIS Compliance Scan (CIS L1)"} + @{Num="35"; Name="SMB Signing & Encryption Enforcement"} ) $matched = @($opsItems | Where-Object { $_.Name -match [regex]::Escape($searchTerm) }) Write-OutputColor "" -color "Info" @@ -272,10 +274,14 @@ function Show-OperationsMenu { Invoke-CISScanInteractive Write-PressEnter } + "35" { + Set-SMBServerSecurity + Write-PressEnter + } "b" { return } "B" { return } default { - Write-OutputColor " Invalid choice. Enter 1-34, [/] to search, or B." -color "Error" + Write-OutputColor " Invalid choice. Enter 1-35, [/] to search, or B." -color "Error" Start-Sleep -Seconds 1 } } @@ -2283,4 +2289,104 @@ function Test-VMMigrationReadiness { Write-OutputColor "`n Pre-flight check complete" -color "Success" } + +# Read-only: current SMB server signing / encryption posture. +function Get-SMBServerSecurityStatus { + try { + $c = Get-SmbServerConfiguration -ErrorAction Stop + return [PSCustomObject]@{ + Available = $true + RequireSecuritySignature = [bool]$c.RequireSecuritySignature + EnableSecuritySignature = [bool]$c.EnableSecuritySignature + EncryptData = [bool]$c.EncryptData + RejectUnencryptedAccess = [bool]$c.RejectUnencryptedAccess + SMB1Enabled = [bool]$c.EnableSMB1Protocol + } + } + catch { return [PSCustomObject]@{ Available = $false } } +} + +# Interactive: require SMB signing + encryption on this server (reversible). +function Set-SMBServerSecurity { + Clear-Host + Write-CenteredOutput "SMB Signing & Encryption Enforcement" -color "Info" + $s = Get-SMBServerSecurityStatus + if (-not $s.Available) { Write-OutputColor " SMB server configuration is not available." -color "Error"; return } + Write-OutputColor " Current: RequireSigning=$($s.RequireSecuritySignature) EncryptData=$($s.EncryptData) SMBv1=$($s.SMB1Enabled)" -color "Info" + Write-OutputColor " Enforcing requires SMB signing AND encryption for all shares served by this host." -color "Info" + Write-OutputColor " NOTE: very old clients that cannot sign/encrypt SMB may lose access." -color "Warning" + if (-not (Confirm-UserAction -Message "Require SMB signing + encryption on this server?")) { Write-OutputColor " Cancelled." -color "Info"; return } + $priorSign = $s.RequireSecuritySignature; $priorEnc = $s.EncryptData + + if ($script:DryRunMode -and -not $script:ApplyingDryRunQueue) { + $cs = $priorSign; $ce = $priorEnc + Push-DryRunStep -Label "Enforce SMB signing + encryption" -Category "Security" -OneWay $false ` + -Params @{ RequireSigning = $true; EncryptData = $true } ` + -Preflight { $true }.GetNewClosure() ` + -Apply { Set-SmbServerConfiguration -RequireSecuritySignature $true -EncryptData $true -Force -ErrorAction SilentlyContinue }.GetNewClosure() ` + -Undo { Set-SmbServerConfiguration -RequireSecuritySignature $cs -EncryptData $ce -Force -ErrorAction SilentlyContinue }.GetNewClosure() + Write-OutputColor " Queued (Dry-Run): enforce SMB signing + encryption." -color "Warning" + Add-SessionChange -Category "DryRun" -Description "Queued SMB signing+encryption enforcement" + return + } + + try { + Set-SmbServerConfiguration -RequireSecuritySignature $true -EncryptData $true -Force -ErrorAction Stop + Write-OutputColor " SMB signing + encryption are now required." -color "Success" + Add-SessionChange -Category "Security" -Description "Enforced SMB signing + encryption" + Add-UndoAction -Category "Security" -Description "Enforced SMB signing + encryption" -UndoScript { + param($Sign, $Enc) + Set-SmbServerConfiguration -RequireSecuritySignature $Sign -EncryptData $Enc -Force -ErrorAction SilentlyContinue + } -UndoParams @{ Sign = $priorSign; Enc = $priorEnc } + Clear-MenuCache + } + catch { + Write-OutputColor " Failed to apply SMB security: $($_.Exception.Message)" -color "Error" + } +} + +# Submenu: SMB signing / encryption. +function Show-SMBSecurityManagement { + Clear-Host + Write-CenteredOutput "SMB Signing & Encryption" -color "Info" + $s = Get-SMBServerSecurityStatus + if ($s.Available) { + Write-OutputColor " RequireSigning : $($s.RequireSecuritySignature)" -color "Info" + Write-OutputColor " EncryptData : $($s.EncryptData)" -color "Info" + Write-OutputColor " SMBv1 enabled : $($s.SMB1Enabled)" -color $(if ($s.SMB1Enabled) { "Warning" } else { "Info" }) + } + Write-OutputColor "" -color "Info" + if (Confirm-UserAction -Message "Enforce SMB signing + encryption now?") { Set-SMBServerSecurity } +} + +# CLI: SmbSecurityCheck — read-only JSON status. +function Start-SmbSecurityCheck { + $s = Get-SMBServerSecurityStatus + if ($script:CLIOutputFormat -eq 'JSON') { + Write-Output (@{ + Tool = $script:ToolFullName; Version = $script:ScriptVersion; Action = 'SmbSecurityCheck' + Timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss"); Hostname = $env:COMPUTERNAME + Available = $s.Available; RequireSigning = $s.RequireSecuritySignature; EncryptData = $s.EncryptData; SMB1Enabled = $s.SMB1Enabled + } | ConvertTo-Json) + } + else { Show-SMBSecurityManagement } + return $true +} + +# CLI: SmbEnforce — apply signing+encryption (headless applies; console is interactive). +function Start-SmbEnforce { + if ($script:CLIOutputFormat -eq 'JSON') { + $ok = $true + try { Set-SmbServerConfiguration -RequireSecuritySignature $true -EncryptData $true -Force -ErrorAction Stop } catch { $ok = $false } + $s = Get-SMBServerSecurityStatus + Write-Output (@{ + Tool = $script:ToolFullName; Version = $script:ScriptVersion; Action = 'SmbEnforce' + Timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss"); Hostname = $env:COMPUTERNAME + Success = $ok; RequireSigning = $s.RequireSecuritySignature; EncryptData = $s.EncryptData + } | ConvertTo-Json) + return $ok + } + Set-SMBServerSecurity + return $true +} #endregion \ No newline at end of file diff --git a/README.md b/README.md index 1ac4440..1363f15 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ OpenSSF Best Practices codecov PSScriptAnalyzer 0 errors - 5048 structural tests + 5061 structural tests Pester 312 tests SLSA Level 3

@@ -37,7 +37,7 @@ --- -RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." Where sconfig gives you 15 options, RackStack gives you 194 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, cloud onboarding, and batch automation, all with undo, transaction rollback, and audit logging. +RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." Where sconfig gives you 15 options, RackStack gives you 196 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, cloud onboarding, and batch automation, all with undo, transaction rollback, and audit logging. Built for MSPs, sysadmins, and infrastructure teams who build servers repeatedly and want it done right every time. @@ -61,7 +61,7 @@ Built for MSPs, sysadmins, and infrastructure teams who build servers repeatedly **Automation** -- JSON-driven batch mode (24 idempotent steps with transaction rollback), Quick Setup Wizard, configuration export/import, HTML reports, JSON audit logging with rotation -**Monitoring** -- 194 CLI actions with JSON output for fleet automation, `ServerScore` (unified 0-100 health grade), `HealthDashboard` (all-in-one monitoring endpoint), `ClusterHealthScore`, `StorageHealthScore`, System Center (SCCM/SCOM/WAC) + Azure AD/Intune integration +**Monitoring** -- 196 CLI actions with JSON output for fleet automation, `ServerScore` (unified 0-100 health grade), `HealthDashboard` (all-in-one monitoring endpoint), `ClusterHealthScore`, `StorageHealthScore`, System Center (SCCM/SCOM/WAC) + Azure AD/Intune integration **Cloud & Security** -- Azure Arc server onboarding (install the Connected Machine Agent, connect the host to Azure's hybrid management plane via service-principal auth); Microsoft Defender for Endpoint onboarding (activate the built-in EDR sensor against your tenant, with a built-in detection test) @@ -439,7 +439,7 @@ $report.Issues **Tiers:** `Light` (minimal, safe for prod), `Standard` (recommended), `Aggressive` (maximum cleanup/debloat). -### 194 CLI Actions +### 196 CLI Actions | Category | Actions | |----------|---------| diff --git a/RackStack.ps1 b/RackStack.ps1 index a756126..5bce3a1 100644 --- a/RackStack.ps1 +++ b/RackStack.ps1 @@ -13,7 +13,7 @@ Environment-specific settings are configured via defaults.json. .VERSION - 1.112.0 + 1.113.0 .NOTES - Requires Windows Server 2012 R2 or later (or Windows 10/11 for testing) diff --git a/RackStack.psd1 b/RackStack.psd1 index 406ec54..746e3e4 100644 --- a/RackStack.psd1 +++ b/RackStack.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'RackStack.psm1' - ModuleVersion = '1.112.0' + ModuleVersion = '1.113.0' GUID = 'c19b8e71-4a35-4f2b-9d06-8a24f7bc0e91' Author = 'TheAbider' CompanyName = 'TheAbider' diff --git a/Tests/Run-Tests.ps1 b/Tests/Run-Tests.ps1 index 8aa8737..bbed3b6 100644 --- a/Tests/Run-Tests.ps1 +++ b/Tests/Run-Tests.ps1 @@ -9104,6 +9104,37 @@ catch { Write-TestResult "VM Inventory Enrichment Tests" $false $_.Exception.Message } +# ============================================================================ +# SECTION 180: SMB SIGNING + ENCRYPTION ENFORCEMENT (v1.113.0, 56-OperationsMenu) +# ============================================================================ +Write-SectionHeader "SECTION 180: SMB SIGNING + ENCRYPTION ENFORCEMENT (56-OperationsMenu)" + +try { + $smbC = Get-Content "$modulesPath\56-OperationsMenu.ps1" -Raw + Write-TestResult "56-Ops: Get-SMBServerSecurityStatus exists" ($smbC -match 'function\s+Get-SMBServerSecurityStatus\b') + Write-TestResult "56-Ops: Set-SMBServerSecurity exists" ($smbC -match 'function\s+Set-SMBServerSecurity\b') + Write-TestResult "56-Ops: Start-SmbSecurityCheck exists" ($smbC -match 'function\s+Start-SmbSecurityCheck\b') + Write-TestResult "56-Ops: Start-SmbEnforce exists" ($smbC -match 'function\s+Start-SmbEnforce\b') + # Reversible: enforce captures prior state and registers an undo action. + Write-TestResult "56-Ops: SMB enforce registers an undo action" ($smbC -match 'function\s+Set-SMBServerSecurity[\s\S]{0,3000}Add-UndoAction') + # Dry-Run aware: queues with an Undo closure (no -OneWay enforcement, it's reversible). + Write-TestResult "56-Ops: SMB enforce is Dry-Run aware (reversible)" ($smbC -match 'Set-SMBServerSecurity[\s\S]{0,1200}Push-DryRunStep[\s\S]{0,400}-OneWay \$false') + # Read-only check makes no Set call before the JSON emit. + Write-TestResult "56-Ops: SmbSecurityCheck JSON-aware" ($smbC -match "Start-SmbSecurityCheck[\s\S]{0,400}CLIOutputFormat -eq 'JSON'") + $smbMenu = $smbC -match '\[35\]\s*SMB Signing' + Write-TestResult "56-Ops: menu item [35] SMB Signing present" $smbMenu + Write-TestResult "56-Ops: Operations invalid msg bumped to 1-35" ($smbC -match 'Enter 1-35, \[/\] to search') + $smbEntry = Get-Content "$modulesPath\50-EntryPoint.ps1" -Raw + Write-TestResult "50-EntryPoint: SmbSecurityCheck dispatch case" ($smbEntry -match "'SmbSecurityCheck'\s*\{") + Write-TestResult "50-EntryPoint: SmbEnforce dispatch case" ($smbEntry -match "'SmbEnforce'\s*\{") + $smbHeader = Get-Content (Join-Path $script:ModuleRoot "Header.ps1") -Raw + Write-TestResult "Header.ps1: SmbSecurityCheck in -Action ValidateSet" ($smbHeader -match "'SmbSecurityCheck'") + Write-TestResult "Header.ps1: SmbEnforce in -Action ValidateSet" ($smbHeader -match "'SmbEnforce'") +} +catch { + Write-TestResult "SMB Security Enforcement Tests" $false $_.Exception.Message +} + # ============================================================================ # SECTION 174: DOCUMENTATION FRESHNESS (counts must match the codebase) # ============================================================================ @@ -13115,7 +13146,7 @@ try { # Action list in -ListActions block has 160 entries $listBlock = [regex]::Match($ep5, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value $listActionCount = @([regex]::Matches($listBlock, "Action\s*=\s*'")).Count - Write-TestResult "50-EntryPoint: action list has 194 entries" ($listActionCount -eq 194) "Found $listActionCount" + Write-TestResult "50-EntryPoint: action list has 196 entries" ($listActionCount -eq 196) "Found $listActionCount" } catch { Write-TestResult "v1.91.0 Tests" $false $_.Exception.Message } @@ -13148,7 +13179,7 @@ try { # Action list count (should be 167 now) $listBlock2 = [regex]::Match($ep6, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value $actionCount2 = @([regex]::Matches($listBlock2, "Action\s*=\s*'")).Count - Write-TestResult "50-EntryPoint: action list has 194 entries" ($actionCount2 -eq 194) "Found $actionCount2" + Write-TestResult "50-EntryPoint: action list has 196 entries" ($actionCount2 -eq 196) "Found $actionCount2" } catch { Write-TestResult "v1.92.0 Tests" $false $_.Exception.Message } @@ -13174,7 +13205,7 @@ try { # Action count updated $listBlock3 = [regex]::Match($ep7, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value $actionCount3 = @([regex]::Matches($listBlock3, "Action\s*=\s*'")).Count - Write-TestResult "50-EntryPoint: action list has 194 entries" ($actionCount3 -eq 194) "Found $actionCount3" + Write-TestResult "50-EntryPoint: action list has 196 entries" ($actionCount3 -eq 196) "Found $actionCount3" } catch { Write-TestResult "v1.93.0 Tests" $false $_.Exception.Message } @@ -13212,7 +13243,7 @@ try { # Action list count $listBlock4 = [regex]::Match($ep8, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value $actionCount4 = @([regex]::Matches($listBlock4, "Action\s*=\s*'")).Count - Write-TestResult "50-EntryPoint: action list has 194 entries" ($actionCount4 -eq 194) "Found $actionCount4" + Write-TestResult "50-EntryPoint: action list has 196 entries" ($actionCount4 -eq 196) "Found $actionCount4" } catch { Write-TestResult "v1.94.1 Tests" $false $_.Exception.Message } @@ -13519,4 +13550,34 @@ Write-Host "" Write-Host "========================================================================" -ForegroundColor Cyan Write-Host "" +# ---------------------------------------------------------------------------- +# Structural-test badge self-heal: the README "structural tests" badge number +# is sourced from this run's live $script:TotalTests rather than hand-edited, +# so it can never drift. Local-only — skipped under CI so the checkout stays +# clean (CI must not produce working-tree changes), and best-effort so a +# read-only tree never fails the run. +# ---------------------------------------------------------------------------- +if (-not $env:CI -and -not $env:GITHUB_ACTIONS) { + try { + $readmePath = Join-Path $script:ModuleRoot 'README.md' + if (Test-Path -LiteralPath $readmePath) { + $readmeText = [System.IO.File]::ReadAllText($readmePath) + $badgePattern = '(structural%20tests-)(\d{2,5})(-brightgreen)' + $m = [regex]::Match($readmeText, $badgePattern) + if ($m.Success -and [int]$m.Groups[2].Value -ne $script:TotalTests) { + $oldCount = $m.Groups[2].Value + $updated = [regex]::Replace($readmeText, $badgePattern, "`${1}$script:TotalTests`${3}") + $altPattern = '(\d{2,5})( structural tests")' + $updated = [regex]::Replace($updated, $altPattern, "$script:TotalTests`${2}") + [System.IO.File]::WriteAllText($readmePath, $updated, (New-Object System.Text.UTF8Encoding $false)) + Write-Host " [badge] Synced README structural-tests badge: $oldCount -> $script:TotalTests" -ForegroundColor Cyan + Write-Host "" + } + } + } + catch { + # Non-fatal: badge sync is cosmetic and must never break the suite. + } +} + exit $exitCode diff --git a/dist/chocolatey/rackstack.nuspec b/dist/chocolatey/rackstack.nuspec index 697eba2..0d00187 100644 --- a/dist/chocolatey/rackstack.nuspec +++ b/dist/chocolatey/rackstack.nuspec @@ -18,7 +18,7 @@ windows-server hyper-v iscsi clustering powershell sysadmin automation msp admin-tools PowerShell automation toolkit for configuring Windows Server hosts -RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." 194 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, and batch automation, all with undo, transaction rollback, and audit logging. +RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." 196 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, and batch automation, all with undo, transaction rollback, and audit logging. Built for MSPs, sysadmins, and infrastructure teams who build servers repeatedly and want it done right every time. diff --git a/dist/scoop/rackstack.json b/dist/scoop/rackstack.json index e000861..60fa280 100644 --- a/dist/scoop/rackstack.json +++ b/dist/scoop/rackstack.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json", "version": "0.0.0", - "description": "PowerShell automation toolkit for configuring Windows Server hosts — Hyper-V virtualization hosts, failover cluster nodes, iSCSI storage clients, Active Directory members, and standalone servers. Ships as a code-signed EXE plus a PowerShell Gallery wrapper module exposing 194 structured CLI actions.", + "description": "PowerShell automation toolkit for configuring Windows Server hosts — Hyper-V virtualization hosts, failover cluster nodes, iSCSI storage clients, Active Directory members, and standalone servers. Ships as a code-signed EXE plus a PowerShell Gallery wrapper module exposing 196 structured CLI actions.", "homepage": "https://github.com/TheAbider/RackStack", "license": "MIT", "url": "https://github.com/TheAbider/RackStack/releases/download/v0.0.0/RackStack.exe", diff --git a/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml b/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml index d52876b..0e5298e 100644 --- a/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml +++ b/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml @@ -13,7 +13,7 @@ Copyright: Copyright (c) 2026 TheAbider ShortDescription: PowerShell automation toolkit for configuring Windows Server hosts. Description: |- RackStack is a menu-driven PowerShell tool that automates everything between - "Windows is installed" and "server is in production." It provides 194 CLI + "Windows is installed" and "server is in production." It provides 196 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, cloud onboarding, and batch automation, all with undo, transaction rollback, and audit logging. Built for MSPs, sysadmins,