Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

* Added support for AuditPolicy rules using "Advanced Audit Policy" language.

## [4.30.0] - 2026-06-19

* This is a bulk add and cleanup update.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#region Header
. $PSScriptRoot\.tests.header.ps1
#endregion

try
{
$checkContent = 'Ensure Audit Process Creation auditing has been enabled:

Computer Configuration >> Windows Settings >> Security Settings >> Advanced Audit Policy Configuration >> System Audit Policy >> Detailed Tracking >> Audit Process Creation.

If "Audit Process Creation" is not set to "Failure", this is a finding.'

Describe 'Advanced Audit Policy Conversion' {
[xml] $stigRule = Get-TestStigRule -CheckContent $checkContent -XccdfTitle Windows
$TestFile = Join-Path -Path $TestDrive -ChildPath 'TextData.xml'
$stigRule.Save( $TestFile )
$rule = ConvertFrom-StigXccdf -Path $TestFile

It 'Should return an AuditPolicyRuleAdvanced Object' {
$rule.GetType() | Should Be 'AuditPolicyRuleAdvanced'
}
It 'Should extract the correct SubCategory' {
$rule.SubCategory | Should Be 'Process Creation'
}
It 'Should extract the correct AuditFlag' {
$rule.AuditFlag | Should be 'Failure'
}
It 'Should set the correct ensure value' {
$rule.Ensure | Should be 'Present'
}
It 'Should set the correct DscResource' {
$rule.DscResource | Should Be 'AuditPolicySubcategory'
}
It 'Should set the Conversion statud to pass ensure value' {
$rule.conversionstatus | Should be 'pass'
}
}
}

finally
{
. $PSScriptRoot\.tests.footer.ps1
}
38 changes: 38 additions & 0 deletions Tests/Unit/Module/AuditPolicyRuleAdvanced.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#region Header
. $PSScriptRoot\.tests.header.ps1
#endregion

try
{
InModuleScope -ModuleName "$($global:moduleName).Convert" {
#region Test Setup
$testRuleList = @(
@{
Subcategory = 'Process Creation'
AuditFlag = 'Failure'
Ensure = 'Present'
OrganizationValueRequired = $false
OrganizationValueTestString = $null
CheckContent = 'Ensure Audit Process Creation auditing has been enabled:

Computer Configuration >> Windows Settings >> Security Settings >> Advanced Audit Policy Configuration >> System Audit Policy >> Detailed Tracking >> Audit Process Creation.

If "Audit Process Creation" is not set to "Failure", this is a finding.'
}
)
#endregion

foreach ($testRule in $testRuleList)
{
. $PSScriptRoot\Convert.CommonTests.ps1
}

#region Add Custom Tests Here

#endregion
}
}
finally
{
. $PSScriptRoot\.tests.footer.ps1
}
33 changes: 33 additions & 0 deletions source/Module/Rule.AuditPolicy/AuditPolicyRule.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,36 @@ class AuditPolicyRule : Rule
}
}
}

class AuditPolicyRuleAdvanced : AuditPolicyRule
{
<#
.SYNOPSIS
Default constructor to support the AsRule cast method
#>
AuditPolicyRuleAdvanced ()
{
}

<#
.SYNOPSIS
Used to load PowerSTIG data from the processed data directory
.PARAMETER Rule
The STIG rule to load
#>
AuditPolicyRuleAdvanced ([xml.xmlelement] $Rule) : base ($Rule)
{
}

<#
.SYNOPSIS
The Convert child class constructor
.PARAMETER Rule
The STIG rule to convert
.PARAMETER Convert
A simple bool flag to create a unique constructor signature
#>
AuditPolicyRuleAdvanced ([xml.xmlelement] $Rule, [switch] $Convert) : base ($Rule, $Convert)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
using module .\..\..\Common\Common.psm1
using module .\..\AuditPolicyRule.psm1
using namespace System.Text
# Header

<#
.SYNOPSIS
Converts the xccdf check-content element into an audit policy object.
#>
class AuditPolicyRuleAdvancedConvert : AuditPolicyRuleAdvanced
{
<#
.SYNOPSIS
Empty constructor for SplitFactory
#>
AuditPolicyRuleAdvancedConvert ()
{
}

<#
.SYNOPSIS
Converts an xccdf stig rule element into a Audit Policy Rule
.PARAMETER XccdfRule
The STIG rule to convert
#>
AuditPolicyRuleAdvancedConvert ([xml.xmlelement] $XccdfRule) : base ($XccdfRule, $true)
{
$tokens = $this.ExtractProperties()
$this.SetSubcategory($tokens)
$this.SetAuditFlag($tokens)
$this.Ensure = [Ensure]::Present
$this.SetDuplicateRule()
$this.SetDscResource()
}

<#
.SYNOPSIS
Extracts and returns the audit policy settings from the check-content.
.DESCRIPTION
This match looks for the policy path and the required audit flag in
the following format:

Computer Configuration >> ... >> Audit <Subcategory>.
If "Audit <Subcategory>" is not set to "<AuditFlag>", this is a finding

The subcategory is taken from the final line of the RawString (the
leading "Audit " prefix is dropped), and the audit flag is taken from
the quoted value in the "is [not] set to" clause.
.NOTES
If any rule does not match this pattern, please update the xccdf
change log file to align to this option.
#>
[RegularExpressions.MatchCollection] ExtractProperties ()
{
return [regex]::Matches(
$this.RawString,
'"(?:Audit\s+)?(?<subcategory>[^"]+)"\s+is(?: not)? set to\s+"(?<auditflag>[^"]+)"'
)
}

<#
.SYNOPSIS
Set the subcategory name
.DESCRIPTION
Set the subcategory value. If the returned audit policy subcategory
is not valid, the parser status is set to fail.
#>
[void] SetSubcategory ([RegularExpressions.MatchCollection] $Regex)
{
$thisSubcategory = $regex.Groups.Where(
{ $_.Name -eq 'subcategory' }
).Value

if (-not $this.SetStatus($thisSubcategory))
{
$this.set_Subcategory($thisSubcategory.trim())
}
}

<#
.SYNOPSIS
Set the subcategory flag
.DESCRIPTION
Set the subcategory flag. If the returned audit policy subcategory
is not valid, the parser status is set to fail.
#>
[void] SetAuditFlag ([RegularExpressions.MatchCollection] $Regex)
{
$thisAuditFlag = $Regex.Groups.Where(
{ $_.Name -eq 'auditflag' }
).Value

if (-not $this.SetStatus($thisAuditFlag))
{
$this.set_AuditFlag($thisAuditFlag)
}
}

hidden [void] SetDscResource ()
{
if ($null -eq $this.DuplicateOf)
{
$this.DscResource = 'AuditPolicySubcategory'
}
else
{
$this.DscResource = 'None'
}
}

<#
.SYNOPSIS
Checks if a rule matches an audit policy setting.
#>
static [bool] Match ([string] $CheckContent)
{
if
(
$CheckContent -Match ">> Advanced Audit Policy Configuration >>"
)
{
return $true
}
return $false
}
}
7 changes: 7 additions & 0 deletions source/Module/Rule/Convert/ConvertFactory.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ using module .\..\..\Common\Common.psm1
using module .\..\..\Rule.HardCoded\Convert\HardCodedRule.Convert.psm1
using module .\..\..\Rule.AccountPolicy\Convert\AccountPolicyRule.Convert.psm1
using module .\..\..\Rule.AuditPolicy\Convert\AuditPolicyRule.Convert.psm1
using module .\..\..\Rule.AuditPolicy\Convert\AuditPolicyRuleAdvanced.Convert.psm1
using module .\..\..\Rule.DnsServerRootHint\Convert\DnsServerRootHintRule.Convert.psm1
using module .\..\..\Rule.DnsServerSetting\Convert\DnsServerSettingRule.Convert.psm1
using module .\..\..\Rule.Document\Convert\DocumentRule.Convert.psm1
Expand Down Expand Up @@ -148,6 +149,12 @@ class ConvertFactory
[AuditPolicyRuleConvert]::new($Rule).AsRule()
)
}
{[AuditPolicyRuleAdvancedConvert]::Match($PSItem)}
{
$null = $ruleTypeList.Add(
[AuditPolicyRuleAdvancedConvert]::new($Rule).AsRule()
)
}
{[DnsServerSettingRuleConvert]::Match($PSItem)}
{
$null = $ruleTypeList.Add(
Expand Down
1 change: 1 addition & 0 deletions source/Module/Rule/Rule.LoadFactory.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class LoadFactory
{
'AccountPolicyRule' {$return = [AccountPolicyRule]::new($Rule)}
'AuditPolicyRule' {$return = [AuditPolicyRule]::new($Rule)}
'AuditPolicyRuleAdvanced' {$return = [AuditPolicyRuleAdvanced]::new($Rule)}
'DnsServerSettingRule' {$return = [DnsServerSettingRule]::new($Rule)}
'DnsServerRootHintRule' {$return = [DnsServerRootHintRule]::new($Rule)}
'DocumentRule' {$return = [DocumentRule]::new($Rule)}
Expand Down
1 change: 1 addition & 0 deletions source/Module/STIG/Convert/Data.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ data dscResourceModule
ConvertFrom-StringData -StringData @'
AccountPolicyRule = SecurityPolicyDsc
AuditPolicyRule = AuditPolicyDsc
AuditPolicyRuleAdvanced = AuditPolicyDsc
DnsServerSettingRule = xDnsServer
DnsServerRootHintRule = PSDscResources
DocumentRule = None
Expand Down
Loading