From ec6a6df68a56265c0e32c0e85606e888c0a6f4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E4=B8=AD=E3=82=B6=E3=83=83=E3=82=AF=20Isaac=20Ma?= =?UTF-8?q?this?= <43838376+Shirofune-Security@users.noreply.github.com> Date: Sun, 20 Sep 2026 18:10:52 +0900 Subject: [PATCH] Export native audit profiles for reviewed Intune client policies (#414) * Add offline Intune Audit CSP exports from shared client profiles * Link Intune audit export changelog to PR 414 --- .github/workflows/intune-audit-export.yml | 30 + CHANGELOG-Japanese.md | 1 + CHANGELOG.md | 1 + WELA.ps1 | 23 + config/intune_audit_csp.json | 559 +++++++++++++++ docs/intune-audit-export.md | 132 ++++ scripts/IntuneAuditExport.ps1 | 161 +++++ tests/IntuneAuditExport.Cli.Tests.ps1 | 34 + tests/IntuneAuditExport.Tests.ps1 | 132 ++++ tests/fixtures/intune-audit-ddf-facts.json | 773 +++++++++++++++++++++ website/docs/resources/changelog.ja.md | 1 + website/docs/resources/changelog.md | 1 + 12 files changed, 1848 insertions(+) create mode 100644 .github/workflows/intune-audit-export.yml create mode 100644 config/intune_audit_csp.json create mode 100644 docs/intune-audit-export.md create mode 100644 scripts/IntuneAuditExport.ps1 create mode 100644 tests/IntuneAuditExport.Cli.Tests.ps1 create mode 100644 tests/IntuneAuditExport.Tests.ps1 create mode 100644 tests/fixtures/intune-audit-ddf-facts.json diff --git a/.github/workflows/intune-audit-export.yml b/.github/workflows/intune-audit-export.yml new file mode 100644 index 00000000..3e9dde28 --- /dev/null +++ b/.github/workflows/intune-audit-export.yml @@ -0,0 +1,30 @@ +name: Offline Intune audit export regressions +on: + push: + branches: ['**'] + pull_request: + workflow_dispatch: +permissions: + contents: read +jobs: + offline-export: + runs-on: windows-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: DDF and export regressions in Windows PowerShell 5.1 + shell: powershell + timeout-minutes: 3 + run: ./tests/IntuneAuditExport.Tests.ps1 + - name: DDF and export regressions in PowerShell 7 + shell: pwsh + timeout-minutes: 3 + run: ./tests/IntuneAuditExport.Tests.ps1 + - name: Public offline CLI in Windows PowerShell 5.1 + shell: powershell + timeout-minutes: 3 + run: ./tests/IntuneAuditExport.Cli.Tests.ps1 + - name: Public offline CLI in PowerShell 7 + shell: pwsh + timeout-minutes: 3 + run: ./tests/IntuneAuditExport.Cli.Tests.ps1 diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index c383c58b..a56cc13d 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -4,6 +4,7 @@ **改善:** +- 検証対象のWindows 11クライアント向けに、共通の標準監査プロファイルからオフラインで出力する`intune-export`を追加しました。Microsoft DDFに基づく59件の明示的な対応表、整数型のOMA-URI CSV/Graphデータ、監査サブカテゴリの優先設定、出典と省略理由の一覧を保存します。最小監査マスクは既定で拒否し、`PromoteToBoth`の明示指定時だけ成功・失敗の両方へ拡張します。新規ローカル出力には検証済みハッシュを付け、アップロード・割り当て・ポリシー削除・Windows設定変更は行いません。Intune配備・競合・復旧・イベントの確認は別途必要です。 (#414) (@Shirofune-Security) - `-ProfileFile`で管理者のJSON詳細監査プロファイルを一覧・計画・監査・設定に使用できるようにしました。標準GUID、役割、設定モード、出典ハッシュを厳密に検証し、組み込みプロファイルを保持します。厳密なJSON字句検証で重複キー検出の回避を防ぎ、レポートは新規ファイルに限ることで別名リンク経由でも入力と既存の証拠を保持します。共通の優先設定、復旧記録、変更直前のファイル確認と最終検証を使用し、イベント生成やSigma検知可能性は別途検証とします。 (#416) (@Shirofune-Security) - ネイティブ Security 4688 の無害な固定プローブを収集する明示的な `native-validation` を追加。型付き前提条件、イベントの厳密な照合、前後の状態、ハッシュ付き証拠を新規の非公開ディレクトリに記録します。不完全・上限到達・曖昧・ドリフトの結果は未検証のままです。監査ポリシー変更や Sigma 利用可能ルール数の加算は行いません。使い捨て Server 2022/2025 テストで実イベントとポリシー復元を確認し、Windows 11/DC/ADCS とバックエンドの検証は別途必要です。 (#413) (@Shirofune-Security) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5bed07..32f886eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ **Improvements:** +- Added offline `intune-export` for shared native audit profiles on reviewed Windows 11 client targets, with 59 explicit Microsoft DDF mappings, typed OMA-URI CSV/Graph artifacts, the audit precedence prerequisite and complete source/omission manifests. Static minimum masks are rejected unless explicitly expanded with `PromoteToBoth`; fresh local bundles include verified fingerprints and never upload, assign, delete policies or change Windows. Intune deployment, conflicts, recovery and event evidence remain separate validation. (#414) (@Shirofune-Security) - Added `-ProfileFile` for strictly validated custom advanced audit profiles in listing, planning, auditing and configuration. Canonical GUIDs, roles, modes and source hashes remain explicit; built-in profiles are preserved. Strict JSON tokens prevent duplicate-key bypasses, and new report files preserve inputs and prior evidence even through file aliases. Shared precedence, recovery journals, pre-write file checks and final verification protect configuration, without claiming event or Sigma readiness. (#416) (@Shirofune-Security) - Added opt-in `native-validation` to collect a fixed benign Security 4688 probe with typed prerequisites, exact native event matching, before/after state and hashed components in a new private directory. Partial, capped, ambiguous and drifted results remain unverified; the collector changes no audit policy and grants no Sigma readiness credit. Disposable Server 2022/2025 tests exercise real events with verified policy restoration; Windows 11/DC/ADCS and backend acceptance remain separate. (#413) (@Shirofune-Security) diff --git a/WELA.ps1 b/WELA.ps1 index 48c8b759..2e985047 100644 --- a/WELA.ps1 +++ b/WELA.ps1 @@ -63,6 +63,11 @@ [ValidateSet('OneSettings','SecurityWarning')][string[]]$NotificationControl, [ValidateRange(1,90)][int]$WarningPercent = 90, [switch]$EnablePrivacyChannel, + [string]$IntuneProfile, + [int]$IntuneBuild, + [string]$IntuneEdition, + [string]$IntuneOutputPath, + [ValidateSet('Reject','PromoteToBoth')][string]$IntuneMinimumMode = 'Reject', [ValidateSet('Plan','Run')][string]$ProbeAction = 'Plan', [string]$ProbeOutputPath, [ValidateRange(1,30)][int]$ProbeTimeoutSeconds = 15, @@ -104,6 +109,7 @@ Import-Module (Join-Path $ScriptRoot "modules/WefSubscriptions.psm1") -ErrorActi . (Join-Path $ScriptRoot "scripts/WefDeployment.ps1") . (Join-Path $ScriptRoot "scripts/RetentionHealth.ps1") . (Join-Path $ScriptRoot "scripts/TargetedSaclPlanning.ps1") +. (Join-Path $ScriptRoot "scripts/IntuneAuditExport.ps1") # 64bit の PowerShell と GPO が読むのは Wow6432Node の無いパス。32bit 用に両方を扱う。 $PowerShellPolicyRoots = @( @@ -1858,6 +1864,7 @@ Usage: ./WELA.ps1 control-applicability # Read-only historical native feature/build assessment ./WELA.ps1 default-evidence -Help # Exact-context observed snapshots and reviewed reference comparison ./WELA.ps1 audit-notifications -Help # OneSettings audit and Security warning policy + ./WELA.ps1 intune-export -Help # Offline native audit OMA-URI/Graph artifacts; no tenant changes ./WELA.ps1 native-validation -Help # Collect a fixed native 4688 probe without changing policy ./WELA.ps1 version # Show the WELA version ./WELA.ps1 help # Show this help @@ -1870,6 +1877,13 @@ Write-Host "" Write-Host "WELA v$WELAVersion - $WELAReleaseName" Write-Host "" +if ($Cmd -ne 'intune-export' -and @($PSBoundParameters.Keys | Where-Object { $_ -in @('IntuneProfile','IntuneBuild','IntuneEdition','IntuneOutputPath','IntuneMinimumMode') }).Count) { + throw 'Intune options require the offline intune-export command. No command was run.' +} +if ($Cmd -eq 'intune-export' -and @($PSBoundParameters.Keys | Where-Object { $_ -notin @('Cmd','IntuneProfile','IntuneBuild','IntuneEdition','IntuneOutputPath','IntuneMinimumMode','IncludeOptional','Help') }).Count) { + throw 'intune-export accepts only Intune target/export options, IncludeOptional and Help. No command was run.' +} + if ($PSBoundParameters.ContainsKey('ProfileFile')) { if ([string]::IsNullOrWhiteSpace($ProfileFile) -or $Cmd -notin @('profiles','plan','audit','audit-settings','configure')) { throw '-ProfileFile requires profiles, plan, audit, audit-settings or configure. No command was run.' } if ($Baseline -or ($Cmd -ne 'profiles' -and -not $Profile)) { throw '-ProfileFile requires an explicit -Profile and cannot be combined with -Baseline (profiles lists the file). No command was run.' } @@ -1977,6 +1991,15 @@ if ($Profile -and $Cmd.ToLower() -in @('plan', 'audit', 'audit-settings', 'confi } switch ($Cmd.ToLower()) { + 'intune-export' { + if ($Help) { Write-Host 'Usage: ./WELA.ps1 intune-export -IntuneProfile shared-profile-id -IntuneBuild 26100|26200 -IntuneEdition Pro|Enterprise|Education|IoTEnterprise -IntuneOutputPath new-local-directory [-IntuneMinimumMode Reject|PromoteToBoth] [-IncludeOptional]. Offline native audit artifacts only; no tenant or Windows changes. See docs/intune-audit-export.md.'; return } + try { + if (-not $IntuneProfile -or -not $IntuneBuild -or -not $IntuneEdition -or -not $IntuneOutputPath) { throw 'IntuneProfile, IntuneBuild, IntuneEdition and IntuneOutputPath are required.' } + $report=Invoke-WelaIntuneAuditExport -Profile $IntuneProfile -Build $IntuneBuild -Edition $IntuneEdition -OutputPath $IntuneOutputPath -MinimumMode $IntuneMinimumMode -IncludeOptional:$IncludeOptional + $report | Select-Object Status,OutputPath,PayloadEmitted,ExitCode + if ($report.ExitCode) { exit $report.ExitCode } + } catch { Write-Host "[Failed] Intune export: $_" -ForegroundColor Red; exit 1 } + } 'native-validation' { if ($Help) { Write-Host 'Usage: ./WELA.ps1 native-validation [-ProbeAction Plan|Run] [-ProbeOutputPath new-directory] [-ProbeTimeoutSeconds 1..30]. Plan reads prerequisites; Run launches a fixed benign cmd.exe probe and collects exact native Security 4688 XML. No policy changes or Sigma readiness credit. See docs/native-validation.md.'; return } $report=Invoke-WelaNativeValidation -Action $ProbeAction -OutputPath $ProbeOutputPath -TimeoutSeconds $ProbeTimeoutSeconds diff --git a/config/intune_audit_csp.json b/config/intune_audit_csp.json new file mode 100644 index 00000000..98ad185d --- /dev/null +++ b/config/intune_audit_csp.json @@ -0,0 +1,559 @@ +{ + "schemaVersion": 1, + "version": "microsoft-ddf-2026-02-reviewed-2026-09-20", + "provenance": { + "ddfIndexUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/configuration-service-provider-ddf", + "packageUrl": "https://download.microsoft.com/download/015bd9f5-9cca-4821-8a85-a4c5f9a5d0f2/DDFv2Feb2026.zip", + "packageSha256": "bf667d895af4a8c8ab5a31065ce0e28ea2f8b649c4dc416f452f62fd1c42ff14", + "auditPath": "DDFDrop012026/Audit_AreaDDF.xml", + "auditSha256": "5c467e7742e5ac64019a2031dfcb9cf33397d97567b4ca4ae6add48cc448ac74", + "precedencePath": "DDFDrop012026/LocalPoliciesSecurityOptions_AreaDDF.xml", + "precedenceSha256": "b2d08684bc723692601e13de2b796cb269e9199138e1e2d927fd1ee4f4f576d1" + }, + "auditDefinition": { + "dataType": "Integer", + "cspFormat": "int", + "scope": "Device", + "allowedValues": [ + 0, + 1, + 2, + 3 + ], + "operations": [ + "Add", + "Delete", + "Get", + "Replace" + ], + "conflictResolution": "LastWrite", + "sourceMinimumVersions": [ + "10.0.19041", + "10.0.18362.329", + "10.0.17763.774", + "10.0.17134.1039" + ], + "editionSkuAllowList": [ + "0x4", + "0x1B", + "0x30", + "0x31", + "0x48", + "0x54", + "0x79", + "0x7A", + "0x7D", + "0x7E", + "0x81", + "0x8A", + "0x8B", + "0xA1", + "0xA2", + "0xA4", + "0xA5", + "0xAB", + "0xAC", + "0xAF", + "0xBC", + "0xBF", + "0xCA", + "0xCB", + "0xCD", + "0xCF", + "0xD2" + ] + }, + "precedenceDefinition": { + "omaUri": "./Device/Vendor/MSFT/Policy/Config/LocalPoliciesSecurityOptions/Audit_ForceAuditPolicySubcategorySettingsToOverrideAuditPolicyCategorySettings", + "dataType": "Integer", + "cspFormat": "int", + "value": 1, + "scope": "Device", + "operations": [ + "Add", + "Delete", + "Get", + "Replace" + ], + "conflictResolution": "LastWrite", + "sourceMinimumVersions": [ + "10.0.26100", + "10.0.22621.5126" + ], + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-localpoliciessecurityoptions#audit_forceauditpolicysubcategorysettingstooverrideauditpolicycategorysettings" + }, + "mappings": [ + { + "id": "Credential Validation", + "guid": "0CCE923F-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogon_AuditCredentialValidation", + "gpEnglishName": "Audit Credential Validation", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogon_auditcredentialvalidation" + }, + { + "id": "Kerberos Authentication Service", + "guid": "0CCE9242-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogon_AuditKerberosAuthenticationService", + "gpEnglishName": "Audit Kerberos Authentication Service", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogon_auditkerberosauthenticationservice" + }, + { + "id": "Kerberos Service Ticket Operations", + "guid": "0CCE9240-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogon_AuditKerberosServiceTicketOperations", + "gpEnglishName": "Audit Kerberos Service Ticket Operations", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogon_auditkerberosserviceticketoperations" + }, + { + "id": "Other Account Logon Events", + "guid": "0CCE9241-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogon_AuditOtherAccountLogonEvents", + "gpEnglishName": "Audit Other Account Logon Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogon_auditotheraccountlogonevents" + }, + { + "id": "Application Group Management", + "guid": "0CCE9239-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountManagement_AuditApplicationGroupManagement", + "gpEnglishName": "Audit Application Group Management", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountmanagement_auditapplicationgroupmanagement" + }, + { + "id": "Computer Account Management", + "guid": "0CCE9236-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountManagement_AuditComputerAccountManagement", + "gpEnglishName": "Audit Computer Account Management", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountmanagement_auditcomputeraccountmanagement" + }, + { + "id": "Distribution Group Management", + "guid": "0CCE9238-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountManagement_AuditDistributionGroupManagement", + "gpEnglishName": "Audit Distributio Group Management", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountmanagement_auditdistributiongroupmanagement" + }, + { + "id": "Other Account Management Events", + "guid": "0CCE923A-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountManagement_AuditOtherAccountManagementEvents", + "gpEnglishName": "Audit Other Account Management Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountmanagement_auditotheraccountmanagementevents" + }, + { + "id": "Security Group Management", + "guid": "0CCE9237-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountManagement_AuditSecurityGroupManagement", + "gpEnglishName": "Audit Security Group Management", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountmanagement_auditsecuritygroupmanagement" + }, + { + "id": "User Account Management", + "guid": "0CCE9235-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountManagement_AuditUserAccountManagement", + "gpEnglishName": "Audit User Account Management", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountmanagement_audituseraccountmanagement" + }, + { + "id": "DPAPI Activity", + "guid": "0CCE922D-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DetailedTracking_AuditDPAPIActivity", + "gpEnglishName": "Audit DPAPI Activity", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#detailedtracking_auditdpapiactivity" + }, + { + "id": "Plug and Play Events", + "guid": "0CCE9248-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DetailedTracking_AuditPNPActivity", + "gpEnglishName": "Audit PNP Activity", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#detailedtracking_auditpnpactivity" + }, + { + "id": "Process Creation", + "guid": "0CCE922B-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DetailedTracking_AuditProcessCreation", + "gpEnglishName": "Audit Process Creation", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#detailedtracking_auditprocesscreation" + }, + { + "id": "Process Termination", + "guid": "0CCE922C-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DetailedTracking_AuditProcessTermination", + "gpEnglishName": "Audit Process Termination", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#detailedtracking_auditprocesstermination" + }, + { + "id": "RPC Events", + "guid": "0CCE922E-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DetailedTracking_AuditRPCEvents", + "gpEnglishName": "Audit RPC Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#detailedtracking_auditrpcevents" + }, + { + "id": "Token Right Adjusted Events", + "guid": "0CCE924A-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DetailedTracking_AuditTokenRightAdjusted", + "gpEnglishName": "Audit Token Right Adjusted", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#detailedtracking_audittokenrightadjusted" + }, + { + "id": "Detailed Directory Service Replication", + "guid": "0CCE923E-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DSAccess_AuditDetailedDirectoryServiceReplication", + "gpEnglishName": "Audit Detailed Directory Service Replication", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#dsaccess_auditdetaileddirectoryservicereplication" + }, + { + "id": "Directory Service Access", + "guid": "0CCE923B-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DSAccess_AuditDirectoryServiceAccess", + "gpEnglishName": "Audit Directory Service Access", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#dsaccess_auditdirectoryserviceaccess" + }, + { + "id": "Directory Service Changes", + "guid": "0CCE923C-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DSAccess_AuditDirectoryServiceChanges", + "gpEnglishName": "Audit Directory Service Changes", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#dsaccess_auditdirectoryservicechanges" + }, + { + "id": "Directory Service Replication", + "guid": "0CCE923D-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/DSAccess_AuditDirectoryServiceReplication", + "gpEnglishName": "Audit Directory Service Replication", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#dsaccess_auditdirectoryservicereplication" + }, + { + "id": "Account Lockout", + "guid": "0CCE9217-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditAccountLockout", + "gpEnglishName": "Audit Account Lockout", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditaccountlockout" + }, + { + "id": "Group Membership", + "guid": "0CCE9249-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditGroupMembership", + "gpEnglishName": "Audit Group Membership", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditgroupmembership" + }, + { + "id": "IPsec Extended Mode", + "guid": "0CCE921A-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditIPsecExtendedMode", + "gpEnglishName": "Audit IPsec Extended Mode", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditipsecextendedmode" + }, + { + "id": "IPsec Main Mode", + "guid": "0CCE9218-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditIPsecMainMode", + "gpEnglishName": "Audit IPsec Main Mode", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditipsecmainmode" + }, + { + "id": "IPsec Quick Mode", + "guid": "0CCE9219-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditIPsecQuickMode", + "gpEnglishName": "Audit IPsec Quick Mode", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditipsecquickmode" + }, + { + "id": "Logoff", + "guid": "0CCE9216-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditLogoff", + "gpEnglishName": "Audit Logoff", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditlogoff" + }, + { + "id": "Logon", + "guid": "0CCE9215-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditLogon", + "gpEnglishName": "Audit Logon", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditlogon" + }, + { + "id": "Network Policy Server", + "guid": "0CCE9243-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditNetworkPolicyServer", + "gpEnglishName": "Audit Network Policy Server", + "cspDocumentedDefault": 3, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditnetworkpolicyserver" + }, + { + "id": "Other Logon/Logoff Events", + "guid": "0CCE921C-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditOtherLogonLogoffEvents", + "gpEnglishName": "Audit Other Logon Logoff Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditotherlogonlogoffevents" + }, + { + "id": "Special Logon", + "guid": "0CCE921B-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditSpecialLogon", + "gpEnglishName": "Audit Special Logon", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_auditspeciallogon" + }, + { + "id": "User/Device Claims", + "guid": "0CCE9247-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/AccountLogonLogoff_AuditUserDeviceClaims", + "gpEnglishName": "Audit User Device Claims", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#accountlogonlogoff_audituserdeviceclaims" + }, + { + "id": "Application Generated", + "guid": "0CCE9222-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditApplicationGenerated", + "gpEnglishName": "Audit Application Generated", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditapplicationgenerated" + }, + { + "id": "Central Access Policy Staging", + "guid": "0CCE9246-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditCentralAccessPolicyStaging", + "gpEnglishName": "Audit Central Access Policy Staging", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditcentralaccesspolicystaging" + }, + { + "id": "Certification Services", + "guid": "0CCE9221-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditCertificationServices", + "gpEnglishName": "Audit Certification Services", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditcertificationservices" + }, + { + "id": "Detailed File Share", + "guid": "0CCE9244-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditDetailedFileShare", + "gpEnglishName": "Audit Detailed File Share", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditdetailedfileshare" + }, + { + "id": "File Share", + "guid": "0CCE9224-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditFileShare", + "gpEnglishName": "Audit File Share", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditfileshare" + }, + { + "id": "File System", + "guid": "0CCE921D-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditFileSystem", + "gpEnglishName": "Audit File System", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditfilesystem" + }, + { + "id": "Filtering Platform Connection", + "guid": "0CCE9226-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditFilteringPlatformConnection", + "gpEnglishName": "Audit Filtering Platform Connection", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditfilteringplatformconnection" + }, + { + "id": "Filtering Platform Packet Drop", + "guid": "0CCE9225-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditFilteringPlatformPacketDrop", + "gpEnglishName": "Audit Filtering Platform Packet Drop", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditfilteringplatformpacketdrop" + }, + { + "id": "Handle Manipulation", + "guid": "0CCE9223-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditHandleManipulation", + "gpEnglishName": "Audit Handle Manipulation", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_audithandlemanipulation" + }, + { + "id": "Kernel Object", + "guid": "0CCE921F-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditKernelObject", + "gpEnglishName": "Audit Kernel Object", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditkernelobject" + }, + { + "id": "Other Object Access Events", + "guid": "0CCE9227-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditOtherObjectAccessEvents", + "gpEnglishName": "Audit Other Object Access Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditotherobjectaccessevents" + }, + { + "id": "Registry", + "guid": "0CCE921E-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditRegistry", + "gpEnglishName": "Audit Registry", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditregistry" + }, + { + "id": "Removable Storage", + "guid": "0CCE9245-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditRemovableStorage", + "gpEnglishName": "Audit Removable Storage", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditremovablestorage" + }, + { + "id": "SAM", + "guid": "0CCE9220-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/ObjectAccess_AuditSAM", + "gpEnglishName": "Audit SAM", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#objectaccess_auditsam" + }, + { + "id": "Audit Policy Change", + "guid": "0CCE922F-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PolicyChange_AuditPolicyChange", + "gpEnglishName": "Audit Policy Change", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#policychange_auditpolicychange" + }, + { + "id": "Authentication Policy Change", + "guid": "0CCE9230-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PolicyChange_AuditAuthenticationPolicyChange", + "gpEnglishName": "Audit Authentication Policy Change", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#policychange_auditauthenticationpolicychange" + }, + { + "id": "Authorization Policy Change", + "guid": "0CCE9231-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PolicyChange_AuditAuthorizationPolicyChange", + "gpEnglishName": "Audit Authorization Policy Change", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#policychange_auditauthorizationpolicychange" + }, + { + "id": "Filtering Platform Policy Change", + "guid": "0CCE9233-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PolicyChange_AuditFilteringPlatformPolicyChange", + "gpEnglishName": "Audit Filtering Platform Policy Change", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#policychange_auditfilteringplatformpolicychange" + }, + { + "id": "MPSSVC Rule-Level Policy Change", + "guid": "0CCE9232-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PolicyChange_AuditMPSSVCRuleLevelPolicyChange", + "gpEnglishName": "Audit MPSSVC Rule Level Policy Change", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#policychange_auditmpssvcrulelevelpolicychange" + }, + { + "id": "Other Policy Change Events", + "guid": "0CCE9234-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PolicyChange_AuditOtherPolicyChangeEvents", + "gpEnglishName": "Audit Other Policy Change Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#policychange_auditotherpolicychangeevents" + }, + { + "id": "Non Sensitive Privilege Use", + "guid": "0CCE9229-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PrivilegeUse_AuditNonSensitivePrivilegeUse", + "gpEnglishName": "Audit Non Sensitive Privilege Use", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#privilegeuse_auditnonsensitiveprivilegeuse" + }, + { + "id": "Other Privilege Use Events", + "guid": "0CCE922A-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PrivilegeUse_AuditOtherPrivilegeUseEvents", + "gpEnglishName": "Audit Other Privilege Use Events", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#privilegeuse_auditotherprivilegeuseevents" + }, + { + "id": "Sensitive Privilege Use", + "guid": "0CCE9228-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/PrivilegeUse_AuditSensitivePrivilegeUse", + "gpEnglishName": "Audit Sensitive Privilege Use", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#privilegeuse_auditsensitiveprivilegeuse" + }, + { + "id": "IPsec Driver", + "guid": "0CCE9213-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/System_AuditIPsecDriver", + "gpEnglishName": "Audit IPsec Driver", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#system_auditipsecdriver" + }, + { + "id": "Other System Events", + "guid": "0CCE9214-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/System_AuditOtherSystemEvents", + "gpEnglishName": "Audit Other System Events", + "cspDocumentedDefault": 3, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#system_auditothersystemevents" + }, + { + "id": "Security State Change", + "guid": "0CCE9210-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/System_AuditSecurityStateChange", + "gpEnglishName": "Audit Security State Change", + "cspDocumentedDefault": 1, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#system_auditsecuritystatechange" + }, + { + "id": "Security System Extension", + "guid": "0CCE9211-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/System_AuditSecuritySystemExtension", + "gpEnglishName": "Audit Security System Extension", + "cspDocumentedDefault": 0, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#system_auditsecuritysystemextension" + }, + { + "id": "System Integrity", + "guid": "0CCE9212-69AE-11D9-BED3-505054503030", + "omaUri": "./Device/Vendor/MSFT/Policy/Config/Audit/System_AuditSystemIntegrity", + "gpEnglishName": "Audit System Integrity", + "cspDocumentedDefault": 3, + "sourceUrl": "https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#system_auditsystemintegrity" + } + ] +} diff --git a/docs/intune-audit-export.md b/docs/intune-audit-export.md new file mode 100644 index 00000000..1d3f21a6 --- /dev/null +++ b/docs/intune-audit-export.md @@ -0,0 +1,132 @@ +# Offline Intune audit policy export + +`intune-export` creates reviewable Windows client Policy CSP artifacts from WELA's +shared advanced audit profiles. It runs offline under Windows PowerShell 5.1 or +PowerShell 7, including on a non-Windows authoring machine. It does not read or +change endpoint policy, authenticate to Graph, upload a profile or assign devices. +Sysmon and EMET are excluded. + +```powershell +./WELA.ps1 intune-export -IntuneProfile wela-2.2.0 ` + -IntuneBuild 26100 -IntuneEdition Enterprise -IntuneOutputPath .\intune-wela-review + +./WELA.ps1 intune-export -IntuneProfile microsoft-sct-win11-25h2 ` + -IntuneBuild 26200 -IntuneEdition Enterprise -IntuneOutputPath .\intune-sct-review + +# Review the expansion beyond each one-bit minimum before selecting this option. +./WELA.ps1 intune-export -IntuneProfile microsoft-wef-reviewed-2026-09 ` + -IntuneBuild 26100 -IntuneEdition Enterprise -IntuneMinimumMode PromoteToBoth ` + -IntuneOutputPath .\intune-wef-expanded +``` + +Use `profiles` to list shared profile IDs. The target is an **operator declaration**: +client build **26100 (24H2)** or **26200 (25H2)**, with edition **Pro**, **Enterprise**, +**Education** or **IoTEnterprise**. Both the profile's client/build scope and the +exporter's reviewed CSP scope must match. Unknown builds/editions and server, +DC or AD CS profiles are rejected. Home is not supported by these CSP settings. +This is CSP applicability, not certification that a source benchmark covers every +declared edition; for example, the reviewed CIS source is Windows 11 Enterprise. +Source versions and limitations remain in the manifest. + +`-IncludeOptional` selects optional rows using their shared profile's exact-mask +semantics. Other commands reject `-Intune*` options before dispatch. This command +rejects configuration, consent, live role/build overrides and unrelated export +options; use the dedicated parameters above. No elevation or tenant access is +needed to generate files. + +| Shared mode | Offline CSP treatment | +| --- | --- | +| `exact` | Integer 0, 1, 2 or 3 exactly as specified; this can disable existing bits. | +| `minimum`, mask 0 | Preserve; no payload setting. | +| `minimum`, mask 3 | Integer 3; equivalent for the native two-bit mask. | +| `minimum`, mask 1 or 2 | Default `Reject`: review-only bundle and exit 1. Explicit `PromoteToBoth`: integer 3 with expansion recorded for every affected row. | +| Selected `optional` | Exact integer mask. | +| Unselected `optional`, `unchanged`, `not-configured`, `not-applicable` | Retained as separate manifest rows; no payload and no Delete. | + +The CSP contract is **0=None, 1=Success, 2=Failure, 3=Success+Failure**, data type +**Integer**, not String/XML, Boolean or registry binary data. Microsoft's DDF marks +these policies `LastWrite`. A static integer cannot implement “enable Success but +preserve whichever Failure bit each device already has.” `PromoteToBoth` sets both +bits and can increase event volume; it is not a live merge or exact reproduction +of the source minimum. Some subcategories produce only one outcome despite +accepting the full mask; exporting a bit is not event-generation evidence. + +Documentary default profiles are blocked. No-setting profiles produce review-only +output rather than an unrelated precedence-only policy. A blocked bundle retains +all 59 rows and reasons, but contains neither deployment JSON nor settings CSV. +Do not manually extract candidate rows from it as though they formed a complete +policy. Correct the blockers and export to a new directory. + +## Artifacts and provenance + +The output must be a **new local directory under an existing parent**. Existing +files/directories, UNC/device paths, drive-relative paths, wildcard/parent-traversal +paths and symlink/reparse ancestors are refused; on Windows use a fixed local +drive. Writes use `CreateNew` and verify bytes after writing. A failure can leave +partial files for review. **`SHA256SUMS.json` is written last**; without it, the +bundle is incomplete. Hashes identify bytes and detect changes, not source trust. + +| File | Purpose | +| --- | --- | +| `manifest.json` | All 59 shared rows, target declaration, omission/expansion reasons, candidate values, prerequisites, source/profile/mapping fingerprints and unverified deployment state. | +| `oma-settings.csv` | Manual-entry/review list: Name, Description, case-sensitive OMA-URI, Integer data type and Value. **Not a portal-importable CSV profile.** | +| `graph-body.json` | Offline Graph v1.0 `windows10CustomConfiguration` body, with typed `omaSettingInteger` rows. No tenant ID, object ID, credentials or assignments. **Not Settings Catalog import JSON.** | +| `README.txt` | Standalone review/deployment notes, included in release-generated bundles. | +| `SHA256SUMS.json` | Completion status and SHA-256/byte length for each preceding artifact. | + +[`config/intune_audit_csp.json`](../config/intune_audit_csp.json) pins the official +[February 2026 DDF package](https://learn.microsoft.com/en-us/windows/client-management/mdm/configuration-service-provider-ddf) +and both exact DDF paths/hashes. It contains 59 explicit GUID-to-URI mappings; +runtime names are not guessed by concatenation. This includes the non-obvious +`DetailedTracking_AuditPNPActivity`, `DetailedTracking_AuditTokenRightAdjusted` and +`PolicyChange_AuditPolicyChange` spellings. The DDF's literal GP label typo +“Distributio Group Management” is preserved as provenance, without changing its +correct URI. Only the 49 client-applicable catalog rows can become client payload +settings, further restricted by the selected profile. Source CSP defaults are +documentary metadata, never assumed endpoint values. + +## Precedence, conflicts and deployment evidence + +Every nonempty deployment payload includes a separate prerequisite Integer **1**: +`./Device/Vendor/MSFT/Policy/Config/LocalPoliciesSecurityOptions/Audit_ForceAuditPolicySubcategorySettingsToOverrideAuditPolicyCategorySettings`. +This controls `SCENoApplyLegacyAuditPolicy`. Microsoft documents this CSP from +build 26100 and its backport to 22621.5126. Earlier Windows 11 releases may support +the audit subcategory CSPs while lacking this prerequisite CSP; this initial +exporter deliberately restricts target builds instead of silently omitting it. +The setting is identified separately from source-profile subcategories. +[Microsoft precedence CSP](https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-localpoliciessecurityoptions#audit_forceauditpolicysubcategorysettingstooverrideauditpolicycategorysettings) + +Audit subcategory precedence does not settle MDM versus GPO ownership. WELA does +not emit `MDMWinsOverGP`. Review overlapping security baselines, Settings Catalog, +custom policies, GPO and scripts before deployment. Microsoft's conflict control +has a distinct scope; `LastWrite` is not proof that a particular competing profile +will win. No policy ordering, tenant conflict check or atomic application is +claimed. [Microsoft conflict control](https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-controlpolicyconflict) + +An authorized operator can enter the CSV rows in a Windows custom profile or +review the Graph body using their organization's deployment process. Intune's +custom-profile documentation requires Add, Replace and Get support; all emitted +nodes provide these operations. An export does not demonstrate the tenant will +accept them. The artifact does not enforce its edition/build declaration through +assignments or filters; scope a matching enrolled pilot explicitly. +[Intune custom settings](https://learn.microsoft.com/en-us/intune/device-configuration/templates/configure-custom-settings-windows), +[Graph custom configuration](https://learn.microsoft.com/en-us/graph/api/intune-deviceconfig-windows10customconfiguration-create?view=graph-rest-1.0), +[Graph integer setting](https://learn.microsoft.com/en-us/graph/api/resources/intune-deviceconfig-omasettinginteger?view=graph-rest-1.0) + +Retain pre-deployment authoritative policy evidence. After a separately authorized +pilot, inspect per-setting Intune status and MDM diagnostics, verify the registry +precedence value and actual subcategory masks using WELA, test ordinary policy +sync/GPO coexistence, and retain benign event/collection evidence. Omitting a +setting from a later export is not a Delete and does not undo an older assignment. +Unassignment/deletion may restore defaults or another policy rather than the prior +local value; recovery requires review of the current policy owners. No automatic +rollback is generated. SACLs, process command-line payloads, channels, log sizes, +retention and forwarding are separate workflows. + +Tests cross-check mappings against extracted DDF facts, validate all mask/mode +cases, exercise the public exporter/CLI and verify file fingerprints and refusal +paths on PowerShell 5.1/7. Native/HTTP adapters are forbidden in offline fixtures. +CI does not enroll a client, upload anything or mutate Windows. Intune acceptance, +pilot assignment, effective masks after sync, conflicts, recovery and event +generation remain deployment evidence needed before fully closing issue #1. +No compliance or Sigma uplift is inferred from export success. diff --git a/scripts/IntuneAuditExport.ps1 b/scripts/IntuneAuditExport.ps1 new file mode 100644 index 00000000..adf0ba5c --- /dev/null +++ b/scripts/IntuneAuditExport.ps1 @@ -0,0 +1,161 @@ +# Offline artifacts only: no Windows policy reads/writes, Graph requests or assignment. +function Import-WelaIntuneAuditMappings { + param([string]$Path=(Join-Path $PSScriptRoot '../config/intune_audit_csp.json'),$Catalog) + $data=Get-Content -LiteralPath $Path -Raw -Encoding UTF8 -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop + if ($data.schemaVersion -ne 1 -or -not $data.version -or @($data.mappings).Count -ne 59 -or @($Catalog).Count -ne 59) { throw 'Unknown Intune mapping schema/catalog; the reviewed 59 mappings are required.' } + foreach ($hash in @($data.provenance.packageSha256,$data.provenance.auditSha256,$data.provenance.precedenceSha256)) { + if ($hash -notmatch '^[a-f0-9]{64}$') { throw 'Missing Intune DDF provenance fingerprint.' } + } + $definition=$data.auditDefinition + if ($definition.dataType -cne 'Integer' -or $definition.cspFormat -cne 'int' -or $definition.scope -cne 'Device' -or + ($definition.allowedValues -join ',') -cne '0,1,2,3' -or ($definition.operations -join ',') -cne 'Add,Delete,Get,Replace' -or $definition.conflictResolution -cne 'LastWrite') { throw 'Unexpected Audit CSP format, masks, operations or conflict semantics.' } + $seenGuids=@{};$seenUris=@{} + foreach ($mapping in $data.mappings) { + $match=@($Catalog | Where-Object { $_.guid -ieq $mapping.guid -and $_.id -ceq $mapping.id }) + if ($match.Count -ne 1 -or $seenGuids.ContainsKey($mapping.guid) -or $seenUris.ContainsKey($mapping.omaUri) -or + $mapping.omaUri -cnotmatch '^\./Device/Vendor/MSFT/Policy/Config/Audit/[A-Za-z]+_Audit[A-Za-z]+$' -or $mapping.omaUri -match 'Sysmon|EMET' -or + $mapping.cspDocumentedDefault -notin @(0,1,2,3) -or -not $mapping.gpEnglishName -or + $mapping.sourceUrl -cne ('https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-audit#'+($mapping.omaUri.Split('/')[-1]).ToLowerInvariant())) { throw "Unknown, duplicate or inconsistent Intune GUID/URI mapping: $($mapping.id)" } + $seenGuids[$mapping.guid]=$true;$seenUris[$mapping.omaUri]=$true + } + $precedence=$data.precedenceDefinition + if ($precedence.omaUri -cne './Device/Vendor/MSFT/Policy/Config/LocalPoliciesSecurityOptions/Audit_ForceAuditPolicySubcategorySettingsToOverrideAuditPolicyCategorySettings' -or + $precedence.dataType -cne 'Integer' -or $precedence.cspFormat -cne 'int' -or $precedence.value -isnot [ValueType] -or $precedence.value -is [bool] -or $precedence.value -ne 1 -or + $precedence.scope -cne 'Device' -or $precedence.conflictResolution -cne 'LastWrite' -or ($precedence.operations -join ',') -cne 'Add,Delete,Get,Replace' -or + ($precedence.sourceMinimumVersions -join ',') -cne '10.0.26100,10.0.22621.5126') { throw 'Unexpected advanced audit precedence CSP definition.' } + return $data +} + +function Get-WelaIntuneAuditExportPlan { + param([Parameter(Mandatory)][string]$Profile,[Parameter(Mandatory)][int]$Build,[Parameter(Mandatory)][string]$Edition, + [ValidateSet('Reject','PromoteToBoth')][string]$MinimumMode='Reject',[switch]$IncludeOptional, + [string]$ProfilePath=(Join-Path $PSScriptRoot '../config/audit_profiles.json'),[string]$MappingPath=(Join-Path $PSScriptRoot '../config/intune_audit_csp.json')) + if ($Build -notin @(26100,26200)) { throw 'Intune export supports reviewed Windows 11 client builds 26100 and 26200 only, including the precedence CSP prerequisite.' } + if ($Edition -cnotin @('Pro','Enterprise','Education','IoTEnterprise')) { throw 'Intune export requires a reviewed client edition: Pro, Enterprise, Education or IoTEnterprise.' } + $profileHash=(Get-FileHash -LiteralPath $ProfilePath -Algorithm SHA256 -ErrorAction Stop).Hash + $mappingHash=(Get-FileHash -LiteralPath $MappingPath -Algorithm SHA256 -ErrorAction Stop).Hash + $catalog=Import-WelaAuditProfiles -Path $ProfilePath + $mapping=Import-WelaIntuneAuditMappings -Path $MappingPath -Catalog $catalog.catalog + $plan=Get-WelaAuditProfilePlan -Profile $Profile -Role Client -Build $Build -IncludeOptional:$IncludeOptional -Path $ProfilePath + if ($profileHash -cne (Get-FileHash -LiteralPath $ProfilePath -Algorithm SHA256).Hash -or $profileHash -cne $plan.schemaSha256 -or + $mappingHash -cne (Get-FileHash -LiteralPath $MappingPath -Algorithm SHA256).Hash) { throw 'Export source changed while being read; retry from consistent input files.' } + $blockers=@();$rows=@();$settings=@() + if ($plan.referenceOnly) { $blockers+='The selected profile is documentary reference only; it cannot be deployed as Windows defaults.' } + foreach ($policy in $plan.policies) { + $mapped=@($mapping.mappings | Where-Object guid -eq $policy.guid)[0] + $value=$null;$disposition='Preserve';$expansion=$false + switch ($policy.mode) { + 'not-applicable' { $disposition='NotApplicable' } + 'not-configured' { $disposition='NotConfiguredPreserved' } + 'unchanged' { $disposition='Preserve' } + 'optional' { if ($IncludeOptional) { $value=[int]$policy.requiredMask;$disposition='SelectedOptionalExact' } else { $disposition='OptionalNotSelected' } } + 'exact' { $value=[int]$policy.requiredMask;$disposition='ExactReplacement' } + 'minimum' { + if ($policy.requiredMask -eq 0) { $disposition='MinimumZeroPreserved' } + elseif ($policy.requiredMask -eq 3) { $value=3;$disposition='MinimumEquivalentToBoth' } + elseif ($MinimumMode -eq 'PromoteToBoth') { $value=3;$disposition='PromotedToBoth';$expansion=$true } + else { $disposition='BlockedMinimum';$blockers+="$($policy.id): minimum mask $($policy.requiredMask) cannot preserve unknown existing bits in a static LastWrite CSP value. Use explicit PromoteToBoth only after reviewing the expansion." } + } + default { throw "Unknown audit profile mode: $($policy.mode)" } + } + $row=[pscustomobject][ordered]@{Id=$policy.id;Guid=$policy.guid;Category=$policy.category;SourceMode=$policy.mode;RequiredMask=$policy.requiredMask;Disposition=$disposition;CandidateValue=$value;ExpandedBeyondMinimum=$expansion;OmaUri=$mapped.omaUri;DataType='Integer';CspFormat='int';ConflictResolution='LastWrite';CspDocumentedDefault=$mapped.cspDocumentedDefault;CurrentValue='Not observed';MappingSource=$mapped.sourceUrl;SourceIds=$policy.sourceIds;Prerequisites=$policy.prerequisites;SourceNote=$policy.note;SourceEvidence=$policy.evidence} + $rows+=$row + if ($null -ne $value) { $settings+=[pscustomobject][ordered]@{Name=$policy.id;Description="WELA $Profile; $($policy.mode) required=$($policy.requiredMask); $disposition. Current state and generated events are unverified.";OmaUri=$mapped.omaUri;DataType='Integer';Value=[int]$value} } + } + if ($settings.Count) { + $precedence=[pscustomobject][ordered]@{Name='Advanced audit subcategory precedence';Description='Required companion setting: SCENoApplyLegacyAuditPolicy=1. This is separate from MDM/GPO ownership and is not a source-profile subcategory.';OmaUri=$mapping.precedenceDefinition.omaUri;DataType='Integer';Value=1} + $settings=@($precedence)+$settings + } + if (-not $settings.Count -and -not $blockers.Count) { $blockers+='The selected profile requests no representable client settings; no precedence-only policy is emitted.' } + [pscustomobject][ordered]@{SchemaVersion=1;Scope='offline-intune-native-audit-export';RecordedUtc=[datetime]::UtcNow.ToString('o');Status=$(if ($blockers.Count) {'BlockedReviewOnly'} else {'PreparedOffline'});ExitCode=$(if ($blockers.Count) {1} else {0});Target=[pscustomobject]@{Role='Client';Build=$Build;Edition=$Edition;Observation='Operator declaration; no endpoint was queried';Support='Reviewed CSP applicability only, not full source-baseline certification'};Profile=$plan.profile;ProfileVersion=$plan.version;ProfileSha256=$profileHash;MappingVersion=$mapping.version;MappingSha256=$mappingHash;DdfProvenance=$mapping.provenance;AuditCspDefinition=$mapping.auditDefinition;PrecedenceDefinition=$mapping.precedenceDefinition;SourceProvenance=$plan.provenance;IncludeOptional=[bool]$IncludeOptional;MinimumMode=$MinimumMode;Rows=$rows;CandidateSettings=$settings;Blockers=$blockers;PayloadEmitted=$false;TenantContacted=$false;Assigned=$false;WindowsConfigurationChanged=$false;SigmaCredit=0;Limitations=@('Integer masks replace values; exact 0/1/2 can disable existing audit bits. Minimum promotion enables both bits and can increase volume.','Omitted, not-configured and unselected optional rows emit no setting and no Delete; they do not remove previous MDM/GPO policy.','No MDMWinsOverGP setting is emitted. Review overlapping GPO, Settings Catalog, baseline, custom profiles and local scripts. LastWrite is not a guarantee against those conflicts.','The target edition/build is declared, not enforced by this artifact. Assign only to a validated matching pilot group.','SACLs, command-line payloads, provider/channel readiness, log size, retention, forwarding and events require separate validation. Sysmon and EMET are excluded.','Successful file export establishes no Intune acceptance, policy application, resultant audit masks, persistence, event generation or Sigma eligibility.')} +} + +function Get-WelaIntuneOutputDirectory { + param([Parameter(Mandatory)][string]$Path) + if ([string]::IsNullOrWhiteSpace($Path) -or $Path -match '[\x00-\x1f*?\[\]]' -or $Path -match '(^|[\\/])\.\.([\\/]|$)' -or $Path -match '^[\\/]{2}' -or $Path -match '^[A-Za-z]:[^\\/]') { throw 'Intune output requires an exact local new directory, without remote, wildcard, device, drive-relative or parent-traversal paths.' } + $provider=$null;$drive=$null + try { $full=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path,[ref]$provider,[ref]$drive) } + catch { throw "Intune output must resolve to a local filesystem path: $($_.Exception.Message)" } + if ($provider.Name -ne 'FileSystem' -or $full -match '^[\\/]{2}') { throw 'Intune output must use the local filesystem.' } + if ([IO.File]::Exists($full) -or [IO.Directory]::Exists($full)) { throw 'Intune output directory already exists; prior artifacts are never overwritten.' } + $parent=[IO.DirectoryInfo]([IO.Path]::GetDirectoryName($full)) + if (-not $parent.Exists) { throw 'Intune output parent directory must already exist.' } + $ancestor=$parent + while ($ancestor) { + if ($ancestor.Attributes -band [IO.FileAttributes]::ReparsePoint) { throw 'Intune output cannot traverse a symlink or reparse point.' } + $ancestor=$ancestor.Parent + } + if ([Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT -and ([IO.DriveInfo]::new([IO.Path]::GetPathRoot($full))).DriveType -ne [IO.DriveType]::Fixed) { throw 'Intune output requires a local fixed drive.' } + return $full +} + +function Write-WelaIntuneArtifact { + param([string]$Directory,[string]$Name,[string]$Text) + if ((Get-Item -LiteralPath $Directory -Force -ErrorAction Stop).Attributes -band [IO.FileAttributes]::ReparsePoint) { throw 'Intune output directory changed to a reparse point.' } + $path=Join-Path $Directory $Name + $bytes=(New-Object Text.UTF8Encoding($false)).GetBytes($Text) + $stream=[IO.File]::Open($path,[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::None) + try { $stream.Write($bytes,0,$bytes.Length);$stream.Flush($true) } finally { $stream.Dispose() } + $hash=(Get-FileHash -LiteralPath $path -Algorithm SHA256 -ErrorAction Stop).Hash + $algorithm=[Security.Cryptography.SHA256]::Create() + try { $expected=([BitConverter]::ToString($algorithm.ComputeHash($bytes))).Replace('-','') } finally { $algorithm.Dispose() } + if ($hash -cne $expected) { throw "Intune artifact readback failed: $Name" } + [pscustomobject]@{Name=$Name;Bytes=$bytes.Length;Sha256=$hash} +} + +function Invoke-WelaIntuneAuditExport { + param([Parameter(Mandatory)][string]$Profile,[Parameter(Mandatory)][int]$Build,[Parameter(Mandatory)][string]$Edition,[Parameter(Mandatory)][string]$OutputPath, + [ValidateSet('Reject','PromoteToBoth')][string]$MinimumMode='Reject',[switch]$IncludeOptional) + $plan=Get-WelaIntuneAuditExportPlan -Profile $Profile -Build $Build -Edition $Edition -MinimumMode $MinimumMode -IncludeOptional:$IncludeOptional + $directory=Get-WelaIntuneOutputDirectory $OutputPath + $text=@{};$plan.PayloadEmitted=-not [bool]$plan.Blockers.Count + if ($plan.PayloadEmitted) { + $omaSettings=@($plan.CandidateSettings | ForEach-Object { [ordered]@{'@odata.type'='#microsoft.graph.omaSettingInteger';displayName=$_.Name;description=$_.Description;omaUri=$_.OmaUri;value=[int]$_.Value} }) + $graph=[ordered]@{'@odata.type'='#microsoft.graph.windows10CustomConfiguration';displayName="WELA $Profile - Windows 11 $Build $Edition";description="Offline reviewed WELA audit export. Profile $($plan.ProfileVersion); minimum mode $MinimumMode. Target $Edition build $Build must be scoped separately. No assignments included.";version=1;omaSettings=$omaSettings} + $text['graph-body.json']=$graph | ConvertTo-Json -Depth 8 + $csv=@($plan.CandidateSettings | Select-Object Name,Description,@{n='OMA-URI';e={$_.OmaUri}},DataType,Value | ConvertTo-Csv -NoTypeInformation) + $text['oma-settings.csv']=$csv -join [Environment]::NewLine + } + $text['manifest.json']=$plan | ConvertTo-Json -Depth 18 + $text['README.txt']=@" +WELA offline Intune native audit export +Status: $($plan.Status). Profile: $Profile. Declared client: $Edition build $Build. +Review every manifest row, omission, expansion, prerequisite and source fingerprint. +BlockedReviewOnly bundles contain no deployable Graph body or settings CSV; resolve +the blockers and export to another new directory. Never deploy candidate rows from +a blocked manifest as though they were a complete policy. + +For PreparedOffline bundles, oma-settings.csv is a manual-entry/review list, NOT a +portal-importable profile. Add its case-sensitive OMA-URI rows as Integer settings +in a Windows custom configuration, or have an authorized operator review the +offline graph-body.json representation of windows10CustomConfiguration. +Graph reference: https://learn.microsoft.com/en-us/graph/api/intune-deviceconfig-windows10customconfiguration-create?view=graph-rest-1.0 +This bundle sends no request and contains no assignment, device ID, tenant ID, +credential or token. It is not a Settings Catalog import file or provisioning XML. + +Validate scope on a matching enrolled pilot client. Check existing GPO, Settings +Catalog, baseline, custom policy and script ownership before deployment. No +MDMWinsOverGP, deletion or rollback request is generated. Omissions do not remove +previously deployed settings. Review exact masks that can remove existing bits; +PromoteToBoth is an explicit expansion, not preservation of unknown current state. +After authorized deployment, verify Intune status, MDM diagnostic evidence, +SCENoApplyLegacyAuditPolicy=1 and native audit masks with WELA; then verify benign +event generation/collection and persistence after normal policy sync. Keep prior +authoritative policy evidence for operator-reviewed recovery. No complete logging, +source-baseline compliance or Sigma eligibility is established by file generation. +Native Windows only; Sysmon/EMET, SACLs and provider configuration are outside scope. + +SHA256SUMS.json is written last after artifact readback. Without that receipt, the +directory is incomplete. Preserve incomplete files for review; export to a fresh +directory after fixing the error. Fingerprints detect changes, not source trust. +"@ + # All semantic validation/serialization happens before the first output write. + $null=New-Item -ItemType Directory -Path $directory -ErrorAction Stop + $files=@() + foreach ($name in @($text.Keys | Sort-Object)) { $files+=Write-WelaIntuneArtifact -Directory $directory -Name $name -Text $text[$name] } + $receipt=[ordered]@{SchemaVersion=1;BundleComplete=$true;Status=$plan.Status;Files=$files} + $null=Write-WelaIntuneArtifact -Directory $directory -Name 'SHA256SUMS.json' -Text ($receipt | ConvertTo-Json -Depth 5) + Write-Host "Intune export $($plan.Status): $directory. No tenant or Windows policy was changed." + foreach ($blocker in $plan.Blockers) { Write-Host "Blocked: $blocker" -ForegroundColor Yellow } + [pscustomobject]@{ExitCode=$plan.ExitCode;Status=$plan.Status;OutputPath=$directory;PayloadEmitted=$plan.PayloadEmitted;Files=$files;Plan=$plan} +} diff --git a/tests/IntuneAuditExport.Cli.Tests.ps1 b/tests/IntuneAuditExport.Cli.Tests.ps1 new file mode 100644 index 00000000..161e6059 --- /dev/null +++ b/tests/IntuneAuditExport.Cli.Tests.ps1 @@ -0,0 +1,34 @@ +# Exercise the real CLI as noninteractive child processes. No tenant is contacted. +$ErrorActionPreference='Stop' +$repo=Split-Path $PSScriptRoot -Parent +$shell=(Get-Process -Id $PID).Path;$script:checks=0 +$temp=Join-Path ([IO.Path]::GetTempPath()) ('wela-intune-cli-'+[guid]::NewGuid().ToString('N')) +$null=New-Item -ItemType Directory -Path $temp +function Assert-Cli([string[]]$Arguments,[int]$Expected,[string]$Text) { + $ErrorActionPreference='Continue' + try { $output=& $shell -NoProfile -NonInteractive -File (Join-Path $repo 'WELA.ps1') @Arguments 2>&1;$code=$LASTEXITCODE } finally { $ErrorActionPreference='Stop' } + if ($code -ne $Expected -or ($output -join "`n") -notmatch [regex]::Escape($Text)) { throw "CLI mismatch for $($Arguments -join ' '): exit=$code`n$($output -join "`n")" } + $script:checks++ +} +try { + Assert-Cli @('intune-export','-Help') 0 'Offline native audit artifacts only' + Assert-Cli @('intune-export') 1 'are required' + foreach ($option in @('IntuneProfile','IntuneBuild','IntuneEdition','IntuneOutputPath','IntuneMinimumMode')) { + $value=switch($option) {'IntuneBuild' {'26100'} 'IntuneMinimumMode' {'Reject'} default {'fixture'}} + Assert-Cli @('configure','-Profile','wela-2.2.0',('-'+$option),$value) 1 'Intune options require' + } + foreach ($option in @('Auto','DryRun','GrantEventLogReaders','AllowPrivilegeRemoval')) { Assert-Cli @('intune-export',('-'+$option)) 1 'accepts only Intune' } + foreach ($pair in @(@('Role','DomainController'),@('Profile','wela-2.2.0'),@('ResultsPath','report.json'),@('WefAction','Configure'))) { Assert-Cli @('intune-export',('-'+$pair[0]),$pair[1]) 1 'accepts only Intune' } + $output=Join-Path $temp 'bundle' + $arguments=@('intune-export','-IntuneProfile','microsoft-sct-win11-25h2','-IntuneBuild','26200','-IntuneEdition','Enterprise','-IntuneOutputPath',$output) + Assert-Cli $arguments 0 'PreparedOffline' + $receipt=Get-Content (Join-Path $output 'SHA256SUMS.json') -Raw -Encoding UTF8|ConvertFrom-Json + if (-not $receipt.BundleComplete -or $receipt.Files.Count -ne 4) { throw 'Public CLI did not create a complete offline bundle.' };$script:checks++ + Assert-Cli $arguments 1 'already exists' + Assert-Cli @('intune-export','-IntuneProfile','microsoft-wef-reviewed-2026-09','-IntuneBuild','26100','-IntuneEdition','Enterprise','-IntuneOutputPath',(Join-Path $temp 'blocked')) 1 'BlockedReviewOnly' + if (Test-Path (Join-Path $temp 'blocked/graph-body.json')) { throw 'Blocked CLI produced a deployable body.' };$script:checks++ + Assert-Cli @('intune-export','-IntuneProfile','wela-2.2.0','-IntuneBuild','20348','-IntuneEdition','Enterprise','-IntuneOutputPath',(Join-Path $temp 'server')) 1 'builds 26100 and 26200' + if (Test-Path (Join-Path $temp 'server')) { throw 'Invalid target created an output directory.' };$script:checks++ + Write-Host "PASS: $script:checks noninteractive Intune CLI assertions. No tenant or Windows policy changes." +} finally { Remove-Item -LiteralPath $temp -Recurse -Force } +$global:LASTEXITCODE=0 diff --git a/tests/IntuneAuditExport.Tests.ps1 b/tests/IntuneAuditExport.Tests.ps1 new file mode 100644 index 00000000..9b665134 --- /dev/null +++ b/tests/IntuneAuditExport.Tests.ps1 @@ -0,0 +1,132 @@ +# Offline public exporter and independent Microsoft DDF fact fixtures. +$ErrorActionPreference='Stop' +$repo=Split-Path $PSScriptRoot -Parent +Import-Module (Join-Path $repo 'modules/AuditProfiles.psm1') -Force +. (Join-Path $repo 'scripts/IntuneAuditExport.ps1') +$script:checks=0 +function Assert($Value,[string]$Message) { if (-not $Value) { throw "FAIL: $Message" };$script:checks++ } +function Reject([scriptblock]$Action,[string]$Pattern) { $message='';try { & $Action | Out-Null } catch { $message=$_.Exception.Message };Assert ($message -match $Pattern) "Expected '$Pattern'; got '$message'" } +# Any hidden endpoint, policy or network dependency must fail this offline suite. +function Get-CimInstance { throw 'Forbidden endpoint query' } +function Get-WinEvent { throw 'Forbidden endpoint query' } +function Get-WelaEffectiveAuditPolicy { throw 'Forbidden endpoint query' } +function Set-WelaEffectiveAuditPolicy { throw 'Forbidden Windows mutation' } +function Invoke-WelaNative { throw 'Forbidden native command' } +function Set-ItemProperty { throw 'Forbidden registry mutation' } +function Invoke-RestMethod { throw 'Forbidden network request' } +function Invoke-WebRequest { throw 'Forbidden network request' } +$temp=Join-Path ([IO.Path]::GetTempPath()) ('wela-intune-tests-'+[guid]::NewGuid().ToString('N')) +$null=New-Item -ItemType Directory -Path $temp +$profilePath=Join-Path $repo 'config/audit_profiles.json';$mappingPath=Join-Path $repo 'config/intune_audit_csp.json' +function New-FixtureProfile($Controls) { + $data=Get-Content -LiteralPath $profilePath -Raw | ConvertFrom-Json + $fixture=[pscustomobject]@{id='fixture';version='1';sourceIds=@('wela');scope='advanced-audit-policy-only';omitted='unchanged';appliesTo=@([pscustomobject]@{roles=@('Client');minBuild=26100;maxBuild=26100});controls=$Controls;roleOverrides=[pscustomobject]@{}} + $data.profiles=@($data.profiles)+$fixture + $path=Join-Path $temp 'profile.json';$data | ConvertTo-Json -Depth 18 | Set-Content -LiteralPath $path -Encoding UTF8 + return $path +} +try { + $catalog=Import-WelaAuditProfiles + $mapping=Import-WelaIntuneAuditMappings -Catalog $catalog.catalog + $facts=Get-Content (Join-Path $PSScriptRoot 'fixtures/intune-audit-ddf-facts.json') -Raw | ConvertFrom-Json + Assert ($facts.sha256 -ceq $mapping.provenance.auditSha256 -and $facts.facts.Count -eq 59) 'Independent source facts identify the pinned official DDF bytes' + foreach ($entry in $mapping.mappings) { + $fact=@($facts.facts | Where-Object node -ceq $entry.omaUri.Split('/')[-1]) + Assert ($fact.Count -eq 1 -and $fact[0].gpName -ceq $entry.gpEnglishName -and $fact[0].default -eq $entry.cspDocumentedDefault) "Exact CSP spelling, policy identity and source default: $($entry.id)" + Assert ($fact[0].format -ceq 'int' -and ($fact[0].values -join ',') -ceq '0,1,2,3' -and $fact[0].conflict -ceq 'LastWrite') "Documented value/conflict contract: $($entry.id)" + # A separate name check catches accidental swaps between valid CSP URIs. + # Retain the DDF's literal "Distributio" spelling as source evidence. + $expected=switch ($entry.id) { 'Plug and Play Events' {'Audit PNP Activity'} 'Token Right Adjusted Events' {'Audit Token Right Adjusted'} 'Audit Policy Change' {'Audit Policy Change'} 'Distribution Group Management' {'Audit Distributio Group Management'} default { 'Audit '+$entry.id } } + Assert (($expected -replace '[^A-Za-z0-9]','') -ieq ($entry.gpEnglishName -replace '[^A-Za-z0-9]','')) "GUID catalog identity matches Microsoft GP identity: $($entry.id)" + } + foreach ($change in @('unknown-guid','duplicate-uri','bad-format','bad-precedence')) { + $data=Get-Content $mappingPath -Raw | ConvertFrom-Json + switch ($change) { + 'unknown-guid' {$data.mappings[0].guid='00000000-0000-0000-0000-000000000000'} + 'duplicate-uri' {$data.mappings[1].omaUri=$data.mappings[0].omaUri} + 'bad-format' {$data.auditDefinition.dataType='String'} + 'bad-precedence' {$data.precedenceDefinition.value=0} + } + $path=Join-Path $temp 'bad-map.json';$data|ConvertTo-Json -Depth 15|Set-Content $path -Encoding UTF8 + Reject {Import-WelaIntuneAuditMappings -Path $path -Catalog $catalog.catalog} 'Unknown|Unexpected' + } + foreach ($build in @(22000,22621,22631,20348,28000)) { Reject {Get-WelaIntuneAuditExportPlan wela-2.2.0 $build Enterprise} 'builds 26100 and 26200' } + foreach ($edition in @('Home','Server','Unknown','enterprise')) { Reject {Get-WelaIntuneAuditExportPlan wela-2.2.0 26100 $edition} 'reviewed client edition' } + Reject {Get-WelaIntuneAuditExportPlan microsoft-sct-server2025-2602 26100 Enterprise} 'does not support role' + foreach ($edition in @('Pro','Enterprise','Education','IoTEnterprise')) { Assert ((Get-WelaIntuneAuditExportPlan wela-2.2.0 26200 $edition).ExitCode -eq 0) 'Reviewed CSP edition/build can be declared without endpoint reads' } + $reference=Get-WelaIntuneAuditExportPlan windows-defaults-reviewed-2026-09 26100 Enterprise + Assert ($reference.ExitCode -eq 1 -and ($reference.Blockers -join '') -match 'reference only') 'Documentary defaults cannot be exported as a deployment baseline' + foreach ($mask in 0..3) { + $path=New-FixtureProfile ([pscustomobject]@{Logon=[pscustomobject]@{mode='exact';mask=$mask}}) + $plan=Get-WelaIntuneAuditExportPlan fixture 26100 Enterprise -ProfilePath $path + Assert ($plan.ExitCode -eq 0 -and $plan.CandidateSettings.Count -eq 2 -and $plan.CandidateSettings[1].Value -eq $mask -and $plan.CandidateSettings[1].Value -is [int]) 'Exact masks remain typed integers, including explicit no-auditing zero' + } + foreach ($mask in 0..3) { + $path=New-FixtureProfile ([pscustomobject]@{Logon=[pscustomobject]@{mode='minimum';mask=$mask}}) + $reject=Get-WelaIntuneAuditExportPlan fixture 26100 Enterprise -ProfilePath $path + $both=Get-WelaIntuneAuditExportPlan fixture 26100 Enterprise -ProfilePath $path -MinimumMode PromoteToBoth + $row=@($both.Rows|Where-Object Id -eq Logon)[0] + if ($mask -eq 0) { Assert ($both.CandidateSettings.Count -eq 0 -and $row.Disposition -eq 'MinimumZeroPreserved') 'Minimum zero emits neither a setting nor a precedence-only payload' } + else { + Assert ($both.ExitCode -eq 0 -and $row.CandidateValue -eq 3) 'A nonzero promoted minimum produces a static both-outcomes setting' + foreach ($current in 0..3) { Assert (($row.CandidateValue -band $current) -eq $current -and ($row.CandidateValue -band $mask) -eq $mask) 'Promoted both preserves every possible existing native mask bit and satisfies the minimum' } + Assert ($row.ExpandedBeyondMinimum -eq ($mask -in @(1,2))) 'Only promotion of one-bit minima is marked as a source expansion' + } + if ($mask -in @(1,2)) { Assert ($reject.ExitCode -eq 1 -and ($reject.Blockers -join '') -match 'cannot preserve unknown') 'Default mode refuses a false static minimum/merge claim' } + } + $path=New-FixtureProfile ([pscustomobject]@{Logon=[pscustomobject]@{mode='exact';mask=3};Logoff=[pscustomobject]@{mode='optional';mask=1};'Process Creation'=[pscustomobject]@{mode='not-configured'}}) + $plan=Get-WelaIntuneAuditExportPlan fixture 26100 Enterprise -ProfilePath $path + Assert ($plan.Rows.Count -eq 59 -and @($plan.Rows|Where-Object Disposition -eq 'NotApplicable').Count -eq 10 -and $plan.CandidateSettings.Count -eq 2) 'All catalog rows survive while server-only and omitted rows never become payload settings' + Assert (@($plan.Rows|Where-Object Disposition -eq 'NotConfiguredPreserved').Count -eq 1 -and @($plan.Rows|Where-Object Disposition -eq 'OptionalNotSelected').Count -eq 1) 'NotConfigured and unselected optional states remain distinct preservation reasons' + $selected=Get-WelaIntuneAuditExportPlan fixture 26100 Enterprise -ProfilePath $path -IncludeOptional + Assert ($selected.CandidateSettings.Count -eq 3 -and @($selected.Rows|Where-Object Disposition -eq 'SelectedOptionalExact').Count -eq 1) 'Optional selection is explicit and exact' + foreach ($profile in @('wela-2.2.0','microsoft-sct-win11-24h2','cis-win11-v4-l1','cis-win11-v4-l2','asd-native-2021-10')) { + $plan=Get-WelaIntuneAuditExportPlan $profile 26100 Enterprise + $shared=Get-WelaAuditProfilePlan $profile Client 26100 + foreach ($setting in @($plan.CandidateSettings|Select-Object -Skip 1)) { + $row=@($plan.Rows|Where-Object OmaUri -eq $setting.OmaUri)[0];$original=@($shared.policies|Where-Object guid -eq $row.Guid)[0] + Assert ($setting.Value -eq $original.requiredMask -and $original.mode -eq 'exact') "Shared profile masks are unchanged: $profile / $($row.Id)" + } + } + $output=Join-Path $temp 'bundle' + $result=Invoke-WelaIntuneAuditExport wela-2.2.0 26100 Enterprise $output + $manifest=Get-Content (Join-Path $output 'manifest.json') -Raw -Encoding UTF8|ConvertFrom-Json + $body=Get-Content (Join-Path $output 'graph-body.json') -Raw -Encoding UTF8|ConvertFrom-Json + $csv=@(Import-Csv (Join-Path $output 'oma-settings.csv')) + Assert ($manifest.PayloadEmitted -and -not $manifest.TenantContacted -and -not $manifest.Assigned -and $manifest.Rows.Count -eq 59 -and $manifest.SigmaCredit -eq 0) 'Public manifest reports artifact generation separately from deployment and rule evidence' + Assert ($body.'@odata.type' -ceq '#microsoft.graph.windows10CustomConfiguration' -and -not $body.PSObject.Properties['assignments'] -and -not $body.PSObject.Properties['id']) 'Offline Graph body has the exact resource type without assignments or a tenant object ID' + Assert ($body.omaSettings.Count -eq $csv.Count -and $body.omaSettings[0].value -eq 1 -and $body.omaSettings[0].omaUri -ceq $mapping.precedenceDefinition.omaUri) 'Prerequisite and settings agree between manual CSV and typed Graph artifacts' + foreach ($setting in $body.omaSettings) { + $c=@($csv|Where-Object 'OMA-URI' -ceq $setting.omaUri) + Assert ($c.Count -eq 1 -and $c[0].DataType -ceq 'Integer' -and [int]$c[0].Value -eq $setting.value -and $setting.value -is [ValueType] -and $setting.'@odata.type' -ceq '#microsoft.graph.omaSettingInteger') 'Every exported CSP is exactly typed and identical across artifact formats' + } + Assert (($body|ConvertTo-Json -Depth 8) -notmatch 'MDMWinsOverGP|Sysmon|EMET|') 'Payload contains no extra ownership, excluded provider or deletion controls' + $receipt=Get-Content (Join-Path $output 'SHA256SUMS.json') -Raw|ConvertFrom-Json + foreach ($file in $receipt.Files) { Assert ((Get-FileHash (Join-Path $output $file.Name)).Hash -ceq $file.Sha256) 'Receipt fingerprints every emitted artifact after readback' } + Assert ($receipt.BundleComplete -and $receipt.Files.Count -eq 4) 'Complete receipt is distinct from its four reviewed artifacts' + Reject {Invoke-WelaIntuneAuditExport wela-2.2.0 26100 Enterprise $output} 'already exists' + $blockedPath=Join-Path $temp 'blocked' + $blocked=Invoke-WelaIntuneAuditExport microsoft-wef-reviewed-2026-09 26100 Enterprise $blockedPath + Assert ($blocked.ExitCode -eq 1 -and -not $blocked.PayloadEmitted -and -not(Test-Path (Join-Path $blockedPath 'graph-body.json')) -and -not(Test-Path (Join-Path $blockedPath 'oma-settings.csv'))) 'Blocked minimum export emits only review evidence, never a partial deployment policy' + $promoted=Invoke-WelaIntuneAuditExport microsoft-wef-reviewed-2026-09 26100 Enterprise (Join-Path $temp 'promoted') -MinimumMode PromoteToBoth + Assert ($promoted.ExitCode -eq 0 -and @($promoted.Plan.Rows|Where-Object ExpandedBeyondMinimum).Count -gt 0) 'Explicit promotion creates a usable artifact with recorded expansions' + foreach ($bad in @('\\server\share','\\?\C:\temp','../parent','wild*card','HKLM:\new','C:relative')) { Reject {Get-WelaIntuneOutputDirectory $bad} 'local|exact' } + Reject {Get-WelaIntuneOutputDirectory (Join-Path $temp 'absent-parent/new')} 'parent directory' + $file=Join-Path $temp 'file';Set-Content $file 'do not overwrite';Reject {Get-WelaIntuneOutputDirectory $file} 'already exists' + $unchanged=(Get-FileHash (Join-Path $output 'manifest.json')).Hash + Reject {Write-WelaIntuneArtifact $output 'manifest.json' 'replacement'} 'already exists|exists' + Assert ((Get-FileHash (Join-Path $output 'manifest.json')).Hash -ceq $unchanged) 'CreateNew refuses overwrite even at the final file-open boundary' + $partialPath=Join-Path $temp 'partial' + $writer=${function:Write-WelaIntuneArtifact} + try { + function Write-WelaIntuneArtifact { + param($Directory,$Name,$Text) + if ($Name -eq 'oma-settings.csv') { throw 'fixture disk write failure' } + & $writer -Directory $Directory -Name $Name -Text $Text + } + Reject {Invoke-WelaIntuneAuditExport wela-2.2.0 26100 Enterprise $partialPath} 'fixture disk write failure' + Assert ((Test-Path $partialPath) -and -not(Test-Path (Join-Path $partialPath 'SHA256SUMS.json'))) 'Partial export retains evidence but cannot create a complete receipt' + } finally { Set-Item Function:\Write-WelaIntuneArtifact $writer } + Write-Host "PASS: $script:checks offline Intune export assertions. Windows and network adapters were forbidden." +} finally { Remove-Item -LiteralPath $temp -Recurse -Force } +$global:LASTEXITCODE=0 diff --git a/tests/fixtures/intune-audit-ddf-facts.json b/tests/fixtures/intune-audit-ddf-facts.json new file mode 100644 index 00000000..2c02edb2 --- /dev/null +++ b/tests/fixtures/intune-audit-ddf-facts.json @@ -0,0 +1,773 @@ +{ + "source": "DDFDrop012026/Audit_AreaDDF.xml", + "sha256": "5c467e7742e5ac64019a2031dfcb9cf33397d97567b4ca4ae6add48cc448ac74", + "facts": [ + { + "node": "AccountLogon_AuditCredentialValidation", + "gpName": "Audit Credential Validation", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogon_AuditKerberosAuthenticationService", + "gpName": "Audit Kerberos Authentication Service", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogon_AuditKerberosServiceTicketOperations", + "gpName": "Audit Kerberos Service Ticket Operations", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogon_AuditOtherAccountLogonEvents", + "gpName": "Audit Other Account Logon Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountManagement_AuditApplicationGroupManagement", + "gpName": "Audit Application Group Management", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountManagement_AuditComputerAccountManagement", + "gpName": "Audit Computer Account Management", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountManagement_AuditDistributionGroupManagement", + "gpName": "Audit Distributio Group Management", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountManagement_AuditOtherAccountManagementEvents", + "gpName": "Audit Other Account Management Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountManagement_AuditSecurityGroupManagement", + "gpName": "Audit Security Group Management", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountManagement_AuditUserAccountManagement", + "gpName": "Audit User Account Management", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DetailedTracking_AuditDPAPIActivity", + "gpName": "Audit DPAPI Activity", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DetailedTracking_AuditPNPActivity", + "gpName": "Audit PNP Activity", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DetailedTracking_AuditProcessCreation", + "gpName": "Audit Process Creation", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DetailedTracking_AuditProcessTermination", + "gpName": "Audit Process Termination", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DetailedTracking_AuditRPCEvents", + "gpName": "Audit RPC Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DetailedTracking_AuditTokenRightAdjusted", + "gpName": "Audit Token Right Adjusted", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DSAccess_AuditDetailedDirectoryServiceReplication", + "gpName": "Audit Detailed Directory Service Replication", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DSAccess_AuditDirectoryServiceAccess", + "gpName": "Audit Directory Service Access", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DSAccess_AuditDirectoryServiceChanges", + "gpName": "Audit Directory Service Changes", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "DSAccess_AuditDirectoryServiceReplication", + "gpName": "Audit Directory Service Replication", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditAccountLockout", + "gpName": "Audit Account Lockout", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditUserDeviceClaims", + "gpName": "Audit User Device Claims", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditGroupMembership", + "gpName": "Audit Group Membership", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditIPsecExtendedMode", + "gpName": "Audit IPsec Extended Mode", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditIPsecMainMode", + "gpName": "Audit IPsec Main Mode", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditIPsecQuickMode", + "gpName": "Audit IPsec Quick Mode", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditLogoff", + "gpName": "Audit Logoff", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditLogon", + "gpName": "Audit Logon", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditNetworkPolicyServer", + "gpName": "Audit Network Policy Server", + "default": 3, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditOtherLogonLogoffEvents", + "gpName": "Audit Other Logon Logoff Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "AccountLogonLogoff_AuditSpecialLogon", + "gpName": "Audit Special Logon", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditApplicationGenerated", + "gpName": "Audit Application Generated", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditCertificationServices", + "gpName": "Audit Certification Services", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditDetailedFileShare", + "gpName": "Audit Detailed File Share", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditFileShare", + "gpName": "Audit File Share", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditFileSystem", + "gpName": "Audit File System", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditFilteringPlatformConnection", + "gpName": "Audit Filtering Platform Connection", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditFilteringPlatformPacketDrop", + "gpName": "Audit Filtering Platform Packet Drop", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditHandleManipulation", + "gpName": "Audit Handle Manipulation", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditKernelObject", + "gpName": "Audit Kernel Object", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditOtherObjectAccessEvents", + "gpName": "Audit Other Object Access Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditRegistry", + "gpName": "Audit Registry", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditRemovableStorage", + "gpName": "Audit Removable Storage", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditSAM", + "gpName": "Audit SAM", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "ObjectAccess_AuditCentralAccessPolicyStaging", + "gpName": "Audit Central Access Policy Staging", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PolicyChange_AuditPolicyChange", + "gpName": "Audit Policy Change", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PolicyChange_AuditAuthenticationPolicyChange", + "gpName": "Audit Authentication Policy Change", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PolicyChange_AuditAuthorizationPolicyChange", + "gpName": "Audit Authorization Policy Change", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PolicyChange_AuditFilteringPlatformPolicyChange", + "gpName": "Audit Filtering Platform Policy Change", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PolicyChange_AuditMPSSVCRuleLevelPolicyChange", + "gpName": "Audit MPSSVC Rule Level Policy Change", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PolicyChange_AuditOtherPolicyChangeEvents", + "gpName": "Audit Other Policy Change Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PrivilegeUse_AuditNonSensitivePrivilegeUse", + "gpName": "Audit Non Sensitive Privilege Use", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PrivilegeUse_AuditOtherPrivilegeUseEvents", + "gpName": "Audit Other Privilege Use Events", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "PrivilegeUse_AuditSensitivePrivilegeUse", + "gpName": "Audit Sensitive Privilege Use", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "System_AuditIPsecDriver", + "gpName": "Audit IPsec Driver", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "System_AuditOtherSystemEvents", + "gpName": "Audit Other System Events", + "default": 3, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "System_AuditSecurityStateChange", + "gpName": "Audit Security State Change", + "default": 1, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "System_AuditSecuritySystemExtension", + "gpName": "Audit Security System Extension", + "default": 0, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + }, + { + "node": "System_AuditSystemIntegrity", + "gpName": "Audit System Integrity", + "default": 3, + "format": "int", + "values": [ + 0, + 1, + 2, + 3 + ], + "conflict": "LastWrite" + } + ] +} \ No newline at end of file diff --git a/website/docs/resources/changelog.ja.md b/website/docs/resources/changelog.ja.md index 3d21301b..c583801a 100644 --- a/website/docs/resources/changelog.ja.md +++ b/website/docs/resources/changelog.ja.md @@ -7,6 +7,7 @@ **改善:** +- 検証対象のWindows 11クライアント向けに、共通の標準監査プロファイルからオフラインで出力する`intune-export`を追加しました。Microsoft DDFに基づく59件の明示的な対応表、整数型のOMA-URI CSV/Graphデータ、監査サブカテゴリの優先設定、出典と省略理由の一覧を保存します。最小監査マスクは既定で拒否し、`PromoteToBoth`の明示指定時だけ成功・失敗の両方へ拡張します。新規ローカル出力には検証済みハッシュを付け、アップロード・割り当て・ポリシー削除・Windows設定変更は行いません。Intune配備・競合・復旧・イベントの確認は別途必要です。 (#414) (@Shirofune-Security) - `-ProfileFile`で管理者のJSON詳細監査プロファイルを一覧・計画・監査・設定に使用できるようにしました。標準GUID、役割、設定モード、出典ハッシュを厳密に検証し、組み込みプロファイルを保持します。厳密なJSON字句検証で重複キー検出の回避を防ぎ、レポートは新規ファイルに限ることで別名リンク経由でも入力と既存の証拠を保持します。共通の優先設定、復旧記録、変更直前のファイル確認と最終検証を使用し、イベント生成やSigma検知可能性は別途検証とします。 (#416) (@Shirofune-Security) - ネイティブ Security 4688 の無害な固定プローブを収集する明示的な `native-validation` を追加。型付き前提条件、イベントの厳密な照合、前後の状態、ハッシュ付き証拠を新規の非公開ディレクトリに記録します。不完全・上限到達・曖昧・ドリフトの結果は未検証のままです。監査ポリシー変更や Sigma 利用可能ルール数の加算は行いません。使い捨て Server 2022/2025 テストで実イベントとポリシー復元を確認し、Windows 11/DC/ADCS とバックエンドの検証は別途必要です。 (#413) (@Shirofune-Security) diff --git a/website/docs/resources/changelog.md b/website/docs/resources/changelog.md index 0221d282..c0bd52a0 100644 --- a/website/docs/resources/changelog.md +++ b/website/docs/resources/changelog.md @@ -7,6 +7,7 @@ **Improvements:** +- Added offline `intune-export` for shared native audit profiles on reviewed Windows 11 client targets, with 59 explicit Microsoft DDF mappings, typed OMA-URI CSV/Graph artifacts, the audit precedence prerequisite and complete source/omission manifests. Static minimum masks are rejected unless explicitly expanded with `PromoteToBoth`; fresh local bundles include verified fingerprints and never upload, assign, delete policies or change Windows. Intune deployment, conflicts, recovery and event evidence remain separate validation. (#414) (@Shirofune-Security) - Added `-ProfileFile` for strictly validated custom advanced audit profiles in listing, planning, auditing and configuration. Canonical GUIDs, roles, modes and source hashes remain explicit; built-in profiles are preserved. Strict JSON tokens prevent duplicate-key bypasses, and new report files preserve inputs and prior evidence even through file aliases. Shared precedence, recovery journals, pre-write file checks and final verification protect configuration, without claiming event or Sigma readiness. (#416) (@Shirofune-Security) - Added opt-in `native-validation` to collect a fixed benign Security 4688 probe with typed prerequisites, exact native event matching, before/after state and hashed components in a new private directory. Partial, capped, ambiguous and drifted results remain unverified; the collector changes no audit policy and grants no Sigma readiness credit. Disposable Server 2022/2025 tests exercise real events with verified policy restoration; Windows 11/DC/ADCS and backend acceptance remain separate. (#413) (@Shirofune-Security)