From e180c8cfdea5812f695f20718798ccde0ceb78a9 Mon Sep 17 00:00:00 2001 From: spydisec <9101327+spydisec@users.noreply.github.com> Date: Fri, 4 Sep 2026 18:50:04 +1000 Subject: [PATCH 1/5] v1.0.0 layout: fleet/ and report/ folders, WinLogKit.Settings.ps1 Step 3 of the v1.0 restructure (ADR-001). Paths move, nothing else. - New-IntuneRemediationPack, New-GpoPack, New-WefSubscription and Test-WefFilter move to fleet/; Export-AttackCoverage and Invoke-WELACheck to report/. The three host scripts, the settings table and the shared helpers stay at the root, so a new reader sees the three scripts first. - Relocated scripts resolve $kitRoot = parent of $PSScriptRoot: settings, helpers, data and the output folders (Intune/, GPO/, WEF/, Results/, Evidence/, WELA lookup) stay at the kit root wherever they run from. - LoggingBaseline.Settings.ps1 renamed to WinLogKit.Settings.ps1; every dot-source, generator, doc, template and config reference updated; Reference page regenerated. - Help examples and printed hints path-qualify the relocated scripts; Commands and Getting Started gain a "where the scripts live" section; release zip packages fleet/ and report/. - CHANGELOG: Unreleased becomes v1.0.0 with the layout entry. Co-Authored-By: Claude Fable 5.1 --- .coderabbit.yaml | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/release.yml | 2 +- CHANGELOG.md | 17 +++++++++++++- CONTRIBUTING.md | 2 +- Enable-LoggingBaseline.ps1 | 2 +- New-LoggingBaseline.ps1 | 2 +- PSScriptAnalyzerSettings.psd1 | 2 +- README.md | 3 +++ Test-LoggingBaseline.ps1 | 2 +- ...ine.Settings.ps1 => WinLogKit.Settings.ps1 | 4 ++-- docs/baselines.md | 6 ++--- docs/commands.md | 23 +++++++++++++++---- docs/deployment.md | 4 ++-- docs/getting-started.md | 13 ++++++++--- docs/mapping.md | 8 +++---- docs/reference.md | 2 +- docs/wec.md | 2 +- New-GpoPack.ps1 => fleet/New-GpoPack.ps1 | 13 +++++++---- .../New-IntuneRemediationPack.ps1 | 13 +++++++---- .../New-WefSubscription.ps1 | 21 +++++++++-------- .../Test-WefFilter.ps1 | 2 +- .../Export-AttackCoverage.ps1 | 17 ++++++++------ .../Invoke-WELACheck.ps1 | 15 +++++++----- tests/Invoke-KitChecks.ps1 | 14 +++++------ tools/Export-ReferenceTable.ps1 | 6 ++--- tools/New-PresetBaselines.ps1 | 2 +- tools/Update-AuditSubcategoryEvents.ps1 | 2 +- 28 files changed, 128 insertions(+), 75 deletions(-) rename LoggingBaseline.Settings.ps1 => WinLogKit.Settings.ps1 (99%) rename New-GpoPack.ps1 => fleet/New-GpoPack.ps1 (93%) rename New-IntuneRemediationPack.ps1 => fleet/New-IntuneRemediationPack.ps1 (96%) rename New-WefSubscription.ps1 => fleet/New-WefSubscription.ps1 (95%) rename Test-WefFilter.ps1 => fleet/Test-WefFilter.ps1 (98%) rename Export-AttackCoverage.ps1 => report/Export-AttackCoverage.ps1 (94%) rename Invoke-WELACheck.ps1 => report/Invoke-WELACheck.ps1 (95%) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index f484106..f0533aa 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -44,7 +44,7 @@ reviews: or parameters. Flag anything 7-only. - $PSScriptRoot is unreliable in param-default expressions under powershell.exe -File; defaults must be resolved in the script body. - - Every logging setting lives in LoggingBaseline.Settings.ps1 with a + - Every logging setting lives in WinLogKit.Settings.ps1 with a plain-language Purpose (and Risk where volume/stability matters). Flag settings hardcoded in the other scripts. - Shared helpers live in WinLogKit.Common.ps1 (host probes, registry diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 086961f..d1eb79f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,7 +8,7 @@ ## Checklist - [ ] `tests\Invoke-KitChecks.ps1` passes locally -- [ ] Settings changes made in `LoggingBaseline.Settings.ps1` only, with a +- [ ] Settings changes made in `WinLogKit.Settings.ps1` only, with a plain-language purpose (and risk note where it matters) - [ ] Generated files (presets, docs Reference page, packs) regenerated via their `tools\` generators, not edited by hand diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99a9f47..24043e7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: Copy-Item *.ps1, PSScriptAnalyzerSettings.psd1, README.md, CHANGELOG.md, LICENSE $stage # Data-dependent scripts (coverage mapping, presets) must work from # the zip, not only from a git clone. - Copy-Item data, presets, tools, tests, addons $stage -Recurse + Copy-Item fleet, report, data, presets, tools, tests, addons $stage -Recurse Compress-Archive -Path $stage -DestinationPath "WinLogKit-$tag.zip" (Get-FileHash "WinLogKit-$tag.zip" -Algorithm SHA256).Hash.ToLower() + " WinLogKit-$tag.zip" | Set-Content "SHA256SUMS.txt" -Encoding ascii diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fa50ce..0c8f5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,24 @@ All notable changes to WinLogKit. Versions follow [SemVer](https://semver.org/); releases are tagged `vX.Y.Z` and published with a zip + SHA256 checksum. -## Unreleased +## v1.0.0 - 2026-09-04 + +The v1.0 restructure ([ADR-001](https://github.com/spydisec/WinLogKit/pull/30)): +docs cut, one copy of the shared helpers, and a layout that shows a new +reader the three scripts they need. Version 1.0.0 because paths move; no +setting changed. ### Changed +- **Layout (breaking: paths).** The fleet generators + (`New-IntuneRemediationPack.ps1`, `New-GpoPack.ps1`, + `New-WefSubscription.ps1`, `Test-WefFilter.ps1`) now live in `fleet\`, + and the coverage report and WELA check (`Export-AttackCoverage.ps1`, + `Invoke-WELACheck.ps1`) in `report\`. The three host scripts stay at the + root with the settings table and the shared helpers. Output folders + (`Intune\`, `GPO\`, `WEF\`, `Results\`, `Evidence\`) stay at the kit + root wherever the script runs from. +- **`LoggingBaseline.Settings.ps1` is now `WinLogKit.Settings.ps1`.** Same + contents. If you carry a modified copy, rename it. - **`WinLogKit.Common.ps1`.** The helpers that Enable, Test, the WELA check, the coverage report and the fleet generators each carried their own copy of (admin check, host role and OS type, registry reads, the diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9560e84..815a30b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ is what tunes the presets. Open an issue with the *Field report* template. ## Ground rules for changes -- **Every setting lives in `LoggingBaseline.Settings.ps1`** with a +- **Every setting lives in `WinLogKit.Settings.ps1`** with a plain-language purpose and, where it matters, a risk note. Scripts, presets, packs and docs derive from it; never hard-code a setting anywhere else. diff --git a/Enable-LoggingBaseline.ps1 b/Enable-LoggingBaseline.ps1 index 74bc9c2..61a3cc4 100644 --- a/Enable-LoggingBaseline.ps1 +++ b/Enable-LoggingBaseline.ps1 @@ -99,7 +99,7 @@ $ErrorActionPreference = 'Stop' if ([string]::IsNullOrEmpty($BaselineDir)) { $BaselineDir = Join-Path $PSScriptRoot 'Baseline' } if ([string]::IsNullOrEmpty($LogDir)) { $LogDir = Join-Path $PSScriptRoot 'Logs' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') +. (Join-Path $PSScriptRoot 'WinLogKit.Settings.ps1') . (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') # ---------------------------------------------------------------- helpers --- diff --git a/New-LoggingBaseline.ps1 b/New-LoggingBaseline.ps1 index e780515..078f181 100644 --- a/New-LoggingBaseline.ps1 +++ b/New-LoggingBaseline.ps1 @@ -91,7 +91,7 @@ Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' if ([string]::IsNullOrEmpty($OutFile)) { $OutFile = Join-Path $PSScriptRoot 'MyBaseline.csv' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') +. (Join-Path $PSScriptRoot 'WinLogKit.Settings.ps1') . (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') if ((Test-Path $OutFile) -and -not $Force -and -not $Show) { diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 index 9bdeb4d..6731faa 100644 --- a/PSScriptAnalyzerSettings.psd1 +++ b/PSScriptAnalyzerSettings.psd1 @@ -7,7 +7,7 @@ # The kit is an interactive console tool: Write-Host with colour IS the UI. 'PSAvoidUsingWriteHost' - # LoggingBaseline.Settings.ps1 defines script-scope tables consumed by the + # WinLogKit.Settings.ps1 defines script-scope tables consumed by the # other scripts after dot-sourcing; per-file analysis cannot see that. 'PSUseDeclaredVarsMoreThanAssignments' diff --git a/README.md b/README.md index 1220b70..2e74c05 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,9 @@ generator accept through `-BaselineFile`; `presets\` ships ready-made ones (ASD, Microsoft, and the kit's own `spydi_*` Minimal / Heavy pairs per role). +The three host scripts are at the kit root; fleet generators (Intune, GPO, +WEF) are in `fleet\` and the coverage report and WELA check in `report\`. + If scripts are blocked, `Set-ExecutionPolicy -Scope Process RemoteSigned` unblocks the current window without persisting anything; downloaded zips also need `Unblock-File`, and a policy enforced by Group Policy cannot be diff --git a/Test-LoggingBaseline.ps1 b/Test-LoggingBaseline.ps1 index 1d83cf3..fed4870 100644 --- a/Test-LoggingBaseline.ps1 +++ b/Test-LoggingBaseline.ps1 @@ -65,7 +65,7 @@ Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' if ([string]::IsNullOrEmpty($OutputDir)) { $OutputDir = Join-Path $PSScriptRoot 'Results' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') +. (Join-Path $PSScriptRoot 'WinLogKit.Settings.ps1') . (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') # ---------------------------------------------------------------- helpers --- diff --git a/LoggingBaseline.Settings.ps1 b/WinLogKit.Settings.ps1 similarity index 99% rename from LoggingBaseline.Settings.ps1 rename to WinLogKit.Settings.ps1 index 3874d68..0a6e884 100644 --- a/LoggingBaseline.Settings.ps1 +++ b/WinLogKit.Settings.ps1 @@ -1,6 +1,6 @@ # ============================================================================= -# LoggingBaseline.Settings.ps1 -# Shared settings table for Enable-LoggingBaseline.ps1 and Test-LoggingBaseline.ps1 +# WinLogKit.Settings.ps1 +# The settings table every kit script dot-sources. # # This is the single source of truth for the kit. Both the enable script and # the verification script dot-source this file, so they can never disagree diff --git a/docs/baselines.md b/docs/baselines.md index ad3e629..a908a9f 100644 --- a/docs/baselines.md +++ b/docs/baselines.md @@ -7,7 +7,7 @@ ready-made lists we ship, how to build your own, and which one to pick. ## The model -The settings table (`LoggingBaseline.Settings.ps1`) is the single source of +The settings table (`WinLogKit.Settings.ps1`) is the single source of truth: every channel, audit subcategory, registry value and SMB audit setting, each with a plain-language purpose, a tier, a scope, behaviour category tags and - where it matters - a volume/stability risk note. @@ -114,7 +114,7 @@ Usage is identical to any baseline CSV: ```powershell .\New-LoggingBaseline.ps1 -Show -BaselineFile .\presets\role_Workstation.csv .\Enable-LoggingBaseline.ps1 -BaselineFile .\presets\role_MemberServer.csv -WhatIf -.\New-IntuneRemediationPack.ps1 -BaselineFile .\presets\role_Workstation.csv -OutDir .\Intune\Workstation +.\fleet\New-IntuneRemediationPack.ps1 -BaselineFile .\presets\role_Workstation.csv -OutDir .\Intune\Workstation ``` To customise a role, copy the CSV, flip `Selected` values in Excel, and keep @@ -208,7 +208,7 @@ Notes, stated plainly: kit's heaviest setting. - Selection CSVs carry item choices, not sizes: the Security log stays at the kit's 1 GB (ASD suggests 2 GB; raise it in - `LoggingBaseline.Settings.ps1` if you take that view). + `WinLogKit.Settings.ps1` if you take that view). - A **GPO pack** generated from a `spydi_Server_*` preset includes the DC-only subcategories. They are inert on member servers and collectors (those events only generate on DCs), but if your GPO hygiene prefers diff --git a/docs/commands.md b/docs/commands.md index d026ce3..f05e58c 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,7 +1,7 @@ # Commands Every script, what it does, and the flags you'll actually use. They all -read the same settings table (`LoggingBaseline.Settings.ps1`) and share one +read the same settings table (`WinLogKit.Settings.ps1`) and share one helper file (`WinLogKit.Common.ps1`), so - given the same selection, and regenerating artefacts after any settings change - what you apply, what you verify and what you deploy can't disagree. @@ -9,6 +9,19 @@ All of the kit's scripts run on PowerShell 7 and on stock Windows PowerShell 5.1 - use whichever your host has. (WELA is Yamato's tool with its own requirements; `Invoke-WELACheck.ps1` drives it either way.) +## Where the scripts live + +| Folder | Scripts | Run from | +|---|---|---| +| kit root | `New-`, `Enable-`, `Test-LoggingBaseline.ps1`, the settings table `WinLogKit.Settings.ps1`, the shared helpers `WinLogKit.Common.ps1` | the host you are configuring | +| `fleet\` | `New-IntuneRemediationPack.ps1`, `New-GpoPack.ps1`, `New-WefSubscription.ps1`, `Test-WefFilter.ps1` | an admin workstation (generators); the collector (`Test-WefFilter`) | +| `report\` | `Export-AttackCoverage.ps1`, `Invoke-WELACheck.ps1` | anywhere (coverage); the host (WELA) | +| `tools\` | regenerators for presets, the Reference page and the WEF event map | maintainers | + +Every script reads the settings table and helpers from the kit root, and +writes its output (`Intune\`, `GPO\`, `WEF\`, `Results\`, `Evidence\`) +there too, wherever it lives. + ## Enable-LoggingBaseline.ps1 Applies the baseline. Idempotent - already-correct items are reported and @@ -65,7 +78,7 @@ which techniques it makes observable - and why the rest are not [Coverage](mapping.md). ```powershell -.\Export-AttackCoverage.ps1 [-IncludeHighVolume] [-IncludeOptional] [-BaselineFile ] +.\report\Export-AttackCoverage.ps1 [-IncludeHighVolume] [-IncludeOptional] [-BaselineFile ] ``` ## Invoke-WELACheck.ps1 @@ -76,7 +89,7 @@ timestamped evidence. Locates WELA in `.\WELA\` or an unzipped `WELA-\` folder; `-Download` fetches it from GitHub on request. ```powershell -.\Invoke-WELACheck.ps1 [-Download] [-WelaPath ] [-Baseline YamatoSecurity|ASD|Microsoft_Client|Microsoft_Server] +.\report\Invoke-WELACheck.ps1 [-Download] [-WelaPath ] [-Baseline YamatoSecurity|ASD|Microsoft_Client|Microsoft_Server] ``` WELA's own commands, for reference (v2.1.0, verified against source; all @@ -123,7 +136,7 @@ local event engine first. See [Collect - filtering with XPath](wec.md#filtering-with-xpath-matching-the-subscription-to-the-baseline). ```powershell -.\New-WefSubscription.ps1 [-BaselineFile ] [-Filter Channel|Baseline] [-Validate] [-SubscriptionId ] [-OutDir ] +.\fleet\New-WefSubscription.ps1 [-BaselineFile ] [-Filter Channel|Baseline] [-Validate] [-SubscriptionId ] [-OutDir ] ``` ## Test-WefFilter.ps1 @@ -136,7 +149,7 @@ checks the deployed subscription's query matches the generated XML on any unexpected ID or mismatch. ```powershell -.\Test-WefFilter.ps1 -ExpectedFile .\WEF\.expected-eventids.csv [-SubscriptionId ] [-Hours 24] +.\fleet\Test-WefFilter.ps1 -ExpectedFile .\WEF\.expected-eventids.csv [-SubscriptionId ] [-Hours 24] ``` ## New-GpoPack.ps1 diff --git a/docs/deployment.md b/docs/deployment.md index 0ccbaf7..9b420fe 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -11,7 +11,7 @@ Central collection (WEF / WEC) has its own page: [Collect](wec.md). ## Intune (workstations and cloud-managed servers) ```powershell -.\New-IntuneRemediationPack.ps1 [-BaselineFile ] [-IncludeHighVolume] [-IncludeOptional] +.\fleet\New-IntuneRemediationPack.ps1 [-BaselineFile ] [-IncludeHighVolume] [-IncludeOptional] ``` Produces a self-contained pair for Intune remediations: @@ -35,7 +35,7 @@ which does not belong in unattended remediation). ## GPO (domain-joined fleets) ```powershell -.\New-GpoPack.ps1 [-BaselineFile ] [-IncludeHighVolume] [-IncludeOptional] +.\fleet\New-GpoPack.ps1 [-BaselineFile ] [-IncludeHighVolume] [-IncludeOptional] ``` Produces: diff --git a/docs/getting-started.md b/docs/getting-started.md index 2cdfc1d..48a7a04 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -111,13 +111,13 @@ From an **elevated** Windows PowerShell prompt in the kit folder: .\Test-LoggingBaseline.ps1 # 3. Decide on the high volume tier with evidence, then apply it. -.\Export-AttackCoverage.ps1 # what Core makes observable -.\Export-AttackCoverage.ps1 -IncludeHighVolume # what HighVolume adds +.\report\Export-AttackCoverage.ps1 # what Core makes observable +.\report\Export-AttackCoverage.ps1 -IncludeHighVolume # what HighVolume adds .\Enable-LoggingBaseline.ps1 -IncludeHighVolume .\Test-LoggingBaseline.ps1 -IncludeHighVolume # 4. Independent second opinion (fetches WELA once, on request). -.\Invoke-WELACheck.ps1 -Download +.\report\Invoke-WELACheck.ps1 -Download # Escape hatch: restore everything captured at first run. .\Enable-LoggingBaseline.ps1 -Rollback @@ -143,6 +143,13 @@ stability risk, and `t` shows the whole tree at any point: Or start from a published reference: see [Baselines & Presets](baselines.md). +## Where the scripts live + +The three host scripts sit at the kit root. Fleet generators are in +`fleet\`, the coverage report and WELA check in `report\`; see +[Commands](commands.md#where-the-scripts-live). Every script finds the +settings table at the root and writes its output there. + ## Where things land | Folder | Contents | diff --git a/docs/mapping.md b/docs/mapping.md index f229f4a..749006f 100644 --- a/docs/mapping.md +++ b/docs/mapping.md @@ -93,7 +93,7 @@ Reading it top to bottom: generated from them. - **One table**: every script - the builder, Enable, Test, the coverage report and all three fleet generators - dot-sources - `LoggingBaseline.Settings.ps1` (and the shared helpers in + `WinLogKit.Settings.ps1` (and the shared helpers in `WinLogKit.Common.ps1`), so applied config, deployed artefacts and verification can never disagree. - **Events out**: hosts write to the Windows Event Log service; @@ -158,9 +158,9 @@ Two data files in `data/attack/` (provenance and attribution in its README): logging), one sourced row per claim. ```powershell -.\Export-AttackCoverage.ps1 # Core tier -.\Export-AttackCoverage.ps1 -IncludeHighVolume -.\Export-AttackCoverage.ps1 -BaselineFile .\presets\role_Workstation.csv +.\report\Export-AttackCoverage.ps1 # Core tier +.\report\Export-AttackCoverage.ps1 -IncludeHighVolume +.\report\Export-AttackCoverage.ps1 -BaselineFile .\presets\role_Workstation.csv ``` Every technique verdict carries a reason: diff --git a/docs/reference.md b/docs/reference.md index 1b49011..d2424e4 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -21,7 +21,7 @@ Reading the columns: **S** = Microsoft Server, **Y** = Yamato (per the shipped reference presets; kit-added extras such as the Server 2025 SMB auditing and the NTLM audit values show no reference letter and are sourced in the - [settings table](https://github.com/spydisec/WinLogKit/blob/main/LoggingBaseline.Settings.ps1)). + [settings table](https://github.com/spydisec/WinLogKit/blob/main/WinLogKit.Settings.ps1)). - **Minimal / Heavy** - membership in `spydi_Server_Minimal` / `spydi_Server_Heavy` (the superset role presets; rows marked **(DC)** are deselected in the Workstation variants and inert off domain controllers). diff --git a/docs/wec.md b/docs/wec.md index b745285..54e5fac 100644 --- a/docs/wec.md +++ b/docs/wec.md @@ -30,7 +30,7 @@ worked example for Microsoft Sentinel is kept as an ## Generate the subscription ```powershell -.\New-WefSubscription.ps1 [-BaselineFile ] [-Filter Channel|Baseline] [-Validate] [-SubscriptionId ] +.\fleet\New-WefSubscription.ps1 [-BaselineFile ] [-Filter Channel|Baseline] [-Validate] [-SubscriptionId ] ``` Generates a source-initiated subscription XML with one query per selected diff --git a/New-GpoPack.ps1 b/fleet/New-GpoPack.ps1 similarity index 93% rename from New-GpoPack.ps1 rename to fleet/New-GpoPack.ps1 index 892cf7f..b173f29 100644 --- a/New-GpoPack.ps1 +++ b/fleet/New-GpoPack.ps1 @@ -45,11 +45,11 @@ Output folder. Default: .\GPO next to this script. .EXAMPLE - .\New-GpoPack.ps1 -IncludeHighVolume + .\fleet\New-GpoPack.ps1 -IncludeHighVolume Core + HighVolume audit policy and registry artefacts. .EXAMPLE - .\New-GpoPack.ps1 -BaselineFile .\presets\Microsoft_Server.csv -OutDir .\GPO\MSServer + .\fleet\New-GpoPack.ps1 -BaselineFile .\presets\Microsoft_Server.csv -OutDir .\GPO\MSServer #> [CmdletBinding()] param( @@ -63,10 +63,13 @@ param( Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' -if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $PSScriptRoot 'GPO' } +# This script lives in fleet\; the settings table, shared helpers, data +# and output folders are at the kit root. +$kitRoot = Split-Path $PSScriptRoot -Parent +if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $kitRoot 'GPO' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') -. (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') +. (Join-Path $kitRoot 'WinLogKit.Settings.ps1') +. (Join-Path $kitRoot 'WinLogKit.Common.ps1') $sel = Resolve-BaselineSelection -BaselineFile $BaselineFile -IncludeHighVolume $IncludeHighVolume -IncludeOptional $IncludeOptional diff --git a/New-IntuneRemediationPack.ps1 b/fleet/New-IntuneRemediationPack.ps1 similarity index 96% rename from New-IntuneRemediationPack.ps1 rename to fleet/New-IntuneRemediationPack.ps1 index f33e0df..10afded 100644 --- a/New-IntuneRemediationPack.ps1 +++ b/fleet/New-IntuneRemediationPack.ps1 @@ -48,11 +48,11 @@ Without -BaselineFile: also embed Optional tier items. .EXAMPLE - .\New-IntuneRemediationPack.ps1 + .\fleet\New-IntuneRemediationPack.ps1 Recommended (Core) pack into .\Intune\. .EXAMPLE - .\New-IntuneRemediationPack.ps1 -BaselineFile .\WorkstationBaseline.csv -OutDir .\Intune\Workstation + .\fleet\New-IntuneRemediationPack.ps1 -BaselineFile .\WorkstationBaseline.csv -OutDir .\Intune\Workstation Pack for a role-specific baseline built with New-LoggingBaseline.ps1. #> [CmdletBinding()] @@ -67,10 +67,13 @@ param( Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' -if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $PSScriptRoot 'Intune' } +# This script lives in fleet\; the settings table, shared helpers, data +# and output folders are at the kit root. +$kitRoot = Split-Path $PSScriptRoot -Parent +if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $kitRoot 'Intune' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') -. (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') +. (Join-Path $kitRoot 'WinLogKit.Settings.ps1') +. (Join-Path $kitRoot 'WinLogKit.Common.ps1') # ---------------------------------------------------------- item selection --- diff --git a/New-WefSubscription.ps1 b/fleet/New-WefSubscription.ps1 similarity index 95% rename from New-WefSubscription.ps1 rename to fleet/New-WefSubscription.ps1 index 15191a9..e1a7ec4 100644 --- a/New-WefSubscription.ps1 +++ b/fleet/New-WefSubscription.ps1 @@ -62,7 +62,7 @@ Security events will silently fail. Transport defaults (ContentFormat, batching, heartbeat, source SDDL) live - in LoggingBaseline.Settings.ps1 ($BaselineWefDefaults); parameters here + in WinLogKit.Settings.ps1 ($BaselineWefDefaults); parameters here override them per run. Generation is read-only: no admin needed, nothing on the host changes. @@ -105,15 +105,15 @@ Computers and Network Service (Microsoft's documented default). .EXAMPLE - .\New-WefSubscription.ps1 + .\fleet\New-WefSubscription.ps1 Core-tier channels, whole-channel forwarding, into .\WEF\WinLogKit-Baseline.xml. .EXAMPLE - .\New-WefSubscription.ps1 -BaselineFile .\presets\spydi_Server_Minimal.csv -Filter Baseline -Validate + .\fleet\New-WefSubscription.ps1 -BaselineFile .\presets\spydi_Server_Minimal.csv -Filter Baseline -Validate Security filtered to exactly what that preset enables; every query parsed locally. .EXAMPLE - .\New-WefSubscription.ps1 -BaselineFile .\presets\ASD.csv -SubscriptionId ASD-Baseline + .\fleet\New-WefSubscription.ps1 -BaselineFile .\presets\ASD.csv -SubscriptionId ASD-Baseline Subscription covering exactly the channels the ASD preset selects. #> [CmdletBinding()] @@ -140,10 +140,13 @@ param( Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' -if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $PSScriptRoot 'WEF' } +# This script lives in fleet\; the settings table, shared helpers, data +# and output folders are at the kit root. +$kitRoot = Split-Path $PSScriptRoot -Parent +if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $kitRoot 'WEF' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') -. (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') +. (Join-Path $kitRoot 'WinLogKit.Settings.ps1') +. (Join-Path $kitRoot 'WinLogKit.Common.ps1') $wefDefaults = $script:BaselineWefDefaults if ([string]::IsNullOrEmpty($ContentFormat)) { $ContentFormat = $wefDefaults.ContentFormat } @@ -202,7 +205,7 @@ if ($Filter -eq 'Baseline') { Write-Error 'Baseline filter mode found no selected audit subcategories in this selection, so the Security query would forward only the log-tamper events. Select subcategories in the baseline, or use -Filter Channel.' exit 1 } - $mapPath = Join-Path (Join-Path (Join-Path $PSScriptRoot 'data') 'wef') 'audit_subcategory_events.csv' + $mapPath = Join-Path (Join-Path (Join-Path $kitRoot 'data') 'wef') 'audit_subcategory_events.csv' if (-not (Test-Path $mapPath)) { Write-Error "Event map not found: $mapPath (regenerate with tools\Update-AuditSubcategoryEvents.ps1)"; exit 1 } $eventMap = Import-Csv $mapPath $idSet = New-Object 'System.Collections.Generic.SortedSet[int]' @@ -404,6 +407,6 @@ Write-Host " Server=http://:5985/wsman/SubscriptionManager/WE Write-Host ' (optionally HTTPS: Server=https://:5986/... - needs a server certificate on the collector)' Write-Host ' For the Security log: add NETWORK SERVICE to "Event Log Readers" on sources, or Security forwarding silently fails.' -ForegroundColor Yellow Write-Host '' -Write-Host "Prove the filter on the collector: .\Test-WefFilter.ps1 -ExpectedFile `"$sidecar`" -SubscriptionId $SubscriptionId" +Write-Host "Prove the filter on the collector: .\fleet\Test-WefFilter.ps1 -ExpectedFile `"$sidecar`" -SubscriptionId $SubscriptionId" Write-Host 'SIEM handoff point: the ForwardedEvents log on the collector. Ingestion beyond that is out of kit scope.' exit 0 diff --git a/Test-WefFilter.ps1 b/fleet/Test-WefFilter.ps1 similarity index 98% rename from Test-WefFilter.ps1 rename to fleet/Test-WefFilter.ps1 index c54e9e3..4436d06 100644 --- a/Test-WefFilter.ps1 +++ b/fleet/Test-WefFilter.ps1 @@ -48,7 +48,7 @@ (.xml next to the sidecar). .EXAMPLE - .\Test-WefFilter.ps1 -ExpectedFile .\WEF\WinLogKit-Baseline.expected-eventids.csv -SubscriptionId WinLogKit-Baseline + .\fleet\Test-WefFilter.ps1 -ExpectedFile .\WEF\WinLogKit-Baseline.expected-eventids.csv -SubscriptionId WinLogKit-Baseline #> [CmdletBinding()] param( diff --git a/Export-AttackCoverage.ps1 b/report/Export-AttackCoverage.ps1 similarity index 94% rename from Export-AttackCoverage.ps1 rename to report/Export-AttackCoverage.ps1 index ce6e344..e11b186 100644 --- a/Export-AttackCoverage.ps1 +++ b/report/Export-AttackCoverage.ps1 @@ -43,10 +43,10 @@ Where the CSVs go. Default: .\Results next to this script. .EXAMPLE - .\Export-AttackCoverage.ps1 -IncludeHighVolume + .\report\Export-AttackCoverage.ps1 -IncludeHighVolume .EXAMPLE - .\Export-AttackCoverage.ps1 -BaselineFile .\presets\role_Workstation.csv + .\report\Export-AttackCoverage.ps1 -BaselineFile .\presets\role_Workstation.csv #> [CmdletBinding()] param( @@ -61,10 +61,13 @@ param( Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' -if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $PSScriptRoot 'Results' } +# This script lives in report\; the settings table, shared helpers, data +# and output folders are at the kit root. +$kitRoot = Split-Path $PSScriptRoot -Parent +if ([string]::IsNullOrEmpty($OutDir)) { $OutDir = Join-Path $kitRoot 'Results' } -. (Join-Path $PSScriptRoot 'LoggingBaseline.Settings.ps1') -. (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') +. (Join-Path $kitRoot 'WinLogKit.Settings.ps1') +. (Join-Path $kitRoot 'WinLogKit.Common.ps1') # ---------------------------------------------- resolve the selection sets --- @@ -106,7 +109,7 @@ $detail = New-Object System.Collections.Generic.List[object] if ($UseOssem) { # ------------------- legacy cross-check: OSSEM-DM snapshot join ---------- - $snapshot = Join-Path (Join-Path (Join-Path $PSScriptRoot 'data') 'ossem') 'techniques_to_events_windows.csv' + $snapshot = Join-Path (Join-Path (Join-Path $kitRoot 'data') 'ossem') 'techniques_to_events_windows.csv' if (-not (Test-Path $snapshot)) { Write-Error "OSSEM snapshot not found at $snapshot"; exit 1 } $subcatAlias = @{ 'PNP Activity' = 'Plug and Play'; 'Policy Change' = 'Audit Policy Change' } $subcatSelectedByName = @{}; $subcatKnownByName = @{} @@ -144,7 +147,7 @@ if ($UseOssem) { } else { # ------------------------ native mapping: ATT&CK v19.2 + kit event map --- # Nested Join-Path keeps these resolvable on non-Windows PowerShell too. - $attackDir = Join-Path (Join-Path $PSScriptRoot 'data') 'attack' + $attackDir = Join-Path (Join-Path $kitRoot 'data') 'attack' $analyticsCsv = Join-Path $attackDir 'windows_analytics.csv' $mapCsv = Join-Path $attackDir 'event_map.csv' foreach ($p in @($analyticsCsv, $mapCsv)) { diff --git a/Invoke-WELACheck.ps1 b/report/Invoke-WELACheck.ps1 similarity index 95% rename from Invoke-WELACheck.ps1 rename to report/Invoke-WELACheck.ps1 index f4782ae..e9f481d 100644 --- a/Invoke-WELACheck.ps1 +++ b/report/Invoke-WELACheck.ps1 @@ -48,11 +48,11 @@ Default: .\Evidence next to this script. .EXAMPLE - .\Invoke-WELACheck.ps1 -Download + .\report\Invoke-WELACheck.ps1 -Download First run on an internet-connected test box: fetch WELA, run both audits. .EXAMPLE - .\Invoke-WELACheck.ps1 -WelaPath C:\Tools\WELA\WELA.ps1 -Baseline ASD + .\report\Invoke-WELACheck.ps1 -WelaPath C:\Tools\WELA\WELA.ps1 -Baseline ASD Air-gapped run against a pre-staged WELA copy, ASD baseline. #> [CmdletBinding()] @@ -68,9 +68,12 @@ param( Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' -if ([string]::IsNullOrEmpty($EvidenceDir)) { $EvidenceDir = Join-Path $PSScriptRoot 'Evidence' } +# This script lives in report\; the settings table, shared helpers, data +# and output folders are at the kit root. +$kitRoot = Split-Path $PSScriptRoot -Parent +if ([string]::IsNullOrEmpty($EvidenceDir)) { $EvidenceDir = Join-Path $kitRoot 'Evidence' } -. (Join-Path $PSScriptRoot 'WinLogKit.Common.ps1') +. (Join-Path $kitRoot 'WinLogKit.Common.ps1') if (-not (Test-IsAdmin)) { Write-Error 'Run as local Administrator - WELA audit-settings reads the audit policy via auditpol.' @@ -79,7 +82,7 @@ if (-not (Test-IsAdmin)) { # ------------------------------------------------------- locate / download --- -$welaDir = Join-Path $PSScriptRoot 'WELA' +$welaDir = Join-Path $kitRoot 'WELA' if ([string]::IsNullOrEmpty($WelaPath)) { # Search order: .\WELA\, any .\WELA-* folder (e.g. an unzipped WELA-2.1.0 # release, newest name first), then WELA.ps1 in the current directory. @@ -89,7 +92,7 @@ if ([string]::IsNullOrEmpty($WelaPath)) { $v = $null if ([version]::TryParse(($_.Name -replace '^WELA-', ''), [ref]$v)) { $v } else { [version]'0.0' } }; Descending = $true } - foreach ($d in (Get-ChildItem -Path $PSScriptRoot -Directory -Filter 'WELA-*' -ErrorAction SilentlyContinue | Sort-Object -Property $versionSort)) { + foreach ($d in (Get-ChildItem -Path $kitRoot -Directory -Filter 'WELA-*' -ErrorAction SilentlyContinue | Sort-Object -Property $versionSort)) { $candidates += Join-Path $d.FullName 'WELA.ps1' } $candidates += Join-Path (Get-Location).Path 'WELA.ps1' diff --git a/tests/Invoke-KitChecks.ps1 b/tests/Invoke-KitChecks.ps1 index 584326e..df36aa5 100644 --- a/tests/Invoke-KitChecks.ps1 +++ b/tests/Invoke-KitChecks.ps1 @@ -113,7 +113,7 @@ if ($notInCommon) { } # 2. Settings table consistency ----------------------------------------------- -. (Join-Path $KitRoot 'LoggingBaseline.Settings.ps1') +. (Join-Path $KitRoot 'WinLogKit.Settings.ps1') $bad = @() foreach ($grp in @($BaselineChannels, $BaselineAuditSubcategories, $BaselineRegistrySettings, $BaselineSmbAuditSettings)) { @@ -190,7 +190,7 @@ try { # 5. Intune pack generation: files parse, placeholders replaced, selection respected $packDir = Join-Path $tmp 'intune' - & (Join-Path $KitRoot 'New-IntuneRemediationPack.ps1') -OutDir $packDir | Out-Null + & (Join-Path $KitRoot 'fleet\New-IntuneRemediationPack.ps1') -OutDir $packDir | Out-Null foreach ($f in @('Detect-LoggingBaseline.ps1', 'Remediate-LoggingBaseline.ps1')) { $p = Join-Path $packDir $f if (-not (Test-Path $p)) { Fail "Intune pack missing $f"; continue } @@ -200,7 +200,7 @@ try { if ((Get-Content $p -Raw) -match '__(MODE|ITEMS|COUNT|SOURCE|FILENAME)__') { Fail "generated $f has unreplaced placeholders" } } $packDir2 = Join-Path $tmp 'intune-csv' - & (Join-Path $KitRoot 'New-IntuneRemediationPack.ps1') -OutDir $packDir2 -BaselineFile $csv1 | Out-Null + & (Join-Path $KitRoot 'fleet\New-IntuneRemediationPack.ps1') -OutDir $packDir2 -BaselineFile $csv1 | Out-Null $detect2 = Get-Content (Join-Path $packDir2 'Detect-LoggingBaseline.ps1') -Raw # The recommended CSV selects only Core, so no HighVolume item may be embedded. if ($detect2 -match 'EnableModuleLogging') { Fail 'Intune pack from Core-only CSV embedded a HighVolume item' } else { Pass 'Intune pack honours the baseline CSV selection' } @@ -231,7 +231,7 @@ try { # 7a. GPO pack: audit.csv row count matches selection; registry.txt has policy values $gpoTmp = Join-Path $tmp 'gpo' - & (Join-Path $KitRoot 'New-GpoPack.ps1') -OutDir $gpoTmp -IncludeHighVolume | Out-Null + & (Join-Path $KitRoot 'fleet\New-GpoPack.ps1') -OutDir $gpoTmp -IncludeHighVolume | Out-Null $auditRows = @(Import-Csv (Join-Path $gpoTmp 'audit.csv')) $expectedAudit = @($BaselineAuditSubcategories | Where-Object { $_.Tier -eq 'Core' -or $_.Tier -eq 'HighVolume' }).Count if ($auditRows.Count -eq $expectedAudit) { Pass "GPO audit.csv rows ($expectedAudit)" } else { Fail "GPO audit.csv has $($auditRows.Count) rows, expected $expectedAudit" } @@ -252,7 +252,7 @@ try { if ($badMap) { Fail "event_map.csv references unknown settings items: $($badMap -join ', ')" } else { Pass 'event map item ids valid against settings table' } $covTmp = Join-Path $tmp 'cov' - & (Join-Path $KitRoot 'Export-AttackCoverage.ps1') -OutDir $covTmp | Out-Null + & (Join-Path $KitRoot 'report\Export-AttackCoverage.ps1') -OutDir $covTmp | Out-Null $covDetail = Get-ChildItem $covTmp -Filter 'AttackCoverage_Detail_*.csv' | Select-Object -First 1 if ($null -eq $covDetail) { Fail 'coverage detail CSV not produced' } else { $covRows = Import-Csv $covDetail.FullName @@ -265,7 +265,7 @@ try { # 7. WEF subscription generation: valid XML, one query per selected channel $wefTmp = Join-Path $tmp 'wef' - & (Join-Path $KitRoot 'New-WefSubscription.ps1') -OutDir $wefTmp -BaselineFile (Join-Path $KitRoot 'presets\ASD.csv') -SubscriptionId 'CheckSub' | Out-Null + & (Join-Path $KitRoot 'fleet\New-WefSubscription.ps1') -OutDir $wefTmp -BaselineFile (Join-Path $KitRoot 'presets\ASD.csv') -SubscriptionId 'CheckSub' | Out-Null try { [xml]$wx = Get-Content (Join-Path $wefTmp 'CheckSub.xml') -Raw $qCount = [regex]::Matches($wx.Subscription.Query.'#cdata-section', '&1 | Out-String + $wefOut = & (Join-Path $KitRoot 'fleet\New-WefSubscription.ps1') -OutDir $wefB -BaselineFile (Join-Path $KitRoot 'presets\spydi_Server_Heavy.csv') -Filter Baseline -Validate -SubscriptionId 'CheckB' 2>&1 | Out-String if ($wefOut -match 'INVALID') { Fail "WEF Baseline filter: a generated query failed local validation: $wefOut" } try { [xml]$wb = Get-Content (Join-Path $wefB 'CheckB.xml') -Raw diff --git a/tools/Export-ReferenceTable.ps1 b/tools/Export-ReferenceTable.ps1 index 27c6724..0ea2657 100644 --- a/tools/Export-ReferenceTable.ps1 +++ b/tools/Export-ReferenceTable.ps1 @@ -7,7 +7,7 @@ .DESCRIPTION Everything is derived, never hand-written: - - items and sizes: LoggingBaseline.Settings.ps1 + - items and sizes: WinLogKit.Settings.ps1 - key events: the curated ATT&CK event map (authoritative for audit subcategories) plus event IDs mentioned in each item's Purpose text - reference membership: the ASD / Microsoft_Client / Microsoft_Server @@ -32,7 +32,7 @@ $ErrorActionPreference = 'Stop' $kitRoot = Split-Path $PSScriptRoot -Parent if ([string]::IsNullOrEmpty($OutFile)) { $OutFile = Join-Path (Join-Path $kitRoot 'docs') 'reference.md' } -. (Join-Path $kitRoot 'LoggingBaseline.Settings.ps1') +. (Join-Path $kitRoot 'WinLogKit.Settings.ps1') # ---- preset membership lookups ---------------------------------------------- @@ -176,7 +176,7 @@ Reading the columns: **S** = Microsoft Server, **Y** = Yamato (per the shipped reference presets; kit-added extras such as the Server 2025 SMB auditing and the NTLM audit values show no reference letter and are sourced in the - [settings table](https://github.com/spydisec/WinLogKit/blob/main/LoggingBaseline.Settings.ps1)). + [settings table](https://github.com/spydisec/WinLogKit/blob/main/WinLogKit.Settings.ps1)). - **Minimal / Heavy** - membership in `spydi_Server_Minimal` / `spydi_Server_Heavy` (the superset role presets; rows marked **(DC)** are deselected in the Workstation variants and inert off domain controllers). diff --git a/tools/New-PresetBaselines.ps1 b/tools/New-PresetBaselines.ps1 index a54ee88..8401529 100644 --- a/tools/New-PresetBaselines.ps1 +++ b/tools/New-PresetBaselines.ps1 @@ -1,7 +1,7 @@ <# .SYNOPSIS Regenerates the reference baseline presets in .\presets\ from the settings - table. Run after changing LoggingBaseline.Settings.ps1; CI fails if the + table. Run after changing WinLogKit.Settings.ps1; CI fails if the committed presets drift from what this script produces. .DESCRIPTION diff --git a/tools/Update-AuditSubcategoryEvents.ps1 b/tools/Update-AuditSubcategoryEvents.ps1 index 6c58a0d..3ccef3c 100644 --- a/tools/Update-AuditSubcategoryEvents.ps1 +++ b/tools/Update-AuditSubcategoryEvents.ps1 @@ -27,7 +27,7 @@ Set-StrictMode -Version 2.0 $ErrorActionPreference = 'Stop' $kitRoot = Split-Path $PSScriptRoot -Parent if ([string]::IsNullOrEmpty($OutFile)) { $OutFile = Join-Path (Join-Path (Join-Path $kitRoot 'data') 'wef') 'audit_subcategory_events.csv' } -. (Join-Path $kitRoot 'LoggingBaseline.Settings.ps1') +. (Join-Path $kitRoot 'WinLogKit.Settings.ps1') $base = 'https://learn.microsoft.com/windows/security/threat-protection/auditing/' # Explicit name -> page slug map. Microsoft's slugs are not derivable for From 3ea3a0dd16cb6833e150a2321d3e6b6de0fb8641 Mon Sep 17 00:00:00 2001 From: spydisec <9101327+spydisec@users.noreply.github.com> Date: Fri, 4 Sep 2026 18:58:38 +1000 Subject: [PATCH 2/5] Commands: say which scripts read the kit root (not the Intune pack or Test-WefFilter) Co-Authored-By: Claude Fable 5.1 --- docs/commands.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index f05e58c..0e8fcdb 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -18,9 +18,11 @@ with its own requirements; `Invoke-WELACheck.ps1` drives it either way.) | `report\` | `Export-AttackCoverage.ps1`, `Invoke-WELACheck.ps1` | anywhere (coverage); the host (WELA) | | `tools\` | regenerators for presets, the Reference page and the WEF event map | maintainers | -Every script reads the settings table and helpers from the kit root, and -writes its output (`Intune\`, `GPO\`, `WEF\`, `Results\`, `Evidence\`) -there too, wherever it lives. +The root, `fleet\` and `report\` scripts read the settings table and +helpers from the kit root and write their output (`Intune\`, `GPO\`, `WEF\`, +`Results\`, `Evidence\`) there too, wherever they live. Two things stand +alone by design: `Test-WefFilter.ps1` needs only its sidecar CSV, and the +generated Intune pack carries everything it needs to the endpoint. ## Enable-LoggingBaseline.ps1 From c896b3a9e8e9705c11e47ab8db09dca886906ada Mon Sep 17 00:00:00 2001 From: spydisec <9101327+spydisec@users.noreply.github.com> Date: Fri, 4 Sep 2026 19:07:26 +1000 Subject: [PATCH 3/5] Relocated scripts: cwd-independent hints, kit-root defaults in help text Devin and CodeRabbit on #32: the printed next-step commands were relative to the caller's working directory (fleet\fleet\... from inside fleet\), so they are built from the script's own location now; the .PARAMETER help still said "next to this script" for defaults that moved to the kit root; and two doc pages said "every script" reads the settings table, which Test-WefFilter.ps1 does not. Co-Authored-By: Claude Fable 5.1 --- fleet/New-GpoPack.ps1 | 4 ++-- fleet/New-IntuneRemediationPack.ps1 | 2 +- fleet/New-WefSubscription.ps1 | 4 ++-- report/Export-AttackCoverage.ps1 | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fleet/New-GpoPack.ps1 b/fleet/New-GpoPack.ps1 index b173f29..3eb41a1 100644 --- a/fleet/New-GpoPack.ps1 +++ b/fleet/New-GpoPack.ps1 @@ -42,7 +42,7 @@ switches decide (Core by default). .PARAMETER OutDir - Output folder. Default: .\GPO next to this script. + Output folder. Default: GPO\ at the kit root (the parent of fleet\). .EXAMPLE .\fleet\New-GpoPack.ps1 -IncludeHighVolume @@ -148,7 +148,7 @@ if ($auditCount -lt $totalAudit) { if ($IncludeHighVolume) { $verifyArgs += ' -IncludeHighVolume' } if ($IncludeOptional) { $verifyArgs += ' -IncludeOptional' } } - Write-Host "the effective result: .\Test-LoggingBaseline.ps1$verifyArgs (it reads the live audit policy, not the file you applied)." -ForegroundColor Yellow + Write-Host "the effective result: $(Join-Path $kitRoot 'Test-LoggingBaseline.ps1')$verifyArgs (it reads the live audit policy, not the file you applied)." -ForegroundColor Yellow } Write-Host 'Note: LGPO /t is additive - deselected registry values are NOT removed by a smaller pack. Use Enable-LoggingBaseline -Rollback or remove them deliberately.' -ForegroundColor Yellow exit 0 diff --git a/fleet/New-IntuneRemediationPack.ps1 b/fleet/New-IntuneRemediationPack.ps1 index 10afded..9f2da8d 100644 --- a/fleet/New-IntuneRemediationPack.ps1 +++ b/fleet/New-IntuneRemediationPack.ps1 @@ -34,7 +34,7 @@ Requires: Windows PowerShell 5.1+. No admin needed to generate. .PARAMETER OutDir - Where to write the pair. Default: .\Intune next to this script. + Where to write the pair. Default: Intune\ at the kit root (the parent of fleet\). .PARAMETER BaselineFile Optional selection CSV from New-LoggingBaseline.ps1. Only Selected = Y diff --git a/fleet/New-WefSubscription.ps1 b/fleet/New-WefSubscription.ps1 index e1a7ec4..dc21a0e 100644 --- a/fleet/New-WefSubscription.ps1 +++ b/fleet/New-WefSubscription.ps1 @@ -84,7 +84,7 @@ Subscription name shown in wecutil / Event Viewer. Default: WinLogKit-Baseline. .PARAMETER OutDir - Where the XML and sidecar are written. Default: .\WEF next to this script. + Where the XML and sidecar are written. Default: WEF\ at the kit root (the parent of fleet\). .PARAMETER ContentFormat Events (binary, locale-independent, smaller on the wire - default) or @@ -407,6 +407,6 @@ Write-Host " Server=http://:5985/wsman/SubscriptionManager/WE Write-Host ' (optionally HTTPS: Server=https://:5986/... - needs a server certificate on the collector)' Write-Host ' For the Security log: add NETWORK SERVICE to "Event Log Readers" on sources, or Security forwarding silently fails.' -ForegroundColor Yellow Write-Host '' -Write-Host "Prove the filter on the collector: .\fleet\Test-WefFilter.ps1 -ExpectedFile `"$sidecar`" -SubscriptionId $SubscriptionId" +Write-Host "Prove the filter on the collector: $(Join-Path $PSScriptRoot 'Test-WefFilter.ps1') -ExpectedFile `"$sidecar`" -SubscriptionId $SubscriptionId" Write-Host 'SIEM handoff point: the ForwardedEvents log on the collector. Ingestion beyond that is out of kit scope.' exit 0 diff --git a/report/Export-AttackCoverage.ps1 b/report/Export-AttackCoverage.ps1 index e11b186..df6efab 100644 --- a/report/Export-AttackCoverage.ps1 +++ b/report/Export-AttackCoverage.ps1 @@ -40,7 +40,7 @@ Use the vendored OSSEM-DM snapshot instead of the native mapping. .PARAMETER OutDir - Where the CSVs go. Default: .\Results next to this script. + Where the CSVs go. Default: Results\ at the kit root (the parent of report\). .EXAMPLE .\report\Export-AttackCoverage.ps1 -IncludeHighVolume From 41f4f009ae7d557380822fce1dcc53f5d5161ebc Mon Sep 17 00:00:00 2001 From: spydisec <9101327+spydisec@users.noreply.github.com> Date: Fri, 4 Sep 2026 19:08:40 +1000 Subject: [PATCH 4/5] Relocated scripts: finish the help text and doc wording; absolute baseline path in the GPO hint The previous commit's edit step failed part-way: the WELA check's help still said "next to this script", and Commands and Getting Started still said "every script" reads the settings table. Also resolve -BaselineFile to an absolute path in the GPO pack's verify hint, so the printed command holds from any directory. Co-Authored-By: Claude Fable 5.1 --- docs/commands.md | 7 ++++--- docs/getting-started.md | 6 ++++-- fleet/New-GpoPack.ps1 | 2 +- report/Invoke-WELACheck.ps1 | 8 +++++--- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index 0e8fcdb..ca65ed9 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,8 +1,9 @@ # Commands -Every script, what it does, and the flags you'll actually use. They all -read the same settings table (`WinLogKit.Settings.ps1`) and share one -helper file (`WinLogKit.Common.ps1`), so - given +Every script, what it does, and the flags you'll actually use. All of them +except `Test-WefFilter.ps1` (which needs only its sidecar CSV) read the +same settings table (`WinLogKit.Settings.ps1`) and share one helper file +(`WinLogKit.Common.ps1`), so - given the same selection, and regenerating artefacts after any settings change - what you apply, what you verify and what you deploy can't disagree. All of the kit's scripts run on PowerShell 7 and on stock Windows diff --git a/docs/getting-started.md b/docs/getting-started.md index 48a7a04..cf28a48 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -147,8 +147,10 @@ Or start from a published reference: see The three host scripts sit at the kit root. Fleet generators are in `fleet\`, the coverage report and WELA check in `report\`; see -[Commands](commands.md#where-the-scripts-live). Every script finds the -settings table at the root and writes its output there. +[Commands](commands.md#where-the-scripts-live). Wherever a script lives, it +reads the settings table from the root and writes its output there; the +one that needs neither is `Test-WefFilter.ps1`, which runs on the collector +from its sidecar CSV alone. ## Where things land diff --git a/fleet/New-GpoPack.ps1 b/fleet/New-GpoPack.ps1 index 3eb41a1..1c8f493 100644 --- a/fleet/New-GpoPack.ps1 +++ b/fleet/New-GpoPack.ps1 @@ -143,7 +143,7 @@ if ($auditCount -lt $totalAudit) { Write-Host ("PARTIAL SELECTION: audit.csv covers {0} of {1} kit subcategories. Apply semantics for the others depend on the tool " -f $auditCount, $totalAudit) -ForegroundColor Yellow Write-Host 'and existing policy (LGPO /ac and GPO application may not preserve unlisted subcategories). After applying, ALWAYS verify' -ForegroundColor Yellow $verifyArgs = '' - if ($null -ne $sel.Map) { $verifyArgs = " -BaselineFile `"$BaselineFile`"" } + if ($null -ne $sel.Map) { $verifyArgs = " -BaselineFile `"$((Resolve-Path $BaselineFile).Path)`"" } else { if ($IncludeHighVolume) { $verifyArgs += ' -IncludeHighVolume' } if ($IncludeOptional) { $verifyArgs += ' -IncludeOptional' } diff --git a/report/Invoke-WELACheck.ps1 b/report/Invoke-WELACheck.ps1 index e9f481d..65ce78d 100644 --- a/report/Invoke-WELACheck.ps1 +++ b/report/Invoke-WELACheck.ps1 @@ -40,12 +40,14 @@ .PARAMETER Download If WELA is not found, download WELA.ps1 and its two config files from - github.com/Yamato-Security/WELA (main branch) into .\WELA\ beside this - script. Off by default so nothing is fetched without an explicit decision. + github.com/Yamato-Security/WELA (main branch) into WELA\ at the kit root + (the parent of report\), which is also where an existing WELA\ or + WELA-\ folder is looked for. Off by default so nothing is fetched + without an explicit decision. .PARAMETER EvidenceDir Root folder for evidence. A timestamped subfolder is created per run. - Default: .\Evidence next to this script. + Default: Evidence\ at the kit root (the parent of report\). .EXAMPLE .\report\Invoke-WELACheck.ps1 -Download From d73a3d131b52647d6a6edf2aec8aff9b572b23cf Mon Sep 17 00:00:00 2001 From: spydisec <9101327+spydisec@users.noreply.github.com> Date: Fri, 4 Sep 2026 19:12:30 +1000 Subject: [PATCH 5/5] Printed hints: quote the script path (& "...") so kit roots with spaces work Devin on #32. Co-Authored-By: Claude Fable 5.1 --- fleet/New-GpoPack.ps1 | 2 +- fleet/New-WefSubscription.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fleet/New-GpoPack.ps1 b/fleet/New-GpoPack.ps1 index 1c8f493..590a7be 100644 --- a/fleet/New-GpoPack.ps1 +++ b/fleet/New-GpoPack.ps1 @@ -148,7 +148,7 @@ if ($auditCount -lt $totalAudit) { if ($IncludeHighVolume) { $verifyArgs += ' -IncludeHighVolume' } if ($IncludeOptional) { $verifyArgs += ' -IncludeOptional' } } - Write-Host "the effective result: $(Join-Path $kitRoot 'Test-LoggingBaseline.ps1')$verifyArgs (it reads the live audit policy, not the file you applied)." -ForegroundColor Yellow + Write-Host "the effective result: & `"$(Join-Path $kitRoot 'Test-LoggingBaseline.ps1')`"$verifyArgs (it reads the live audit policy, not the file you applied)." -ForegroundColor Yellow } Write-Host 'Note: LGPO /t is additive - deselected registry values are NOT removed by a smaller pack. Use Enable-LoggingBaseline -Rollback or remove them deliberately.' -ForegroundColor Yellow exit 0 diff --git a/fleet/New-WefSubscription.ps1 b/fleet/New-WefSubscription.ps1 index dc21a0e..1430c80 100644 --- a/fleet/New-WefSubscription.ps1 +++ b/fleet/New-WefSubscription.ps1 @@ -407,6 +407,6 @@ Write-Host " Server=http://:5985/wsman/SubscriptionManager/WE Write-Host ' (optionally HTTPS: Server=https://:5986/... - needs a server certificate on the collector)' Write-Host ' For the Security log: add NETWORK SERVICE to "Event Log Readers" on sources, or Security forwarding silently fails.' -ForegroundColor Yellow Write-Host '' -Write-Host "Prove the filter on the collector: $(Join-Path $PSScriptRoot 'Test-WefFilter.ps1') -ExpectedFile `"$sidecar`" -SubscriptionId $SubscriptionId" +Write-Host "Prove the filter on the collector: & `"$(Join-Path $PSScriptRoot 'Test-WefFilter.ps1')`" -ExpectedFile `"$sidecar`" -SubscriptionId $SubscriptionId" Write-Host 'SIEM handoff point: the ForwardedEvents log on the collector. Ingestion beyond that is out of kit scope.' exit 0