functions/System/Hardening/Invoke-RemoteHardening.ps1
|
function Invoke-RemoteHardening { <# .SYNOPSIS Applies hardening rules to remote Windows systems via PowerShell Remoting. .DESCRIPTION Orchestrates hardening on remote systems using PowerShell remoting over WinRM. Supports batch operations on multiple systems with progress tracking. Features: - Apply hardening to single or multiple remote systems - Parallel execution on multiple targets - Progress tracking and reporting - Error handling with per-system reporting - Optional remediation verification - Session credential management Requires: - PowerShell Remoting enabled on remote systems (Enable-PSRemoting) - WinRM service running (port 5985/5986) - Network connectivity to remote systems - Administrative credentials on remote systems .PARAMETER ComputerName Array of remote computer names to harden. Mandatory. .PARAMETER Profile Hardening profile: Basis, Recommended, or Strict. Mandatory. .PARAMETER Credential PSCredential object for remote authentication. If omitted, uses current user credentials (must have admin rights). Optional. .PARAMETER SkipVerification If specified, skips compliance verification after hardening. Useful for speed in fast operations. .PARAMETER Parallel If specified, hardens multiple systems in parallel. Default: Sequential processing. .PARAMETER Port WinRM port: 5985 (HTTP) or 5986 (HTTPS). Default: 5985 .PARAMETER UseSSL If specified, uses HTTPS for remote connections. Requires WinRM HTTPS listener configured. .EXAMPLE Invoke-RemoteHardening -ComputerName 'Server1', 'Server2' -Profile Recommended Applies Recommended hardening to two servers sequentially. .EXAMPLE Invoke-RemoteHardening -ComputerName @('Web1','Web2','Web3') -Profile Basis -Parallel Applies hardening to three servers in parallel. .EXAMPLE $cred = Get-Credential Invoke-RemoteHardening -ComputerName 'RemoteServer' -Profile Strict -Credential $cred -UseSSL Applies strict hardening with explicit credentials over HTTPS. .NOTES DEPENDENCIES: Write-Log (Core), New-HardeningSession, Invoke-SecurityHardening REMOTING: Requires PowerShell Remoting enabled on targets ADMIN: Requires administrative rights on remote systems #> [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string[]] $ComputerName, [Parameter(Mandatory = $true)] [ValidateSet('Basis', 'Recommended', 'Strict')] [string] $Profile, [Parameter(Mandatory = $false)] [PSCredential] $Credential, [switch] $SkipVerification, [switch] $Parallel, [Parameter(Mandatory = $false)] [ValidateSet(5985, 5986)] [int] $Port = 5985, [switch] $UseSSL ) $ErrorActionPreference = 'Stop' try { if (-not $PSCmdlet.ShouldProcess("$($ComputerName.Count) remote systems", "Apply hardening profile: $Profile")) { return } Write-Log -Message "Starting remote hardening: Computers=$($ComputerName.Count), Profile=$Profile" -Level Info $results = @() $sessionParams = @{ ComputerName = $ComputerName Port = $Port ErrorAction = 'SilentlyContinue' } if ($UseSSL) { $sessionParams['UseSSL'] = $true } if ($Credential) { $sessionParams['Credential'] = $Credential } # Create remote sessions Write-Verbose "Establishing remote sessions..." $remoteSessions = New-PSSession @sessionParams if ($null -eq $remoteSessions) { throw "Failed to establish remote sessions. Check connectivity and WinRM status." } $processingSessions = if ($Parallel) { $remoteSessions } else { @($remoteSessions) } # Execute hardening on remote systems $hardening_code = { param($Profile, $SkipVerification, $ModulePath) # Import modules on remote system if (-not (Test-Path $ModulePath)) { throw "Required module not found on remote system: $ModulePath" } Import-Module $ModulePath -Force -ErrorAction Stop # Create and apply hardening $session = New-HardeningSession -Profile $Profile -TargetSystem Client -SkipPrerequisiteCheck $result = Invoke-SecurityHardening -Session $session -SkipVerification:$SkipVerification $result } # Resolve module path to pass to remote systems $systemModulePath = Join-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) 'modules\System.psm1' foreach ($rs in $processingSessions) { Write-Verbose "Invoking hardening on $($rs.ComputerName)..." try { $remoteResult = Invoke-Command -Session $rs -ScriptBlock $hardening_code -ArgumentList $Profile, $SkipVerification, $systemModulePath $results += [PSCustomObject]@{ ComputerName = $rs.ComputerName Success = $true Profile = $Profile AppliedRules = $remoteResult.AppliedRules.Count FailedRules = $remoteResult.FailedRules.Count CompliancePercentage = $remoteResult.ComplianceReport.CompliancePercentage Status = $remoteResult.ComplianceReport.Status Duration = $remoteResult.Duration } Write-Log -Message "Hardening succeeded on $($rs.ComputerName): $($remoteResult.AppliedRules.Count) rules applied" -Level Info } catch { $results += [PSCustomObject]@{ ComputerName = $rs.ComputerName Success = $false Error = $_.Exception.Message } Write-Log -Message "Hardening failed on $($rs.ComputerName): $($_.Exception.Message)" -Level Error } } # Cleanup sessions Remove-PSSession -Session $remoteSessions -ErrorAction SilentlyContinue Write-Log -Message "Remote hardening complete: $(($results | Where-Object Success).Count)/$($ComputerName.Count) systems succeeded" -Level Info $results } catch { Write-ErrorLog -Message "Failed to execute remote hardening: $($_.Exception.Message)" -Caller $MyInvocation.MyCommand.Name throw } } |