Hello!
I have a requirement to recursively search N levels of directories and log where the folder NTFS Inheritance permission is disabled. E.g.
C:\ACLTest
C:\ACLTest\myFolder1-InheritOn
C:\ACLTest\myFolder2-InheritOff <- - NTFS Inheritance is disabled; log this directory in my output
C:\ACLTest\myFolder3-InheritOn\mySubFolderA-InheritOFF <- - NTFS Inheritance is disabled; log this directory in my output
Specifics:
• The directories are very large – 10s of thousands of directories
• I only need to know if one (1) ACL is NOT inherited.
First, I started with Get-ChildItem for the directory list. But that proved very inefficient/slow for the number of directories I’m working with. I did some research and found that the .NET assembly System.IO.Directory.EnumerateDirectories is much faster. That’s the rabbit hole I’m in now. I’m following the Microsoft Docs .NET reference found here.
Here is a sample of what I’m doing:
$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest')
Foreach ($myDir in $enumFolders){
$myDirACL = Get-Acl -Path $myDir
If ($myDirACL[0].Access.IsInherited -eq $false){ # only need to find one, NTFS persmissions lists the non-inherited permissions first.
Write-Output "Non-Inherited Folder $myDir"
}
}
Output (Missing subdirectory C:\ACLTest\myFolder3-InheritOn\mySubFolderA-InheritOFF ):
PS C:\ACLTest> C:\ACLTest\Get-ACLEnum.ps1
Non-Inherited Folder C:\ACLTest\myFolder2-InheritOff
PS C:\ACLTest>
Now, referencing the Microsoft Docs, I found that I can use EnumerationOptions which is “An object that describes the search and enumeration configuration to use.” Following the Docs, I then find another page that describes an EnumerationOptions Boolean Property named “RecurseSubdirectories.” However, I have yet to figure out how to create “An object that describes the search and enumeration configuration to use” and use it in my code.
I’ve tried many variations such as (see below) but none have worked.
$enumOptions = New-Object -TypeName psobject -Property @{'RecurseSubDirectories' = $true}
#$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest')
#From the MS Docs EnumerateDirectories(String, String, EnumerationOptions) or EnumerateDirectories(<path>, <search pattern>, EnumerationOptions)
$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest', '*', $enumOptions)
Foreach ($myDir in $enumFolders){
$myDirACL = Get-Acl -Path $myDir
If ($myDirACL[0].Access.IsInherited -eq $false){ # only need to find one, NTFS persmissions lists the non-inherited permissions first.
Write-Output "Non-Inherited Folder $myDir"
}
}
Output:
PS C:\ACLTest> c:\ACLTest\Get-ACLEnum.ps1
Cannot find an overload for "EnumerateDirectories" and the argument count: "3".
At C:\ACLTest\Get-ACLEnum.ps1:5 char:1
+ $enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTes ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Non-Inherited Folder C:\ACLTest\myFolder2-InheritOff
PS C:\ACLTest>
The way I read the docs is that I can overload the EnumerateDirectories method with three arguments. I’ve yet to find the proper syntax to recurse subdirectories. I would be very thankful if someone could point me in the right direction.
Thank you!