From 437d353c8f43f780e713760e1eb63289374e8c6e Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 5 Oct 2026 02:30:06 +0200 Subject: [PATCH] feat!: keep entries in Set-NTFSInheritance like the dedicated cmdlets -AccessInheritanceEnabled $false now copies the inherited access entries into the DACL, and -AuditInheritanceEnabled $true keeps the explicit audit entries, as Disable-NTFSAccessInheritance and Enable-NTFSAuditInheritance do without their switches (Decision 13). BREAKING CHANGE: to remove the entries, use Disable-NTFSAccessInheritance -RemoveInheritedAccessRules or Enable-NTFSAuditInheritance -RemoveExplicitAuditRules. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: AI Assistant --- .../0013-set-inheritance-keeps-entries.md | 34 ++++++++++++++++ .memory-bank/systemPatterns.md | 1 + CHANGELOG.md | 6 +++ Docs/Cmdlets/Set-NTFSInheritance.md | 10 ++--- Docs/Concepts.md | 10 +++-- .../InheritanceCmdlets/SetInheritance.cs | 8 ++-- NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml | 18 ++++----- Tests/Inheritance.Tests.ps1 | 39 +++++++++++++++++++ 8 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 .memory-bank/decisions/0013-set-inheritance-keeps-entries.md diff --git a/.memory-bank/decisions/0013-set-inheritance-keeps-entries.md b/.memory-bank/decisions/0013-set-inheritance-keeps-entries.md new file mode 100644 index 0000000..12c768b --- /dev/null +++ b/.memory-bank/decisions/0013-set-inheritance-keeps-entries.md @@ -0,0 +1,34 @@ +--- +status: accepted +date: 2026-10-05 +last-verified: 2026-10-05 +owner: shared +source: maintainer decision D3 for the overnight run of 2026-10-04 (defect group E) +--- + +# Decision 13: Set-NTFSInheritance keeps entries like the dedicated cmdlets + +- Choice: `Set-NTFSInheritance` uses the defaults of the dedicated cmdlets. + `-AccessInheritanceEnabled $false` copies the inherited access entries + into the DACL, like `Disable-NTFSAccessInheritance`, and + `-AuditInheritanceEnabled $true` keeps the explicit audit entries, like + `Enable-NTFSAuditInheritance`. The other two directions already matched. + The same applies to a security descriptor in memory, whose kept entries + stay marked as inherited until it is written. +- Way back: `Disable-NTFSAccessInheritance -RemoveInheritedAccessRules` + removes the inherited access entries, and + `Enable-NTFSAuditInheritance -RemoveExplicitAuditRules` removes the + explicit audit entries. `Set-NTFSInheritance` gets no switches for that. +- Rationale: Before 5.0.0, two of the four directions removed entries, + unlike the dedicated cmdlets. Turning access inheritance off on an item + without explicit entries left an empty DACL, which denies access to + everyone. 5.0.0 is a major version, so the change ships there, listed + under `Changed` in the changelog. +- Related: `Clear-NTFSAccess -DisableInheritance` keeps discarding the + inherited entries, because removing every entry is the purpose of that + cmdlet; its page states the empty DACL and its risk (decision D2 of the + same run). The audit switches were renamed to `-RemoveInheritedAuditRules` + and `-RemoveExplicitAuditRules`, with the old names as aliases (D4). +- Rejected: adding `-RemoveInheritedAccessRules` and + `-RemoveExplicitAuditRules` switches to `Set-NTFSInheritance`, which would + duplicate the dedicated cmdlets. diff --git a/.memory-bank/systemPatterns.md b/.memory-bank/systemPatterns.md index 35d657d..83394d7 100644 --- a/.memory-bank/systemPatterns.md +++ b/.memory-bank/systemPatterns.md @@ -58,6 +58,7 @@ Each Decision record is a file in `decisions/`; read only the relevant ones. | 10 | [One version for the manifest, assemblies, and changelog](decisions/0010-one-version.md) | | 11 | [CI and the wiki run on GitHub Actions](decisions/0011-github-actions.md) | | 12 | [Releases are built and published by CI on a version tag](decisions/0012-ci-releases.md) | +| 13 | [Set-NTFSInheritance keeps entries like the dedicated cmdlets](decisions/0013-set-inheritance-keeps-entries.md) | ## Patterns diff --git a/CHANGELOG.md b/CHANGELOG.md index a9ecb9a..ba8dd57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,12 @@ The format is based on `-RemoveInheritedAuditRules` and `-RemoveExplicitAccessRules` of `Enable-NTFSAuditInheritance` to `-RemoveExplicitAuditRules`, because they act on audit entries; the old names still work as aliases +- `Set-NTFSInheritance` keeps entries like the dedicated cmdlets: + `-AccessInheritanceEnabled $false` now copies the inherited access entries + into the DACL instead of removing them, and + `-AuditInheritanceEnabled $true` now keeps the explicit audit entries. To + remove them, use `Disable-NTFSAccessInheritance -RemoveInheritedAccessRules` + or `Enable-NTFSAuditInheritance -RemoveExplicitAuditRules` ### Deprecated diff --git a/Docs/Cmdlets/Set-NTFSInheritance.md b/Docs/Cmdlets/Set-NTFSInheritance.md index be5a2d4..855d9c2 100644 --- a/Docs/Cmdlets/Set-NTFSInheritance.md +++ b/Docs/Cmdlets/Set-NTFSInheritance.md @@ -29,7 +29,7 @@ Set-NTFSInheritance [-SecurityDescriptor] [-AccessInheri The `Set-NTFSInheritance` cmdlet turns the inheritance of access rules and audit rules on or off in a single call. It reads the current state of the item first and changes a section only when the requested value differs from the current one, which makes the cmdlet suitable for repeatedly applying a desired state to a folder tree. -The cmdlet performs the same operations as `Enable-NTFSAccessInheritance`, `Disable-NTFSAccessInheritance`, `Enable-NTFSAuditInheritance`, and `Disable-NTFSAuditInheritance`, but it does not expose their switches and it does not use their defaults. `-AccessInheritanceEnabled $false` discards the inherited access rules instead of copying them into the item's own DACL, `-AccessInheritanceEnabled $true` keeps the explicit access rules, `-AuditInheritanceEnabled $false` copies the inherited audit rules into the item's own SACL, and `-AuditInheritanceEnabled $true` removes the explicit audit rules. Use the individual Enable and Disable cmdlets when you need the opposite behavior. +The cmdlet performs the same operations as `Enable-NTFSAccessInheritance`, `Disable-NTFSAccessInheritance`, `Enable-NTFSAuditInheritance`, and `Disable-NTFSAuditInheritance`, but it does not expose their switches; it uses their defaults instead. `-AccessInheritanceEnabled $false` copies the inherited access rules into the item's own DACL, `-AccessInheritanceEnabled $true` keeps the explicit access rules, `-AuditInheritanceEnabled $false` copies the inherited audit rules into the item's own SACL, and `-AuditInheritanceEnabled $true` keeps the explicit audit rules. To remove the rules instead, use `Disable-NTFSAccessInheritance -RemoveInheritedAccessRules` or `Enable-NTFSAuditInheritance -RemoveExplicitAuditRules`. Before 5.0.0, `-AccessInheritanceEnabled $false` discarded the inherited access rules, and `-AuditInheritanceEnabled $true` removed the explicit audit rules. Omit `-AccessInheritanceEnabled` or `-AuditInheritanceEnabled` to leave that section unchanged. Changing the audit section requires the Security privilege and therefore an elevated session. @@ -43,7 +43,7 @@ In the `Path` parameter set the cmdlet writes each changed section back to disk PS C:\> Set-NTFSInheritance -Path C:\Data\Projects -AccessInheritanceEnabled $false -AuditInheritanceEnabled $false ``` -This command protects the DACL and the SACL of `C:\Data\Projects`. The inherited access rules are discarded, so make sure the folder has explicit access rules of its own; the inherited audit rules are copied into the folder's SACL. Changing the audit section requires an elevated session. +This command protects the DACL and the SACL of `C:\Data\Projects`. The inherited access and audit rules are copied into the folder's DACL and SACL, so the effective permissions and the auditing stay the same. Changing the audit section requires an elevated session. ### Example 2: Restore inheritance of both sections @@ -51,7 +51,7 @@ This command protects the DACL and the SACL of `C:\Data\Projects`. The inherited PS C:\> Set-NTFSInheritance -Path C:\Data\Projects -AccessInheritanceEnabled $true -AuditInheritanceEnabled $true -PassThru ``` -This command lets the folder inherit from `C:\Data` again. The explicit access rules are kept, the explicit audit rules are removed, and `-PassThru` returns the resulting state. +This command lets the folder inherit from `C:\Data` again. The explicit access and audit rules are kept, and `-PassThru` returns the resulting state. ### Example 3: Save a state and apply it again @@ -77,7 +77,7 @@ The first two commands read the security descriptor and change its inheritance i ### -AccessInheritanceEnabled -Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and discards the rules the item currently inherits, which leaves only its explicit rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. +Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and copies the rules the item currently inherits into it, so the effective permissions stay the same. Before 5.0.0, `$false` discarded the inherited rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. ```yaml Type: Boolean @@ -93,7 +93,7 @@ Accept wildcard characters: False ### -AuditInheritanceEnabled -Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and removes the audit rules that are stored directly on the item; `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. +Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and keeps the audit rules that are stored directly on the item (before 5.0.0, it removed them); `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. ```yaml Type: Boolean diff --git a/Docs/Concepts.md b/Docs/Concepts.md index 18f347c..1852861 100644 --- a/Docs/Concepts.md +++ b/Docs/Concepts.md @@ -126,11 +126,13 @@ entries: - `Enable-NTFSAccessInheritance` restores inheritance and keeps the explicit entries unless you use `-RemoveExplicitAccessRules`. - `Get-NTFSInheritance` and `Set-NTFSInheritance` read and set both - settings at once. Unlike the dedicated cmdlets, `Set-NTFSInheritance` - removes the inherited access entries when it turns access inheritance off, - and removes the explicit audit entries when it turns audit inheritance on. + settings at once. Like the dedicated cmdlets without their switches, + `Set-NTFSInheritance` keeps the entries; before 5.0.0, it removed the + inherited access entries when it turned access inheritance off, and the + explicit audit entries when it turned audit inheritance on. The audit equivalents of the dedicated cmdlets are - `Disable-NTFSAuditInheritance` and `Enable-NTFSAuditInheritance`. + `Disable-NTFSAuditInheritance` and `Enable-NTFSAuditInheritance`, with + the switches `-RemoveInheritedAuditRules` and `-RemoveExplicitAuditRules`. ### The AppliesTo parameter diff --git a/NTFSSecurity/InheritanceCmdlets/SetInheritance.cs b/NTFSSecurity/InheritanceCmdlets/SetInheritance.cs index ec3333b..ecc4459 100644 --- a/NTFSSecurity/InheritanceCmdlets/SetInheritance.cs +++ b/NTFSSecurity/InheritanceCmdlets/SetInheritance.cs @@ -142,7 +142,7 @@ namespace NTFSSecurity else { WriteVerbose("Calling DisableAccessInheritance"); - FileSystemInheritanceInfo.DisableAccessInheritance(item, true); + FileSystemInheritanceInfo.DisableAccessInheritance(item, false); } } @@ -151,7 +151,7 @@ namespace NTFSSecurity if (auditInheritanceEnabled.Value) { WriteVerbose("Calling EnableAuditInheritance"); - FileSystemInheritanceInfo.EnableAuditInheritance(item, true); + FileSystemInheritanceInfo.EnableAuditInheritance(item, false); } else { @@ -175,7 +175,7 @@ namespace NTFSSecurity else { WriteVerbose("Calling DisableAccessInheritance"); - FileSystemInheritanceInfo.DisableAccessInheritance(sd, true); + FileSystemInheritanceInfo.DisableAccessInheritance(sd, false); } } @@ -184,7 +184,7 @@ namespace NTFSSecurity if (auditInheritanceEnabled.Value) { WriteVerbose("Calling EnableAuditInheritance"); - FileSystemInheritanceInfo.EnableAuditInheritance(sd, true); + FileSystemInheritanceInfo.EnableAuditInheritance(sd, false); } else { diff --git a/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml b/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml index 185672a..cea22cd 100644 --- a/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml +++ b/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml @@ -9334,7 +9334,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd The `Set-NTFSInheritance` cmdlet turns the inheritance of access rules and audit rules on or off in a single call. It reads the current state of the item first and changes a section only when the requested value differs from the current one, which makes the cmdlet suitable for repeatedly applying a desired state to a folder tree. - The cmdlet performs the same operations as `Enable-NTFSAccessInheritance`, `Disable-NTFSAccessInheritance`, `Enable-NTFSAuditInheritance`, and `Disable-NTFSAuditInheritance`, but it does not expose their switches and it does not use their defaults. `-AccessInheritanceEnabled $false` discards the inherited access rules instead of copying them into the item's own DACL, `-AccessInheritanceEnabled $true` keeps the explicit access rules, `-AuditInheritanceEnabled $false` copies the inherited audit rules into the item's own SACL, and `-AuditInheritanceEnabled $true` removes the explicit audit rules. Use the individual Enable and Disable cmdlets when you need the opposite behavior. + The cmdlet performs the same operations as `Enable-NTFSAccessInheritance`, `Disable-NTFSAccessInheritance`, `Enable-NTFSAuditInheritance`, and `Disable-NTFSAuditInheritance`, but it does not expose their switches; it uses their defaults instead. `-AccessInheritanceEnabled $false` copies the inherited access rules into the item's own DACL, `-AccessInheritanceEnabled $true` keeps the explicit access rules, `-AuditInheritanceEnabled $false` copies the inherited audit rules into the item's own SACL, and `-AuditInheritanceEnabled $true` keeps the explicit audit rules. To remove the rules instead, use `Disable-NTFSAccessInheritance -RemoveInheritedAccessRules` or `Enable-NTFSAuditInheritance -RemoveExplicitAuditRules`. Before 5.0.0, `-AccessInheritanceEnabled $false` discarded the inherited access rules, and `-AuditInheritanceEnabled $true` removed the explicit audit rules. Omit `-AccessInheritanceEnabled` or `-AuditInheritanceEnabled` to leave that section unchanged. Changing the audit section requires the Security privilege and therefore an elevated session. In the `Path` parameter set the cmdlet writes each changed section back to disk immediately. In the `SecurityDescriptor` parameter set it changes the `Security2.FileSystemSecurity2` object in memory only; nothing reaches the file system until you pass that object to `Set-NTFSSecurityDescriptor`. `-Path`, `-AccessInheritanceEnabled`, and `-AuditInheritanceEnabled` all accept pipeline input by property name, so a `Security2.FileSystemInheritanceInfo` object from `Get-NTFSInheritance` binds to all three at once. @@ -9356,7 +9356,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd AccessInheritanceEnabled - Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and discards the rules the item currently inherits, which leaves only its explicit rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. + Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and copies the rules the item currently inherits into it, so the effective permissions stay the same. Before 5.0.0, `$false` discarded the inherited rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. Boolean @@ -9368,7 +9368,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd AuditInheritanceEnabled - Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and removes the audit rules that are stored directly on the item; `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. + Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and keeps the audit rules that are stored directly on the item (before 5.0.0, it removed them); `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. Boolean @@ -9408,7 +9408,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd AccessInheritanceEnabled - Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and discards the rules the item currently inherits, which leaves only its explicit rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. + Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and copies the rules the item currently inherits into it, so the effective permissions stay the same. Before 5.0.0, `$false` discarded the inherited rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. Boolean @@ -9420,7 +9420,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd AuditInheritanceEnabled - Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and removes the audit rules that are stored directly on the item; `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. + Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and keeps the audit rules that are stored directly on the item (before 5.0.0, it removed them); `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. Boolean @@ -9446,7 +9446,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd AccessInheritanceEnabled - Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and discards the rules the item currently inherits, which leaves only its explicit rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. + Specifies whether the item inherits access rules from its parent folder. `$true` removes the protection from the DACL and keeps the access rules that are stored directly on the item; `$false` protects the DACL and copies the rules the item currently inherits into it, so the effective permissions stay the same. Before 5.0.0, `$false` discarded the inherited rules. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the access section is left unchanged. Boolean @@ -9458,7 +9458,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd AuditInheritanceEnabled - Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and removes the audit rules that are stored directly on the item; `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. + Specifies whether the item inherits audit rules from its parent folder. `$true` removes the protection from the SACL and keeps the audit rules that are stored directly on the item (before 5.0.0, it removed them); `$false` protects the SACL and copies the inherited audit rules into it. The section is left untouched when the requested value already matches the current state. When you omit the parameter, the audit section is left unchanged. Reading and writing the audit section requires the Security privilege and therefore an elevated session. Boolean @@ -9558,14 +9558,14 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd -------- Example 1: Block inheritance of both sections -------- PS C:\> Set-NTFSInheritance -Path C:\Data\Projects -AccessInheritanceEnabled $false -AuditInheritanceEnabled $false - This command protects the DACL and the SACL of `C:\Data\Projects`. The inherited access rules are discarded, so make sure the folder has explicit access rules of its own; the inherited audit rules are copied into the folder's SACL. Changing the audit section requires an elevated session. + This command protects the DACL and the SACL of `C:\Data\Projects`. The inherited access and audit rules are copied into the folder's DACL and SACL, so the effective permissions and the auditing stay the same. Changing the audit section requires an elevated session. ------- Example 2: Restore inheritance of both sections ------- PS C:\> Set-NTFSInheritance -Path C:\Data\Projects -AccessInheritanceEnabled $true -AuditInheritanceEnabled $true -PassThru - This command lets the folder inherit from `C:\Data` again. The explicit access rules are kept, the explicit audit rules are removed, and `-PassThru` returns the resulting state. + This command lets the folder inherit from `C:\Data` again. The explicit access and audit rules are kept, and `-PassThru` returns the resulting state. diff --git a/Tests/Inheritance.Tests.ps1 b/Tests/Inheritance.Tests.ps1 index b3a1976..b0fbc7b 100644 --- a/Tests/Inheritance.Tests.ps1 +++ b/Tests/Inheritance.Tests.ps1 @@ -108,6 +108,45 @@ Describe 'Inheritance cmdlets with -PassThru' { } Describe 'Set-NTFSInheritance' { + Context 'When it changes the inheritance' { + # Before 5.0.0, -AccessInheritanceEnabled $false removed the inherited access entries and + # -AuditInheritanceEnabled $true removed the explicit audit entries, unlike the dedicated cmdlets. + It 'Should keep the inherited access entries as explicit ones when it disables access inheritance' { + $file = New-TestSandboxItem -Sandbox $sandbox -Name 'KeepAccess' + Assert-TestSandboxPath -Sandbox $sandbox -Path $file + $inheritedCount = @((Get-Acl -LiteralPath $file).Access | Where-Object -Property IsInherited).Count + + Set-NTFSInheritance -Path $file -AccessInheritanceEnabled $false + + $acl = Get-Acl -LiteralPath $file + $acl.AreAccessRulesProtected | Should -BeTrue + @($acl.Access | Where-Object -Property IsInherited -EQ -Value $false) | Should -HaveCount $inheritedCount + } + + # In memory, the kept entries stay marked as inherited; Windows stores them as explicit ones on write. + It 'Should keep the inherited access entries of a security descriptor' { + $file = New-TestSandboxItem -Sandbox $sandbox -Name 'KeepDescriptor' + $sd = Get-NTFSSecurityDescriptor -Path $file + $sidType = [System.Security.Principal.SecurityIdentifier] + $inheritedCount = @($sd.SecurityDescriptor.GetAccessRules($false, $true, $sidType)).Count + + Set-NTFSInheritance -SecurityDescriptor $sd -AccessInheritanceEnabled $false + + $sd.SecurityDescriptor.AreAccessRulesProtected | Should -BeTrue + @($sd.SecurityDescriptor.GetAccessRules($true, $true, $sidType)) | Should -HaveCount $inheritedCount + } + + It 'Should keep the explicit audit entries when it enables audit inheritance' -Skip:(-not $canChangeAudit) { + $file = New-TestSandboxItem -Sandbox $sandbox -Name 'KeepAudit' + Assert-TestSandboxPath -Sandbox $sandbox -Path $file + Add-NTFSAudit -Path $file -Account 'Everyone' -AccessRights Delete -AuditFlags Failure + Disable-NTFSAuditInheritance -Path $file + + Set-NTFSInheritance -Path $file -AuditInheritanceEnabled $true + + @(Get-NTFSAudit -Path $file -ExcludeInherited) | Should -HaveCount 1 + } + } Context 'When -AccessInheritanceEnabled or -AuditInheritanceEnabled is omitted' { BeforeEach { $file = New-TestSandboxItem -Sandbox $sandbox -Name 'File'