first commit
This commit is contained in:
1 parent
89330fd20e
commit
b5cf9695eb
7 files changed
+1002
-1
No files matched your search
+102
@@ -0,0 +1,102 @@
|
||||
# Copyright (c) 2026 Comitari. Read-only wrapper for HardeningKitty.
|
||||
# Run ONLY Invoke-HardeningKitty -Mode Audit. Never invoke HailMary, GPO or Config.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$InstallRoot,
|
||||
[Parameter(Mandatory=$true)][string]$CsvFile,
|
||||
[Parameter(Mandatory=$true)][string]$MetadataFile,
|
||||
[Parameter(Mandatory=$true)][ValidateSet('GPO','Intune')][string]$Source,
|
||||
[Parameter(Mandatory=$true)][string]$Profile
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Get-MachineFindingList {
|
||||
param([string]$ProfileName, [string]$AuditSource)
|
||||
if ($ProfileName -ne 'auto') {
|
||||
if ($ProfileName -eq 'community') {
|
||||
return 'finding_list_0x6d69636b_machine.csv'
|
||||
}
|
||||
if ($ProfileName -match '_user\.csv$') {
|
||||
throw 'A machine audit running as SYSTEM cannot assess an interactive user baseline.'
|
||||
}
|
||||
if ($ProfileName -notmatch '^finding_list_[A-Za-z0-9_.-]+\.csv$' -or $ProfileName.Contains('..')) {
|
||||
throw 'Invalid finding list override. Only a basename starting finding_list_ is allowed.'
|
||||
}
|
||||
return $ProfileName
|
||||
}
|
||||
|
||||
# Get-CimInstance is supported, unlike the deprecated wmic.exe command.
|
||||
$os = Get-CimInstance -ClassName Win32_OperatingSystem
|
||||
$cv = Get-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
|
||||
$build = [int]$cv.CurrentBuildNumber
|
||||
$display = if ($cv.PSObject.Properties['DisplayVersion']) { [string]$cv.DisplayVersion } else { '' }
|
||||
$version = $display.ToLowerInvariant()
|
||||
|
||||
if ([int]$os.ProductType -eq 1) {
|
||||
if ($build -ge 22000) {
|
||||
if ($version -notin @('21h2','22h2','23h2','24h2','25h2','26h2')) {
|
||||
throw "Unsupported Windows 11 DisplayVersion '$display' (build $build); set profile explicitly."
|
||||
}
|
||||
return ('finding_list_msft_security_baseline_windows_11_' + $version + '_machine.csv')
|
||||
}
|
||||
if ($version -eq '20h2' -or $version -eq '21h1') {
|
||||
return 'finding_list_msft_security_baseline_windows_10_20h2_21h1_machine.csv'
|
||||
}
|
||||
if ($version -notin @('21h2','22h2')) {
|
||||
throw "Unsupported Windows 10 DisplayVersion '$display' (build $build); set profile explicitly."
|
||||
}
|
||||
return ('finding_list_msft_security_baseline_windows_10_' + $version + '_machine.csv')
|
||||
}
|
||||
|
||||
# Domain controllers and member servers use distinct security baselines.
|
||||
$role = if ([int]$os.ProductType -eq 2) { 'dc' } else { 'member' }
|
||||
switch ($build) {
|
||||
9600 { return 'finding_list_cis_microsoft_windows_server_2012_r2_3.0.0_machine.csv' }
|
||||
14393 { return 'finding_list_cis_microsoft_windows_server_2016_1607_3.0.0_machine.csv' }
|
||||
17763 { return 'finding_list_cis_microsoft_windows_server_2019_1809_3.0.0_machine.csv' }
|
||||
20348 { return ('finding_list_msft_security_baseline_windows_server_2022_21h2_' + $role + '_machine.csv') }
|
||||
26100 { return ('finding_list_msft_security_baseline_windows_server_2025_24h2_' + $role + '_machine.csv') }
|
||||
default { throw "Unsupported Windows Server build $build; set profile explicitly." }
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (-not (Test-Path -LiteralPath $InstallRoot -PathType Container)) { throw 'Installed package data missing.' }
|
||||
$listName = Get-MachineFindingList -ProfileName $Profile -AuditSource $Source
|
||||
$listPath = Join-Path (Join-Path $InstallRoot 'lists') $listName
|
||||
if (-not (Test-Path -LiteralPath $listPath -PathType Leaf)) {
|
||||
throw "Required finding list not bundled: $listName"
|
||||
}
|
||||
$module = Join-Path $InstallRoot 'HardeningKitty.psm1'
|
||||
if (-not (Test-Path -LiteralPath $module -PathType Leaf)) { throw 'HardeningKitty module not bundled.' }
|
||||
|
||||
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
|
||||
$cvInfo = Get-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
|
||||
$metaDisplay = if ($cvInfo.PSObject.Properties['DisplayVersion']) { [string]$cvInfo.DisplayVersion } else { '' }
|
||||
$metadata = [ordered]@{
|
||||
hostname = [Environment]::MachineName
|
||||
os_caption = [string]$osInfo.Caption
|
||||
product_type = [int]$osInfo.ProductType
|
||||
build = [string]$cvInfo.CurrentBuildNumber
|
||||
display_version = $metaDisplay
|
||||
benchmark = $listName
|
||||
source = $Source
|
||||
execution_identity = [Security.Principal.WindowsIdentity]::GetCurrent().Name
|
||||
}
|
||||
$json = $metadata | ConvertTo-Json -Depth 5
|
||||
[System.IO.File]::WriteAllText($MetadataFile, $json, [System.Text.UTF8Encoding]::new($false))
|
||||
|
||||
# HardeningKitty supports write modes, but this wrapper never exposes them.
|
||||
Import-Module -Name $module -Force -ErrorAction Stop
|
||||
# Upstream may emit non-terminating errors for unsupported individual tests.
|
||||
# We detect skipped checks by comparing CSV rows to the input finding list.
|
||||
$ErrorActionPreference = 'Continue'
|
||||
Invoke-HardeningKitty -Mode Audit -Source $Source -FileFindingList $listPath -Report -ReportFile $CsvFile -SkipUserInformation -SkipMachineInformation | Out-Null
|
||||
if ((-not (Test-Path -LiteralPath $CsvFile -PathType Leaf)) -or ((Get-Item -LiteralPath $CsvFile).Length -lt 40)) {
|
||||
throw 'Audit did not produce a valid CSV report.'
|
||||
}
|
||||
exit 0
|
||||
} catch {
|
||||
[Console]::Error.WriteLine('HardeningKitty audit failed: ' + $_.Exception.Message)
|
||||
exit 1
|
||||
}
|
||||
Reference in new issue
Block a user