Unify event-log size and retention profiles with verified configuration

This commit is contained in:
Shirofune-Security committed 2026-09-19 02:30:41 +09:00
1 parent c45f7a1319
commit d29ffdd01b
15 files changed
+1025 -168

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
name: Event-log settings regressions
on:
push:
branches: ['**']
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
eventlog-settings:
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Safe event-log fixtures in Windows PowerShell 5.1
shell: powershell
run: ./tests/EventLogSettings.Tests.ps1
- name: Safe event-log fixtures in PowerShell 7
shell: pwsh
run: ./tests/EventLogSettings.Tests.ps1
- name: Read-only Windows event-log smoke in Windows PowerShell 5.1
shell: powershell
run: ./tests/EventLogSettings.Windows.Tests.ps1
- name: Read-only Windows event-log smoke in PowerShell 7
shell: pwsh
run: ./tests/EventLogSettings.Windows.Tests.ps1
+2
View File
@@ -4,6 +4,8 @@
**改善:**
- イベントログのサイズ監査と設定に共通のバイト単位プロファイルを導入し、AppLocker・ファイアウォールログの256 MiB、Setupの32 MiB、ASD推奨のSecurityログ2048 MiBに対応した。`-LogProfile`と`configure-eventlogs`で送信元と収集サーバーのサイズ・保存方式を選択できる。明示的に指定しない限り、既存の大きいバッファと保存方式は維持する。結果には検証した設定を記録し、未測定の保存日数は不明と表示する。 (issue #379) (@Shirofune-Security)
- `audit-settings`、`plan`、`configure`で共有するバージョン付きの詳細監査ポリシープロファイルを追加した。59のサブカテゴリと14のプロファイルで、WELA、文書に基づくWindows既定値、Microsoft、確認済みのCIS v4.0.0、ASDのWindows標準機能向け監査ガイドに対応する。ホストの役割とビルドの検証、オフラインでの設定計画、出典と前提条件を含むJSON出力をサポートする。完全一致、最低限、任意、変更なし、未構成、適用対象外を区別する。Windows既定値は参照専用で、プロファイルの対象はSecurityログの詳細監査ポリシーに限定される。 (#390) (@Shirofune-Security)
- WELAのプロファイルにWindows標準の監査サブカテゴリを6つ追加した。Group MembershipとAuthorization Policy Changeは成功、Application Group Management、MPSSVC Rule-Level Policy Change、IPsec Driver、Kernel Objectは成功と失敗を監査する。各ガイドに対応するプロファイルでは、それぞれの監査設定と前提条件を維持する。Kernel Objectのイベント生成には対象オブジェクトに適切なSACLが必要であり、この変更ではそのSACLを作成しない。 (#391) (@Shirofune-Security)
- `configure`と`configure -Profile`に`-DryRun`と`-ResultsPath`を追加し、Windows設定を変更せずに変更内容を確認し、設定項目ごとの結果をJSONで出力できるようにした。`-DryRun`に対応していないコマンドは、実行前にエラーで停止する。 (#392) (@Shirofune-Security)
+2
View File
@@ -4,6 +4,8 @@
**Improvements:**
- Unified event-log size auditing and configuration with shared byte-based profiles, including 256 MiB AppLocker/firewall logs, 32 MiB Setup and ASD 2048 MiB Security. Added separate source and collector size/mode choices through `-LogProfile` and `configure-eventlogs`; larger buffers and existing retention modes are preserved unless explicitly changed. Results include verified state and unknown retention duration. (issue #379) (@Shirofune-Security)
- Added versioned advanced audit-policy profiles shared by `audit-settings`, `plan` and `configure`: 59 subcategories and 14 profiles covering WELA, documented Windows defaults, Microsoft, reviewed CIS v4.0.0 and ASD native guidance. Profiles support role/build validation, offline planning and JSON exports with sources and prerequisites. Exact, minimum, optional, unchanged, Not Configured and not-applicable settings remain distinct. Windows defaults are reference-only; profile scope is advanced Security audit policy. (#390) (@Shirofune-Security)
- Added six native Windows audit subcategories to WELA's profile: Group Membership and Authorization Policy Change (Success), plus Application Group Management, MPSSVC Rule-Level Policy Change, IPsec Driver and Kernel Object (Success and Failure). Source-specific profiles retain their own audit settings and prerequisites; Kernel Object events require matching object SACLs, which this change does not create. (#391) (@Shirofune-Security)
- Added `-DryRun` and `-ResultsPath` to `configure` and `configure -Profile` to preview changes without modifying Windows settings and export per-control results as JSON. Commands that do not support `-DryRun` reject it before running. (#392) (@Shirofune-Security)
+58 -157
View File
@@ -4,6 +4,9 @@
[switch]$Debug,
[string]$Baseline,
[string]$Profile,
[string]$LogProfile,
[switch]$ResizeLogs,
[switch]$ApplyLogMode,
[ValidateSet("Client", "MemberServer", "DomainController", "ADCS")][string]$Role,
[int]$Build,
[string]$PlanPath,
@@ -29,6 +32,8 @@ $AuditpolTxtPath = Join-Path $ScriptRoot "auditpol.txt"
$SaclTargetsPath = Join-Path $ScriptRoot "config/audit_sacl_targets.json"
. (Join-Path $ScriptRoot "scripts/Configuration.ps1")
Import-Module (Join-Path $ScriptRoot "modules/AuditProfiles.psm1") -ErrorAction Stop
Import-Module (Join-Path $ScriptRoot "modules/EventLogSettings.psm1") -ErrorAction Stop
. (Join-Path $ScriptRoot "scripts/EventLogConfiguration.ps1")
# 64bit の PowerShell と GPO が読むのは Wow6432Node の無いパス。32bit 用に両方を扱う。
$PowerShellPolicyRoots = @(
@@ -954,119 +959,15 @@ function Export-MitreHeatmap {
function AuditFileSize {
# 推奨サイズはベースラインによらず共通のため、パラメータは取らない
if (-not (TestWindows)) {
Write-Host "[ERROR] 'audit-filesize' reads Windows event logs and can only run on Windows." -ForegroundColor Red
return
}
# 対象のイベントログ名をハッシュテーブル化
$logNames = @{
"Application" = @("20 MB", "128 MB+")
"Microsoft-Windows-AppLocker/EXE and DLL" = @("1 MB", "256 MB+")
"Microsoft-Windows-AppLocker/MSI and Script" = @("1 MB", "256 MB+")
"Microsoft-Windows-AppLocker/Packaged app-Deployment" = @("1 MB", "256 MB+")
"Microsoft-Windows-AppLocker/Packaged app-Execution" = @("1 MB", "256 MB+")
"Microsoft-Windows-Bits-Client/Analytic" = @("1 MB", "128 MB+")
"Microsoft-Windows-Bits-Client/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-CodeIntegrity/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-Crypto-DPAPI/Debug" = @("1 MB", "128 MB+")
"Microsoft-Windows-DFSN-Server/Admin" = @("1 MB", "128 MB+")
"Microsoft-Windows-DriverFrameworks-UserMode/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-NTLM/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-PowerShell/Operational" = @("15 MB", "256 MB+")
"Microsoft-Windows-PrintService/Admin" = @("1 MB", "128 MB+")
"Microsoft-Windows-PrintService/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-Security-Mitigations/KernelMode" = @("1 MB", "128 MB+")
"Microsoft-Windows-Security-Mitigations/UserMode" = @("1 MB", "128 MB+")
"Microsoft-Windows-SmbClient/Security" = @("8 MB", "128 MB+")
"Microsoft-Windows-TaskScheduler/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" = @("1 MB", "128 MB+")
"Microsoft-Windows-Windows Defender/Operational" = @("16MB", "128 MB+")
"Microsoft-Windows-Windows Firewall With Advanced Security/Firewall" = @("1 MB", "256 MB+")
"Microsoft-Windows-WMI-Activity/Operational" = @("1 MB", "128 MB+")
"Security" = @("20 MB", "256 MB+")
"System" = @("20 MB", "128 MB+")
"Windows PowerShell" = @("15 MB", "256 MB+")
}
$results = @()
$missingLogs = @()
foreach ($logName in $logNames.Keys | Sort-Object) {
# 存在しないログ(役割やOSエディションによる)で全体を止めない
$logInfo = Get-WinEvent -ListLog $logName -ErrorAction SilentlyContinue
if (-not $logInfo) {
$missingLogs += $logName
continue
}
$maxLogSize = [math]::Floor($logInfo.MaximumSizeInBytes / 1MB)
$recommendedSize = [int]($logNames[$logName][1] -replace " MB\+?", "")
# ローテーション直前までファイルは上限まで育つので、95%以上を「ほぼ満杯」とみなす
$logIsFull = $logInfo.MaximumSizeInBytes -gt 0 -and
$logInfo.FileSize -ge ($logInfo.MaximumSizeInBytes * 0.95)
$logMode = if ($logInfo.LogMode -eq "Retain") { "NoOverwrite" } else { $logInfo.LogMode }
$correctSetting = if ($maxLogSize -ge $recommendedSize -and $logMode -ne "NoOverwrite") { "Y" } else { "N" }
$results += [PSCustomObject]@{
LogFile = Split-Path $logInfo.LogFilePath -Leaf
CurrentLogSize = "{0:N2} MB" -f ($logInfo.FileSize / 1MB)
MaxLogSize = "$maxLogSize MB"
Default = $logNames[$logName][0]
Recommended = $logNames[$logName][1]
IsLogFull = $logIsFull
LogMode = $logMode
CorrectSetting = $correctSetting
}
}
# Format-Tableには色つき出力の機能はないので、Write-Hostで色をつける
$tableLayout = "{0,-75} {1,-15} {2,-10} {3,-10} {4,-15} {5,-10} {6,-15} {7,-10}"
Write-Host ($tableLayout -f `
"Log File", `
"Current Size", `
"Max Size", `
"Default", `
"Recommended", `
"Is Full", `
"Log Mode", `
"Correct Setting" `
)
Write-Host ($tableLayout -f `
"--------", `
"------------", `
"--------", `
"------", `
"-----------", `
"-------", `
"--------", `
"--------------" `
)
foreach ($result in $results) {
$color = if ($result.CorrectSetting -eq "Y") { "Green" } else { "Red" }
Write-Host ($tableLayout -f `
$result.LogFile, `
$result.CurrentLogSize, `
$result.MaxLogSize, `
$result.Default, `
$result.Recommended, `
$result.IsLogFull, `
$result.LogMode, `
$result.CorrectSetting `
) -ForegroundColor $color
}
if ($missingLogs.Count -gt 0) {
Write-Host ""
Write-Host "Skipped $($missingLogs.Count) log(s) that do not exist on this machine:" -ForegroundColor DarkYellow
$missingLogs | ForEach-Object { Write-Host " - $_" -ForegroundColor DarkYellow }
}
param([string]$LogProfile = 'wela-source-2.2.0')
if (-not (TestWindows)) { throw "'audit-filesize' reads Windows event logs and can only run on Windows." }
$results = @(Get-WelaEventLogAudit -Profile $LogProfile)
$results | Format-Table Log, ReadStatus, CurrentMaximumMiB, MinimumBytes, SizeStatus, CurrentMode, RecommendedMode, ModeStatus -AutoSize | Out-Host
Write-Host 'Sizes use exact bytes (MiB = 1048576 bytes). Retention days: Unknown; measure event volume and verify collection/archive storage.'
Write-Host 'Mode recommendations are separate from size compliance. configure-eventlogs changes modes only with -ApplyLogMode.'
$fileSizeCsv = Join-Path $script:ScriptRoot "WELA-FileSize-Result.csv"
$results | Export-Csv -Path $fileSizeCsv -NoTypeInformation
Write-Host ""
Write-Host "Audit file size result saved to: $fileSizeCsv"
$results | Export-Csv -LiteralPath $fileSizeCsv -NoTypeInformation -Encoding UTF8 -ErrorAction Stop
Write-Host "Event-log audit saved to: $fileSizeCsv"
}
@@ -1428,37 +1329,8 @@ function ConfigureAuditSettings {
$context = New-WelaConfigurationContext -Auto:$Auto -DryRun:$DryRun -BackupPath $BackupPath
if (-not $DryRun) { Write-Host "Recovery journal: $($context.BackupPath)" }
foreach ($log in @('Security', 'Microsoft-Windows-PowerShell/Operational', 'Windows PowerShell')) {
Set-WelaEventLogControl -Context $context -Log $log -Property MaximumSizeInBytes -Desired 1073741824
}
$mediumLogs = @(
"System",
"Application",
"Microsoft-Windows-Windows Defender/Operational",
"Microsoft-Windows-Bits-Client/Operational",
"Microsoft-Windows-Windows Firewall With Advanced Security/Firewall",
"Microsoft-Windows-NTLM/Operational",
"Microsoft-Windows-Security-Mitigations/KernelMode",
"Microsoft-Windows-Security-Mitigations/UserMode",
"Microsoft-Windows-PrintService/Admin",
"Microsoft-Windows-PrintService/Operational",
"Microsoft-Windows-SmbClient/Security",
"Microsoft-Windows-AppLocker/MSI and Script",
"Microsoft-Windows-AppLocker/EXE and DLL",
"Microsoft-Windows-AppLocker/Packaged app-Deployment",
"Microsoft-Windows-AppLocker/Packaged app-Execution",
"Microsoft-Windows-CodeIntegrity/Operational",
"Microsoft-Windows-Crypto-DPAPI/Debug",
"Microsoft-Windows-Diagnosis-Scripted/Operational",
"Microsoft-Windows-DriverFrameworks-UserMode/Operational",
"Microsoft-Windows-WMI-Activity/Operational",
"Microsoft-Windows-TerminalServices-LocalSessionManager/Operational",
"Microsoft-Windows-TaskScheduler/Operational"
)
foreach ($log in $mediumLogs) {
Set-WelaEventLogControl -Context $context -Log $log -Property MaximumSizeInBytes -Desired 134217728
}
# Audit and configure consume the same default size thresholds; modes stay unchanged.
Set-WelaEventLogProfileControls -Context $context -Profile 'wela-source-2.2.0'
foreach ($log in @('Microsoft-Windows-TaskScheduler/Operational', 'Microsoft-Windows-DriverFrameworks-UserMode/Operational', 'Microsoft-Windows-Crypto-DPAPI/Debug')) {
Set-WelaEventLogControl -Context $context -Log $log -Property IsEnabled -Desired $true
}
@@ -1758,7 +1630,10 @@ Usage:
# -Profile changes advanced audit policy ONLY. Optional controls need -IncludeOptional.
./WELA.ps1 audit-settings -Baseline YamatoSecurity # Audit current setting and show in stdout, save to csv
./WELA.ps1 audit-settings -Baseline ASD -OutType gui # Audit current setting and show in gui, save to csv
./WELA.ps1 audit-filesize -Baseline YamatoSecurity # Audit current file size and show in stdout, save to csv
./WELA.ps1 eventlog-profiles # List size/mode profiles (separate from -Profile)
./WELA.ps1 audit-filesize -LogProfile wela-source-2.2.0 # Audit live sizes/modes, save to CSV
./WELA.ps1 configure-eventlogs -LogProfile asd-source-2021-10 -DryRun
./WELA.ps1 configure-eventlogs -LogProfile asd-collector-archive-2021-10 -ApplyLogMode # Explicit archive choice
./WELA.ps1 configure -Baseline YamatoSecurity # Configure audit settings based on the specified baseline
./WELA.ps1 configure -Baseline YamatoSecurity -Auto # Configure audit settings automatically without prompts
./WELA.ps1 configure-sacl # Add targeted File System/Registry audit SACLs (ASEP keys + sensitive files) needed by the rules, without global auditing
@@ -1776,8 +1651,17 @@ Write-Host "WELA v$WELAVersion - $WELAReleaseName"
Write-Host ""
# Reject unsupported dry-run requests before reaching any command's mutation path.
if ($DryRun -and $Cmd -ne 'configure') {
throw "-DryRun is supported only by configure (including configure -Profile). No command was run."
if ($DryRun -and $Cmd -notin @('configure', 'configure-eventlogs')) {
throw "-DryRun is supported only by configure (including configure -Profile) and configure-eventlogs. No command was run."
}
if ($Profile -and $Cmd -in @('eventlog-profiles', 'audit-filesize', 'configure-eventlogs')) {
throw '-Profile selects advanced audit policy only. Use -LogProfile for event-log size/mode settings.'
}
if ($LogProfile -and $Cmd -notin @('audit-filesize', 'configure-eventlogs')) {
throw '-LogProfile is supported only by audit-filesize and configure-eventlogs.'
}
if (($ResizeLogs -or $ApplyLogMode) -and $Cmd -ne 'configure-eventlogs') {
throw '-ResizeLogs and -ApplyLogMode require configure-eventlogs. No command was run.'
}
if ($Profile -and $Cmd.ToLower() -in @('plan', 'audit', 'audit-settings', 'configure') -and -not $Help) {
@@ -1810,21 +1694,38 @@ switch ($Cmd.ToLower()) {
}
AuditLogSetting -outType $OutType -Baseline $Baseline -debug:$Debug
}
"eventlog-profiles" {
(Import-WelaEventLogProfiles).profiles | Select-Object id, kind, scope, note | Format-List
}
"audit-filesize" {
if ($Help){
Write-Host "Audit current Windows Event Log file sizes"
Write-Host ""
Write-Host "Usage: ./WELA.ps1 audit-filesize"
Write-Host ""
Write-Host "Note: the recommended sizes are the same for every baseline, so -Baseline is not required."
Write-Host ""
if ($Help) {
Write-Host 'Usage: ./WELA.ps1 audit-filesize [-LogProfile <id>]'
Write-Host 'Read live sizes and retention modes; list IDs with eventlog-profiles. Default: wela-source-2.2.0.'
return
}
if (-not [string]::IsNullOrEmpty($Baseline) -and $Baseline -ne "YamatoSecurity") {
Write-Host "Note: audit-filesize uses the same recommended sizes for every baseline; '-Baseline $Baseline' is ignored." -ForegroundColor DarkYellow
Write-Host ""
if ($Baseline -and $Baseline -ne 'YamatoSecurity') { throw 'Use -LogProfile for source-specific event-log sizes; -Baseline does not select a log profile.' }
if (-not $LogProfile) { $LogProfile = 'wela-source-2.2.0' }
AuditFileSize -LogProfile $LogProfile
}
"configure-eventlogs" {
if ($Help) {
Write-Host 'Usage: ./WELA.ps1 configure-eventlogs [-LogProfile <id>] [-ApplyLogMode] [-ResizeLogs] [-Auto] [-DryRun] [-BackupPath <new-directory>] [-ResultsPath <json-file>]'
Write-Host 'Default: wela-source-2.2.0, minimum sizes, modes unchanged. -ResizeLogs explicitly permits shrinking; -ApplyLogMode explicitly applies circular source or collector archive behavior.'
Write-Host 'This command changes only event-log size/mode. It does not enable channels, configure forwarding or establish retention days.'
return
}
if ($Baseline) { throw 'configure-eventlogs uses -LogProfile, not -Baseline.' }
if (-not (TestWindows)) { throw 'configure-eventlogs requires Windows.' }
if (-not (TestAdministrator)) { throw 'configure-eventlogs requires Administrator privileges.' }
if (-not $LogProfile) { $LogProfile = 'wela-source-2.2.0' }
try {
$report = Invoke-WelaEventLogConfiguration -Profile $LogProfile -Auto:$Auto -DryRun:$DryRun -ResizeLogs:$ResizeLogs -ApplyLogMode:$ApplyLogMode -BackupPath $BackupPath -ResultsPath $ResultsPath
$report
if ($report.ExitCode -ne 0) { exit $report.ExitCode }
} catch {
Write-Host "[Failed] Event-log configuration aborted: $_" -ForegroundColor Red
exit 1
}
AuditFileSize
}
"configure" {
+383
View File
@@ -0,0 +1,383 @@
{
"schemaVersion": 1,
"sources": {
"wela": {
"title": "WELA 2.2.0 logging choices",
"url": "https://github.com/Yamato-Security/WELA/issues/379"
},
"cis-v4": {
"title": "CIS Windows 11 Enterprise / Windows Server 2022 v4.0.0 (historical reviewed editions)",
"url": "https://www.cisecurity.org/benchmark/microsoft_windows_desktop",
"note": "Event Log Service size and full-log behavior recommendations only; effective local values do not establish configured GPO or full benchmark compliance."
},
"asd-2021": {
"title": "ASD Windows event logging and forwarding, October 2021",
"url": "https://www.cyber.gov.au/business-government/detecting-responding-to-threats/event-logging/windows-event-logging-and-forwarding"
},
"ms-wevtutil": {
"title": "Microsoft wevtutil reference",
"url": "https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/wevtutil"
}
},
"profiles": [
{
"id": "wela-source-2.2.0",
"kind": "source",
"scope": "event-log-size-and-mode-only",
"note": "Default configure/audit-filesize model. Circular mode is a recommendation; applying it requires -ApplyLogMode. Sizes are minima unless -ResizeLogs is explicit.",
"controls": [
{
"log": "Application",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-AppLocker/EXE and DLL",
"minimumBytes": 268435456,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-AppLocker/MSI and Script",
"minimumBytes": 268435456,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-AppLocker/Packaged app-Deployment",
"minimumBytes": 268435456,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-AppLocker/Packaged app-Execution",
"minimumBytes": 268435456,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Bits-Client/Analytic",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Bits-Client/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-CodeIntegrity/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Crypto-DPAPI/Debug",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-DFSN-Server/Admin",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-DriverFrameworks-UserMode/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-NTLM/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-PowerShell/Operational",
"minimumBytes": 1073741824,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-PrintService/Admin",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-PrintService/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Security-Mitigations/KernelMode",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Security-Mitigations/UserMode",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-SmbClient/Security",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-TaskScheduler/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Windows Defender/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-Windows Firewall With Advanced Security/Firewall",
"minimumBytes": 268435456,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Microsoft-Windows-WMI-Activity/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Security",
"minimumBytes": 1073741824,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "System",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Windows PowerShell",
"minimumBytes": 1073741824,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "WELA 2.2.0 shared size model; preserves prior configure 1024 MiB thresholds and fixes audit/configure mismatches."
},
{
"log": "Setup",
"minimumBytes": 33554432,
"mode": "Circular",
"sourceIds": [
"cis-v4"
],
"evidence": "CIS v4.0.0 18.10.26.3.2: Setup >=32768 KiB; Windows 11 p.1047, Server 2022 p.849."
},
{
"log": "Microsoft-Windows-Diagnosis-Scripted/Operational",
"minimumBytes": 134217728,
"mode": "Circular",
"sourceIds": [
"wela"
],
"evidence": "Retains the prior WELA configure 128 MiB setting; now shared with size auditing."
}
]
},
{
"id": "cis-v4-source",
"kind": "source",
"scope": "event-log-size-and-mode-only",
"note": "Reviewed Windows 11 Enterprise and Server 2022 v4.0.0 effective log settings only; not a GPO compliance assessment.",
"controls": [
{
"log": "Application",
"minimumBytes": 33554432,
"mode": "Circular",
"sourceIds": [
"cis-v4"
],
"evidence": "Client v4.0.0 18.10.26.1.1 p.1035; Client v4.0.0 18.10.26.1.2 p.1037; Server v4.0.0 18.10.26.1.1 p.837; Server v4.0.0 18.10.26.1.2 p.839. Size minimum; full-log retention Disabled (overwrite)."
},
{
"log": "Security",
"minimumBytes": 201326592,
"mode": "Circular",
"sourceIds": [
"cis-v4"
],
"evidence": "Client v4.0.0 18.10.26.2.1 p.1040; Client v4.0.0 18.10.26.2.2 p.1042; Server v4.0.0 18.10.26.2.1 p.842; Server v4.0.0 18.10.26.2.2 p.844. Size minimum; full-log retention Disabled (overwrite)."
},
{
"log": "Setup",
"minimumBytes": 33554432,
"mode": "Circular",
"sourceIds": [
"cis-v4"
],
"evidence": "Client v4.0.0 18.10.26.3.1 p.1045; Client v4.0.0 18.10.26.3.2 p.1047; Server v4.0.0 18.10.26.3.1 p.847; Server v4.0.0 18.10.26.3.2 p.849. Size minimum; full-log retention Disabled (overwrite)."
},
{
"log": "System",
"minimumBytes": 33554432,
"mode": "Circular",
"sourceIds": [
"cis-v4"
],
"evidence": "Client v4.0.0 18.10.26.4.1 p.1050; Client v4.0.0 18.10.26.4.2 p.1052; Server v4.0.0 18.10.26.4.1 p.852; Server v4.0.0 18.10.26.4.2 p.854. Size minimum; full-log retention Disabled (overwrite)."
}
]
},
{
"id": "asd-source-2021-10",
"kind": "source",
"scope": "event-log-size-and-mode-only",
"note": "ASD source buffer sizes. Circular mode is an explicit WELA source-host operating choice; ASD collector archival is a separate profile.",
"controls": [
{
"log": "Application",
"minimumBytes": 67108864,
"mode": "Circular",
"sourceIds": [
"asd-2021",
"wela"
],
"evidence": "ASD source size: Security 2097152 KiB; Application/System 65536 KiB. Circular source mode is a WELA operating choice."
},
{
"log": "Security",
"minimumBytes": 2147483648,
"mode": "Circular",
"sourceIds": [
"asd-2021",
"wela"
],
"evidence": "ASD source size: Security 2097152 KiB; Application/System 65536 KiB. Circular source mode is a WELA operating choice."
},
{
"log": "System",
"minimumBytes": 67108864,
"mode": "Circular",
"sourceIds": [
"asd-2021",
"wela"
],
"evidence": "ASD source size: Security 2097152 KiB; Application/System 65536 KiB. Circular source mode is a WELA operating choice."
}
]
},
{
"id": "asd-collector-archive-2021-10",
"kind": "collector",
"scope": "event-log-size-and-mode-only",
"note": "ForwardedEvents only. Requires a provisioned collector, secure archive storage, capacity monitoring and backup/move procedures. Does not create WEF subscriptions or guarantee retention duration.",
"controls": [
{
"log": "ForwardedEvents",
"minimumBytes": 2147483648,
"mode": "AutoBackup",
"sourceIds": [
"asd-2021"
],
"evidence": "ASD collection server: 2097152 KiB; archive when full when not forwarding to a secure central logging facility."
}
]
}
]
}
+7 -4
View File
@@ -53,7 +53,7 @@ was already written.
Each line of `before.jsonl` records the computer, timestamp, control identity,
requested setting and exact pre-change state. Registry entries include whether the
key/value existed and the previous registry type. Event-log entries capture size or
key/value existed and the previous registry type. Event-log entries capture size, mode or
enabled state; audit policies capture the numeric mask; CA entries also capture
service state. A journal write failure prevents that control's mutation. The
journal is per control, not a full system backup, and can contain records for failed
@@ -70,7 +70,10 @@ GPO change and could interrupt certificate services. Before recovery:
Do not blindly replay a journal or restore an entire audit policy backup.
3. Restore only the intended controls, normally in reverse application order:
- **EventLog:** `wevtutil sl <log> /ms:<previous-bytes>` or `/e:<previous-bool>`.
Review shrinking buffers or disabling a channel before proceeding.
Profile size/mode entries include a complete state object; see
[event-log recovery](eventlog-settings.md#recovery) for mode flags and the
fresh `ImmediatePreWrite` journal record. Review shrinking buffers, changing
retention or disabling a channel before proceeding.
- **AuditPolicy:** `auditpol /set /subcategory:{<guid>} /success:<enable|disable>
/failure:<enable|disable>`. Previous mask bit 1 means success, bit 2 means
failure. Restore that subcategory, not unrelated policy.
@@ -146,8 +149,8 @@ selection behavior while adding shared execution and recovery reporting.
paths without touching Windows policy, including exact/minimum behavior, concurrent
flags, unknown-state preflight, reference-only defaults, metadata and dry runs.
`-DryRun` is supported only by `configure`, including its `-Profile` form. Other
commands reject the flag before dispatch, so `configure-sacl -DryRun` and
`-DryRun` is supported by `configure`, including its `-Profile` form, and by
`configure-eventlogs`. Other commands reject the flag before dispatch, so `configure-sacl -DryRun` and
`update-rules -DryRun` cannot silently perform their normal mutations.
Outgoing `PreserveOrAudit` checks the shared runner's fresh registry snapshot and
+138
View File
@@ -0,0 +1,138 @@
# Event-log sizes and retention modes
`audit-filesize` and ordinary `configure` now use the same
`config/eventlog_profiles.json` definitions. `-Profile` continues to select
**advanced audit policy only**. Use the separate `-LogProfile` option with
`audit-filesize` or `configure-eventlogs` for channel buffer and retention settings.
```powershell
.\WELA.ps1 eventlog-profiles
.\WELA.ps1 audit-filesize -LogProfile wela-source-2.2.0
.\WELA.ps1 configure-eventlogs -LogProfile asd-source-2021-10 -DryRun -ResultsPath .\log-plan.json
# Increase undersized buffers; preserve existing modes and larger buffers.
.\WELA.ps1 configure-eventlogs -LogProfile asd-source-2021-10 -Auto -ResultsPath .\log-results.json
# Explicit source circular overwrite choice. Mode changes require this separate flag.
.\WELA.ps1 configure-eventlogs -LogProfile cis-v4-source -ApplyLogMode
# Explicit collector archive choice, only on an already provisioned collector.
.\WELA.ps1 configure-eventlogs -LogProfile asd-collector-archive-2021-10 -ApplyLogMode
# Deliberately resize to profile values, including shrinking larger buffers.
.\WELA.ps1 configure-eventlogs -LogProfile cis-v4-source -ResizeLogs -DryRun
```
`-ResizeLogs` and `-ApplyLogMode` are accepted only by `configure-eventlogs`.
Neither is implied by `-Auto`. The command supports the same `-DryRun`,
`-BackupPath` and `-ResultsPath` semantics as ordinary configuration. It requires
Windows and an elevated shell. It changes only size and the explicitly selected
mode: it does not enable or disable channels, install sensors, configure an audit
subcategory, write policy registry keys, or provision event forwarding.
| Log profile | Minimum sizes | Mode recommendation, applied only with `-ApplyLogMode` |
| --- | --- | --- |
| `wela-source-2.2.0` | Security and both PowerShell logs 1024 MiB; four AppLocker channels and firewall channel 256 MiB; Setup 32 MiB; remaining listed channels 128 MiB | Circular |
| `cis-v4-source` | Application, Setup, System 32 MiB; Security 192 MiB | Circular |
| `asd-source-2021-10` | Security 2048 MiB; Application and System 64 MiB | Circular (explicit WELA source-host choice, not an additional ASD prescription) |
| `asd-collector-archive-2021-10` | ForwardedEvents 2048 MiB | AutoBackup; collector only |
The WELA list also includes the previously audit-only BITS Analytic and DFSN Admin
channels. Missing role-specific channels remain explicit failed observations;
they are not silently removed from the result. Debug/analytic channels may impose
provider restrictions on changing their configuration while enabled. WELA reports
such a native failure and does not disable a channel or clear events to work
around it. Profile selection is not an assertion that every channel is installed
on every Windows role or edition.
The CIS values are from the reviewed **v4.0.0 Windows 11 Enterprise and Windows
Server 2022** editions, not the latest benchmark. This feature compares and changes
effective local channel values; it does not check the CIS requirement to configure
the corresponding Administrative Template policy or establish full baseline
compliance. GPO and MDM may restore different effective settings later. Source
identifiers and setting evidence are retained in JSON and audit CSV output.
Sizes are compared as integer bytes. One MiB is 1,048,576 bytes; profile targets are
rounded upward to the Windows 65,536-byte unit so rounding cannot undershoot a
minimum. The default comparison is `observed >= target`. Larger buffers are never
shrunk unless `-ResizeLogs` is explicit. Before writing, WELA rechecks state after
operator confirmation, preserving any newly enlarged buffer in minimum mode.
Windows does not provide an atomic compare-and-set for channel settings, so a
later concurrent writer remains outside this guarantee. Changing retention or
shrinking a buffer can affect event availability; review the dry run and storage
requirements before opting in.
`Circular` overwrites older events as the active buffer fills. `AutoBackup`
archives a full log and starts a new active log. `Retain` keeps existing events
and can discard incoming events when full. Audit output shows observed and
recommended modes separately from size compliance; omitting `-ApplyLogMode`
does not claim that a mismatching existing mode was corrected.
**Retention days remain Unknown.** A capacity setting does not establish event
rate, archive survival, or a retention period. For collectors, first configure
and verify subscriptions, forwarding, archive ACLs, available disk space,
capacity alerts, and backup/move procedures. Archive files accumulate: this
feature neither deletes them nor manages their age. A disabled channel remains
disabled, and no event-production or Sigma-coverage increase is claimed.
## Results and failures
The audit reads `Get-WinEvent -ListLog` live. Missing channels, access denied and
other unreadable state stay explicit; they are never replaced by documentary
Windows defaults. The CSV contains exact observed bytes, minimum and rounded
target bytes, size status, observed/recommended modes, mode status, channel
enabled state, source evidence and any read diagnostic. Access failures are not
misreported as missing channels. Displaying MiB does not round the compliance
decision.
Configuration uses the shared runner: journal before mutation, native exit-code
checks, immediate read-back, and a final drift check. Missing/unreadable channels,
ineffective changes and drift produce failed/overridden results and a nonzero
overall exit code while other selected channels are assessed. Successful size
configuration leaves no size warning for the same selected profile. Retention
warnings remain when the operator has not requested mode changes. `-DryRun`
performs no native setter calls and creates no recovery journal; an explicitly
requested JSON report may still be written.
## Recovery
Use a new protected `-BackupPath` and save the result JSON beside it. Do not use a
journal to overwrite a later intentional administrator or GPO change. For each
channel that needs recovery, review its current state and the latest journal
entry with `Phase: ImmediatePreWrite`: that record stores the fresh byte count and
mode observed immediately before the attempted write. The earlier runner entry
records the initial observation. A journal entry alone does not prove a successful
write; consult the result and live state. `BeforeWrite` is also in each result.
From an elevated shell, restore only the reviewed settings with `wevtutil sl`:
| Previous property | Restore arguments |
| --- | --- |
| Maximum size | `/ms:<Before.MaximumSizeInBytes>` |
| Circular | `/rt:false /ab:false` |
| AutoBackup | `/rt:true /ab:true` |
| Retain | `/rt:true /ab:false` |
Check the native exit code and read back the channel afterward. Review shrinking
or changes to event overwrite behavior first. Restoring a size or mode does not
recover overwritten records; WELA does not clear logs or delete archive files.
For a failed write, the original settings may already remain in place. This is a
manual per-channel procedure, not an automated rollback or complete log backup.
## Sources and validation
- [Microsoft wevtutil](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/wevtutil)
documents byte sizing, 64 KiB units, retention and auto-backup flags.
- [ASD Windows event logging and forwarding (October 2021)](https://www.cyber.gov.au/business-government/detecting-responding-to-threats/event-logging/windows-event-logging-and-forwarding)
provides the source buffer values and separate collector/archive guidance.
- [CIS Microsoft Windows benchmark catalog](https://www.cisecurity.org/benchmark/microsoft_windows_desktop)
provides the benchmark access point; the values implemented here are the
historical v4.0.0 editions reviewed for issue #379, Event Log Service settings.
`tests/EventLogSettings.Tests.ps1` uses safe channel/native fixtures and temporary
journals. It checks audit/configure agreement, preservation, explicit resize/mode
choices, rounding, missing/denied reads, concurrent growth, false-success writes,
journal failures and drift. Windows CI also runs
`tests/EventLogSettings.Windows.Tests.ps1`, which reads real channels and verifies
missing-channel handling without changing machine policy. Both run in Windows
PowerShell 5.1 and PowerShell 7. Real mutating behavior and ingestion still require
isolated Windows source/collector validation; these tests do not claim it.
Release packaging already includes the complete `config`, `modules` and `scripts`
directories. Keep them beside `WELA.ps1`, including the new JSON and module.
+87
View File
@@ -0,0 +1,87 @@
# Shared, native event-log size and retention model. Windows PowerShell 5.1 compatible.
function ConvertTo-WelaEventLogBytes {
param([ValidateRange(1048576, 2199023255552)][long]$Bytes)
# wevtutil uses 64 KiB units. Round UP so a minimum never becomes too small.
return [long]([math]::Ceiling($Bytes / 65536.0) * 65536)
}
function Import-WelaEventLogProfiles {
param([string]$Path = (Join-Path $PSScriptRoot '../config/eventlog_profiles.json'))
$data = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
if ($data.schemaVersion -ne 1) { throw 'Unsupported event-log profile schema.' }
$ids = @{}
foreach ($profile in $data.profiles) {
if (-not $profile.id -or $ids.ContainsKey($profile.id)) { throw 'Missing or duplicate event-log profile ID.' }
$ids[$profile.id] = $true
if ($profile.kind -notin @('source', 'collector') -or $profile.scope -ne 'event-log-size-and-mode-only') { throw "Invalid event-log profile: $($profile.id)" }
$logs = @{}
foreach ($control in $profile.controls) {
if (-not $control.log -or $control.log -match '[*?\[\]\r\n]' -or $logs.ContainsKey($control.log)) { throw "Invalid/duplicate event log: $($control.log)" }
$logs[$control.log] = $true
if ($control.mode -notin @('Circular', 'AutoBackup') -or -not $control.evidence) { throw "Invalid mode/evidence: $($control.log)" }
if ($control.minimumBytes -isnot [long] -and $control.minimumBytes -isnot [int]) { throw 'Log size must be an integer byte count.' }
$null = ConvertTo-WelaEventLogBytes $control.minimumBytes
if (@($control.sourceIds).Count -eq 0) { throw 'Event-log source evidence is required.' }
foreach ($id in $control.sourceIds) {
if (-not $data.sources.PSObject.Properties[$id]) { throw "Unknown event-log source: $id" }
}
}
if ($logs.Count -eq 0) { throw 'An event-log profile must contain controls.' }
}
return $data
}
function Get-WelaEventLogProfile {
param([string]$Id = 'wela-source-2.2.0')
$data = Import-WelaEventLogProfiles
$profile = @($data.profiles | Where-Object { $_.id -eq $Id })
if ($profile.Count -ne 1) { throw "Unknown log profile '$Id'. Use eventlog-profiles to list IDs." }
return $profile[0]
}
function Get-WelaEventLogState {
param([string]$Log)
$state = [ordered]@{
Log = $Log; ReadStatus = 'Unreadable'; MaximumSizeInBytes = $null
LogMode = $null; FileSize = $null; IsEnabled = $null; Diagnostic = ''
}
try {
$info = @(Get-WinEvent -ListLog $Log -ErrorAction Stop)
if ($info.Count -ne 1 -or $null -eq $info[0].MaximumSizeInBytes -or [long]$info[0].MaximumSizeInBytes -le 0) { throw 'A unique channel with a readable positive maximum size was not returned.' }
if ([string]$info[0].LogMode -notin @('Circular', 'AutoBackup', 'Retain')) { throw 'Channel retention mode is unknown.' }
$state.MaximumSizeInBytes = [long]$info[0].MaximumSizeInBytes
$state.LogMode = [string]$info[0].LogMode
$state.FileSize = $info[0].FileSize
$state.IsEnabled = $info[0].IsEnabled
$state.ReadStatus = 'Available'
} catch {
# Do not turn permission/provider failures into a claim that a channel is absent.
if ($_.FullyQualifiedErrorId -like 'NoMatchingLogsFound*' -or $_.Exception.GetType().FullName -eq 'System.Diagnostics.Eventing.Reader.EventLogNotFoundException') { $state.ReadStatus = 'Missing' }
$state.Diagnostic = $_.ToString()
}
return [pscustomobject]$state
}
function Get-WelaEventLogAudit {
param([string]$Profile = 'wela-source-2.2.0', [scriptblock]$Read = { param($log) Get-WelaEventLogState -Log $log })
$selected = Get-WelaEventLogProfile -Id $Profile
foreach ($control in $selected.controls) {
$current = & $Read $control.log
$available = $current.ReadStatus -eq 'Available'
$target = ConvertTo-WelaEventLogBytes $control.minimumBytes
[pscustomobject][ordered]@{
Profile = $selected.id; Log = $control.log; ReadStatus = $current.ReadStatus
CurrentMaximumBytes = $current.MaximumSizeInBytes
CurrentMaximumMiB = $(if ($available) { $current.MaximumSizeInBytes / 1048576.0 } else { $null })
MinimumBytes = [long]$control.minimumBytes; RoundedTargetBytes = $target
SizeStatus = $(if (-not $available) { 'Unknown' } elseif ($current.MaximumSizeInBytes -ge $target) { 'Compliant' } else { 'BelowMinimum' })
CurrentMode = $current.LogMode; RecommendedMode = $control.mode
ModeStatus = $(if (-not $available) { 'Unknown' } elseif ($current.LogMode -eq $control.mode) { 'Compliant' } else { 'Different' })
RetentionDays = 'Unknown'; IsEnabled = $current.IsEnabled
IsNearlyFull = $(if ($available -and $null -ne $current.FileSize) { $current.FileSize -ge ($current.MaximumSizeInBytes * 0.95) } else { $null })
SourceIds = ($control.sourceIds -join ','); Evidence = $control.evidence; Diagnostic = $current.Diagnostic
}
}
}
Export-ModuleMember -Function ConvertTo-WelaEventLogBytes, Import-WelaEventLogProfiles, Get-WelaEventLogProfile, Get-WelaEventLogState, Get-WelaEventLogAudit
+1 -1
View File
@@ -94,7 +94,7 @@ function Invoke-WelaConfigurationControl {
function Complete-WelaConfiguration {
param($Context, [string]$ResultsPath, $Plan,
[ValidateSet("native-windows-configuration", "advanced-audit-policy-only")]
[ValidateSet("native-windows-configuration", "advanced-audit-policy-only", "event-log-size-and-mode-only")]
[string]$Scope = "native-windows-configuration")
# A second read detects a value that was compliant earlier but changed during
# this run. It does not establish whether GPO or another writer caused drift.
+82
View File
@@ -0,0 +1,82 @@
# Uses the same configuration runner as other native WELA settings. No closures.
function Set-WelaEventLogProfileControls {
param($Context, [string]$Profile = 'wela-source-2.2.0', [switch]$ResizeLogs, [switch]$ApplyLogMode)
$selected = Get-WelaEventLogProfile -Id $Profile
foreach ($control in $selected.controls) {
$state = @{
Log = $control.log; Bytes = (ConvertTo-WelaEventLogBytes $control.minimumBytes)
ExactSize = [bool]$ResizeLogs; Mode = $(if ($ApplyLogMode) { $control.mode } else { $null })
Context = $Context; BeforeWrite = $null
}
$read = {
param($state)
$observed = Get-WelaEventLogState -Log $state.Log
if ($observed.ReadStatus -ne 'Available') { throw "$($observed.ReadStatus) channel '$($state.Log)': $($observed.Diagnostic)" }
return $observed
}
$test = {
param($value, $state)
$sizeOK = if ($state.ExactSize) { $value.MaximumSizeInBytes -eq $state.Bytes } else { $value.MaximumSizeInBytes -ge $state.Bytes }
return $sizeOK -and (-not $state.Mode -or $value.LogMode -eq $state.Mode)
}
$apply = {
param($state)
# Recheck after prompting/journaling. A newly increased buffer must not
# be shrunk in minimum mode. Windows has no atomic compare-and-set here.
$fresh = Get-WelaEventLogState -Log $state.Log
if ($fresh.ReadStatus -ne 'Available') { throw 'Event-log state became unreadable before write.' }
$arguments = @('sl', $state.Log)
if (($state.ExactSize -and $fresh.MaximumSizeInBytes -ne $state.Bytes) -or $fresh.MaximumSizeInBytes -lt $state.Bytes) {
$arguments += "/ms:$($state.Bytes)"
}
if ($state.Mode -and $fresh.LogMode -ne $state.Mode) {
if ($state.Mode -eq 'Circular') { $arguments += @('/rt:false', '/ab:false') }
elseif ($state.Mode -eq 'AutoBackup') { $arguments += @('/rt:true', '/ab:true') }
else { throw 'Unsupported event-log mode.' }
}
if ($arguments.Count -gt 2) {
# The prompt can outlive another administrator's change. Keep the
# fresh snapshot as well as the runner's original observation.
$state.BeforeWrite = $fresh
[ordered]@{
Version = 1; ComputerName = $env:COMPUTERNAME; RecordedUtc = [DateTime]::UtcNow.ToString('o')
Id = "EventLog/$($state.Log)/ProfileSettings"; Kind = 'EventLog'; Phase = 'ImmediatePreWrite'
Target = @{ Log = $state.Log }; Before = $fresh
Desired = @{ MaximumSizeInBytes = $state.Bytes; SizeMode = $(if ($state.ExactSize) { 'Exact' } else { 'Minimum' }); LogMode = $state.Mode }
} | ConvertTo-Json -Depth 12 -Compress | Add-Content -LiteralPath (Join-Path $state.Context.BackupPath 'before.jsonl') -Encoding UTF8 -ErrorAction Stop
Invoke-WelaNative -FilePath 'wevtutil.exe' -Arguments $arguments
}
}
$description = if ($ResizeLogs) { "Set exact size $($state.Bytes) bytes (shrinking can discard events)." } else { "Set minimum size $($state.Bytes) bytes; preserve larger buffers." }
$description += if ($ApplyLogMode) { " Apply $($state.Mode) mode." } else { ' Preserve the current retention mode.' }
Invoke-WelaConfigurationControl -Context $Context -Id "EventLog/$($control.log)/ProfileSettings" -Kind EventLog `
-Target @{ Log = $control.log; Profile = $selected.id } `
-Desired @{ MaximumSizeInBytes = $state.Bytes; SizeMode = $(if ($ResizeLogs) { 'Exact' } else { 'Minimum' }); LogMode = $state.Mode } `
-Description $description `
-Read $read -Compliant $test -Apply $apply -CallbackState $state
$result = $Context.Results[$Context.Results.Count - 1]
$result | Add-Member NoteProperty SourceIds @($control.sourceIds)
$result | Add-Member NoteProperty Evidence $control.evidence
$result | Add-Member NoteProperty RecommendedMode $control.mode
$result | Add-Member NoteProperty RetentionDays 'Unknown'
$result | Add-Member NoteProperty BeforeWrite $state.BeforeWrite
}
}
function Invoke-WelaEventLogConfiguration {
param([string]$Profile = 'wela-source-2.2.0', [switch]$Auto, [switch]$DryRun,
[switch]$ResizeLogs, [switch]$ApplyLogMode, [string]$BackupPath, [string]$ResultsPath)
# Validate before a journal is created. The CLI checks Windows/elevation.
$selected = Get-WelaEventLogProfile -Id $Profile
$context = New-WelaConfigurationContext -Auto:$Auto -DryRun:$DryRun -BackupPath $BackupPath
Set-WelaEventLogProfileControls -Context $context -Profile $Profile -ResizeLogs:$ResizeLogs -ApplyLogMode:$ApplyLogMode
$report = Complete-WelaConfiguration -Context $context -Scope 'event-log-size-and-mode-only'
$report | Add-Member NoteProperty LogProfile $selected.id
$report | Add-Member NoteProperty ProfileKind $selected.kind
$report | Add-Member NoteProperty RetentionDays 'Unknown'
if ($ResultsPath) {
try { $report | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $ResultsPath -Encoding UTF8 -ErrorAction Stop }
catch { $report.ExitCode = 1; Write-Host "[Failed] Writing event-log results: $_" -ForegroundColor Red }
}
return $report
}
+206
View File
@@ -0,0 +1,206 @@
# Safe fixtures only: never invokes real wevtutil or changes a Windows channel.
$ErrorActionPreference = 'Stop'
$repo = Split-Path $PSScriptRoot -Parent
Import-Module (Join-Path $repo 'modules/EventLogSettings.psm1') -Force
. (Join-Path $repo 'scripts/Configuration.ps1')
. (Join-Path $repo 'scripts/EventLogConfiguration.ps1')
$script:ScriptRoot = $repo
$script:assertions = 0
$script:cleanup = New-Object 'System.Collections.Generic.List[string]'
function Assert($Condition, [string]$Message) {
if (-not $Condition) { throw "FAIL: $Message" }
$script:assertions++
}
function New-TestContext([switch]$DryRun, [switch]$Prompt) {
$path = Join-Path ([IO.Path]::GetTempPath()) ('wela-eventlog-' + [guid]::NewGuid().ToString('N'))
if (-not $DryRun) { $script:cleanup.Add($path) }
New-WelaConfigurationContext -Auto:(-not $Prompt) -DryRun:$DryRun -BackupPath $path
}
function New-State([string]$Log, [long]$Bytes = 1048576, [string]$Mode = 'Retain') {
[pscustomobject]@{ Log = $Log; ReadStatus = 'Available'; MaximumSizeInBytes = $Bytes; LogMode = $Mode; FileSize = 100; IsEnabled = $true; Diagnostic = '' }
}
$data = Import-WelaEventLogProfiles
$wela = Get-WelaEventLogProfile
Assert ($data.profiles.Count -eq 4 -and $wela.controls.Count -eq 28) 'Catalog includes four separate source/collector choices and all WELA channels'
foreach ($log in @('Microsoft-Windows-AppLocker/EXE and DLL', 'Microsoft-Windows-AppLocker/MSI and Script', 'Microsoft-Windows-AppLocker/Packaged app-Deployment', 'Microsoft-Windows-AppLocker/Packaged app-Execution', 'Microsoft-Windows-Windows Firewall With Advanced Security/Firewall')) {
Assert (($wela.controls | Where-Object log -eq $log).minimumBytes -eq 268435456) "$log uses the same 256 MiB audit/apply threshold"
}
Assert (($wela.controls | Where-Object log -eq 'Setup').minimumBytes -eq 33554432) 'WELA includes Setup at CIS 32 MiB minimum'
Assert (($wela.controls | Where-Object log -eq 'Security').minimumBytes -eq 1073741824) 'Default preserves WELA configure 1024 MiB Security choice'
Assert (((Get-WelaEventLogProfile 'asd-source-2021-10').controls | Where-Object log -eq 'Security').minimumBytes -eq 2147483648) 'ASD Security size remains a 64-bit 2048 MiB byte count'
$collector = Get-WelaEventLogProfile 'asd-collector-archive-2021-10'
Assert ($collector.kind -eq 'collector' -and $collector.controls.Count -eq 1 -and $collector.controls[0].log -eq 'ForwardedEvents' -and $collector.controls[0].mode -eq 'AutoBackup') 'Collector archive does not leak into source logs'
Assert ((ConvertTo-WelaEventLogBytes 1048577) -eq 1114112) 'Fractional 64 KiB request rounds upward, never below the requested minimum'
Assert ((ConvertTo-WelaEventLogBytes 2147483648) -eq 2147483648) 'Aligned 2 GiB remains exact without integer overflow'
$caught = $false; try { Get-WelaEventLogProfile 'unrecognized' } catch { $caught = $true }
Assert $caught 'Unknown profile fails rather than silently using default values'
# Exercise the real reader inside its module, safely replacing only Get-WinEvent.
$module = Get-Module EventLogSettings
& $module {
$script:case = 'normal'
function script:Get-WinEvent {
param($ListLog, $ErrorAction)
if ($script:case -eq 'denied') { throw [UnauthorizedAccessException]::new('fixture access denied') }
if ($script:case -eq 'missing') { throw [Management.Automation.ErrorRecord]::new([Exception]::new('fixture missing'), 'NoMatchingLogsFound', [Management.Automation.ErrorCategory]::ObjectNotFound, $ListLog) }
[pscustomobject]@{ MaximumSizeInBytes = $(if ($script:case -eq 'null') { $null } else { 1048577 }); LogMode = 'Circular'; FileSize = 42; IsEnabled = $false }
}
}
$observed = Get-WelaEventLogState 'Fixture'
Assert ($observed.ReadStatus -eq 'Available' -and $observed.MaximumSizeInBytes -eq 1048577 -and -not $observed.IsEnabled) 'Reader preserves exact bytes and does not claim a disabled channel is enabled'
& $module { $script:case = 'denied' }
Assert ((Get-WelaEventLogState 'Fixture').ReadStatus -eq 'Unreadable') 'Access denial is not classified as a missing channel'
& $module { $script:case = 'missing' }
Assert ((Get-WelaEventLogState 'Fixture').ReadStatus -eq 'Missing') 'Known missing-channel error remains explicit'
& $module { $script:case = 'null' }
Assert ((Get-WelaEventLogState 'Fixture').ReadStatus -eq 'Unreadable') 'Null maximum does not become a static/default size'
& $module { Remove-Item Function:script:Get-WinEvent }
# The audit compares bytes, not rounded display values, and never invents duration.
$audit = @(Get-WelaEventLogAudit -Profile 'cis-v4-source' -Read { param($log) New-State $log 33554431 })
Assert (($audit | Where-Object Log -eq 'Setup').SizeStatus -eq 'BelowMinimum') 'One byte under the minimum is not rounded to compliant'
Assert (@($audit | Where-Object RetentionDays -ne 'Unknown').Count -eq 0) 'Buffer size is not converted into an unmeasured retention age'
$audit = @(Get-WelaEventLogAudit -Profile 'cis-v4-source' -Read { param($log) [pscustomobject]@{ ReadStatus = 'Unreadable'; MaximumSizeInBytes = $null; LogMode = $null; IsEnabled = $null; Diagnostic = 'denied' } })
Assert ($audit[0].SizeStatus -eq 'Unknown' -and $null -eq $audit[0].CurrentMaximumBytes -and $audit[0].Diagnostic -eq 'denied') 'Unreadable audit rows retain unknown state and failure evidence'
# Script-scoped fixtures override exported commands at the same scope as helpers.
function Reset-Fixture([string]$Profile = 'cis-v4-source', [long]$Bytes = 1048576, [string]$Mode = 'Retain') {
$script:states = @{}; $script:writes = New-Object 'System.Collections.Generic.List[object]'
foreach ($control in (Get-WelaEventLogProfile $Profile).controls) { $script:states[$control.log] = New-State $control.log $Bytes $Mode }
$script:failWrite = $false; $script:falseSuccess = $false; $script:growOnPrompt = $false; $script:unreadableOnPrompt = $false
}
function Get-WelaEventLogState {
param($Log)
if (-not $script:states.ContainsKey($Log)) { return [pscustomobject]@{ ReadStatus = 'Missing'; Diagnostic = 'Fixture channel absent' } }
# Return a snapshot, not the mutable fixture reference, so journals are realistic.
return $script:states[$Log].PSObject.Copy()
}
function Read-Host {
param($Prompt)
if ($script:growOnPrompt) { foreach ($key in @($script:states.Keys)) { $script:states[$key].MaximumSizeInBytes = 4294967296 } }
if ($script:unreadableOnPrompt) { foreach ($key in @($script:states.Keys)) { $script:states[$key].ReadStatus = 'Unreadable' } }
return 'Y'
}
function Invoke-WelaNative {
param($FilePath, $Arguments)
Assert ($FilePath -eq 'wevtutil.exe' -and $Arguments[0] -eq 'sl') 'Only the intended native channel-setting command is issued'
Assert (Test-Path -LiteralPath (Join-Path $script:activeContext.BackupPath 'before.jsonl')) 'Pre-change journal is durable before each native write'
$script:writes.Add(@($Arguments))
if ($script:failWrite) { throw 'fixture native nonzero exit' }
if (-not $script:falseSuccess) {
$current = $script:states[$Arguments[1]]
foreach ($argument in $Arguments) {
if ($argument -like '/ms:*') { $current.MaximumSizeInBytes = [long]$argument.Substring(4) }
}
if ($Arguments -contains '/ab:true' -and $Arguments -contains '/rt:true') { $current.LogMode = 'AutoBackup' }
if ($Arguments -contains '/ab:false' -and $Arguments -contains '/rt:false') { $current.LogMode = 'Circular' }
}
[pscustomobject]@{ Diagnostic = 'Safe fixture write' }
}
try {
Reset-Fixture 'wela-source-2.2.0'
$script:activeContext = New-TestContext
Set-WelaEventLogProfileControls -Context $script:activeContext
$audit = @(Get-WelaEventLogAudit -Read { param($log) Get-WelaEventLogState $log })
Assert (@($audit | Where-Object SizeStatus -ne 'Compliant').Count -eq 0) 'Successful default configuration leaves no default-profile size warning'
Assert (@($script:writes | Where-Object { ($_ -join ' ') -match '/[ar][bt]:' }).Count -eq 0) 'Ordinary configuration never changes retention modes'
Assert ($script:states.Security.LogMode -eq 'Retain') 'Existing retain policy is preserved without explicit mode opt-in'
$result = Complete-WelaConfiguration -Context $script:activeContext
Assert ($result.ExitCode -eq 0) 'All default sizes pass final verification'
Reset-Fixture 'cis-v4-source' 4294967296
$script:activeContext = New-TestContext
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'cis-v4-source'
Assert ($script:writes.Count -eq 0 -and $script:activeContext.Checks.Count -eq 4) 'Minimum mode preserves larger buffers and still registers final verification'
$script:states.Setup.MaximumSizeInBytes = 1048576
$result = Complete-WelaConfiguration -Context $script:activeContext
Assert ($result.ExitCode -eq 1 -and @($result.Results | Where-Object Status -eq 'Overridden').Count -eq 1) 'Final drift is not reported as success'
Reset-Fixture 'cis-v4-source' 4294967296
$script:activeContext = New-TestContext
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'cis-v4-source' -ResizeLogs -ApplyLogMode
Assert ($script:states.Setup.MaximumSizeInBytes -eq 33554432 -and $script:states.Setup.LogMode -eq 'Circular') 'Explicit resize and mode flags allow reviewed shrink/circular choices'
Assert ($script:writes[0] -contains '/rt:false' -and $script:writes[0] -contains '/ab:false') 'Source circular uses both retention and autobackup false'
$firstJournal = (Get-Content -LiteralPath (Join-Path $script:activeContext.BackupPath 'before.jsonl'))[0] | ConvertFrom-Json
Assert ($firstJournal.Before.MaximumSizeInBytes -eq 4294967296 -and $firstJournal.Before.LogMode -eq 'Retain') 'Journal records exact previous bytes and mode for manual recovery'
Reset-Fixture 'asd-collector-archive-2021-10'
$script:activeContext = New-TestContext
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'asd-collector-archive-2021-10' -ApplyLogMode
Assert ($script:writes.Count -eq 1 -and $script:writes[0] -contains '/rt:true' -and $script:writes[0] -contains '/ab:true') 'Collector archive explicitly applies retention plus autobackup'
Assert ($script:states.ForwardedEvents.MaximumSizeInBytes -eq 2147483648 -and $script:states.ForwardedEvents.LogMode -eq 'AutoBackup') 'Collector exact 2 GiB and mode are read back'
Reset-Fixture
$script:activeContext = New-TestContext -DryRun
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'cis-v4-source' -ResizeLogs -ApplyLogMode
Assert ($script:writes.Count -eq 0 -and -not (Test-Path -LiteralPath $script:activeContext.BackupPath)) 'Dry run performs no native writes and creates no journal'
Reset-Fixture
$script:activeContext = New-TestContext -Prompt; $script:growOnPrompt = $true
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'cis-v4-source'
Assert ($script:writes.Count -eq 0 -and $script:states.Setup.MaximumSizeInBytes -eq 4294967296) 'Fresh prewrite state preserves buffer enlarged during operator confirmation'
Reset-Fixture
$script:activeContext = New-TestContext -Prompt; $script:unreadableOnPrompt = $true
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'cis-v4-source'
Assert ($script:writes.Count -eq 0 -and $script:activeContext.Results[0].Status -eq 'Failed') 'Unknown fresh state refuses writes'
foreach ($case in @('missing', 'denied', 'native', 'false-success', 'journal')) {
Reset-Fixture 'asd-collector-archive-2021-10'
$script:activeContext = New-TestContext
if ($case -eq 'missing') { $script:states.Clear() }
if ($case -eq 'denied') { $script:states.ForwardedEvents.ReadStatus = 'Unreadable'; $script:states.ForwardedEvents.Diagnostic = 'access denied' }
if ($case -eq 'native') { $script:failWrite = $true }
if ($case -eq 'false-success') { $script:falseSuccess = $true }
if ($case -eq 'journal') { $script:activeContext.BackupPath = Join-Path $script:activeContext.BackupPath 'absent-parent' }
Set-WelaEventLogProfileControls -Context $script:activeContext -Profile 'asd-collector-archive-2021-10' -ApplyLogMode
$result = Complete-WelaConfiguration -Context $script:activeContext
Assert ($result.ExitCode -eq 1 -and $result.Results[0].Status -eq 'Failed') "$case is surfaced as failed configuration"
if ($case -in @('missing', 'denied', 'journal')) { Assert ($script:writes.Count -eq 0) "$case prevents the native write" }
}
# Parse actual production entry points; same profile is selected in both paths.
$tokens = $null; $errors = $null
$ast = [Management.Automation.Language.Parser]::ParseFile((Join-Path $repo 'WELA.ps1'), [ref]$tokens, [ref]$errors)
Assert ($errors.Count -eq 0) 'WELA remains parseable'
$configure = $ast.Find({ param($n) $n -is [Management.Automation.Language.FunctionDefinitionAst] -and $n.Name -eq 'ConfigureAuditSettings' }, $true).Extent.Text
Assert ($configure.Contains("Set-WelaEventLogProfileControls -Context `$context -Profile 'wela-source-2.2.0'") -and $configure -notmatch '-Property MaximumSizeInBytes') 'Default configure consumes the shared model rather than another hardcoded size list'
$release = Get-Content (Join-Path $repo '.github/workflows/release.yml') -Raw
foreach ($directory in @('config', 'scripts', 'modules')) { Assert ($release -match "Copy-Item -Recurse -Path ./($directory) ") "Release packages the new $directory dependency" }
Reset-Fixture
$output = Join-Path ([IO.Path]::GetTempPath()) ('wela-eventlog-results-' + [guid]::NewGuid().ToString('N') + '.json')
$script:cleanup.Add($output)
$result = Invoke-WelaEventLogConfiguration -Profile 'cis-v4-source' -DryRun -ResultsPath $output
$saved = Get-Content -LiteralPath $output -Raw | ConvertFrom-Json
Assert ($result.ExitCode -eq 0 -and $saved.Scope -eq 'event-log-size-and-mode-only' -and $saved.LogProfile -eq 'cis-v4-source') 'Dedicated configuration exports its narrow scope and selected log profile'
Assert ($saved.Results.Count -eq 4 -and $saved.Results[0].SourceIds -contains 'cis-v4' -and $saved.RetentionDays -eq 'Unknown') 'Structured result preserves source provenance and unknown retention duration'
# Execute only actual option guards, then the dispatcher with harmless stubs.
$guards = @($ast.EndBlock.Statements | Where-Object { $_ -is [Management.Automation.Language.IfStatementAst] -and $_.Extent.Text -match 'No command was run|selects advanced audit policy only|LogProfile is supported only' })
$guardBlock = [scriptblock]::Create(($guards | ForEach-Object { $_.Extent.Text }) -join "`n")
$Cmd = 'configure'; $Profile = 'wela-2.2.0'; $LogProfile = 'cis-v4-source'; $ResizeLogs = $false; $ApplyLogMode = $false; $DryRun = $true
$caught = $false; try { & $guardBlock } catch { $caught = $true }
Assert $caught 'Advanced audit profile configure rejects log options instead of silently ignoring them'
$Cmd = 'configure-eventlogs'; $Profile = 'wela-2.2.0'
$caught = $false; try { & $guardBlock } catch { $caught = $true }
Assert $caught 'Event-log command rejects the advanced -Profile option'
$Profile = $null; $ResizeLogs = $true; $ApplyLogMode = $true
& $guardBlock
Assert $true 'Dedicated event-log dry run accepts explicit size/mode options'
$Help = $false; $Baseline = $null; $Auto = $true; $BackupPath = $null; $ResultsPath = $null
function TestWindows { return $true }
function TestAdministrator { return $true }
function Invoke-WelaEventLogConfiguration {
param($Profile, [switch]$Auto, [switch]$DryRun, [switch]$ResizeLogs, [switch]$ApplyLogMode, $BackupPath, $ResultsPath)
$script:dispatched = @{ Profile = $Profile; DryRun = [bool]$DryRun; ResizeLogs = [bool]$ResizeLogs; ApplyLogMode = [bool]$ApplyLogMode }
[pscustomobject]@{ ExitCode = 0 }
}
$dispatch = $ast.Find({ param($n) $n -is [Management.Automation.Language.SwitchStatementAst] -and $n.Condition.Extent.Text -eq '$Cmd.ToLower()' }, $false)
& ([scriptblock]::Create($dispatch.Extent.Text)) | Out-Null
Assert ($script:dispatched.Profile -eq 'cis-v4-source' -and $script:dispatched.DryRun -and $script:dispatched.ResizeLogs -and $script:dispatched.ApplyLogMode) 'CLI passes every explicit event-log choice to the dedicated runner'
} finally {
foreach ($path in $script:cleanup) { if (Test-Path -LiteralPath $path) { Remove-Item -LiteralPath $path -Recurse -Force } }
}
$global:LASTEXITCODE = 0
Write-Host "PASS: $script:assertions event-log assertions; no machine policies changed."
+14
View File
@@ -0,0 +1,14 @@
# Real Windows reader smoke only. No native setter, SaveChanges or policy mutation.
$ErrorActionPreference = 'Stop'
Import-Module (Join-Path $PSScriptRoot '../modules/EventLogSettings.psm1') -Force
foreach ($log in @('Application', 'System', 'Setup', 'Security')) {
$before = Get-WelaEventLogState -Log $log
if ($before.ReadStatus -ne 'Available') { throw "Cannot inspect $log : $($before.Diagnostic)" }
$row = @(Get-WelaEventLogAudit -Profile 'cis-v4-source' | Where-Object Log -eq $log)
$after = Get-WelaEventLogState -Log $log
if ($row.Count -ne 1 -or $row[0].CurrentMaximumBytes -ne $before.MaximumSizeInBytes -or $row[0].RetentionDays -ne 'Unknown') { throw "Audit did not represent the live $log configuration." }
if ($before.MaximumSizeInBytes -ne $after.MaximumSizeInBytes -or $before.LogMode -ne $after.LogMode) { throw "Observed concurrent change to $log during read-only smoke." }
}
$missing = Get-WelaEventLogState -Log ('WELA-Unregistered-' + [guid]::NewGuid().ToString('N'))
if ($missing.ReadStatus -ne 'Missing') { throw "Missing Windows channel was misclassified: $($missing.ReadStatus) $($missing.Diagnostic)" }
Write-Host 'PASS: live read-only event-log audit; exact bytes, modes and missing-channel reporting verified.'
+16 -6
View File
@@ -24,15 +24,25 @@ Check with Microsoft's recommended Client OS settings and display results in tab
./WELA.ps1 audit-settings -Baseline Microsoft_Client -OutType table
```
## audit-filesize
The `audit-filesize` command checks the Windows event logs' file size and compares them with the recommended settings from Yamato Security's recommendations.
## audit-filesize and configure-eventlogs
### `audit-filesize` command examples
Check the Windows event log file size with Yamato Security's recommendations and save results to CSV:
```
./WELA.ps1 audit-filesize -Baseline YamatoSecurity
`audit-filesize` reads live event-log sizes and retention modes using the same
profile as configuration, preserving exact byte counts in its CSV output.
Use `eventlog-profiles` to list the separate `-LogProfile` choices. The existing
`-Profile` option selects advanced audit policy only.
```powershell
./WELA.ps1 audit-filesize -LogProfile wela-source-2.2.0
./WELA.ps1 configure-eventlogs -LogProfile asd-source-2021-10 -DryRun
./WELA.ps1 configure-eventlogs -LogProfile asd-collector-archive-2021-10 -ApplyLogMode
```
`configure-eventlogs` preserves larger buffers and current modes by default.
`-ResizeLogs` explicitly permits shrinking; `-ApplyLogMode` explicitly applies
source circular or collector archive behavior. Retention days remain unknown
until event volume and archive retention are measured. See the
[event-log profiles and recovery guide](https://github.com/Yamato-Security/WELA/blob/dev/docs/eventlog-settings.md).
## configure
The `configure` command sets the recommended Windows event log audit policy and file size.
+2
View File
@@ -7,6 +7,8 @@
**改善:**
- イベントログのサイズ監査と設定に共通のバイト単位プロファイルを導入し、AppLocker・ファイアウォールログの256 MiB、Setupの32 MiB、ASD推奨のSecurityログ2048 MiBに対応した。`-LogProfile`と`configure-eventlogs`で送信元と収集サーバーのサイズ・保存方式を選択できる。明示的に指定しない限り、既存の大きいバッファと保存方式は維持する。結果には検証した設定を記録し、未測定の保存日数は不明と表示する。 (issue #379) (@Shirofune-Security)
- `audit-settings`、`plan`、`configure`で共有するバージョン付きの詳細監査ポリシープロファイルを追加した。59のサブカテゴリと14のプロファイルで、WELA、文書に基づくWindows既定値、Microsoft、確認済みのCIS v4.0.0、ASDのWindows標準機能向け監査ガイドに対応する。ホストの役割とビルドの検証、オフラインでの設定計画、出典と前提条件を含むJSON出力をサポートする。完全一致、最低限、任意、変更なし、未構成、適用対象外を区別する。Windows既定値は参照専用で、プロファイルの対象はSecurityログの詳細監査ポリシーに限定される。 (#390) (@Shirofune-Security)
- WELAのプロファイルにWindows標準の監査サブカテゴリを6つ追加した。Group MembershipとAuthorization Policy Changeは成功、Application Group Management、MPSSVC Rule-Level Policy Change、IPsec Driver、Kernel Objectは成功と失敗を監査する。各ガイドに対応するプロファイルでは、それぞれの監査設定と前提条件を維持する。Kernel Objectのイベント生成には対象オブジェクトに適切なSACLが必要であり、この変更ではそのSACLを作成しない。 (#391) (@Shirofune-Security)
- `configure`と`configure -Profile`に`-DryRun`と`-ResultsPath`を追加し、Windows設定を変更せずに変更内容を確認し、設定項目ごとの結果をJSONで出力できるようにした。`-DryRun`に対応していないコマンドは、実行前にエラーで停止する。 (#392) (@Shirofune-Security)
+2
View File
@@ -7,6 +7,8 @@
**Improvements:**
- Unified event-log size auditing and configuration with shared byte-based profiles, including 256 MiB AppLocker/firewall logs, 32 MiB Setup and ASD 2048 MiB Security. Added separate source and collector size/mode choices through `-LogProfile` and `configure-eventlogs`; larger buffers and existing retention modes are preserved unless explicitly changed. Results include verified state and unknown retention duration. (issue #379) (@Shirofune-Security)
- Added versioned advanced audit-policy profiles shared by `audit-settings`, `plan` and `configure`: 59 subcategories and 14 profiles covering WELA, documented Windows defaults, Microsoft, reviewed CIS v4.0.0 and ASD native guidance. Profiles support role/build validation, offline planning and JSON exports with sources and prerequisites. Exact, minimum, optional, unchanged, Not Configured and not-applicable settings remain distinct. Windows defaults are reference-only; profile scope is advanced Security audit policy. (#390) (@Shirofune-Security)
- Added six native Windows audit subcategories to WELA's profile: Group Membership and Authorization Policy Change (Success), plus Application Group Management, MPSSVC Rule-Level Policy Change, IPsec Driver and Kernel Object (Success and Failure). Source-specific profiles retain their own audit settings and prerequisites; Kernel Object events require matching object SACLs, which this change does not create. (#391) (@Shirofune-Security)
- Added `-DryRun` and `-ResultsPath` to `configure` and `configure -Profile` to preview changes without modifying Windows settings and export per-control results as JSON. Commands that do not support `-DryRun` reject it before running. (#392) (@Shirofune-Security)