mirror of https://github.com/raandree/NTFSSecurity
Browse Source
Defect 4, both parts:
- Get-NTFSAudit kept the entries of the previous item and wrote them in a
finally block, so a path whose security descriptor failed to read
returned the previous item's entries again. Each item now starts empty,
and entries are written only after a successful read.
- Without the Security privilege, the cmdlet read the descriptor without
its SACL and returned nothing, like an item without audit entries. It
now reads the SACL alone, so a missing privilege is a ReadSecurityError
("A required privilege is not held by the client"). A descriptor from
Get-NTFSSecurityDescriptor that was read without the SACL gets the same
error; FileSystemSecurity2 now records which sections it read
(internal, visible to NTFSSecurity).
Tests/Audit.Tests.ps1 (new): 3 tests. The repeat test needs the Security
privilege to add an audit entry and runs in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
pull/100/head
7 changed files with 154 additions and 25 deletions
@ -0,0 +1,100 @@ |
|||
<# |
|||
Tests the audit cmdlets of the module built in NTFSSecurity\bin\Release on files in a sandbox folder. Reading |
|||
and changing audit entries needs the Security privilege; tests that need it skip without it and run in CI, |
|||
whose runners are elevated. |
|||
#> |
|||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute( |
|||
'PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Pester shares variables between blocks.' |
|||
)] |
|||
param () |
|||
|
|||
BeforeDiscovery { |
|||
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'TestHelpers.psm1') -Force |
|||
$canReadAudit = Test-PrivilegeHeld -Name 'SeSecurityPrivilege' |
|||
} |
|||
|
|||
BeforeAll { |
|||
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'TestHelpers.psm1') -Force |
|||
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\NTFSSecurity\bin\Release\NTFSSecurity.psd1' |
|||
Import-Module -Name $modulePath -Force -ErrorAction Stop |
|||
$sandbox = New-TestSandbox -Name 'Audit' |
|||
Push-Location -LiteralPath $sandbox |
|||
|
|||
function New-SandboxItem { |
|||
param ( |
|||
[string] $Name, |
|||
[switch] $Directory |
|||
) |
|||
|
|||
$path = Join-Path -Path $sandbox -ChildPath ('{0}-{1}' -f $Name, [guid]::NewGuid().ToString('N').Substring(0, 8)) |
|||
Assert-TestSandboxPath -Sandbox $sandbox -Path $path |
|||
if ($Directory) { |
|||
New-Item -ItemType Directory -Path $path | Out-Null |
|||
} |
|||
else { |
|||
Set-Content -LiteralPath $path -Value 'Audit test' |
|||
} |
|||
$path |
|||
} |
|||
|
|||
# Denies the owner, the current account, to read the security descriptor of the item. |
|||
function Deny-ReadPermission { |
|||
param ([string] $Path) |
|||
|
|||
Assert-TestSandboxPath -Sandbox $sandbox -Path $Path |
|||
$acl = Get-Acl -LiteralPath $Path |
|||
$ownerRights = New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList 'S-1-3-4' |
|||
$rule = New-Object -TypeName 'System.Security.AccessControl.FileSystemAccessRule' -ArgumentList ( |
|||
$ownerRights, [System.Security.AccessControl.FileSystemRights]::ReadPermissions, [System.Security.AccessControl.AccessControlType]::Deny |
|||
) |
|||
$acl.AddAccessRule($rule) |
|||
Set-Acl -LiteralPath $Path -AclObject $acl |
|||
} |
|||
} |
|||
|
|||
AfterAll { |
|||
Pop-Location |
|||
Remove-TestSandbox -Sandbox $sandbox |
|||
Remove-Module -Name NTFSSecurity -Force -ErrorAction SilentlyContinue |
|||
} |
|||
|
|||
Describe 'Get-NTFSAudit' { |
|||
Context 'When the audit entries cannot be read' { |
|||
It 'Should write an error without the Security privilege instead of returning nothing' -Skip:$canReadAudit { |
|||
$file = New-SandboxItem -Name 'NoPrivilege' |
|||
|
|||
$entries = @(Get-NTFSAudit -Path $file -ErrorVariable auditErrors -ErrorAction SilentlyContinue) |
|||
|
|||
$entries | Should -BeNullOrEmpty |
|||
$auditErrors | Should -HaveCount 1 |
|||
$auditErrors[0].FullyQualifiedErrorId | Should -BeLike 'ReadSecurityError,*' |
|||
} |
|||
|
|||
It 'Should write an error for a security descriptor that was read without the audit entries' { |
|||
$file = New-SandboxItem -Name 'AccessOnly' |
|||
$sd = New-Object -TypeName 'Security2.FileSystemSecurity2' -ArgumentList ( |
|||
(Get-Item2 -Path $file), [System.Security.AccessControl.AccessControlSections]::Access |
|||
) |
|||
|
|||
$entries = @(Get-NTFSAudit -SecurityDescriptor $sd -ErrorVariable auditErrors -ErrorAction SilentlyContinue) |
|||
|
|||
$entries | Should -BeNullOrEmpty |
|||
$auditErrors | Should -HaveCount 1 |
|||
$auditErrors[0].FullyQualifiedErrorId | Should -BeLike 'ReadSecurityError,*' |
|||
} |
|||
} |
|||
|
|||
Context 'When a path fails after a path with audit entries' { |
|||
# Before 5.0.0, the cmdlet wrote the entries of the previous item again for the failing path. |
|||
It 'Should return the entries of the first item once' -Skip:(-not $canReadAudit) { |
|||
$folder = New-SandboxItem -Name 'Audited' -Directory |
|||
$denied = New-SandboxItem -Name 'Denied' |
|||
Add-NTFSAudit -Path $folder -Account 'Everyone' -AccessRights Delete -AuditFlags Success |
|||
Deny-ReadPermission -Path $denied |
|||
|
|||
$entries = @(Get-NTFSAudit -Path $folder, $denied -ExcludeInherited -ErrorAction SilentlyContinue) |
|||
|
|||
@($entries | Where-Object -Property FullName -EQ -Value $folder) | Should -HaveCount 1 |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue