You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
(GH-1755) Add two new DSC resources to manage AuditPolicy - #1758
Adds the Microsoft.Windows/AuditPolicy resource, which manages success and failure auditing for one advanced audit policy subcategory per instance. The subcategory key accepts the English name (case-insensitive) or the GUID, and the optional success and failure booleans leave an omitted flag unchanged. get, set, export, and --what-if are supported.
Adds the Microsoft.Windows/AuditPolicyOption resource, which manages the CrashOnAuditFail, FullPrivilegeAuditing, AuditBaseObjects, and AuditBaseDirectories options as a name key with an enabled boolean, with the same operations.
Adds the windows_audit_policy crate that implements both resources from one binary and one windows_audit_policy.dsc.manifests.json file, following the environment_variable layout.
Enables the Win32_Security_Authentication_Identity and Win32_System_Threading features of the workspace windows dependency.
Adds reference docs and examples for both resources, the overview and changelog entries, the package file entries, and Pester and Rust unit tests.
Addresses the AuditPolicyDsc half of Hardening with dsc 3 ? #1755. SecurityPolicyDsc isn't covered by this change.
PR Context
#1755 asks for built-in replacements for the AuditPolicyDsc and SecurityPolicyDsc community modules so Windows hardening doesn't depend on the PowerShell adapter. AuditPolicyDsc shells out to auditpol.exe and parses its CSV output, which is localized. Its AuditPolicyGUID resource exists only to work around that, through a backup and restore of the whole policy, and its static GUID table is missing the Access Rights subcategory that current Windows builds report. Every Set in the module also swallows errors.
The new resource uses the LSA audit APIs (AuditQuerySystemPolicy, AuditSetSystemPolicy, and the enumeration and lookup functions) instead of auditpol.exe. The APIs identify subcategories by GUID and only return display names in the system language, so the crate carries a static table of the 60 known subcategories and 9 categories with their English names. Input is matched against that table or parsed as a GUID, and output always uses the English names. A GUID that isn't in the table is still accepted when the LSA knows it, and a name that isn't in the table is compared against the localized names the LSA reports, so localized input and subcategories newer than the table keep working. The resource echoes subcategory as given on get and set, so the synthetic test compares like for like, and export returns the canonical English name.
Remarks on the design
AuditPolicyDsc keys an instance on the subcategory plus a single flag and uses Ensure to turn that flag on or off. One instance per subcategory with two optional booleans covers the same cases: one flag at a time, or the full setting, without two instances for one subcategory fighting each other. When neither flag is set, the resource sends POLICY_AUDIT_EVENT_NONE rather than 0, because 0 means "unchanged" to AuditSetSystemPolicy.
Reading the audit policy needs SeSecurityPrivilege, so the manifest requires an elevated context for get and export as well as set, and the binary returns exit code 4 when invoked directly without elevation. The privilege is enabled on the process token before the API calls, because an elevated token holds it but doesn't enable it by default.
The four options are the registry values under HKLM\SYSTEM\CurrentControlSet\Control\Lsa that secedit and Group Policy write, so the option resource reads and writes them through dsc-lib-registry instead of parsing auditpol /get /option output, which is localized too. The existing value type (REG_DWORD, or the one-byte REG_BINARY of FullPrivilegeAuditing) is preserved, any non-zero value reads as enabled (including the 2 that marks a system that already halted on CrashOnAuditFail), and a set emits a warning that the change takes effect after a restart.
The AuditPolicyCsv backup and restore resource and per-user audit policy aren't ported.
Lastly, the PR used most of the instructions to create it.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Argument validation can allow unintended live policy changes, and preview error handling, registry type preservation, and test assumptions need correction.
Schema/UX looks good to me. One reminder before merge: please make sure the --what-if argument-parsing issue Copilot flagged is fixed, since a preview run shouldn’t be able to write. I haven’t reviewed the code.
The reason will be displayed to describe this comment to others. Learn more.
Quick review of the schemas and for the most part, everything looks good to me. I do feel a little uncomfortable with subcategory accepting either <english name> or <guid> but always returning <english name> especially when we also have guid as a read-only property. It seems like users should specify eitherguid or subcategory but not both and always return subcategory as the name and guid as the GUID.
I don't have strong enough feelings to block the PR on this design aspect though.
An elevated administrator can still lack SeSecurityPrivilege when policy restricts the “Manage auditing and security log” user right. require_elevated() then succeeds, but this branch returns exit code 4 and tells the user to elevate again, which cannot resolve the failure. For an elevated token, return the existing audit.privilegeFailed diagnostic with the Windows error so the missing privilege is identified. Keep ElevationRequired for non-elevated callers, and capture the Windows error before checking the security context.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Summary
This change:
Microsoft.Windows/AuditPolicyresource, which manages success and failure auditing for one advanced audit policy subcategory per instance. Thesubcategorykey accepts the English name (case-insensitive) or the GUID, and the optionalsuccessandfailurebooleans leave an omitted flag unchanged.get,set,export, and--what-ifare supported.Microsoft.Windows/AuditPolicyOptionresource, which manages theCrashOnAuditFail,FullPrivilegeAuditing,AuditBaseObjects, andAuditBaseDirectoriesoptions as anamekey with anenabledboolean, with the same operations.windows_audit_policycrate that implements both resources from one binary and onewindows_audit_policy.dsc.manifests.jsonfile, following theenvironment_variablelayout.Win32_Security_Authentication_IdentityandWin32_System_Threadingfeatures of the workspacewindowsdependency.PR Context
#1755 asks for built-in replacements for the AuditPolicyDsc and SecurityPolicyDsc community modules so Windows hardening doesn't depend on the PowerShell adapter. AuditPolicyDsc shells out to
auditpol.exeand parses its CSV output, which is localized. ItsAuditPolicyGUIDresource exists only to work around that, through a backup and restore of the whole policy, and its static GUID table is missing theAccess Rightssubcategory that current Windows builds report. EverySetin the module also swallows errors.The new resource uses the LSA audit APIs (
AuditQuerySystemPolicy,AuditSetSystemPolicy, and the enumeration and lookup functions) instead ofauditpol.exe. The APIs identify subcategories by GUID and only return display names in the system language, so the crate carries a static table of the 60 known subcategories and 9 categories with their English names. Input is matched against that table or parsed as a GUID, and output always uses the English names. A GUID that isn't in the table is still accepted when the LSA knows it, and a name that isn't in the table is compared against the localized names the LSA reports, so localized input and subcategories newer than the table keep working. The resource echoessubcategoryas given ongetandset, so the synthetic test compares like for like, andexportreturns the canonical English name.Remarks on the design
Ensureto turn that flag on or off. One instance per subcategory with two optional booleans covers the same cases: one flag at a time, or the full setting, without two instances for one subcategory fighting each other. When neither flag is set, the resource sendsPOLICY_AUDIT_EVENT_NONErather than 0, because 0 means "unchanged" toAuditSetSystemPolicy.SeSecurityPrivilege, so the manifest requires an elevated context forgetandexportas well asset, and the binary returns exit code 4 when invoked directly without elevation. The privilege is enabled on the process token before the API calls, because an elevated token holds it but doesn't enable it by default.HKLM\SYSTEM\CurrentControlSet\Control\Lsathatseceditand Group Policy write, so the option resource reads and writes them throughdsc-lib-registryinstead of parsingauditpol /get /optionoutput, which is localized too. The existing value type (REG_DWORD, or the one-byteREG_BINARYofFullPrivilegeAuditing) is preserved, any non-zero value reads as enabled (including the2that marks a system that already halted onCrashOnAuditFail), and asetemits a warning that the change takes effect after a restart.AuditPolicyCsvbackup and restore resource and per-user audit policy aren't ported.Lastly, the PR used most of the instructions to create it.