noid-privacy/Core/Validator.ps1

427 lines
13 KiB
PowerShell
Raw Permalink Normal View History

<#
.SYNOPSIS
System validation for NoID Privacy Framework
.DESCRIPTION
Provides pre-execution validation checks and post-execution verification
to ensure system safety and compliance.
.NOTES
Author: NexusOne23
Version: 2.2.3
Requires: PowerShell 5.1+
#>
function Test-Prerequisites {
<#
.SYNOPSIS
Validate all system prerequisites before hardening
.OUTPUTS
PSCustomObject with validation results
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param()
Write-Log -Level INFO -Message "Starting prerequisite validation" -Module "Validator"
$result = [PSCustomObject]@{
Success = $true
Errors = @()
Warnings = @()
SystemInfo = $null
}
# Check 1: Administrator privileges
if (-not (Test-IsAdministrator)) {
Write-Log -Level ERROR -Message "Administrator privileges required" -Module "Validator"
$result.Success = $false
$result.Errors += "Administrator privileges required"
}
else {
Write-Log -Level SUCCESS -Message "Administrator check: PASSED" -Module "Validator"
}
# Check 2: Windows version
$osInfo = Get-WindowsVersion
if ($osInfo.IsSupported) {
Write-Log -Level SUCCESS -Message "Windows version check: PASSED ($($osInfo.Version))" -Module "Validator"
}
else {
Write-Log -Level ERROR -Message "Unsupported Windows version: $($osInfo.Version)" -Module "Validator"
$result.Success = $false
$result.Errors += "Unsupported Windows version: $($osInfo.Version)"
}
# Check 3: Disk space
$diskSpace = Get-AvailableDiskSpace
if ($diskSpace -gt 500MB) {
Write-Log -Level SUCCESS -Message "Disk space check: PASSED ($([math]::Round($diskSpace/1MB, 2)) MB available)" -Module "Validator"
}
else {
Write-Log -Level WARNING -Message "Low disk space: $([math]::Round($diskSpace/1MB, 2)) MB" -Module "Validator"
$result.Warnings += "Low disk space: $([math]::Round($diskSpace/1MB, 2)) MB"
}
# Check 4: PowerShell version
if ($PSVersionTable.PSVersion.Major -ge 5) {
Write-Log -Level SUCCESS -Message "PowerShell version check: PASSED ($($PSVersionTable.PSVersion))" -Module "Validator"
}
else {
Write-Log -Level ERROR -Message "PowerShell 5.1 or higher required" -Module "Validator"
$result.Success = $false
$result.Errors += "PowerShell 5.1 or higher required (found: $($PSVersionTable.PSVersion))"
}
# Get system info
$result.SystemInfo = Get-SystemInfo
if ($result.Success) {
Write-Log -Level SUCCESS -Message "All prerequisite checks passed" -Module "Validator"
}
else {
Write-Log -Level ERROR -Message "One or more prerequisite checks failed" -Module "Validator"
}
return $result
}
function Test-IsAdministrator {
<#
.SYNOPSIS
Check if script is running with administrator privileges
.OUTPUTS
Boolean indicating administrator status
#>
[CmdletBinding()]
[OutputType([bool])]
param()
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Get-WindowsVersion {
<#
.SYNOPSIS
Get Windows version information
.OUTPUTS
PSCustomObject with version details and support status
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param()
$os = Get-CimInstance -ClassName Win32_OperatingSystem
$buildNumber = [int]$os.BuildNumber
# Windows 11 build numbers
# 22000 = 21H2, 22621 = 22H2, 22631 = 23H2, 26100 = 24H2, 26200 = 25H2
$isWindows11 = $buildNumber -ge 22000
$isSupported = $buildNumber -ge 26100 # 24H2 or newer required
$versionName = switch ($buildNumber) {
{ $_ -ge 26200 } { "Windows 11 25H2"; break }
{ $_ -ge 26100 } { "Windows 11 24H2"; break }
{ $_ -ge 22631 } { "Windows 11 23H2"; break }
{ $_ -ge 22621 } { "Windows 11 22H2"; break }
{ $_ -ge 22000 } { "Windows 11 21H2"; break }
default { "Windows $($os.Version)" }
}
return [PSCustomObject]@{
Version = $versionName
BuildNumber = $buildNumber
IsWindows11 = $isWindows11
IsSupported = $isSupported
Edition = $os.Caption
Architecture = $os.OSArchitecture
}
}
function Get-AvailableDiskSpace {
<#
.SYNOPSIS
Get available disk space on system drive
.OUTPUTS
Int64 representing available bytes
#>
[CmdletBinding()]
[OutputType([Int64])]
param()
$systemDrive = $env:SystemDrive
$drive = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='$systemDrive'"
return $drive.FreeSpace
}
function Test-InternetConnectivity {
<#
.SYNOPSIS
Test internet connectivity
.OUTPUTS
Boolean indicating connectivity status
#>
[CmdletBinding()]
[OutputType([bool])]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingComputerNameHardcoded', '')]
param()
try {
# Using Microsoft NCSI endpoint - same as Windows uses for connectivity detection
$response = Test-Connection -ComputerName "www.msftconnecttest.com" -Count 1 -Quiet -ErrorAction Stop
return $response
}
catch {
return $false
}
}
function Test-TPMAvailable {
<#
.SYNOPSIS
Check if TPM 2.0 is available
.OUTPUTS
PSCustomObject with TPM information
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param()
try {
$tpm = Get-Tpm -ErrorAction SilentlyContinue
if ($null -eq $tpm) {
return [PSCustomObject]@{
Present = $false
Version = "N/A"
Enabled = $false
Activated = $false
}
}
return [PSCustomObject]@{
Present = $tpm.TpmPresent
Version = if ($tpm.ManufacturerVersion) { $tpm.ManufacturerVersion } else { "2.0" }
Enabled = $tpm.TpmEnabled
Activated = $tpm.TpmActivated
}
}
catch {
Write-Log -Level WARNING -Message "Unable to check TPM status: $_" -Module "Validator"
return [PSCustomObject]@{
Present = $false
Version = "Unknown"
Enabled = $false
Activated = $false
}
}
}
function Test-SecureBootEnabled {
<#
.SYNOPSIS
Check if Secure Boot is enabled
.OUTPUTS
Boolean indicating Secure Boot status
#>
[CmdletBinding()]
[OutputType([bool])]
param()
try {
$secureBoot = Confirm-SecureBootUEFI -ErrorAction Stop
return $secureBoot
}
catch {
Write-Log -Level WARNING -Message "Unable to check Secure Boot status (may not be UEFI): $_" -Module "Validator"
return $false
}
}
function Test-VirtualizationEnabled {
<#
.SYNOPSIS
Check if CPU virtualization is enabled
.OUTPUTS
Boolean indicating virtualization status
#>
[CmdletBinding()]
[OutputType([bool])]
param()
try {
$cpu = Get-CimInstance -ClassName Win32_Processor
# Check for Intel VT-x or AMD-V
$vmxEnabled = $cpu.VirtualizationFirmwareEnabled
return $vmxEnabled
}
catch {
Write-Log -Level WARNING -Message "Unable to check virtualization status: $_" -Module "Validator"
return $false
}
}
function Get-SystemInfo {
<#
.SYNOPSIS
Get comprehensive system information
.OUTPUTS
PSCustomObject with detailed system information
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param()
$osInfo = Get-WindowsVersion
$tpmInfo = Test-TPMAvailable
$secureBoot = Test-SecureBootEnabled
$virtualization = Test-VirtualizationEnabled
$isAdmin = Test-IsAdministrator
$diskSpace = Get-AvailableDiskSpace
$internet = Test-InternetConnectivity
return [PSCustomObject]@{
OS = $osInfo
TPM = $tpmInfo
SecureBoot = $secureBoot
Virtualization = $virtualization
IsAdministrator = $isAdmin
DiskSpaceAvailable = $diskSpace
InternetConnected = $internet
PowerShellVersion = $PSVersionTable.PSVersion.ToString()
}
}
function Test-DomainJoined {
<#
.SYNOPSIS
Check if system is joined to an Active Directory domain
.DESCRIPTION
Detects if the system is domain-joined and warns about potential
Group Policy conflicts with local hardening settings.
.PARAMETER Interactive
If set, prompts user to confirm continuation on domain-joined systems
.OUTPUTS
PSCustomObject with domain status information
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param(
[switch]$Interactive
)
try {
$computerSystem = Get-CimInstance Win32_ComputerSystem -ErrorAction Stop
$isDomainJoined = $computerSystem.PartOfDomain
$result = [PSCustomObject]@{
IsDomainJoined = $isDomainJoined
DomainName = if ($isDomainJoined) { $computerSystem.Domain } else { "N/A" }
Workgroup = if (-not $isDomainJoined) { $computerSystem.Workgroup } else { "N/A" }
UserConfirmed = $false
}
if ($isDomainJoined) {
Write-Log -Level WARNING -Message "System is domain-joined: $($computerSystem.Domain)" -Module "Validator"
if ($Interactive) {
Write-Host ""
Write-Host "========================================" -ForegroundColor Yellow
Write-Host " WARNING: DOMAIN-JOINED SYSTEM" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Yellow
Write-Host ""
Write-Host "This system is joined to domain: " -NoNewline -ForegroundColor White
Write-Host "$($computerSystem.Domain)" -ForegroundColor Cyan
Write-Host ""
Write-Host "IMPORTANT CONSIDERATIONS:" -ForegroundColor Red
Write-Host " - Domain Group Policies will override local policies" -ForegroundColor Yellow
Write-Host " - GPO refresh occurs every 90 minutes" -ForegroundColor Yellow
Write-Host " - Some hardening may be reset automatically" -ForegroundColor Yellow
Write-Host " - Coordinate with AD team before proceeding" -ForegroundColor Yellow
Write-Host ""
Write-Host "RECOMMENDED FOR DOMAIN ENVIRONMENTS:" -ForegroundColor Cyan
Write-Host " - Integrate these settings into Domain GPOs instead" -ForegroundColor White
Write-Host " - Use this tool only for testing/standalone systems" -ForegroundColor White
Write-Host ""
$continue = Read-Host "Do you want to continue anyway? (yes/no)"
if ($continue -ne "yes") {
Write-Log -Level INFO -Message "User cancelled due to domain-joined warning" -Module "Validator"
Write-Host ""
Write-Host "Operation cancelled by user." -ForegroundColor Gray
Write-Host ""
exit 1
}
$result.UserConfirmed = $true
Write-Log -Level INFO -Message "User confirmed continuation on domain-joined system" -Module "Validator"
}
}
else {
Write-Log -Level INFO -Message "System is standalone (workgroup: $($computerSystem.Workgroup))" -Module "Validator"
}
return $result
}
catch {
Write-Log -Level ERROR -Message "Failed to check domain status: $_" -Module "Validator" -Exception $_.Exception
return [PSCustomObject]@{
IsDomainJoined = $false
DomainName = "Error"
Workgroup = "Error"
UserConfirmed = $false
}
}
}
function Confirm-SystemBackup {
<#
.SYNOPSIS
Non-interactive system backup recommendation
.DESCRIPTION
Historically this function displayed an interactive prompt asking the
user to confirm that a full system backup exists before proceeding.
For modern CLI and GUI workflows this interaction is removed to avoid
blocking automation. The function now simply logs that a backup is
recommended and returns a confirmation object.
.PARAMETER Force
Retained for backwards compatibility. No longer changes behaviour.
.OUTPUTS
PSCustomObject with backup confirmation status
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param()
Write-Log -Level INFO -Message "Backup recommendation: non-interactive confirmation (no prompt shown)" -Module "Validator"
$result = [PSCustomObject]@{
UserConfirmed = $true
BackupRecommended = $true
}
return $result
}
# Note: Export-ModuleMember not used - this script is dot-sourced, not imported as module