Repository navigation
(GH-1755) Add two new DSC resources to manage AuditPolicy - #1758
Gijs Reijn (Gijsreyn) wants to merge 4 commits into
Conversation
b915f29 to
b1532c9
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Argument validation can allow unintended live policy changes, and preview error handling, registry type preservation, and test assumptions need correction.
8 open findings
Reject unknown arguments before dispatching set operations · New Propagate policy query errors in what-if mode · New Preserve REG_QWORD type when updating audit policy options · New Use UI culture for auditpol language detection · New Establish disabled state before idempotency assertion · New Preserve existing type when testing FullPrivilegeAuditing · New Use UI culture when asserting localized auditpol output · New Make tests independent of preceding test state · New
What changed in this PR
Adds native Windows audit-policy resources, addressing the AuditPolicyDsc portion of #1755 without requiring the PowerShell adapter.
Changes:
- Implements subcategory auditing and registry-backed audit options with get, set, export, and what-if support.
- Integrates the resources into Windows builds and packaging.
- Adds tests, reference documentation, and configuration examples.
| File | Description |
|---|---|
| resources/windows_audit_policy/windows_audit_policy.dsc.manifests.json | Defines both resource contracts. |
| resources/windows_audit_policy/tests/windows_audit_policy_whatif.tests.ps1 | Tests previews and non-mutation. |
| resources/windows_audit_policy/tests/windows_audit_policy_set.tests.ps1 | Tests subcategory changes. |
| resources/windows_audit_policy/tests/windows_audit_policy_option.tests.ps1 | Tests registry-backed options. |
| resources/windows_audit_policy/tests/windows_audit_policy_get.tests.ps1 | Tests lookup and validation. |
| resources/windows_audit_policy/tests/windows_audit_policy_export.tests.ps1 | Tests exported policy state. |
| resources/windows_audit_policy/src/types.rs | Defines state, flags, and errors. |
| resources/windows_audit_policy/src/subcategories.rs | Maps English names and GUIDs. |
| resources/windows_audit_policy/src/options.rs | Reads and writes audit options. |
| resources/windows_audit_policy/src/main.rs | Dispatches resource operations. |
| resources/windows_audit_policy/src/audit.rs | Implements native audit API operations. |
| resources/windows_audit_policy/locales/en-us.toml | Supplies localized messages. |
| resources/windows_audit_policy/Cargo.toml | Defines crate dependencies. |
| resources/windows_audit_policy/build.rs | Tracks translation changes. |
| resources/windows_audit_policy/.project.data.json | Registers the Windows build project. |
| docs/reference/resources/overview.md | Lists both resources. |
| docs/reference/resources/Microsoft/Windows/AuditPolicyOption/index.md | Documents audit options. |
| docs/reference/resources/Microsoft/Windows/AuditPolicyOption/examples/configure-audit-policy-option.md | Demonstrates option configuration. |
| docs/reference/resources/Microsoft/Windows/AuditPolicyOption/examples/auditpolicyoption.config.dsc.yaml | Provides an option configuration. |
| docs/reference/resources/Microsoft/Windows/AuditPolicy/index.md | Documents subcategory auditing. |
| docs/reference/resources/Microsoft/Windows/AuditPolicy/examples/get-audit-policy.md | Demonstrates retrieval and export. |
| docs/reference/resources/Microsoft/Windows/AuditPolicy/examples/configure-audit-policy.md | Demonstrates configuration and previews. |
| docs/reference/resources/Microsoft/Windows/AuditPolicy/examples/auditpolicy.config.dsc.yaml | Provides a subcategory configuration. |
| data.build.json | Adds Windows package files. |
| CHANGELOG.md | Announces the resources. |
| Cargo.toml | Registers the crate and Windows features. |
| Cargo.lock | Records crate dependencies. |
| .github/skills/code-review/windows.instructions.md | Extends Windows review scope. |
| .github/skills/code-review/security.instructions.md | Extends security review scope. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…into PowerShellgh-1755/main/add-auditpolicy-dsc-resource
There was a problem hiding this comment.
🔵 Needs a closer look
Privileged audit-policy changes require Windows runtime validation and human security review before approval.
1 open issue
8 resolved since last review
Reject unknown arguments before dispatching set operations Make tests independent of preceding test state Use UI culture when asserting localized auditpol output Preserve existing type when testing FullPrivilegeAuditing Establish disabled state before idempotency assertion Use UI culture for auditpol language detection Preserve REG_QWORD type when updating audit policy options Propagate policy query errors in what-if mode
Review effort: Balanced
|
Jason Helmick (@theJasonHelmick) Michael Greene (@mgreenegit) can you help review from a schema/user experience perspective? |
|
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. |
Jason Helmick (theJasonHelmick)
left a comment
There was a problem hiding this comment.
LGTM!
Mikey Lombardi (He/Him) (michaeltlombardi)
left a comment
There was a problem hiding this comment.
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 either guid 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.
| [01]: ../../../../../../cli/resource/get.md | ||
| [02]: ../../../../../../cli/resource/test.md | ||
| [03]: ../../../../../../cli/resource/export.md |
| /// English subcategory name from the static table, falling back to the LSA's localized name. | ||
| fn subcategory_display_name(guid: &GUID) -> Result<String, AuditError> { | ||
| match subcategories::find_by_guid(guid.to_u128()) { | ||
| Some(entry) => Ok(entry.name.to_string()), | ||
| None => lookup_subcategory_name(guid), |
| let all = enumerate_subcategories(None)?; | ||
| for guid in all.as_slice() { | ||
| let name = lookup_subcategory_name(guid)?; | ||
| if name.eq_ignore_ascii_case(wanted) { |


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.