I’ve taken on the task of doing folder/file cleanup on our NAS and I’ve run into a scenario where I’m definitely thinking that Powershell can really help. To note, my PS experience is limited at best. I’m familair with some of the AD/Office 365 cmdlets from my daily tasks but do not have a ton of experience when creating advanced scripts.
I have a parent folder on our NAS with a large amount of access entries on it. This parent folder has hundreds of subfolders. I’m doing some organization of the access entries, but over the years, inheritance has been broken on several subfolders and ACLs have been changed. I’d like to develop a script (or be pointed towards a good resource) that I can recursively run against my parent folder and get a list of subfolders where the ACL is different than that of the parent folder.
I’m thinking that I can leverage both the Get-ChildItem and Get-Acl cmdlets to accomplish what I want but I’m having some difficulty in bringing it all together.
I appreciate any advice that you can share with me or resources that you can point me to.
That - or something similar - will give you a difference object for each child whose ACL is different from the parent’s.
But… Get-ACL only shows direct ACEs, not inherited ones. So a child folder with no ACEs will show as “different” from the parent, because it’s inheriting from the parent, which is in fact what you wanted. So in that case, “different” is good, not bad.
It might be worth thinking carefully about what, exactly, you want to look at and mitigate, before you go down the path of a lot of coding.
Hey Don …Nice logic and code. Awesome…
Just wanted to understand David’s requirement here…
Do you want the script to ask for a path of folder and should match the ACL with its parent folder ?
Thank you, Don. Really like how this came together.
Deepak…it doesn’t necessarily need to prompt for a folder path. I can supply the top level parent directory. I’m just looking for it to recursively move through all of the subfolders and determine the difference between each one of them against what the ACLs on the top level parent folder are.
Get-ChildItem C:\folder -Recurse | ForEach-Object {
try { # Get-Acl throws terminating errors, so wrap it in a try/catch block
$_ | Get-Acl |
where { $_.AreAccessRulesProtected -or ($_.Access | where { $_.IsInherited -eq $false }) } |
foreach { Convert-Path $_.Path }
}
catch {
Write-Error $_
}
}
That should return the path to any files/folders (depends on how you call Get-ChildItem) where DACL inheritance is disabled or a single non-inherited ACE is present. It would be a much prettier command if Get-Acl handled errors properly and you didn’t have to put it in that ForEach-Object block…
With a little tweaking, you could get it to show you the differences instead of just giving you the paths.
Your script is using Write-Host, which isn’t a good practice to begin with. The Power of Powershell comes from working with objects. In your script, you’re just writing information to the prompt, which tells you what is wrong but you have to dig thru output to understand how many directories have non-inherited permissions. If I use the script I posted, I just have to do a simple query to see what folder are not set the way I want:
$Acls | Where{$_."Non-Inherited Count" -gt 0}
Additionally, if I want to fix them, it’s a simple as: